Reduce to a warning the commit-without-apparent-begin exception from 7d216b10
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultSource.pm
CommitLineData
9c992ba1 1package DBIx::Class::ResultSource;
2
3use strict;
4use warnings;
5
6use DBIx::Class::ResultSet;
aec3eff1 7use DBIx::Class::ResultSourceHandle;
1a58752c 8
9use DBIx::Class::Exception;
701da8c4 10use Carp::Clan qw/^DBIx::Class/;
ed7ab0f4 11use Try::Tiny;
6298a324 12use List::Util 'first';
50261284 13use Scalar::Util qw/weaken isweak/;
14use Storable qw/nfreeze thaw/;
fd323bf1 15use namespace::clean;
6da5894c 16
9c992ba1 17use base qw/DBIx::Class/;
9c992ba1 18
aa1088bf 19__PACKAGE__->mk_group_accessors('simple' => qw/_ordered_columns
20 _columns _primaries _unique_constraints name resultset_attributes
4376a157 21 from _relationships column_info_from_storage source_info
f89bb832 22 source_name sqlt_deploy_callback/);
aa1088bf 23
fac560c2 24__PACKAGE__->mk_group_accessors('component_class' => qw/resultset_class
b0dd0e03 25 result_class/);
9c992ba1 26
75d07914 27=head1 NAME
9c992ba1 28
29DBIx::Class::ResultSource - Result source object
30
31=head1 SYNOPSIS
32
16ccb4fe 33 # Create a table based result source, in a result class.
34
35 package MyDB::Schema::Result::Artist;
d88ecca6 36 use base qw/DBIx::Class::Core/;
16ccb4fe 37
16ccb4fe 38 __PACKAGE__->table('artist');
39 __PACKAGE__->add_columns(qw/ artistid name /);
40 __PACKAGE__->set_primary_key('artistid');
41 __PACKAGE__->has_many(cds => 'MyDB::Schema::Result::CD');
42
43 1;
44
45 # Create a query (view) based result source, in a result class
46 package MyDB::Schema::Result::Year2000CDs;
d88ecca6 47 use base qw/DBIx::Class::Core/;
16ccb4fe 48
d88ecca6 49 __PACKAGE__->load_components('InflateColumn::DateTime');
16ccb4fe 50 __PACKAGE__->table_class('DBIx::Class::ResultSource::View');
51
52 __PACKAGE__->table('year2000cds');
53 __PACKAGE__->result_source_instance->is_virtual(1);
54 __PACKAGE__->result_source_instance->view_definition(
55 "SELECT cdid, artist, title FROM cd WHERE year ='2000'"
56 );
57
58
9c992ba1 59=head1 DESCRIPTION
60
16ccb4fe 61A ResultSource is an object that represents a source of data for querying.
62
63This class is a base class for various specialised types of result
64sources, for example L<DBIx::Class::ResultSource::Table>. Table is the
65default result source type, so one is created for you when defining a
66result class as described in the synopsis above.
67
d88ecca6 68More specifically, the L<DBIx::Class::Core> base class pulls in the
69L<DBIx::Class::ResultSourceProxy::Table> component, which defines
70the L<table|DBIx::Class::ResultSourceProxy::Table/table> method.
71When called, C<table> creates and stores an instance of
16ccb4fe 72L<DBIx::Class::ResultSoure::Table>. Luckily, to use tables as result
73sources, you don't need to remember any of this.
74
75Result sources representing select queries, or views, can also be
76created, see L<DBIx::Class::ResultSource::View> for full details.
77
78=head2 Finding result source objects
79
80As mentioned above, a result source instance is created and stored for
81you when you define a L<Result Class|DBIx::Class::Manual::Glossary/Result Class>.
82
83You can retrieve the result source at runtime in the following ways:
84
85=over
86
87=item From a Schema object:
88
89 $schema->source($source_name);
90
91=item From a Row object:
9c992ba1 92
16ccb4fe 93 $row->result_source;
94
95=item From a ResultSet object:
96
97 $rs->result_source;
98
99=back
00be2e0b 100
9c992ba1 101=head1 METHODS
102
7eb4ecc8 103=pod
104
9c992ba1 105=cut
106
107sub new {
108 my ($class, $attrs) = @_;
109 $class = ref $class if ref $class;
04786a4c 110
6b051e14 111 my $new = bless { %{$attrs || {}} }, $class;
9c992ba1 112 $new->{resultset_class} ||= 'DBIx::Class::ResultSet';
5ac6a044 113 $new->{resultset_attributes} = { %{$new->{resultset_attributes} || {}} };
6da5894c 114 $new->{_ordered_columns} = [ @{$new->{_ordered_columns}||[]}];
115 $new->{_columns} = { %{$new->{_columns}||{}} };
116 $new->{_relationships} = { %{$new->{_relationships}||{}} };
9c992ba1 117 $new->{name} ||= "!!NAME NOT SET!!";
5afa2a15 118 $new->{_columns_info_loaded} ||= 0;
f89bb832 119 $new->{sqlt_deploy_callback} ||= "default_sqlt_deploy_hook";
9c992ba1 120 return $new;
121}
122
988bf309 123=pod
124
5ac6a044 125=head2 add_columns
126
391ccf38 127=over
128
129=item Arguments: @columns
130
131=item Return value: The ResultSource object
132
133=back
134
843f6bc1 135 $source->add_columns(qw/col1 col2 col3/);
5ac6a044 136
843f6bc1 137 $source->add_columns('col1' => \%col1_info, 'col2' => \%col2_info, ...);
5ac6a044 138
16ccb4fe 139Adds columns to the result source. If supplied colname => hashref
140pairs, uses the hashref as the L</column_info> for that column. Repeated
141calls of this method will add more columns, not replace them.
5ac6a044 142
5d9d9e87 143The column names given will be created as accessor methods on your
7e51afbf 144L<DBIx::Class::Row> objects. You can change the name of the accessor
5d9d9e87 145by supplying an L</accessor> in the column_info hash.
146
157ce0cf 147If a column name beginning with a plus sign ('+col1') is provided, the
148attributes provided will be merged with any existing attributes for the
149column, with the new attributes taking precedence in the case that an
fd323bf1 150attribute already exists. Using this without a hashref
157ce0cf 151(C<< $source->add_columns(qw/+col1 +col2/) >>) is legal, but useless --
152it does the same thing it would do without the plus.
153
2053ab2a 154The contents of the column_info are not set in stone. The following
155keys are currently recognised/used by DBIx::Class:
988bf309 156
157=over 4
158
75d07914 159=item accessor
988bf309 160
16ccb4fe 161 { accessor => '_name' }
162
163 # example use, replace standard accessor with one of your own:
164 sub name {
165 my ($self, $value) = @_;
166
167 die "Name cannot contain digits!" if($value =~ /\d/);
168 $self->_name($value);
169
170 return $self->_name();
171 }
172
5d9d9e87 173Use this to set the name of the accessor method for this column. If unset,
988bf309 174the name of the column will be used.
175
176=item data_type
177
16ccb4fe 178 { data_type => 'integer' }
179
180This contains the column type. It is automatically filled if you use the
181L<SQL::Translator::Producer::DBIx::Class::File> producer, or the
fd323bf1 182L<DBIx::Class::Schema::Loader> module.
988bf309 183
2053ab2a 184Currently there is no standard set of values for the data_type. Use
185whatever your database supports.
988bf309 186
187=item size
188
16ccb4fe 189 { size => 20 }
190
988bf309 191The length of your column, if it is a column type that can have a size
16ccb4fe 192restriction. This is currently only used to create tables from your
193schema, see L<DBIx::Class::Schema/deploy>.
988bf309 194
195=item is_nullable
196
16ccb4fe 197 { is_nullable => 1 }
198
199Set this to a true value for a columns that is allowed to contain NULL
200values, default is false. This is currently only used to create tables
201from your schema, see L<DBIx::Class::Schema/deploy>.
988bf309 202
203=item is_auto_increment
204
16ccb4fe 205 { is_auto_increment => 1 }
206
2053ab2a 207Set this to a true value for a column whose value is somehow
16ccb4fe 208automatically set, defaults to false. This is used to determine which
209columns to empty when cloning objects using
210L<DBIx::Class::Row/copy>. It is also used by
d7be2784 211L<DBIx::Class::Schema/deploy>.
988bf309 212
26a29815 213=item is_numeric
214
16ccb4fe 215 { is_numeric => 1 }
216
26a29815 217Set this to a true or false value (not C<undef>) to explicitly specify
218if this column contains numeric data. This controls how set_column
219decides whether to consider a column dirty after an update: if
0bad1823 220C<is_numeric> is true a numeric comparison C<< != >> will take place
26a29815 221instead of the usual C<eq>
222
223If not specified the storage class will attempt to figure this out on
224first access to the column, based on the column C<data_type>. The
225result will be cached in this attribute.
226
988bf309 227=item is_foreign_key
228
16ccb4fe 229 { is_foreign_key => 1 }
230
2053ab2a 231Set this to a true value for a column that contains a key from a
16ccb4fe 232foreign table, defaults to false. This is currently only used to
233create tables from your schema, see L<DBIx::Class::Schema/deploy>.
988bf309 234
235=item default_value
236
16ccb4fe 237 { default_value => \'now()' }
238
239Set this to the default value which will be inserted into a column by
240the database. Can contain either a value or a function (use a
4858fea7 241reference to a scalar e.g. C<\'now()'> if you want a function). This
16ccb4fe 242is currently only used to create tables from your schema, see
243L<DBIx::Class::Schema/deploy>.
988bf309 244
a4fcda00 245See the note on L<DBIx::Class::Row/new> for more information about possible
246issues related to db-side default values.
247
988bf309 248=item sequence
249
16ccb4fe 250 { sequence => 'my_table_seq' }
251
2053ab2a 252Set this on a primary key column to the name of the sequence used to
253generate a new key value. If not specified, L<DBIx::Class::PK::Auto>
254will attempt to retrieve the name of the sequence from the database
255automatically.
988bf309 256
838ef78d 257=item auto_nextval
258
ca791b95 259Set this to a true value for a column whose value is retrieved automatically
260from a sequence or function (if supported by your Storage driver.) For a
261sequence, if you do not use a trigger to get the nextval, you have to set the
262L</sequence> value as well.
263
264Also set this for MSSQL columns with the 'uniqueidentifier'
e1958268 265L<data_type|DBIx::Class::ResultSource/data_type> whose values you want to
266automatically generate using C<NEWID()>, unless they are a primary key in which
267case this will be done anyway.
838ef78d 268
190615a7 269=item extra
d7be2784 270
271This is used by L<DBIx::Class::Schema/deploy> and L<SQL::Translator>
190615a7 272to add extra non-generic data to the column. For example: C<< extra
d7be2784 273=> { unsigned => 1} >> is used by the MySQL producer to set an integer
274column to unsigned. For more details, see
275L<SQL::Translator::Producer::MySQL>.
276
988bf309 277=back
278
5ac6a044 279=head2 add_column
280
391ccf38 281=over
282
16ccb4fe 283=item Arguments: $colname, \%columninfo?
391ccf38 284
285=item Return value: 1/0 (true/false)
286
287=back
288
16ccb4fe 289 $source->add_column('col' => \%info);
5ac6a044 290
391ccf38 291Add a single column and optional column info. Uses the same column
292info keys as L</add_columns>.
5ac6a044 293
294=cut
295
9c992ba1 296sub add_columns {
297 my ($self, @cols) = @_;
8e04bf91 298 $self->_ordered_columns(\@cols) unless $self->_ordered_columns;
002a359a 299
20518cb4 300 my @added;
301 my $columns = $self->_columns;
9c992ba1 302 while (my $col = shift @cols) {
157ce0cf 303 my $column_info = {};
304 if ($col =~ s/^\+//) {
305 $column_info = $self->column_info($col);
306 }
307
8e04bf91 308 # If next entry is { ... } use that for the column info, if not
309 # use an empty hashref
157ce0cf 310 if (ref $cols[0]) {
311 my $new_info = shift(@cols);
312 %$column_info = (%$column_info, %$new_info);
313 }
20518cb4 314 push(@added, $col) unless exists $columns->{$col};
20518cb4 315 $columns->{$col} = $column_info;
9c992ba1 316 }
20518cb4 317 push @{ $self->_ordered_columns }, @added;
30126ac7 318 return $self;
9c992ba1 319}
320
b25e9fa0 321sub add_column { shift->add_columns(@_); } # DO NOT CHANGE THIS TO GLOB
9c992ba1 322
3842b955 323=head2 has_column
324
391ccf38 325=over
326
327=item Arguments: $colname
328
329=item Return value: 1/0 (true/false)
330
331=back
332
843f6bc1 333 if ($source->has_column($colname)) { ... }
988bf309 334
2053ab2a 335Returns true if the source has a column of this name, false otherwise.
988bf309 336
337=cut
9c992ba1 338
339sub has_column {
340 my ($self, $column) = @_;
341 return exists $self->_columns->{$column};
342}
343
87c4e602 344=head2 column_info
9c992ba1 345
391ccf38 346=over
347
348=item Arguments: $colname
349
350=item Return value: Hashref of info
351
352=back
353
843f6bc1 354 my $info = $source->column_info($col);
9c992ba1 355
391ccf38 356Returns the column metadata hashref for a column, as originally passed
16ccb4fe 357to L</add_columns>. See L</add_columns> above for information on the
358contents of the hashref.
9c992ba1 359
988bf309 360=cut
9c992ba1 361
362sub column_info {
363 my ($self, $column) = @_;
75d07914 364 $self->throw_exception("No such column $column")
701da8c4 365 unless exists $self->_columns->{$column};
52416317 366
75d07914 367 if ( ! $self->_columns->{$column}{data_type}
368 and ! $self->{_columns_info_loaded}
52416317 369 and $self->column_info_from_storage
4376a157 370 and my $stor = try { $self->storage } )
8e04bf91 371 {
372 $self->{_columns_info_loaded}++;
52b420dd 373
ed7ab0f4 374 # try for the case of storage without table
52b420dd 375 try {
52416317 376 my $info = $stor->columns_info_for( $self->from );
377 my $lc_info = { map
378 { (lc $_) => $info->{$_} }
379 ( keys %$info )
380 };
381
8e04bf91 382 foreach my $col ( keys %{$self->_columns} ) {
d51f93c8 383 $self->_columns->{$col} = {
384 %{ $self->_columns->{$col} },
385 %{ $info->{$col} || $lc_info->{lc $col} || {} }
386 };
a953d8d9 387 }
52b420dd 388 };
a953d8d9 389 }
52416317 390
9c992ba1 391 return $self->_columns->{$column};
392}
393
394=head2 columns
395
391ccf38 396=over
397
398=item Arguments: None
399
400=item Return value: Ordered list of column names
401
402=back
403
404 my @column_names = $source->columns;
20518cb4 405
391ccf38 406Returns all column names in the order they were declared to L</add_columns>.
87f0da6a 407
408=cut
9c992ba1 409
410sub columns {
8e04bf91 411 my $self = shift;
aa1088bf 412 $self->throw_exception(
413 "columns() is a read-only accessor, did you mean add_columns()?"
9851dada 414 ) if @_;
701da8c4 415 return @{$self->{_ordered_columns}||[]};
571dced3 416}
417
52416317 418=head2 columns_info
419
420=over
421
422=item Arguments: \@colnames ?
423
424=item Return value: Hashref of column name/info pairs
425
426=back
427
428 my $columns_info = $source->columns_info;
429
430Like L</column_info> but returns information for the requested columns. If
431the optional column-list arrayref is ommitted it returns info on all columns
432currently defined on the ResultSource via L</add_columns>.
433
434=cut
435
436sub columns_info {
437 my ($self, $columns) = @_;
438
439 my $colinfo = $self->_columns;
440
441 if (
442 first { ! $_->{data_type} } values %$colinfo
443 and
444 ! $self->{_columns_info_loaded}
445 and
446 $self->column_info_from_storage
447 and
4376a157 448 my $stor = try { $self->storage }
52416317 449 ) {
450 $self->{_columns_info_loaded}++;
451
452 # try for the case of storage without table
453 try {
454 my $info = $stor->columns_info_for( $self->from );
455 my $lc_info = { map
456 { (lc $_) => $info->{$_} }
457 ( keys %$info )
458 };
459
460 foreach my $col ( keys %$colinfo ) {
461 $colinfo->{$col} = {
462 %{ $colinfo->{$col} },
463 %{ $info->{$col} || $lc_info->{lc $col} || {} }
464 };
465 }
466 };
467 }
468
469 my %ret;
470
471 if ($columns) {
472 for (@$columns) {
473 if (my $inf = $colinfo->{$_}) {
474 $ret{$_} = $inf;
475 }
476 else {
477 $self->throw_exception( sprintf (
478 "No such column '%s' on source %s",
479 $_,
480 $self->source_name,
481 ));
482 }
483 }
484 }
485 else {
486 %ret = %$colinfo;
487 }
488
489 return \%ret;
490}
491
002a359a 492=head2 remove_columns
493
391ccf38 494=over
002a359a 495
391ccf38 496=item Arguments: @colnames
497
498=item Return value: undefined
499
500=back
501
502 $source->remove_columns(qw/col1 col2 col3/);
503
504Removes the given list of columns by name, from the result source.
505
506B<Warning>: Removing a column that is also used in the sources primary
507key, or in one of the sources unique constraints, B<will> result in a
508broken result source.
002a359a 509
510=head2 remove_column
511
391ccf38 512=over
513
514=item Arguments: $colname
515
516=item Return value: undefined
517
518=back
002a359a 519
391ccf38 520 $source->remove_column('col');
521
522Remove a single column by name from the result source, similar to
523L</remove_columns>.
524
525B<Warning>: Removing a column that is also used in the sources primary
526key, or in one of the sources unique constraints, B<will> result in a
527broken result source.
002a359a 528
529=cut
530
531sub remove_columns {
4738027b 532 my ($self, @to_remove) = @_;
002a359a 533
4738027b 534 my $columns = $self->_columns
535 or return;
002a359a 536
4738027b 537 my %to_remove;
538 for (@to_remove) {
a918d901 539 delete $columns->{$_};
4738027b 540 ++$to_remove{$_};
541 }
002a359a 542
4738027b 543 $self->_ordered_columns([ grep { not $to_remove{$_} } @{$self->_ordered_columns} ]);
002a359a 544}
545
b25e9fa0 546sub remove_column { shift->remove_columns(@_); } # DO NOT CHANGE THIS TO GLOB
002a359a 547
87c4e602 548=head2 set_primary_key
549
27f01d1f 550=over 4
551
ebc77b53 552=item Arguments: @cols
27f01d1f 553
391ccf38 554=item Return value: undefined
555
27f01d1f 556=back
87f0da6a 557
16ccb4fe 558Defines one or more columns as primary key for this source. Must be
391ccf38 559called after L</add_columns>.
87f0da6a 560
391ccf38 561Additionally, defines a L<unique constraint|add_unique_constraint>
562named C<primary>.
87f0da6a 563
90f250bc 564Note: you normally do want to define a primary key on your sources
565B<even if the underlying database table does not have a primary key>.
566See
0c1a4a15 567L<DBIx::Class::Manual::Intro/The Significance and Importance of Primary Keys>
90f250bc 568for more info.
988bf309 569
87f0da6a 570=cut
9c992ba1 571
572sub set_primary_key {
573 my ($self, @cols) = @_;
574 # check if primary key columns are valid columns
8e04bf91 575 foreach my $col (@cols) {
576 $self->throw_exception("No such column $col on table " . $self->name)
577 unless $self->has_column($col);
9c992ba1 578 }
579 $self->_primaries(\@cols);
87f0da6a 580
581 $self->add_unique_constraint(primary => \@cols);
9c992ba1 582}
583
87f0da6a 584=head2 primary_columns
585
391ccf38 586=over 4
587
588=item Arguments: None
589
590=item Return value: Ordered list of primary column names
591
592=back
593
594Read-only accessor which returns the list of primary keys, supplied by
595L</set_primary_key>.
30126ac7 596
87f0da6a 597=cut
9c992ba1 598
599sub primary_columns {
600 return @{shift->_primaries||[]};
601}
602
b1d8e3fd 603# a helper method that will automatically die with a descriptive message if
604# no pk is defined on the source in question. For internal use to save
605# on if @pks... boilerplate
e8fb771b 606sub _pri_cols {
607 my $self = shift;
608 my @pcols = $self->primary_columns
609 or $self->throw_exception (sprintf(
455a33cb 610 "Operation requires a primary key to be declared on '%s' via set_primary_key",
7f505c17 611 # source_name is set only after schema-registration
612 $self->source_name || $self->result_class || $self->name || 'Unknown source...?',
e8fb771b 613 ));
614 return @pcols;
615}
616
89170201 617=head2 sequence
618
619Manually define the correct sequence for your table, to avoid the overhead
620associated with looking up the sequence automatically. The supplied sequence
621will be applied to the L</column_info> of each L<primary_key|/set_primary_key>
622
623=over 4
624
625=item Arguments: $sequence_name
626
627=item Return value: undefined
628
629=back
630
631=cut
632
633sub sequence {
52416317 634 my ($self,$seq) = @_;
635
636 my $rsrc = $self->result_source;
637 my @pks = $rsrc->primary_columns
638 or next;
639
640 $_->{sequence} = $seq
641 for values %{ $rsrc->columns_info (\@pks) };
89170201 642}
643
644
87f0da6a 645=head2 add_unique_constraint
646
391ccf38 647=over 4
648
16ccb4fe 649=item Arguments: $name?, \@colnames
391ccf38 650
651=item Return value: undefined
652
653=back
654
87f0da6a 655Declare a unique constraint on this source. Call once for each unique
58b5bb8c 656constraint.
27f01d1f 657
658 # For UNIQUE (column1, column2)
659 __PACKAGE__->add_unique_constraint(
660 constraint_name => [ qw/column1 column2/ ],
661 );
87f0da6a 662
368a5228 663Alternatively, you can specify only the columns:
664
665 __PACKAGE__->add_unique_constraint([ qw/column1 column2/ ]);
666
16ccb4fe 667This will result in a unique constraint named
668C<table_column1_column2>, where C<table> is replaced with the table
669name.
368a5228 670
16ccb4fe 671Unique constraints are used, for example, when you pass the constraint
672name as the C<key> attribute to L<DBIx::Class::ResultSet/find>. Then
673only columns in the constraint are searched.
58b5bb8c 674
391ccf38 675Throws an error if any of the given column names do not yet exist on
676the result source.
677
87f0da6a 678=cut
679
680sub add_unique_constraint {
368a5228 681 my $self = shift;
034d0be4 682
683 if (@_ > 2) {
684 $self->throw_exception(
685 'add_unique_constraint() does not accept multiple constraints, use '
686 . 'add_unique_constraints() instead'
687 );
688 }
689
368a5228 690 my $cols = pop @_;
034d0be4 691 if (ref $cols ne 'ARRAY') {
692 $self->throw_exception (
693 'Expecting an arrayref of constraint columns, got ' . ($cols||'NOTHING')
694 );
695 }
696
697 my $name = shift @_;
368a5228 698
699 $name ||= $self->name_unique_constraint($cols);
87f0da6a 700
8e04bf91 701 foreach my $col (@$cols) {
702 $self->throw_exception("No such column $col on table " . $self->name)
703 unless $self->has_column($col);
87f0da6a 704 }
705
706 my %unique_constraints = $self->unique_constraints;
707 $unique_constraints{$name} = $cols;
708 $self->_unique_constraints(\%unique_constraints);
709}
710
034d0be4 711=head2 add_unique_constraints
712
713=over 4
714
715=item Arguments: @constraints
716
717=item Return value: undefined
718
719=back
720
721Declare multiple unique constraints on this source.
722
723 __PACKAGE__->add_unique_constraints(
724 constraint_name1 => [ qw/column1 column2/ ],
725 constraint_name2 => [ qw/column2 column3/ ],
726 );
727
728Alternatively, you can specify only the columns:
729
730 __PACKAGE__->add_unique_constraints(
731 [ qw/column1 column2/ ],
732 [ qw/column3 column4/ ]
733 );
734
735This will result in unique constraints named C<table_column1_column2> and
736C<table_column3_column4>, where C<table> is replaced with the table name.
737
738Throws an error if any of the given column names do not yet exist on
739the result source.
740
741See also L</add_unique_constraint>.
742
743=cut
744
745sub add_unique_constraints {
746 my $self = shift;
747 my @constraints = @_;
748
749 if ( !(@constraints % 2) && first { ref $_ ne 'ARRAY' } @constraints ) {
750 # with constraint name
751 while (my ($name, $constraint) = splice @constraints, 0, 2) {
752 $self->add_unique_constraint($name => $constraint);
753 }
754 }
755 else {
756 # no constraint name
757 foreach my $constraint (@constraints) {
758 $self->add_unique_constraint($constraint);
759 }
760 }
761}
762
d9c74322 763=head2 name_unique_constraint
368a5228 764
391ccf38 765=over 4
766
6515609b 767=item Arguments: \@colnames
391ccf38 768
769=item Return value: Constraint name
770
771=back
772
773 $source->table('mytable');
6515609b 774 $source->name_unique_constraint(['col1', 'col2']);
391ccf38 775 # returns
776 'mytable_col1_col2'
777
778Return a name for a unique constraint containing the specified
779columns. The name is created by joining the table name and each column
780name, using an underscore character.
368a5228 781
782For example, a constraint on a table named C<cd> containing the columns
783C<artist> and C<title> would result in a constraint name of C<cd_artist_title>.
784
391ccf38 785This is used by L</add_unique_constraint> if you do not specify the
786optional constraint name.
787
368a5228 788=cut
789
790sub name_unique_constraint {
791 my ($self, $cols) = @_;
792
3e6c1131 793 my $name = $self->name;
4678e9da 794 $name = $$name if (ref $name eq 'SCALAR');
3e6c1131 795
796 return join '_', $name, @$cols;
368a5228 797}
798
87f0da6a 799=head2 unique_constraints
800
391ccf38 801=over 4
802
803=item Arguments: None
804
805=item Return value: Hash of unique constraint data
806
807=back
808
809 $source->unique_constraints();
810
16ccb4fe 811Read-only accessor which returns a hash of unique constraints on this
812source.
391ccf38 813
814The hash is keyed by constraint name, and contains an arrayref of
815column names as values.
87f0da6a 816
817=cut
818
819sub unique_constraints {
820 return %{shift->_unique_constraints||{}};
821}
822
e6a0e17c 823=head2 unique_constraint_names
824
391ccf38 825=over 4
826
827=item Arguments: None
828
829=item Return value: Unique constraint names
830
831=back
832
833 $source->unique_constraint_names();
834
e6a0e17c 835Returns the list of unique constraint names defined on this source.
836
837=cut
838
839sub unique_constraint_names {
840 my ($self) = @_;
841
842 my %unique_constraints = $self->unique_constraints;
843
844 return keys %unique_constraints;
845}
846
847=head2 unique_constraint_columns
848
391ccf38 849=over 4
850
851=item Arguments: $constraintname
852
853=item Return value: List of constraint columns
854
855=back
856
857 $source->unique_constraint_columns('myconstraint');
858
e6a0e17c 859Returns the list of columns that make up the specified unique constraint.
860
861=cut
862
863sub unique_constraint_columns {
864 my ($self, $constraint_name) = @_;
865
866 my %unique_constraints = $self->unique_constraints;
867
868 $self->throw_exception(
869 "Unknown unique constraint $constraint_name on '" . $self->name . "'"
870 ) unless exists $unique_constraints{$constraint_name};
871
872 return @{ $unique_constraints{$constraint_name} };
873}
874
880c075b 875=head2 sqlt_deploy_callback
876
877=over
878
879=item Arguments: $callback
880
881=back
882
883 __PACKAGE__->sqlt_deploy_callback('mycallbackmethod');
884
885An accessor to set a callback to be called during deployment of
886the schema via L<DBIx::Class::Schema/create_ddl_dir> or
887L<DBIx::Class::Schema/deploy>.
888
889The callback can be set as either a code reference or the name of a
890method in the current result class.
891
892If not set, the L</default_sqlt_deploy_hook> is called.
893
894Your callback will be passed the $source object representing the
895ResultSource instance being deployed, and the
896L<SQL::Translator::Schema::Table> object being created from it. The
897callback can be used to manipulate the table object or add your own
898customised indexes. If you need to manipulate a non-table object, use
899the L<DBIx::Class::Schema/sqlt_deploy_hook>.
900
901See L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To
902Your SQL> for examples.
903
904This sqlt deployment callback can only be used to manipulate
905SQL::Translator objects as they get turned into SQL. To execute
906post-deploy statements which SQL::Translator does not currently
907handle, override L<DBIx::Class::Schema/deploy> in your Schema class
908and call L<dbh_do|DBIx::Class::Storage::DBI/dbh_do>.
909
910=head2 default_sqlt_deploy_hook
911
912=over
913
914=item Arguments: $source, $sqlt_table
915
916=item Return value: undefined
917
918=back
919
920This is the sensible default for L</sqlt_deploy_callback>.
921
922If a method named C<sqlt_deploy_hook> exists in your Result class, it
923will be called and passed the current C<$source> and the
924C<$sqlt_table> being deployed.
925
926=cut
927
928sub default_sqlt_deploy_hook {
929 my $self = shift;
930
931 my $class = $self->result_class;
932
933 if ($class and $class->can('sqlt_deploy_hook')) {
934 $class->sqlt_deploy_hook(@_);
935 }
936}
937
938sub _invoke_sqlt_deploy_hook {
939 my $self = shift;
940 if ( my $hook = $self->sqlt_deploy_callback) {
941 $self->$hook(@_);
942 }
943}
944
843f6bc1 945=head2 resultset
946
947=over 4
948
949=item Arguments: None
950
951=item Return value: $resultset
952
953=back
954
955Returns a resultset for the given source. This will initially be created
956on demand by calling
957
958 $self->resultset_class->new($self, $self->resultset_attributes)
959
960but is cached from then on unless resultset_class changes.
961
962=head2 resultset_class
963
964=over 4
965
966=item Arguments: $classname
967
968=item Return value: $classname
969
970=back
971
16ccb4fe 972 package My::Schema::ResultSet::Artist;
843f6bc1 973 use base 'DBIx::Class::ResultSet';
974 ...
975
16ccb4fe 976 # In the result class
977 __PACKAGE__->resultset_class('My::Schema::ResultSet::Artist');
978
979 # Or in code
980 $source->resultset_class('My::Schema::ResultSet::Artist');
843f6bc1 981
7e51afbf 982Set the class of the resultset. This is useful if you want to create your
843f6bc1 983own resultset methods. Create your own class derived from
984L<DBIx::Class::ResultSet>, and set it here. If called with no arguments,
985this method returns the name of the existing resultset class, if one
986exists.
987
988=head2 resultset_attributes
989
990=over 4
991
992=item Arguments: \%attrs
993
994=item Return value: \%attrs
995
996=back
997
16ccb4fe 998 # In the result class
999 __PACKAGE__->resultset_attributes({ order_by => [ 'id' ] });
1000
1001 # Or in code
843f6bc1 1002 $source->resultset_attributes({ order_by => [ 'id' ] });
1003
1004Store a collection of resultset attributes, that will be set on every
1005L<DBIx::Class::ResultSet> produced from this result source. For a full
1006list see L<DBIx::Class::ResultSet/ATTRIBUTES>.
1007
1008=cut
1009
1010sub resultset {
1011 my $self = shift;
1012 $self->throw_exception(
1013 'resultset does not take any arguments. If you want another resultset, '.
1014 'call it on the schema instead.'
1015 ) if scalar @_;
1016
4376a157 1017 $self->resultset_class->new(
843f6bc1 1018 $self,
1019 {
4376a157 1020 try { %{$self->schema->default_resultset_attributes} },
843f6bc1 1021 %{$self->{resultset_attributes}},
843f6bc1 1022 },
1023 );
1024}
1025
1026=head2 source_name
1027
1028=over 4
1029
1030=item Arguments: $source_name
1031
1032=item Result value: $source_name
1033
1034=back
1035
1036Set an alternate name for the result source when it is loaded into a schema.
1037This is useful if you want to refer to a result source by a name other than
1038its class name.
1039
1040 package ArchivedBooks;
1041 use base qw/DBIx::Class/;
1042 __PACKAGE__->table('books_archive');
1043 __PACKAGE__->source_name('Books');
1044
1045 # from your schema...
1046 $schema->resultset('Books')->find(1);
1047
9c992ba1 1048=head2 from
1049
391ccf38 1050=over 4
1051
1052=item Arguments: None
1053
1054=item Return value: FROM clause
1055
1056=back
1057
1058 my $from_clause = $source->from();
1059
9c992ba1 1060Returns an expression of the source to be supplied to storage to specify
2053ab2a 1061retrieval from this source. In the case of a database, the required FROM
1062clause contents.
9c992ba1 1063
f9b7bd6e 1064=head2 schema
1065
391ccf38 1066=over 4
1067
4376a157 1068=item Arguments: $schema
391ccf38 1069
1070=item Return value: A schema object
1071
1072=back
1073
1074 my $schema = $source->schema();
1075
4376a157 1076Sets and/or returns the L<DBIx::Class::Schema> object to which this
1077result source instance has been attached to.
1078
1079=cut
1080
1081sub schema {
1082 if (@_ > 1) {
1083 $_[0]->{schema} = $_[1];
1084 }
1085 else {
1086 $_[0]->{schema} || do {
1087 my $name = $_[0]->{source_name} || '_unnamed_';
1088 my $err = 'Unable to perform storage-dependent operations with a detached result source '
1089 . "(source '$name' is not associated with a schema).";
1090
1091 $err .= ' You need to use $schema->thaw() or manually set'
1092 . ' $DBIx::Class::ResultSourceHandle::thaw_schema while thawing.'
1093 if $_[0]->{_detached_thaw};
1094
1095 DBIx::Class::Exception->throw($err);
1096 };
1097 }
1098}
9c992ba1 1099
1100=head2 storage
1101
391ccf38 1102=over 4
1103
1104=item Arguments: None
1105
1106=item Return value: A Storage object
1107
1108=back
1109
1110 $source->storage->debug(1);
1111
75d07914 1112Returns the storage handle for the current schema.
988bf309 1113
1114See also: L<DBIx::Class::Storage>
9c992ba1 1115
1116=cut
1117
1118sub storage { shift->schema->storage; }
1119
8452e496 1120=head2 add_relationship
1121
391ccf38 1122=over 4
1123
1124=item Arguments: $relname, $related_source_name, \%cond, [ \%attrs ]
1125
1126=item Return value: 1/true if it succeeded
1127
1128=back
1129
8452e496 1130 $source->add_relationship('relname', 'related_source', $cond, $attrs);
1131
391ccf38 1132L<DBIx::Class::Relationship> describes a series of methods which
1133create pre-defined useful types of relationships. Look there first
1134before using this method directly.
1135
24d67825 1136The relationship name can be arbitrary, but must be unique for each
1137relationship attached to this result source. 'related_source' should
1138be the name with which the related result source was registered with
1139the current schema. For example:
8452e496 1140
24d67825 1141 $schema->source('Book')->add_relationship('reviews', 'Review', {
1142 'foreign.book_id' => 'self.id',
1143 });
1144
2053ab2a 1145The condition C<$cond> needs to be an L<SQL::Abstract>-style
24d67825 1146representation of the join between the tables. For example, if you're
391ccf38 1147creating a relation from Author to Book,
988bf309 1148
1149 { 'foreign.author_id' => 'self.id' }
1150
1151will result in the JOIN clause
1152
1153 author me JOIN book foreign ON foreign.author_id = me.id
1154
8452e496 1155You can specify as many foreign => self mappings as necessary.
1156
988bf309 1157Valid attributes are as follows:
1158
1159=over 4
1160
1161=item join_type
1162
1163Explicitly specifies the type of join to use in the relationship. Any
1164SQL join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in
1165the SQL command immediately before C<JOIN>.
1166
1167=item proxy
1168
24d67825 1169An arrayref containing a list of accessors in the foreign class to proxy in
1170the main class. If, for example, you do the following:
002a359a 1171
24d67825 1172 CD->might_have(liner_notes => 'LinerNotes', undef, {
1173 proxy => [ qw/notes/ ],
1174 });
002a359a 1175
24d67825 1176Then, assuming LinerNotes has an accessor named notes, you can do:
988bf309 1177
24d67825 1178 my $cd = CD->find(1);
2053ab2a 1179 # set notes -- LinerNotes object is created if it doesn't exist
1180 $cd->notes('Notes go here');
988bf309 1181
1182=item accessor
1183
1184Specifies the type of accessor that should be created for the
75d07914 1185relationship. Valid values are C<single> (for when there is only a single
1186related object), C<multi> (when there can be many), and C<filter> (for
1187when there is a single related object, but you also want the relationship
1188accessor to double as a column accessor). For C<multi> accessors, an
1189add_to_* method is also created, which calls C<create_related> for the
988bf309 1190relationship.
1191
8452e496 1192=back
1193
391ccf38 1194Throws an exception if the condition is improperly supplied, or cannot
6d0ee587 1195be resolved.
391ccf38 1196
8452e496 1197=cut
1198
1199sub add_relationship {
1200 my ($self, $rel, $f_source_name, $cond, $attrs) = @_;
27f01d1f 1201 $self->throw_exception("Can't create relationship without join condition")
1202 unless $cond;
8452e496 1203 $attrs ||= {};
87772e46 1204
eba322a7 1205 # Check foreign and self are right in cond
1206 if ( (ref $cond ||'') eq 'HASH') {
1207 for (keys %$cond) {
1208 $self->throw_exception("Keys of condition should be of form 'foreign.col', not '$_'")
1209 if /\./ && !/^foreign\./;
1210 }
1211 }
1212
8452e496 1213 my %rels = %{ $self->_relationships };
1214 $rels{$rel} = { class => $f_source_name,
87772e46 1215 source => $f_source_name,
8452e496 1216 cond => $cond,
1217 attrs => $attrs };
1218 $self->_relationships(\%rels);
1219
30126ac7 1220 return $self;
87772e46 1221
52b420dd 1222# XXX disabled. doesn't work properly currently. skip in tests.
953a18ef 1223
8452e496 1224 my $f_source = $self->schema->source($f_source_name);
1225 unless ($f_source) {
c037c03a 1226 $self->ensure_class_loaded($f_source_name);
8452e496 1227 $f_source = $f_source_name->result_source;
87772e46 1228 #my $s_class = ref($self->schema);
1229 #$f_source_name =~ m/^${s_class}::(.*)$/;
1230 #$self->schema->register_class(($1 || $f_source_name), $f_source_name);
1231 #$f_source = $self->schema->source($f_source_name);
8452e496 1232 }
1233 return unless $f_source; # Can't test rel without f_source
1234
ed7ab0f4 1235 try { $self->_resolve_join($rel, 'me', {}, []) }
1236 catch {
1237 # If the resolve failed, back out and re-throw the error
52b420dd 1238 delete $rels{$rel};
8452e496 1239 $self->_relationships(\%rels);
ed7ab0f4 1240 $self->throw_exception("Error creating relationship $rel: $_");
1241 };
52b420dd 1242
8452e496 1243 1;
1244}
1245
87c4e602 1246=head2 relationships
8452e496 1247
391ccf38 1248=over 4
1249
1250=item Arguments: None
1251
1252=item Return value: List of relationship names
1253
1254=back
1255
1256 my @relnames = $source->relationships();
1257
2053ab2a 1258Returns all relationship names for this source.
8452e496 1259
1260=cut
1261
1262sub relationships {
1263 return keys %{shift->_relationships};
1264}
1265
87c4e602 1266=head2 relationship_info
1267
27f01d1f 1268=over 4
1269
ebc77b53 1270=item Arguments: $relname
27f01d1f 1271
391ccf38 1272=item Return value: Hashref of relation data,
1273
27f01d1f 1274=back
8452e496 1275
2053ab2a 1276Returns a hash of relationship information for the specified relationship
391ccf38 1277name. The keys/values are as specified for L</add_relationship>.
8452e496 1278
1279=cut
1280
1281sub relationship_info {
1282 my ($self, $rel) = @_;
1283 return $self->_relationships->{$rel};
75d07914 1284}
8452e496 1285
87c4e602 1286=head2 has_relationship
1287
27f01d1f 1288=over 4
1289
ebc77b53 1290=item Arguments: $rel
27f01d1f 1291
391ccf38 1292=item Return value: 1/0 (true/false)
1293
27f01d1f 1294=back
953a18ef 1295
2053ab2a 1296Returns true if the source has a relationship of this name, false otherwise.
988bf309 1297
1298=cut
953a18ef 1299
1300sub has_relationship {
1301 my ($self, $rel) = @_;
1302 return exists $self->_relationships->{$rel};
1303}
1304
de60a93d 1305=head2 reverse_relationship_info
1306
1307=over 4
1308
1309=item Arguments: $relname
1310
391ccf38 1311=item Return value: Hashref of relationship data
1312
de60a93d 1313=back
1314
391ccf38 1315Looks through all the relationships on the source this relationship
1316points to, looking for one whose condition is the reverse of the
1317condition on this relationship.
1318
1319A common use of this is to find the name of the C<belongs_to> relation
1320opposing a C<has_many> relation. For definition of these look in
1321L<DBIx::Class::Relationship>.
1322
1323The returned hashref is keyed by the name of the opposing
faaba25f 1324relationship, and contains its data in the same manner as
391ccf38 1325L</relationship_info>.
de60a93d 1326
1327=cut
1328
1329sub reverse_relationship_info {
1330 my ($self, $rel) = @_;
1331 my $rel_info = $self->relationship_info($rel);
1332 my $ret = {};
1333
1334 return $ret unless ((ref $rel_info->{cond}) eq 'HASH');
1335
1336 my @cond = keys(%{$rel_info->{cond}});
1337 my @refkeys = map {/^\w+\.(\w+)$/} @cond;
1338 my @keys = map {$rel_info->{cond}->{$_} =~ /^\w+\.(\w+)$/} @cond;
bab77431 1339
de60a93d 1340 # Get the related result source for this relationship
1341 my $othertable = $self->related_source($rel);
1342
1343 # Get all the relationships for that source that related to this source
1344 # whose foreign column set are our self columns on $rel and whose self
bab77431 1345 # columns are our foreign columns on $rel.
de60a93d 1346 my @otherrels = $othertable->relationships();
1347 my $otherrelationship;
1348 foreach my $otherrel (@otherrels) {
1349 my $otherrel_info = $othertable->relationship_info($otherrel);
1350
1351 my $back = $othertable->related_source($otherrel);
f3fb2641 1352 next unless $back->source_name eq $self->source_name;
de60a93d 1353
1354 my @othertestconds;
1355
1356 if (ref $otherrel_info->{cond} eq 'HASH') {
1357 @othertestconds = ($otherrel_info->{cond});
1358 }
1359 elsif (ref $otherrel_info->{cond} eq 'ARRAY') {
1360 @othertestconds = @{$otherrel_info->{cond}};
1361 }
1362 else {
1363 next;
1364 }
1365
1366 foreach my $othercond (@othertestconds) {
1367 my @other_cond = keys(%$othercond);
1368 my @other_refkeys = map {/^\w+\.(\w+)$/} @other_cond;
1369 my @other_keys = map {$othercond->{$_} =~ /^\w+\.(\w+)$/} @other_cond;
6d0ee587 1370 next if (!$self->_compare_relationship_keys(\@refkeys, \@other_keys) ||
1371 !$self->_compare_relationship_keys(\@other_refkeys, \@keys));
de60a93d 1372 $ret->{$otherrel} = $otherrel_info;
1373 }
1374 }
1375 return $ret;
1376}
1377
de60a93d 1378sub compare_relationship_keys {
6d0ee587 1379 carp 'compare_relationship_keys is a private method, stop calling it';
1380 my $self = shift;
1381 $self->_compare_relationship_keys (@_);
1382}
1383
1384# Returns true if both sets of keynames are the same, false otherwise.
1385sub _compare_relationship_keys {
de60a93d 1386 my ($self, $keys1, $keys2) = @_;
1387
1388 # Make sure every keys1 is in keys2
1389 my $found;
1390 foreach my $key (@$keys1) {
1391 $found = 0;
1392 foreach my $prim (@$keys2) {
1393 if ($prim eq $key) {
1394 $found = 1;
1395 last;
1396 }
1397 }
1398 last unless $found;
1399 }
1400
1401 # Make sure every key2 is in key1
1402 if ($found) {
1403 foreach my $prim (@$keys2) {
1404 $found = 0;
1405 foreach my $key (@$keys1) {
1406 if ($prim eq $key) {
1407 $found = 1;
1408 last;
1409 }
1410 }
1411 last unless $found;
1412 }
1413 }
1414
1415 return $found;
1416}
1417
6d0ee587 1418# Returns the {from} structure used to express JOIN conditions
1419sub _resolve_join {
8a3fa4ae 1420 my ($self, $join, $alias, $seen, $jpath, $parent_force_left) = @_;
1979278e 1421
1422 # we need a supplied one, because we do in-place modifications, no returns
6d0ee587 1423 $self->throw_exception ('You must supply a seen hashref as the 3rd argument to _resolve_join')
88a66388 1424 unless ref $seen eq 'HASH';
1979278e 1425
88a66388 1426 $self->throw_exception ('You must supply a joinpath arrayref as the 4th argument to _resolve_join')
1427 unless ref $jpath eq 'ARRAY';
1428
38f42d85 1429 $jpath = [@$jpath]; # copy
1979278e 1430
8a3fa4ae 1431 if (not defined $join) {
1432 return ();
1433 }
1434 elsif (ref $join eq 'ARRAY') {
caac1708 1435 return
1436 map {
8a3fa4ae 1437 $self->_resolve_join($_, $alias, $seen, $jpath, $parent_force_left);
caac1708 1438 } @$join;
8a3fa4ae 1439 }
1440 elsif (ref $join eq 'HASH') {
1441
1442 my @ret;
1443 for my $rel (keys %$join) {
1444
1445 my $rel_info = $self->relationship_info($rel)
455a33cb 1446 or $self->throw_exception("No such relationship '$rel' on " . $self->source_name);
8a3fa4ae 1447
1448 my $force_left = $parent_force_left;
1449 $force_left ||= lc($rel_info->{attrs}{join_type}||'') eq 'left';
1450
1451 # the actual seen value will be incremented by the recursion
6c0230de 1452 my $as = $self->storage->relname_to_table_alias(
1453 $rel, ($seen->{$rel} && $seen->{$rel} + 1)
1454 );
1979278e 1455
8a3fa4ae 1456 push @ret, (
1457 $self->_resolve_join($rel, $alias, $seen, [@$jpath], $force_left),
1458 $self->related_source($rel)->_resolve_join(
38f42d85 1459 $join->{$rel}, $as, $seen, [@$jpath, { $rel => $as }], $force_left
8a3fa4ae 1460 )
1461 );
1462 }
1463 return @ret;
096395af 1464
8a3fa4ae 1465 }
1466 elsif (ref $join) {
1467 $self->throw_exception("No idea how to resolve join reftype ".ref $join);
1468 }
1469 else {
489709af 1470 my $count = ++$seen->{$join};
6c0230de 1471 my $as = $self->storage->relname_to_table_alias(
1472 $join, ($count > 1 && $count)
1473 );
1979278e 1474
8a3fa4ae 1475 my $rel_info = $self->relationship_info($join)
455a33cb 1476 or $self->throw_exception("No such relationship $join on " . $self->source_name);
ba61fa2a 1477
1478 my $rel_src = $self->related_source($join);
1479 return [ { $as => $rel_src->from,
4376a157 1480 -rsrc => $rel_src,
8a3fa4ae 1481 -join_type => $parent_force_left
1482 ? 'left'
1483 : $rel_info->{attrs}{join_type}
1484 ,
38f42d85 1485 -join_path => [@$jpath, { $join => $as } ],
b82c8a28 1486 -is_single => (
1487 $rel_info->{attrs}{accessor}
1488 &&
6298a324 1489 first { $rel_info->{attrs}{accessor} eq $_ } (qw/single filter/)
b82c8a28 1490 ),
ba61fa2a 1491 -alias => $as,
1979278e 1492 -relation_chain_depth => $seen->{-relation_chain_depth} || 0,
1493 },
6d0ee587 1494 $self->_resolve_condition($rel_info->{cond}, $as, $alias) ];
953a18ef 1495 }
1496}
1497
370f2ba2 1498sub pk_depends_on {
6d0ee587 1499 carp 'pk_depends_on is a private method, stop calling it';
1500 my $self = shift;
1501 $self->_pk_depends_on (@_);
1502}
1503
1504# Determines whether a relation is dependent on an object from this source
1505# having already been inserted. Takes the name of the relationship and a
1506# hashref of columns of the related object.
1507sub _pk_depends_on {
370f2ba2 1508 my ($self, $relname, $rel_data) = @_;
370f2ba2 1509
c39b48e5 1510 my $relinfo = $self->relationship_info($relname);
1511
1512 # don't assume things if the relationship direction is specified
1513 return $relinfo->{attrs}{is_foreign_key_constraint}
1514 if exists ($relinfo->{attrs}{is_foreign_key_constraint});
1515
1516 my $cond = $relinfo->{cond};
370f2ba2 1517 return 0 unless ref($cond) eq 'HASH';
1518
1519 # map { foreign.foo => 'self.bar' } to { bar => 'foo' }
370f2ba2 1520 my $keyhash = { map { my $x = $_; $x =~ s/.*\.//; $x; } reverse %$cond };
1521
1522 # assume anything that references our PK probably is dependent on us
1523 # rather than vice versa, unless the far side is (a) defined or (b)
1524 # auto-increment
370f2ba2 1525 my $rel_source = $self->related_source($relname);
1526
1527 foreach my $p ($self->primary_columns) {
1528 if (exists $keyhash->{$p}) {
1529 unless (defined($rel_data->{$keyhash->{$p}})
1530 || $rel_source->column_info($keyhash->{$p})
1531 ->{is_auto_increment}) {
1532 return 0;
1533 }
1534 }
1535 }
1536
1537 return 1;
1538}
1539
6d0ee587 1540sub resolve_condition {
1541 carp 'resolve_condition is a private method, stop calling it';
1542 my $self = shift;
1543 $self->_resolve_condition (@_);
1544}
953a18ef 1545
6d0ee587 1546# Resolves the passed condition to a concrete query fragment. If given an alias,
1547# returns a join condition; if given an object, inverts that object to produce
1548# a related conditional from that object.
8c368cf3 1549our $UNRESOLVABLE_CONDITION = \'1 = 0';
1550
6d0ee587 1551sub _resolve_condition {
489709af 1552 my ($self, $cond, $as, $for) = @_;
953a18ef 1553 if (ref $cond eq 'HASH') {
1554 my %ret;
bd054cb4 1555 foreach my $k (keys %{$cond}) {
1556 my $v = $cond->{$k};
953a18ef 1557 # XXX should probably check these are valid columns
27f01d1f 1558 $k =~ s/^foreign\.// ||
75d07914 1559 $self->throw_exception("Invalid rel cond key ${k}");
27f01d1f 1560 $v =~ s/^self\.// ||
75d07914 1561 $self->throw_exception("Invalid rel cond val ${v}");
953a18ef 1562 if (ref $for) { # Object
3842b955 1563 #warn "$self $k $for $v";
370f2ba2 1564 unless ($for->has_column_loaded($v)) {
1565 if ($for->in_storage) {
8bbfe6b2 1566 $self->throw_exception(sprintf
5c89c897 1567 "Unable to resolve relationship '%s' from object %s: column '%s' not "
1568 . 'loaded from storage (or not passed to new() prior to insert()). You '
1569 . 'probably need to call ->discard_changes to get the server-side defaults '
1570 . 'from the database.',
8bbfe6b2 1571 $as,
971beb94 1572 $for,
5c89c897 1573 $v,
a4fcda00 1574 );
370f2ba2 1575 }
68f3b0dd 1576 return $UNRESOLVABLE_CONDITION;
370f2ba2 1577 }
1578 $ret{$k} = $for->get_column($v);
1579 #$ret{$k} = $for->get_column($v) if $for->has_column_loaded($v);
3842b955 1580 #warn %ret;
2c037e6b 1581 } elsif (!defined $for) { # undef, i.e. "no object"
1582 $ret{$k} = undef;
2ec8e594 1583 } elsif (ref $as eq 'HASH') { # reverse hashref
1584 $ret{$v} = $as->{$k};
fde6e28e 1585 } elsif (ref $as) { # reverse object
1586 $ret{$v} = $as->get_column($k);
2c037e6b 1587 } elsif (!defined $as) { # undef, i.e. "no reverse object"
1588 $ret{$v} = undef;
953a18ef 1589 } else {
489709af 1590 $ret{"${as}.${k}"} = "${for}.${v}";
953a18ef 1591 }
953a18ef 1592 }
1593 return \%ret;
5efe4c79 1594 } elsif (ref $cond eq 'ARRAY') {
6d0ee587 1595 return [ map { $self->_resolve_condition($_, $as, $for) } @$cond ];
953a18ef 1596 } else {
35c77aa3 1597 die("Can't handle condition $cond yet :(");
87772e46 1598 }
1599}
1600
988bf309 1601
6d0ee587 1602# Accepts one or more relationships for the current source and returns an
1603# array of column names for each of those relationships. Column names are
1604# prefixed relative to the current source, in accordance with where they appear
38f42d85 1605# in the supplied relationships.
b3e8ac9b 1606
6d0ee587 1607sub _resolve_prefetch {
1979278e 1608 my ($self, $pre, $alias, $alias_map, $order, $collapse, $pref_path) = @_;
1609 $pref_path ||= [];
1610
8a3fa4ae 1611 if (not defined $pre) {
1612 return ();
1613 }
1614 elsif( ref $pre eq 'ARRAY' ) {
0f66a01b 1615 return
6d0ee587 1616 map { $self->_resolve_prefetch( $_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ) }
0f66a01b 1617 @$pre;
b3e8ac9b 1618 }
1619 elsif( ref $pre eq 'HASH' ) {
1620 my @ret =
1621 map {
6d0ee587 1622 $self->_resolve_prefetch($_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ),
1623 $self->related_source($_)->_resolve_prefetch(
1979278e 1624 $pre->{$_}, "${alias}.$_", $alias_map, $order, $collapse, [ @$pref_path, $_] )
0f66a01b 1625 } keys %$pre;
b3e8ac9b 1626 return @ret;
1627 }
1628 elsif( ref $pre ) {
a86b1efe 1629 $self->throw_exception(
1630 "don't know how to resolve prefetch reftype ".ref($pre));
b3e8ac9b 1631 }
1632 else {
1979278e 1633 my $p = $alias_map;
1634 $p = $p->{$_} for (@$pref_path, $pre);
1635
1636 $self->throw_exception (
5e8cb53c 1637 "Unable to resolve prefetch '$pre' - join alias map does not contain an entry for path: "
1979278e 1638 . join (' -> ', @$pref_path, $pre)
1639 ) if (ref $p->{-join_aliases} ne 'ARRAY' or not @{$p->{-join_aliases}} );
88a66388 1640
1979278e 1641 my $as = shift @{$p->{-join_aliases}};
1642
b3e8ac9b 1643 my $rel_info = $self->relationship_info( $pre );
455a33cb 1644 $self->throw_exception( $self->source_name . " has no such relationship '$pre'" )
a86b1efe 1645 unless $rel_info;
37f23589 1646 my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : '');
a86b1efe 1647 my $rel_source = $self->related_source($pre);
0f66a01b 1648
b82c8a28 1649 if ($rel_info->{attrs}{accessor} && $rel_info->{attrs}{accessor} eq 'multi') {
0f66a01b 1650 $self->throw_exception(
1651 "Can't prefetch has_many ${pre} (join cond too complex)")
1652 unless ref($rel_info->{cond}) eq 'HASH';
cb136e67 1653 my $dots = @{[$as_prefix =~ m/\./g]} + 1; # +1 to match the ".${as_prefix}"
1654 if (my ($fail) = grep { @{[$_ =~ m/\./g]} == $dots }
1655 keys %{$collapse}) {
1656 my ($last) = ($fail =~ /([^\.]+)$/);
616b461d 1657 carp (
1658 "Prefetching multiple has_many rels ${last} and ${pre} "
1659 .(length($as_prefix)
1660 ? "at the same level (${as_prefix}) "
1661 : "at top level "
1662 )
2e251255 1663 . 'will explode the number of row objects retrievable via ->next or ->all. '
616b461d 1664 . 'Use at your own risk.'
1665 );
cb136e67 1666 }
b25e9fa0 1667 #my @col = map { (/^self\.(.+)$/ ? ("${as_prefix}.$1") : ()); }
1668 # values %{$rel_info->{cond}};
b1d8e3fd 1669 $collapse->{".${as_prefix}${pre}"} = [ $rel_source->_pri_cols ];
b25e9fa0 1670 # action at a distance. prepending the '.' allows simpler code
1671 # in ResultSet->_collapse_result
37f23589 1672 my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); }
0f66a01b 1673 keys %{$rel_info->{cond}};
d2fcb9b3 1674 push @$order, map { "${as}.$_" } @key;
fd323bf1 1675
d2fcb9b3 1676 if (my $rel_order = $rel_info->{attrs}{order_by}) {
1677 # this is kludgy and incomplete, I am well aware
1678 # but the parent method is going away entirely anyway
1679 # so sod it
1680 my $sql_maker = $self->storage->sql_maker;
1681 my ($orig_ql, $orig_qr) = $sql_maker->_quote_chars;
1682 my $sep = $sql_maker->name_sep;
1683
1684 # install our own quoter, so we can catch unqualified stuff
1685 local $sql_maker->{quote_char} = ["\x00", "\xFF"];
1686
1687 my $quoted_prefix = "\x00${as}\xFF";
1688
1689 for my $chunk ( $sql_maker->_order_by_chunks ($rel_order) ) {
1690 my @bind;
1691 ($chunk, @bind) = @$chunk if ref $chunk;
1692
1693 $chunk = "${quoted_prefix}${sep}${chunk}"
1694 unless $chunk =~ /\Q$sep/;
1695
1696 $chunk =~ s/\x00/$orig_ql/g;
1697 $chunk =~ s/\xFF/$orig_qr/g;
1698 push @$order, \[$chunk, @bind];
1699 }
1700 }
0f66a01b 1701 }
1702
489709af 1703 return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] }
a86b1efe 1704 $rel_source->columns;
b3e8ac9b 1705 }
1706}
953a18ef 1707
87c4e602 1708=head2 related_source
1709
27f01d1f 1710=over 4
1711
ebc77b53 1712=item Arguments: $relname
27f01d1f 1713
391ccf38 1714=item Return value: $source
1715
27f01d1f 1716=back
87772e46 1717
2053ab2a 1718Returns the result source object for the given relationship.
87772e46 1719
1720=cut
1721
1722sub related_source {
1723 my ($self, $rel) = @_;
aea52c85 1724 if( !$self->has_relationship( $rel ) ) {
455a33cb 1725 $self->throw_exception("No such relationship '$rel' on " . $self->source_name);
aea52c85 1726 }
87772e46 1727 return $self->schema->source($self->relationship_info($rel)->{source});
8452e496 1728}
1729
77254782 1730=head2 related_class
1731
27f01d1f 1732=over 4
1733
ebc77b53 1734=item Arguments: $relname
27f01d1f 1735
391ccf38 1736=item Return value: $classname
1737
27f01d1f 1738=back
77254782 1739
2053ab2a 1740Returns the class name for objects in the given relationship.
77254782 1741
1742=cut
1743
1744sub related_class {
1745 my ($self, $rel) = @_;
1746 if( !$self->has_relationship( $rel ) ) {
455a33cb 1747 $self->throw_exception("No such relationship '$rel' on " . $self->source_name);
77254782 1748 }
1749 return $self->schema->class($self->relationship_info($rel)->{source});
1750}
1751
aec3eff1 1752=head2 handle
1753
4376a157 1754=over 4
1755
1756=item Arguments: None
1757
1758=item Return value: $source_handle
1759
1760=back
1761
1762Obtain a new L<result source handle instance|DBIx::Class::ResultSourceHandle>
1763for this source. Used as a serializable pointer to this resultsource, as it is not
1764easy (nor advisable) to serialize CODErefs which may very well be present in e.g.
1765relationship definitions.
aec3eff1 1766
1767=cut
1768
1769sub handle {
4376a157 1770 return DBIx::Class::ResultSourceHandle->new({
1771 source_moniker => $_[0]->source_name,
1772
1773 # so that a detached thaw can be re-frozen
1774 $_[0]->{_detached_thaw}
1775 ? ( _detached_source => $_[0] )
1776 : ( schema => $_[0]->schema )
1777 ,
1778 });
aec3eff1 1779}
1780
50261284 1781{
1782 my $global_phase_destroy;
1783
1784 END { $global_phase_destroy++ }
1785
1786 sub DESTROY {
1787 return if $global_phase_destroy;
1788
1789######
1790# !!! ACHTUNG !!!!
1791######
1792#
1793# Under no circumstances shall $_[0] be stored anywhere else (like copied to
1794# a lexical variable, or shifted, or anything else). Doing so will mess up
1795# the refcount of this particular result source, and will allow the $schema
1796# we are trying to save to reattach back to the source we are destroying.
1797# The relevant code checking refcounts is in ::Schema::DESTROY()
1798
1799 # if we are not a schema instance holder - we don't matter
1800 return if(
1801 ! ref $_[0]->{schema}
1802 or
1803 isweak $_[0]->{schema}
1804 );
1805
1806 # weaken our schema hold forcing the schema to find somewhere else to live
1807 weaken $_[0]->{schema};
1808
1809 # if schema is still there reintroduce ourselves with strong refs back
1810 if ($_[0]->{schema}) {
1811 my $srcregs = $_[0]->{schema}->source_registrations;
1812 for (keys %$srcregs) {
1813 $srcregs->{$_} = $_[0] if $srcregs->{$_} == $_[0];
1814 }
1815 }
1816 }
1817}
1818
4376a157 1819sub STORABLE_freeze { nfreeze($_[0]->handle) }
50261284 1820
1821sub STORABLE_thaw {
1822 my ($self, $cloning, $ice) = @_;
1823 %$self = %{ (thaw $ice)->resolve };
1824}
1825
701da8c4 1826=head2 throw_exception
1827
2053ab2a 1828See L<DBIx::Class::Schema/"throw_exception">.
701da8c4 1829
1830=cut
1831
1832sub throw_exception {
1833 my $self = shift;
1a58752c 1834
4376a157 1835 $self->{schema}
1836 ? $self->{schema}->throw_exception(@_)
1837 : DBIx::Class::Exception->throw(@_)
1838 ;
701da8c4 1839}
1840
843f6bc1 1841=head2 source_info
d2f3e87b 1842
843f6bc1 1843Stores a hashref of per-source metadata. No specific key names
1844have yet been standardized, the examples below are purely hypothetical
1845and don't actually accomplish anything on their own:
391ccf38 1846
843f6bc1 1847 __PACKAGE__->source_info({
1848 "_tablespace" => 'fast_disk_array_3',
1849 "_engine" => 'InnoDB',
1850 });
391ccf38 1851
843f6bc1 1852=head2 new
391ccf38 1853
843f6bc1 1854 $class->new();
391ccf38 1855
843f6bc1 1856 $class->new({attribute_name => value});
d2f3e87b 1857
843f6bc1 1858Creates a new ResultSource object. Not normally called directly by end users.
391ccf38 1859
843f6bc1 1860=head2 column_info_from_storage
1861
1862=over
1863
1864=item Arguments: 1/0 (default: 0)
1865
1866=item Return value: 1/0
1867
1868=back
1869
880c075b 1870 __PACKAGE__->column_info_from_storage(1);
1871
843f6bc1 1872Enables the on-demand automatic loading of the above column
c1300297 1873metadata from storage as necessary. This is *deprecated*, and
843f6bc1 1874should not be used. It will be removed before 1.0.
1875
f89bb832 1876
9c992ba1 1877=head1 AUTHORS
1878
1879Matt S. Trout <mst@shadowcatsystems.co.uk>
1880
1881=head1 LICENSE
1882
1883You may distribute this code under the same terms as Perl itself.
1884
1885=cut
1886
b25e9fa0 18871;