And yet another INDIRECT guard missed in both e5053694 and d99f2db7
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultSource.pm
1 package DBIx::Class::ResultSource;
2
3 use strict;
4 use warnings;
5
6 use base 'DBIx::Class::ResultSource::RowParser';
7 use mro 'c3';
8
9 use DBIx::Class::Carp;
10 use DBIx::Class::_Util qw( UNRESOLVABLE_CONDITION dbic_internal_try fail_on_internal_call );
11 use SQL::Abstract 'is_literal_value';
12 use Devel::GlobalDestruction;
13 use Scalar::Util qw/blessed weaken isweak/;
14
15 # FIXME - somehow breaks ResultSetManager, do not remove until investigated
16 use DBIx::Class::ResultSet;
17
18 use namespace::clean;
19
20 __PACKAGE__->mk_group_accessors(simple => qw/
21   source_name name source_info
22   _ordered_columns _columns _primaries _unique_constraints
23   _relationships resultset_attributes
24   column_info_from_storage sqlt_deploy_callback
25 /);
26
27 __PACKAGE__->mk_group_accessors(component_class => qw/
28   resultset_class
29   result_class
30 /);
31
32 =head1 NAME
33
34 DBIx::Class::ResultSource - Result source object
35
36 =head1 SYNOPSIS
37
38   # Create a table based result source, in a result class.
39
40   package MyApp::Schema::Result::Artist;
41   use base qw/DBIx::Class::Core/;
42
43   __PACKAGE__->table('artist');
44   __PACKAGE__->add_columns(qw/ artistid name /);
45   __PACKAGE__->set_primary_key('artistid');
46   __PACKAGE__->has_many(cds => 'MyApp::Schema::Result::CD');
47
48   1;
49
50   # Create a query (view) based result source, in a result class
51   package MyApp::Schema::Result::Year2000CDs;
52   use base qw/DBIx::Class::Core/;
53
54   __PACKAGE__->load_components('InflateColumn::DateTime');
55   __PACKAGE__->table_class('DBIx::Class::ResultSource::View');
56
57   __PACKAGE__->table('year2000cds');
58   __PACKAGE__->result_source_instance->is_virtual(1);
59   __PACKAGE__->result_source_instance->view_definition(
60       "SELECT cdid, artist, title FROM cd WHERE year ='2000'"
61       );
62
63
64 =head1 DESCRIPTION
65
66 A ResultSource is an object that represents a source of data for querying.
67
68 This class is a base class for various specialised types of result
69 sources, for example L<DBIx::Class::ResultSource::Table>. Table is the
70 default result source type, so one is created for you when defining a
71 result class as described in the synopsis above.
72
73 More specifically, the L<DBIx::Class::Core> base class pulls in the
74 L<DBIx::Class::ResultSourceProxy::Table> component, which defines
75 the L<table|DBIx::Class::ResultSourceProxy::Table/table> method.
76 When called, C<table> creates and stores an instance of
77 L<DBIx::Class::ResultSource::Table>. Luckily, to use tables as result
78 sources, you don't need to remember any of this.
79
80 Result sources representing select queries, or views, can also be
81 created, see L<DBIx::Class::ResultSource::View> for full details.
82
83 =head2 Finding result source objects
84
85 As mentioned above, a result source instance is created and stored for
86 you when you define a
87 L<Result Class|DBIx::Class::Manual::Glossary/Result Class>.
88
89 You can retrieve the result source at runtime in the following ways:
90
91 =over
92
93 =item From a Schema object:
94
95    $schema->source($source_name);
96
97 =item From a Result object:
98
99    $result->result_source;
100
101 =item From a ResultSet object:
102
103    $rs->result_source;
104
105 =back
106
107 =head1 METHODS
108
109 =head2 new
110
111   $class->new();
112
113   $class->new({attribute_name => value});
114
115 Creates a new ResultSource object.  Not normally called directly by end users.
116
117 =cut
118
119 sub new {
120   my ($class, $attrs) = @_;
121   $class = ref $class if ref $class;
122
123   my $new = bless { %{$attrs || {}} }, $class;
124   $new->{resultset_class} ||= 'DBIx::Class::ResultSet';
125   $new->{resultset_attributes} = { %{$new->{resultset_attributes} || {}} };
126   $new->{_ordered_columns} = [ @{$new->{_ordered_columns}||[]}];
127   $new->{_columns} = { %{$new->{_columns}||{}} };
128   $new->{_relationships} = { %{$new->{_relationships}||{}} };
129   $new->{name} ||= "!!NAME NOT SET!!";
130   $new->{_columns_info_loaded} ||= 0;
131   $new->{sqlt_deploy_callback} ||= 'default_sqlt_deploy_hook';
132   return $new;
133 }
134
135 =pod
136
137 =head2 add_columns
138
139 =over
140
141 =item Arguments: @columns
142
143 =item Return Value: L<$result_source|/new>
144
145 =back
146
147   $source->add_columns(qw/col1 col2 col3/);
148
149   $source->add_columns('col1' => \%col1_info, 'col2' => \%col2_info, ...);
150
151   $source->add_columns(
152     'col1' => { data_type => 'integer', is_nullable => 1, ... },
153     'col2' => { data_type => 'text',    is_auto_increment => 1, ... },
154   );
155
156 Adds columns to the result source. If supplied colname => hashref
157 pairs, uses the hashref as the L</column_info> for that column. Repeated
158 calls of this method will add more columns, not replace them.
159
160 The column names given will be created as accessor methods on your
161 L<Result|DBIx::Class::Manual::ResultClass> objects. You can change the name of the accessor
162 by supplying an L</accessor> in the column_info hash.
163
164 If a column name beginning with a plus sign ('+col1') is provided, the
165 attributes provided will be merged with any existing attributes for the
166 column, with the new attributes taking precedence in the case that an
167 attribute already exists. Using this without a hashref
168 (C<< $source->add_columns(qw/+col1 +col2/) >>) is legal, but useless --
169 it does the same thing it would do without the plus.
170
171 The contents of the column_info are not set in stone. The following
172 keys are currently recognised/used by DBIx::Class:
173
174 =over 4
175
176 =item accessor
177
178    { accessor => '_name' }
179
180    # example use, replace standard accessor with one of your own:
181    sub name {
182        my ($self, $value) = @_;
183
184        die "Name cannot contain digits!" if($value =~ /\d/);
185        $self->_name($value);
186
187        return $self->_name();
188    }
189
190 Use this to set the name of the accessor method for this column. If unset,
191 the name of the column will be used.
192
193 =item data_type
194
195    { data_type => 'integer' }
196
197 This contains the column type. It is automatically filled if you use the
198 L<SQL::Translator::Producer::DBIx::Class::File> producer, or the
199 L<DBIx::Class::Schema::Loader> module.
200
201 Currently there is no standard set of values for the data_type. Use
202 whatever your database supports.
203
204 =item size
205
206    { size => 20 }
207
208 The length of your column, if it is a column type that can have a size
209 restriction. This is currently only used to create tables from your
210 schema, see L<DBIx::Class::Schema/deploy>.
211
212    { size => [ 9, 6 ] }
213
214 For decimal or float values you can specify an ArrayRef in order to
215 control precision, assuming your database's
216 L<SQL::Translator::Producer> supports it.
217
218 =item is_nullable
219
220    { is_nullable => 1 }
221
222 Set this to a true value for a column that is allowed to contain NULL
223 values, default is false. This is currently only used to create tables
224 from your schema, see L<DBIx::Class::Schema/deploy>.
225
226 =item is_auto_increment
227
228    { is_auto_increment => 1 }
229
230 Set this to a true value for a column whose value is somehow
231 automatically set, defaults to false. This is used to determine which
232 columns to empty when cloning objects using
233 L<DBIx::Class::Row/copy>. It is also used by
234 L<DBIx::Class::Schema/deploy>.
235
236 =item is_numeric
237
238    { is_numeric => 1 }
239
240 Set this to a true or false value (not C<undef>) to explicitly specify
241 if this column contains numeric data. This controls how set_column
242 decides whether to consider a column dirty after an update: if
243 C<is_numeric> is true a numeric comparison C<< != >> will take place
244 instead of the usual C<eq>
245
246 If not specified the storage class will attempt to figure this out on
247 first access to the column, based on the column C<data_type>. The
248 result will be cached in this attribute.
249
250 =item is_foreign_key
251
252    { is_foreign_key => 1 }
253
254 Set this to a true value for a column that contains a key from a
255 foreign table, defaults to false. This is currently only used to
256 create tables from your schema, see L<DBIx::Class::Schema/deploy>.
257
258 =item default_value
259
260    { default_value => \'now()' }
261
262 Set this to the default value which will be inserted into a column by
263 the database. Can contain either a value or a function (use a
264 reference to a scalar e.g. C<\'now()'> if you want a function). This
265 is currently only used to create tables from your schema, see
266 L<DBIx::Class::Schema/deploy>.
267
268 See the note on L<DBIx::Class::Row/new> for more information about possible
269 issues related to db-side default values.
270
271 =item sequence
272
273    { sequence => 'my_table_seq' }
274
275 Set this on a primary key column to the name of the sequence used to
276 generate a new key value. If not specified, L<DBIx::Class::PK::Auto>
277 will attempt to retrieve the name of the sequence from the database
278 automatically.
279
280 =item retrieve_on_insert
281
282   { retrieve_on_insert => 1 }
283
284 For every column where this is set to true, DBIC will retrieve the RDBMS-side
285 value upon a new row insertion (normally only the autoincrement PK is
286 retrieved on insert). C<INSERT ... RETURNING> is used automatically if
287 supported by the underlying storage, otherwise an extra SELECT statement is
288 executed to retrieve the missing data.
289
290 =item auto_nextval
291
292    { auto_nextval => 1 }
293
294 Set this to a true value for a column whose value is retrieved automatically
295 from a sequence or function (if supported by your Storage driver.) For a
296 sequence, if you do not use a trigger to get the nextval, you have to set the
297 L</sequence> value as well.
298
299 Also set this for MSSQL columns with the 'uniqueidentifier'
300 L<data_type|DBIx::Class::ResultSource/data_type> whose values you want to
301 automatically generate using C<NEWID()>, unless they are a primary key in which
302 case this will be done anyway.
303
304 =item extra
305
306 This is used by L<DBIx::Class::Schema/deploy> and L<SQL::Translator>
307 to add extra non-generic data to the column. For example: C<< extra
308 => { unsigned => 1} >> is used by the MySQL producer to set an integer
309 column to unsigned. For more details, see
310 L<SQL::Translator::Producer::MySQL>.
311
312 =back
313
314 =head2 add_column
315
316 =over
317
318 =item Arguments: $colname, \%columninfo?
319
320 =item Return Value: 1/0 (true/false)
321
322 =back
323
324   $source->add_column('col' => \%info);
325
326 Add a single column and optional column info. Uses the same column
327 info keys as L</add_columns>.
328
329 =cut
330
331 sub add_columns {
332   my ($self, @cols) = @_;
333   $self->_ordered_columns(\@cols) unless $self->_ordered_columns;
334
335   my @added;
336   my $columns = $self->_columns;
337   while (my $col = shift @cols) {
338     my $column_info = {};
339     if ($col =~ s/^\+//) {
340       $column_info = $self->column_info($col);
341     }
342
343     # If next entry is { ... } use that for the column info, if not
344     # use an empty hashref
345     if (ref $cols[0]) {
346       my $new_info = shift(@cols);
347       %$column_info = (%$column_info, %$new_info);
348     }
349     push(@added, $col) unless exists $columns->{$col};
350     $columns->{$col} = $column_info;
351   }
352   push @{ $self->_ordered_columns }, @added;
353   return $self;
354 }
355
356 sub add_column {
357   DBIx::Class::_ENV_::ASSERT_NO_INTERNAL_INDIRECT_CALLS and fail_on_internal_call;
358   shift->add_columns(@_)
359 }
360
361 =head2 has_column
362
363 =over
364
365 =item Arguments: $colname
366
367 =item Return Value: 1/0 (true/false)
368
369 =back
370
371   if ($source->has_column($colname)) { ... }
372
373 Returns true if the source has a column of this name, false otherwise.
374
375 =cut
376
377 sub has_column {
378   my ($self, $column) = @_;
379   return exists $self->_columns->{$column};
380 }
381
382 =head2 column_info
383
384 =over
385
386 =item Arguments: $colname
387
388 =item Return Value: Hashref of info
389
390 =back
391
392   my $info = $source->column_info($col);
393
394 Returns the column metadata hashref for a column, as originally passed
395 to L</add_columns>. See L</add_columns> above for information on the
396 contents of the hashref.
397
398 =cut
399
400 sub column_info {
401   my ($self, $column) = @_;
402   $self->throw_exception("No such column $column")
403     unless exists $self->_columns->{$column};
404
405   if ( ! $self->_columns->{$column}{data_type}
406        and ! $self->{_columns_info_loaded}
407        and $self->column_info_from_storage
408        and my $stor = dbic_internal_try { $self->schema->storage } )
409   {
410     $self->{_columns_info_loaded}++;
411
412     # try for the case of storage without table
413     dbic_internal_try {
414       my $info = $stor->columns_info_for( $self->from );
415       my $lc_info = { map
416         { (lc $_) => $info->{$_} }
417         ( keys %$info )
418       };
419
420       foreach my $col ( keys %{$self->_columns} ) {
421         $self->_columns->{$col} = {
422           %{ $self->_columns->{$col} },
423           %{ $info->{$col} || $lc_info->{lc $col} || {} }
424         };
425       }
426     };
427   }
428
429   return $self->_columns->{$column};
430 }
431
432 =head2 columns
433
434 =over
435
436 =item Arguments: none
437
438 =item Return Value: Ordered list of column names
439
440 =back
441
442   my @column_names = $source->columns;
443
444 Returns all column names in the order they were declared to L</add_columns>.
445
446 =cut
447
448 sub columns {
449   my $self = shift;
450   $self->throw_exception(
451     "columns() is a read-only accessor, did you mean add_columns()?"
452   ) if @_;
453   return @{$self->{_ordered_columns}||[]};
454 }
455
456 =head2 columns_info
457
458 =over
459
460 =item Arguments: \@colnames ?
461
462 =item Return Value: Hashref of column name/info pairs
463
464 =back
465
466   my $columns_info = $source->columns_info;
467
468 Like L</column_info> but returns information for the requested columns. If
469 the optional column-list arrayref is omitted it returns info on all columns
470 currently defined on the ResultSource via L</add_columns>.
471
472 =cut
473
474 sub columns_info {
475   my ($self, $columns) = @_;
476
477   my $colinfo = $self->_columns;
478
479   if (
480     ! $self->{_columns_info_loaded}
481       and
482     $self->column_info_from_storage
483       and
484     grep { ! $_->{data_type} } values %$colinfo
485       and
486     my $stor = dbic_internal_try { $self->schema->storage }
487   ) {
488     $self->{_columns_info_loaded}++;
489
490     # try for the case of storage without table
491     dbic_internal_try {
492       my $info = $stor->columns_info_for( $self->from );
493       my $lc_info = { map
494         { (lc $_) => $info->{$_} }
495         ( keys %$info )
496       };
497
498       foreach my $col ( keys %$colinfo ) {
499         $colinfo->{$col} = {
500           %{ $colinfo->{$col} },
501           %{ $info->{$col} || $lc_info->{lc $col} || {} }
502         };
503       }
504     };
505   }
506
507   my %ret;
508
509   if ($columns) {
510     for (@$columns) {
511       if (my $inf = $colinfo->{$_}) {
512         $ret{$_} = $inf;
513       }
514       else {
515         $self->throw_exception( sprintf (
516           "No such column '%s' on source '%s'",
517           $_,
518           $self->source_name || $self->name || 'Unknown source...?',
519         ));
520       }
521     }
522   }
523   else {
524     %ret = %$colinfo;
525   }
526
527   return \%ret;
528 }
529
530 =head2 remove_columns
531
532 =over
533
534 =item Arguments: @colnames
535
536 =item Return Value: not defined
537
538 =back
539
540   $source->remove_columns(qw/col1 col2 col3/);
541
542 Removes the given list of columns by name, from the result source.
543
544 B<Warning>: Removing a column that is also used in the sources primary
545 key, or in one of the sources unique constraints, B<will> result in a
546 broken result source.
547
548 =head2 remove_column
549
550 =over
551
552 =item Arguments: $colname
553
554 =item Return Value: not defined
555
556 =back
557
558   $source->remove_column('col');
559
560 Remove a single column by name from the result source, similar to
561 L</remove_columns>.
562
563 B<Warning>: Removing a column that is also used in the sources primary
564 key, or in one of the sources unique constraints, B<will> result in a
565 broken result source.
566
567 =cut
568
569 sub remove_columns {
570   my ($self, @to_remove) = @_;
571
572   my $columns = $self->_columns
573     or return;
574
575   my %to_remove;
576   for (@to_remove) {
577     delete $columns->{$_};
578     ++$to_remove{$_};
579   }
580
581   $self->_ordered_columns([ grep { not $to_remove{$_} } @{$self->_ordered_columns} ]);
582 }
583
584 sub remove_column {
585   DBIx::Class::_ENV_::ASSERT_NO_INTERNAL_INDIRECT_CALLS and fail_on_internal_call;
586   shift->remove_columns(@_)
587 }
588
589 =head2 set_primary_key
590
591 =over 4
592
593 =item Arguments: @cols
594
595 =item Return Value: not defined
596
597 =back
598
599 Defines one or more columns as primary key for this source. Must be
600 called after L</add_columns>.
601
602 Additionally, defines a L<unique constraint|/add_unique_constraint>
603 named C<primary>.
604
605 Note: you normally do want to define a primary key on your sources
606 B<even if the underlying database table does not have a primary key>.
607 See
608 L<DBIx::Class::Manual::Intro/The Significance and Importance of Primary Keys>
609 for more info.
610
611 =cut
612
613 sub set_primary_key {
614   my ($self, @cols) = @_;
615
616   my $colinfo = $self->columns_info(\@cols);
617   for my $col (@cols) {
618     carp_unique(sprintf (
619       "Primary key of source '%s' includes the column '%s' which has its "
620     . "'is_nullable' attribute set to true. This is a mistake and will cause "
621     . 'various Result-object operations to fail',
622       $self->source_name || $self->name || 'Unknown source...?',
623       $col,
624     )) if $colinfo->{$col}{is_nullable};
625   }
626
627   $self->_primaries(\@cols);
628
629   $self->add_unique_constraint(primary => \@cols);
630 }
631
632 =head2 primary_columns
633
634 =over 4
635
636 =item Arguments: none
637
638 =item Return Value: Ordered list of primary column names
639
640 =back
641
642 Read-only accessor which returns the list of primary keys, supplied by
643 L</set_primary_key>.
644
645 =cut
646
647 sub primary_columns {
648   return @{shift->_primaries||[]};
649 }
650
651 # a helper method that will automatically die with a descriptive message if
652 # no pk is defined on the source in question. For internal use to save
653 # on if @pks... boilerplate
654 sub _pri_cols_or_die {
655   my $self = shift;
656   my @pcols = $self->primary_columns
657     or $self->throw_exception (sprintf(
658       "Operation requires a primary key to be declared on '%s' via set_primary_key",
659       # source_name is set only after schema-registration
660       $self->source_name || $self->result_class || $self->name || 'Unknown source...?',
661     ));
662   return @pcols;
663 }
664
665 # same as above but mandating single-column PK (used by relationship condition
666 # inference)
667 sub _single_pri_col_or_die {
668   my $self = shift;
669   my ($pri, @too_many) = $self->_pri_cols_or_die;
670
671   $self->throw_exception( sprintf(
672     "Operation requires a single-column primary key declared on '%s'",
673     $self->source_name || $self->result_class || $self->name || 'Unknown source...?',
674   )) if @too_many;
675   return $pri;
676 }
677
678
679 =head2 sequence
680
681 Manually define the correct sequence for your table, to avoid the overhead
682 associated with looking up the sequence automatically. The supplied sequence
683 will be applied to the L</column_info> of each L<primary_key|/set_primary_key>
684
685 =over 4
686
687 =item Arguments: $sequence_name
688
689 =item Return Value: not defined
690
691 =back
692
693 =cut
694
695 sub sequence {
696   my ($self,$seq) = @_;
697
698   my @pks = $self->primary_columns
699     or return;
700
701   $_->{sequence} = $seq
702     for values %{ $self->columns_info (\@pks) };
703 }
704
705
706 =head2 add_unique_constraint
707
708 =over 4
709
710 =item Arguments: $name?, \@colnames
711
712 =item Return Value: not defined
713
714 =back
715
716 Declare a unique constraint on this source. Call once for each unique
717 constraint.
718
719   # For UNIQUE (column1, column2)
720   __PACKAGE__->add_unique_constraint(
721     constraint_name => [ qw/column1 column2/ ],
722   );
723
724 Alternatively, you can specify only the columns:
725
726   __PACKAGE__->add_unique_constraint([ qw/column1 column2/ ]);
727
728 This will result in a unique constraint named
729 C<table_column1_column2>, where C<table> is replaced with the table
730 name.
731
732 Unique constraints are used, for example, when you pass the constraint
733 name as the C<key> attribute to L<DBIx::Class::ResultSet/find>. Then
734 only columns in the constraint are searched.
735
736 Throws an error if any of the given column names do not yet exist on
737 the result source.
738
739 =cut
740
741 sub add_unique_constraint {
742   my $self = shift;
743
744   if (@_ > 2) {
745     $self->throw_exception(
746         'add_unique_constraint() does not accept multiple constraints, use '
747       . 'add_unique_constraints() instead'
748     );
749   }
750
751   my $cols = pop @_;
752   if (ref $cols ne 'ARRAY') {
753     $self->throw_exception (
754       'Expecting an arrayref of constraint columns, got ' . ($cols||'NOTHING')
755     );
756   }
757
758   my $name = shift @_;
759
760   $name ||= $self->name_unique_constraint($cols);
761
762   foreach my $col (@$cols) {
763     $self->throw_exception("No such column $col on table " . $self->name)
764       unless $self->has_column($col);
765   }
766
767   my %unique_constraints = $self->unique_constraints;
768   $unique_constraints{$name} = $cols;
769   $self->_unique_constraints(\%unique_constraints);
770 }
771
772 =head2 add_unique_constraints
773
774 =over 4
775
776 =item Arguments: @constraints
777
778 =item Return Value: not defined
779
780 =back
781
782 Declare multiple unique constraints on this source.
783
784   __PACKAGE__->add_unique_constraints(
785     constraint_name1 => [ qw/column1 column2/ ],
786     constraint_name2 => [ qw/column2 column3/ ],
787   );
788
789 Alternatively, you can specify only the columns:
790
791   __PACKAGE__->add_unique_constraints(
792     [ qw/column1 column2/ ],
793     [ qw/column3 column4/ ]
794   );
795
796 This will result in unique constraints named C<table_column1_column2> and
797 C<table_column3_column4>, where C<table> is replaced with the table name.
798
799 Throws an error if any of the given column names do not yet exist on
800 the result source.
801
802 See also L</add_unique_constraint>.
803
804 =cut
805
806 sub add_unique_constraints {
807   DBIx::Class::_ENV_::ASSERT_NO_INTERNAL_INDIRECT_CALLS and fail_on_internal_call;
808
809   my $self = shift;
810   my @constraints = @_;
811
812   if ( !(@constraints % 2) && grep { ref $_ ne 'ARRAY' } @constraints ) {
813     # with constraint name
814     while (my ($name, $constraint) = splice @constraints, 0, 2) {
815       $self->add_unique_constraint($name => $constraint);
816     }
817   }
818   else {
819     # no constraint name
820     foreach my $constraint (@constraints) {
821       $self->add_unique_constraint($constraint);
822     }
823   }
824 }
825
826 =head2 name_unique_constraint
827
828 =over 4
829
830 =item Arguments: \@colnames
831
832 =item Return Value: Constraint name
833
834 =back
835
836   $source->table('mytable');
837   $source->name_unique_constraint(['col1', 'col2']);
838   # returns
839   'mytable_col1_col2'
840
841 Return a name for a unique constraint containing the specified
842 columns. The name is created by joining the table name and each column
843 name, using an underscore character.
844
845 For example, a constraint on a table named C<cd> containing the columns
846 C<artist> and C<title> would result in a constraint name of C<cd_artist_title>.
847
848 This is used by L</add_unique_constraint> if you do not specify the
849 optional constraint name.
850
851 =cut
852
853 sub name_unique_constraint {
854   my ($self, $cols) = @_;
855
856   my $name = $self->name;
857   $name = $$name if (ref $name eq 'SCALAR');
858   $name =~ s/ ^ [^\.]+ \. //x;  # strip possible schema qualifier
859
860   return join '_', $name, @$cols;
861 }
862
863 =head2 unique_constraints
864
865 =over 4
866
867 =item Arguments: none
868
869 =item Return Value: Hash of unique constraint data
870
871 =back
872
873   $source->unique_constraints();
874
875 Read-only accessor which returns a hash of unique constraints on this
876 source.
877
878 The hash is keyed by constraint name, and contains an arrayref of
879 column names as values.
880
881 =cut
882
883 sub unique_constraints {
884   return %{shift->_unique_constraints||{}};
885 }
886
887 =head2 unique_constraint_names
888
889 =over 4
890
891 =item Arguments: none
892
893 =item Return Value: Unique constraint names
894
895 =back
896
897   $source->unique_constraint_names();
898
899 Returns the list of unique constraint names defined on this source.
900
901 =cut
902
903 sub unique_constraint_names {
904   my ($self) = @_;
905
906   my %unique_constraints = $self->unique_constraints;
907
908   return keys %unique_constraints;
909 }
910
911 =head2 unique_constraint_columns
912
913 =over 4
914
915 =item Arguments: $constraintname
916
917 =item Return Value: List of constraint columns
918
919 =back
920
921   $source->unique_constraint_columns('myconstraint');
922
923 Returns the list of columns that make up the specified unique constraint.
924
925 =cut
926
927 sub unique_constraint_columns {
928   my ($self, $constraint_name) = @_;
929
930   my %unique_constraints = $self->unique_constraints;
931
932   $self->throw_exception(
933     "Unknown unique constraint $constraint_name on '" . $self->name . "'"
934   ) unless exists $unique_constraints{$constraint_name};
935
936   return @{ $unique_constraints{$constraint_name} };
937 }
938
939 =head2 sqlt_deploy_callback
940
941 =over
942
943 =item Arguments: $callback_name | \&callback_code
944
945 =item Return Value: $callback_name | \&callback_code
946
947 =back
948
949   __PACKAGE__->result_source_instance->sqlt_deploy_callback('mycallbackmethod');
950
951    or
952
953   __PACKAGE__->result_source_instance->sqlt_deploy_callback(sub {
954     my ($source_instance, $sqlt_table) = @_;
955     ...
956   } );
957
958 An accessor to set a callback to be called during deployment of
959 the schema via L<DBIx::Class::Schema/create_ddl_dir> or
960 L<DBIx::Class::Schema/deploy>.
961
962 The callback can be set as either a code reference or the name of a
963 method in the current result class.
964
965 Defaults to L</default_sqlt_deploy_hook>.
966
967 Your callback will be passed the $source object representing the
968 ResultSource instance being deployed, and the
969 L<SQL::Translator::Schema::Table> object being created from it. The
970 callback can be used to manipulate the table object or add your own
971 customised indexes. If you need to manipulate a non-table object, use
972 the L<DBIx::Class::Schema/sqlt_deploy_hook>.
973
974 See L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To
975 Your SQL> for examples.
976
977 This sqlt deployment callback can only be used to manipulate
978 SQL::Translator objects as they get turned into SQL. To execute
979 post-deploy statements which SQL::Translator does not currently
980 handle, override L<DBIx::Class::Schema/deploy> in your Schema class
981 and call L<dbh_do|DBIx::Class::Storage::DBI/dbh_do>.
982
983 =head2 default_sqlt_deploy_hook
984
985 This is the default deploy hook implementation which checks if your
986 current Result class has a C<sqlt_deploy_hook> method, and if present
987 invokes it B<on the Result class directly>. This is to preserve the
988 semantics of C<sqlt_deploy_hook> which was originally designed to expect
989 the Result class name and the
990 L<$sqlt_table instance|SQL::Translator::Schema::Table> of the table being
991 deployed.
992
993 =cut
994
995 sub default_sqlt_deploy_hook {
996   my $self = shift;
997
998   my $class = $self->result_class;
999
1000   if ($class and $class->can('sqlt_deploy_hook')) {
1001     $class->sqlt_deploy_hook(@_);
1002   }
1003 }
1004
1005 sub _invoke_sqlt_deploy_hook {
1006   my $self = shift;
1007   if ( my $hook = $self->sqlt_deploy_callback) {
1008     $self->$hook(@_);
1009   }
1010 }
1011
1012 =head2 result_class
1013
1014 =over 4
1015
1016 =item Arguments: $classname
1017
1018 =item Return Value: $classname
1019
1020 =back
1021
1022  use My::Schema::ResultClass::Inflator;
1023  ...
1024
1025  use My::Schema::Artist;
1026  ...
1027  __PACKAGE__->result_class('My::Schema::ResultClass::Inflator');
1028
1029 Set the default result class for this source. You can use this to create
1030 and use your own result inflator. See L<DBIx::Class::ResultSet/result_class>
1031 for more details.
1032
1033 Please note that setting this to something like
1034 L<DBIx::Class::ResultClass::HashRefInflator> will make every result unblessed
1035 and make life more difficult.  Inflators like those are better suited to
1036 temporary usage via L<DBIx::Class::ResultSet/result_class>.
1037
1038 =head2 resultset
1039
1040 =over 4
1041
1042 =item Arguments: none
1043
1044 =item Return Value: L<$resultset|DBIx::Class::ResultSet>
1045
1046 =back
1047
1048 Returns a resultset for the given source. This will initially be created
1049 on demand by calling
1050
1051   $self->resultset_class->new($self, $self->resultset_attributes)
1052
1053 but is cached from then on unless resultset_class changes.
1054
1055 =head2 resultset_class
1056
1057 =over 4
1058
1059 =item Arguments: $classname
1060
1061 =item Return Value: $classname
1062
1063 =back
1064
1065   package My::Schema::ResultSet::Artist;
1066   use base 'DBIx::Class::ResultSet';
1067   ...
1068
1069   # In the result class
1070   __PACKAGE__->resultset_class('My::Schema::ResultSet::Artist');
1071
1072   # Or in code
1073   $source->resultset_class('My::Schema::ResultSet::Artist');
1074
1075 Set the class of the resultset. This is useful if you want to create your
1076 own resultset methods. Create your own class derived from
1077 L<DBIx::Class::ResultSet>, and set it here. If called with no arguments,
1078 this method returns the name of the existing resultset class, if one
1079 exists.
1080
1081 =head2 resultset_attributes
1082
1083 =over 4
1084
1085 =item Arguments: L<\%attrs|DBIx::Class::ResultSet/ATTRIBUTES>
1086
1087 =item Return Value: L<\%attrs|DBIx::Class::ResultSet/ATTRIBUTES>
1088
1089 =back
1090
1091   # In the result class
1092   __PACKAGE__->resultset_attributes({ order_by => [ 'id' ] });
1093
1094   # Or in code
1095   $source->resultset_attributes({ order_by => [ 'id' ] });
1096
1097 Store a collection of resultset attributes, that will be set on every
1098 L<DBIx::Class::ResultSet> produced from this result source.
1099
1100 B<CAVEAT>: C<resultset_attributes> comes with its own set of issues and
1101 bugs! While C<resultset_attributes> isn't deprecated per se, its usage is
1102 not recommended!
1103
1104 Since relationships use attributes to link tables together, the "default"
1105 attributes you set may cause unpredictable and undesired behavior.  Furthermore,
1106 the defaults cannot be turned off, so you are stuck with them.
1107
1108 In most cases, what you should actually be using are project-specific methods:
1109
1110   package My::Schema::ResultSet::Artist;
1111   use base 'DBIx::Class::ResultSet';
1112   ...
1113
1114   # BAD IDEA!
1115   #__PACKAGE__->resultset_attributes({ prefetch => 'tracks' });
1116
1117   # GOOD IDEA!
1118   sub with_tracks { shift->search({}, { prefetch => 'tracks' }) }
1119
1120   # in your code
1121   $schema->resultset('Artist')->with_tracks->...
1122
1123 This gives you the flexibility of not using it when you don't need it.
1124
1125 For more complex situations, another solution would be to use a virtual view
1126 via L<DBIx::Class::ResultSource::View>.
1127
1128 =cut
1129
1130 sub resultset {
1131   my $self = shift;
1132   $self->throw_exception(
1133     'resultset does not take any arguments. If you want another resultset, '.
1134     'call it on the schema instead.'
1135   ) if scalar @_;
1136
1137   $self->resultset_class->new(
1138     $self,
1139     {
1140       ( dbic_internal_try { %{$self->schema->default_resultset_attributes} } ),
1141       %{$self->{resultset_attributes}},
1142     },
1143   );
1144 }
1145
1146 =head2 name
1147
1148 =over 4
1149
1150 =item Arguments: none
1151
1152 =item Result value: $name
1153
1154 =back
1155
1156 Returns the name of the result source, which will typically be the table
1157 name. This may be a scalar reference if the result source has a non-standard
1158 name.
1159
1160 =head2 source_name
1161
1162 =over 4
1163
1164 =item Arguments: $source_name
1165
1166 =item Result value: $source_name
1167
1168 =back
1169
1170 Set an alternate name for the result source when it is loaded into a schema.
1171 This is useful if you want to refer to a result source by a name other than
1172 its class name.
1173
1174   package ArchivedBooks;
1175   use base qw/DBIx::Class/;
1176   __PACKAGE__->table('books_archive');
1177   __PACKAGE__->source_name('Books');
1178
1179   # from your schema...
1180   $schema->resultset('Books')->find(1);
1181
1182 =head2 from
1183
1184 =over 4
1185
1186 =item Arguments: none
1187
1188 =item Return Value: FROM clause
1189
1190 =back
1191
1192   my $from_clause = $source->from();
1193
1194 Returns an expression of the source to be supplied to storage to specify
1195 retrieval from this source. In the case of a database, the required FROM
1196 clause contents.
1197
1198 =cut
1199
1200 sub from { die 'Virtual method!' }
1201
1202 =head2 source_info
1203
1204 Stores a hashref of per-source metadata.  No specific key names
1205 have yet been standardized, the examples below are purely hypothetical
1206 and don't actually accomplish anything on their own:
1207
1208   __PACKAGE__->source_info({
1209     "_tablespace" => 'fast_disk_array_3',
1210     "_engine" => 'InnoDB',
1211   });
1212
1213 =head2 schema
1214
1215 =over 4
1216
1217 =item Arguments: L<$schema?|DBIx::Class::Schema>
1218
1219 =item Return Value: L<$schema|DBIx::Class::Schema>
1220
1221 =back
1222
1223   my $schema = $source->schema();
1224
1225 Sets and/or returns the L<DBIx::Class::Schema> object to which this
1226 result source instance has been attached to.
1227
1228 =cut
1229
1230 sub schema {
1231   if (@_ > 1) {
1232     $_[0]->{schema} = $_[1];
1233   }
1234   else {
1235     $_[0]->{schema} || do {
1236       my $name = $_[0]->{source_name} || '_unnamed_';
1237       my $err = 'Unable to perform storage-dependent operations with a detached result source '
1238               . "(source '$name' is not associated with a schema).";
1239
1240       $err .= ' You need to use $schema->thaw() or manually set'
1241             . ' $DBIx::Class::ResultSourceHandle::thaw_schema while thawing.'
1242         if $_[0]->{_detached_thaw};
1243
1244       DBIx::Class::Exception->throw($err);
1245     };
1246   }
1247 }
1248
1249 =head2 storage
1250
1251 =over 4
1252
1253 =item Arguments: none
1254
1255 =item Return Value: L<$storage|DBIx::Class::Storage>
1256
1257 =back
1258
1259   $source->storage->debug(1);
1260
1261 Returns the L<storage handle|DBIx::Class::Storage> for the current schema.
1262
1263 =cut
1264
1265 sub storage {
1266   DBIx::Class::_ENV_::ASSERT_NO_INTERNAL_INDIRECT_CALLS and fail_on_internal_call;
1267   $_[0]->schema->storage
1268 }
1269
1270 =head2 add_relationship
1271
1272 =over 4
1273
1274 =item Arguments: $rel_name, $related_source_name, \%cond, \%attrs?
1275
1276 =item Return Value: 1/true if it succeeded
1277
1278 =back
1279
1280   $source->add_relationship('rel_name', 'related_source', $cond, $attrs);
1281
1282 L<DBIx::Class::Relationship> describes a series of methods which
1283 create pre-defined useful types of relationships. Look there first
1284 before using this method directly.
1285
1286 The relationship name can be arbitrary, but must be unique for each
1287 relationship attached to this result source. 'related_source' should
1288 be the name with which the related result source was registered with
1289 the current schema. For example:
1290
1291   $schema->source('Book')->add_relationship('reviews', 'Review', {
1292     'foreign.book_id' => 'self.id',
1293   });
1294
1295 The condition C<$cond> needs to be an L<SQL::Abstract>-style
1296 representation of the join between the tables. For example, if you're
1297 creating a relation from Author to Book,
1298
1299   { 'foreign.author_id' => 'self.id' }
1300
1301 will result in the JOIN clause
1302
1303   author me JOIN book foreign ON foreign.author_id = me.id
1304
1305 You can specify as many foreign => self mappings as necessary.
1306
1307 Valid attributes are as follows:
1308
1309 =over 4
1310
1311 =item join_type
1312
1313 Explicitly specifies the type of join to use in the relationship. Any
1314 SQL join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in
1315 the SQL command immediately before C<JOIN>.
1316
1317 =item proxy
1318
1319 An arrayref containing a list of accessors in the foreign class to proxy in
1320 the main class. If, for example, you do the following:
1321
1322   CD->might_have(liner_notes => 'LinerNotes', undef, {
1323     proxy => [ qw/notes/ ],
1324   });
1325
1326 Then, assuming LinerNotes has an accessor named notes, you can do:
1327
1328   my $cd = CD->find(1);
1329   # set notes -- LinerNotes object is created if it doesn't exist
1330   $cd->notes('Notes go here');
1331
1332 =item accessor
1333
1334 Specifies the type of accessor that should be created for the
1335 relationship. Valid values are C<single> (for when there is only a single
1336 related object), C<multi> (when there can be many), and C<filter> (for
1337 when there is a single related object, but you also want the relationship
1338 accessor to double as a column accessor). For C<multi> accessors, an
1339 add_to_* method is also created, which calls C<create_related> for the
1340 relationship.
1341
1342 =back
1343
1344 Throws an exception if the condition is improperly supplied, or cannot
1345 be resolved.
1346
1347 =cut
1348
1349 sub add_relationship {
1350   my ($self, $rel, $f_source_name, $cond, $attrs) = @_;
1351   $self->throw_exception("Can't create relationship without join condition")
1352     unless $cond;
1353   $attrs ||= {};
1354
1355   # Check foreign and self are right in cond
1356   if ( (ref $cond ||'') eq 'HASH') {
1357     $_ =~ /^foreign\./ or $self->throw_exception("Malformed relationship condition key '$_': must be prefixed with 'foreign.'")
1358       for keys %$cond;
1359
1360     $_ =~ /^self\./ or $self->throw_exception("Malformed relationship condition value '$_': must be prefixed with 'self.'")
1361       for values %$cond;
1362   }
1363
1364   my %rels = %{ $self->_relationships };
1365   $rels{$rel} = { class => $f_source_name,
1366                   source => $f_source_name,
1367                   cond  => $cond,
1368                   attrs => $attrs };
1369   $self->_relationships(\%rels);
1370
1371   return $self;
1372 }
1373
1374 =head2 relationships
1375
1376 =over 4
1377
1378 =item Arguments: none
1379
1380 =item Return Value: L<@rel_names|DBIx::Class::Relationship>
1381
1382 =back
1383
1384   my @rel_names = $source->relationships();
1385
1386 Returns all relationship names for this source.
1387
1388 =cut
1389
1390 sub relationships {
1391   keys %{$_[0]->_relationships};
1392 }
1393
1394 =head2 relationship_info
1395
1396 =over 4
1397
1398 =item Arguments: L<$rel_name|DBIx::Class::Relationship>
1399
1400 =item Return Value: L<\%rel_data|DBIx::Class::Relationship::Base/add_relationship>
1401
1402 =back
1403
1404 Returns a hash of relationship information for the specified relationship
1405 name. The keys/values are as specified for L<DBIx::Class::Relationship::Base/add_relationship>.
1406
1407 =cut
1408
1409 sub relationship_info {
1410   #my ($self, $rel) = @_;
1411   return shift->_relationships->{+shift};
1412 }
1413
1414 =head2 has_relationship
1415
1416 =over 4
1417
1418 =item Arguments: L<$rel_name|DBIx::Class::Relationship>
1419
1420 =item Return Value: 1/0 (true/false)
1421
1422 =back
1423
1424 Returns true if the source has a relationship of this name, false otherwise.
1425
1426 =cut
1427
1428 sub has_relationship {
1429   #my ($self, $rel) = @_;
1430   return exists shift->_relationships->{+shift};
1431 }
1432
1433 =head2 reverse_relationship_info
1434
1435 =over 4
1436
1437 =item Arguments: L<$rel_name|DBIx::Class::Relationship>
1438
1439 =item Return Value: L<\%rel_data|DBIx::Class::Relationship::Base/add_relationship>
1440
1441 =back
1442
1443 Looks through all the relationships on the source this relationship
1444 points to, looking for one whose condition is the reverse of the
1445 condition on this relationship.
1446
1447 A common use of this is to find the name of the C<belongs_to> relation
1448 opposing a C<has_many> relation. For definition of these look in
1449 L<DBIx::Class::Relationship>.
1450
1451 The returned hashref is keyed by the name of the opposing
1452 relationship, and contains its data in the same manner as
1453 L</relationship_info>.
1454
1455 =cut
1456
1457 sub reverse_relationship_info {
1458   my ($self, $rel) = @_;
1459
1460   my $rel_info = $self->relationship_info($rel)
1461     or $self->throw_exception("No such relationship '$rel'");
1462
1463   my $ret = {};
1464
1465   return $ret unless ((ref $rel_info->{cond}) eq 'HASH');
1466
1467   my $stripped_cond = $self->__strip_relcond ($rel_info->{cond});
1468
1469   my $registered_source_name = $self->source_name;
1470
1471   # this may be a partial schema or something else equally esoteric
1472   my $other_rsrc = $self->related_source($rel);
1473
1474   # Get all the relationships for that source that related to this source
1475   # whose foreign column set are our self columns on $rel and whose self
1476   # columns are our foreign columns on $rel
1477   foreach my $other_rel ($other_rsrc->relationships) {
1478
1479     # only consider stuff that points back to us
1480     # "us" here is tricky - if we are in a schema registration, we want
1481     # to use the source_names, otherwise we will use the actual classes
1482
1483     # the schema may be partial
1484     my $roundtrip_rsrc = dbic_internal_try { $other_rsrc->related_source($other_rel) }
1485       or next;
1486
1487     if ($registered_source_name) {
1488       next if $registered_source_name ne ($roundtrip_rsrc->source_name || '')
1489     }
1490     else {
1491       next if $self->result_class ne $roundtrip_rsrc->result_class;
1492     }
1493
1494     my $other_rel_info = $other_rsrc->relationship_info($other_rel);
1495
1496     # this can happen when we have a self-referential class
1497     next if $other_rel_info eq $rel_info;
1498
1499     next unless ref $other_rel_info->{cond} eq 'HASH';
1500     my $other_stripped_cond = $self->__strip_relcond($other_rel_info->{cond});
1501
1502     $ret->{$other_rel} = $other_rel_info if (
1503       $self->_compare_relationship_keys (
1504         [ keys %$stripped_cond ], [ values %$other_stripped_cond ]
1505       )
1506         and
1507       $self->_compare_relationship_keys (
1508         [ values %$stripped_cond ], [ keys %$other_stripped_cond ]
1509       )
1510     );
1511   }
1512
1513   return $ret;
1514 }
1515
1516 # all this does is removes the foreign/self prefix from a condition
1517 sub __strip_relcond {
1518   +{
1519     map
1520       { map { /^ (?:foreign|self) \. (\w+) $/x } ($_, $_[1]{$_}) }
1521       keys %{$_[1]}
1522   }
1523 }
1524
1525 sub compare_relationship_keys {
1526   carp 'compare_relationship_keys is a private method, stop calling it';
1527   my $self = shift;
1528   $self->_compare_relationship_keys (@_);
1529 }
1530
1531 # Returns true if both sets of keynames are the same, false otherwise.
1532 sub _compare_relationship_keys {
1533 #  my ($self, $keys1, $keys2) = @_;
1534   return
1535     join ("\x00", sort @{$_[1]})
1536       eq
1537     join ("\x00", sort @{$_[2]})
1538   ;
1539 }
1540
1541 # optionally takes either an arrayref of column names, or a hashref of already
1542 # retrieved colinfos
1543 # returns an arrayref of column names of the shortest unique constraint
1544 # (matching some of the input if any), giving preference to the PK
1545 sub _identifying_column_set {
1546   my ($self, $cols) = @_;
1547
1548   my %unique = $self->unique_constraints;
1549   my $colinfos = ref $cols eq 'HASH' ? $cols : $self->columns_info($cols||());
1550
1551   # always prefer the PK first, and then shortest constraints first
1552   USET:
1553   for my $set (delete $unique{primary}, sort { @$a <=> @$b } (values %unique) ) {
1554     next unless $set && @$set;
1555
1556     for (@$set) {
1557       next USET unless ($colinfos->{$_} && !$colinfos->{$_}{is_nullable} );
1558     }
1559
1560     # copy so we can mangle it at will
1561     return [ @$set ];
1562   }
1563
1564   return undef;
1565 }
1566
1567 sub _minimal_valueset_satisfying_constraint {
1568   my $self = shift;
1569   my $args = { ref $_[0] eq 'HASH' ? %{ $_[0] } : @_ };
1570
1571   $args->{columns_info} ||= $self->columns_info;
1572
1573   my $vals = $self->schema->storage->_extract_fixed_condition_columns(
1574     $args->{values},
1575     ($args->{carp_on_nulls} ? 'consider_nulls' : undef ),
1576   );
1577
1578   my $cols;
1579   for my $col ($self->unique_constraint_columns($args->{constraint_name}) ) {
1580     if( ! exists $vals->{$col} or ( $vals->{$col}||'' ) eq UNRESOLVABLE_CONDITION ) {
1581       $cols->{missing}{$col} = undef;
1582     }
1583     elsif( ! defined $vals->{$col} ) {
1584       $cols->{$args->{carp_on_nulls} ? 'undefined' : 'missing'}{$col} = undef;
1585     }
1586     else {
1587       # we need to inject back the '=' as _extract_fixed_condition_columns
1588       # will strip it from literals and values alike, resulting in an invalid
1589       # condition in the end
1590       $cols->{present}{$col} = { '=' => $vals->{$col} };
1591     }
1592
1593     $cols->{fc}{$col} = 1 if (
1594       ( ! $cols->{missing} or ! exists $cols->{missing}{$col} )
1595         and
1596       keys %{ $args->{columns_info}{$col}{_filter_info} || {} }
1597     );
1598   }
1599
1600   $self->throw_exception( sprintf ( "Unable to satisfy requested constraint '%s', missing values for column(s): %s",
1601     $args->{constraint_name},
1602     join (', ', map { "'$_'" } sort keys %{$cols->{missing}} ),
1603   ) ) if $cols->{missing};
1604
1605   $self->throw_exception( sprintf (
1606     "Unable to satisfy requested constraint '%s', FilterColumn values not usable for column(s): %s",
1607     $args->{constraint_name},
1608     join (', ', map { "'$_'" } sort keys %{$cols->{fc}}),
1609   )) if $cols->{fc};
1610
1611   if (
1612     $cols->{undefined}
1613       and
1614     !$ENV{DBIC_NULLABLE_KEY_NOWARN}
1615   ) {
1616     carp_unique ( sprintf (
1617       "NULL/undef values supplied for requested unique constraint '%s' (NULL "
1618     . 'values in column(s): %s). This is almost certainly not what you wanted, '
1619     . 'though you can set DBIC_NULLABLE_KEY_NOWARN to disable this warning.',
1620       $args->{constraint_name},
1621       join (', ', map { "'$_'" } sort keys %{$cols->{undefined}}),
1622     ));
1623   }
1624
1625   return { map { %{ $cols->{$_}||{} } } qw(present undefined) };
1626 }
1627
1628 # Returns the {from} structure used to express JOIN conditions
1629 sub _resolve_join {
1630   my ($self, $join, $alias, $seen, $jpath, $parent_force_left) = @_;
1631
1632   # we need a supplied one, because we do in-place modifications, no returns
1633   $self->throw_exception ('You must supply a seen hashref as the 3rd argument to _resolve_join')
1634     unless ref $seen eq 'HASH';
1635
1636   $self->throw_exception ('You must supply a joinpath arrayref as the 4th argument to _resolve_join')
1637     unless ref $jpath eq 'ARRAY';
1638
1639   $jpath = [@$jpath]; # copy
1640
1641   if (not defined $join or not length $join) {
1642     return ();
1643   }
1644   elsif (ref $join eq 'ARRAY') {
1645     return
1646       map {
1647         $self->_resolve_join($_, $alias, $seen, $jpath, $parent_force_left);
1648       } @$join;
1649   }
1650   elsif (ref $join eq 'HASH') {
1651
1652     my @ret;
1653     for my $rel (keys %$join) {
1654
1655       my $rel_info = $self->relationship_info($rel)
1656         or $self->throw_exception("No such relationship '$rel' on " . $self->source_name);
1657
1658       my $force_left = $parent_force_left;
1659       $force_left ||= lc($rel_info->{attrs}{join_type}||'') eq 'left';
1660
1661       # the actual seen value will be incremented by the recursion
1662       my $as = $self->schema->storage->relname_to_table_alias(
1663         $rel, ($seen->{$rel} && $seen->{$rel} + 1)
1664       );
1665
1666       push @ret, (
1667         $self->_resolve_join($rel, $alias, $seen, [@$jpath], $force_left),
1668         $self->related_source($rel)->_resolve_join(
1669           $join->{$rel}, $as, $seen, [@$jpath, { $rel => $as }], $force_left
1670         )
1671       );
1672     }
1673     return @ret;
1674
1675   }
1676   elsif (ref $join) {
1677     $self->throw_exception("No idea how to resolve join reftype ".ref $join);
1678   }
1679   else {
1680     my $count = ++$seen->{$join};
1681     my $as = $self->schema->storage->relname_to_table_alias(
1682       $join, ($count > 1 && $count)
1683     );
1684
1685     my $rel_info = $self->relationship_info($join)
1686       or $self->throw_exception("No such relationship $join on " . $self->source_name);
1687
1688     my $rel_src = $self->related_source($join);
1689     return [ { $as => $rel_src->from,
1690                -rsrc => $rel_src,
1691                -join_type => $parent_force_left
1692                   ? 'left'
1693                   : $rel_info->{attrs}{join_type}
1694                 ,
1695                -join_path => [@$jpath, { $join => $as } ],
1696                -is_single => (
1697                   ! $rel_info->{attrs}{accessor}
1698                     or
1699                   $rel_info->{attrs}{accessor} eq 'single'
1700                     or
1701                   $rel_info->{attrs}{accessor} eq 'filter'
1702                 ),
1703                -alias => $as,
1704                -relation_chain_depth => ( $seen->{-relation_chain_depth} || 0 ) + 1,
1705              },
1706              $self->_resolve_relationship_condition(
1707                rel_name => $join,
1708                self_alias => $alias,
1709                foreign_alias => $as,
1710              )->{condition},
1711           ];
1712   }
1713 }
1714
1715 sub pk_depends_on {
1716   carp 'pk_depends_on is a private method, stop calling it';
1717   my $self = shift;
1718   $self->_pk_depends_on (@_);
1719 }
1720
1721 # Determines whether a relation is dependent on an object from this source
1722 # having already been inserted. Takes the name of the relationship and a
1723 # hashref of columns of the related object.
1724 sub _pk_depends_on {
1725   my ($self, $rel_name, $rel_data) = @_;
1726
1727   my $relinfo = $self->relationship_info($rel_name);
1728
1729   # don't assume things if the relationship direction is specified
1730   return $relinfo->{attrs}{is_foreign_key_constraint}
1731     if exists ($relinfo->{attrs}{is_foreign_key_constraint});
1732
1733   my $cond = $relinfo->{cond};
1734   return 0 unless ref($cond) eq 'HASH';
1735
1736   # map { foreign.foo => 'self.bar' } to { bar => 'foo' }
1737   my $keyhash = { map { my $x = $_; $x =~ s/.*\.//; $x; } reverse %$cond };
1738
1739   # assume anything that references our PK probably is dependent on us
1740   # rather than vice versa, unless the far side is (a) defined or (b)
1741   # auto-increment
1742   my $rel_source = $self->related_source($rel_name);
1743
1744   foreach my $p ($self->primary_columns) {
1745     if (exists $keyhash->{$p}) {
1746       unless (defined($rel_data->{$keyhash->{$p}})
1747               || $rel_source->column_info($keyhash->{$p})
1748                             ->{is_auto_increment}) {
1749         return 0;
1750       }
1751     }
1752   }
1753
1754   return 1;
1755 }
1756
1757 sub resolve_condition {
1758   carp 'resolve_condition is a private method, stop calling it';
1759   shift->_resolve_condition (@_);
1760 }
1761
1762 sub _resolve_condition {
1763 #  carp_unique sprintf
1764 #    '_resolve_condition is a private method, and moreover is about to go '
1765 #  . 'away. Please contact the development team at %s if you believe you '
1766 #  . 'have a genuine use for this method, in order to discuss alternatives.',
1767 #    DBIx::Class::_ENV_::HELP_URL,
1768 #  ;
1769
1770 #######################
1771 ### API Design? What's that...? (a backwards compatible shim, kill me now)
1772
1773   my ($self, $cond, @res_args, $rel_name);
1774
1775   # we *SIMPLY DON'T KNOW YET* which arg is which, yay
1776   ($self, $cond, $res_args[0], $res_args[1], $rel_name) = @_;
1777
1778   # assume that an undef is an object-like unset (set_from_related(undef))
1779   my @is_objlike = map { ! defined $_ or length ref $_ } (@res_args);
1780
1781   # turn objlike into proper objects for saner code further down
1782   for (0,1) {
1783     next unless $is_objlike[$_];
1784
1785     if ( defined blessed $res_args[$_] ) {
1786
1787       # but wait - there is more!!! WHAT THE FUCK?!?!?!?!
1788       if ($res_args[$_]->isa('DBIx::Class::ResultSet')) {
1789         carp('Passing a resultset for relationship resolution makes no sense - invoking __gremlins__');
1790         $is_objlike[$_] = 0;
1791         $res_args[$_] = '__gremlins__';
1792       }
1793     }
1794     else {
1795       $res_args[$_] ||= {};
1796
1797       # hate everywhere - have to pass in as a plain hash
1798       # pretending to be an object at least for now
1799       $self->throw_exception("Unsupported object-like structure encountered: $res_args[$_]")
1800         unless ref $res_args[$_] eq 'HASH';
1801     }
1802   }
1803
1804   my $args = {
1805     # where-is-waldo block guesses relname, then further down we override it if available
1806     (
1807       $is_objlike[1] ? ( rel_name => $res_args[0], self_alias => $res_args[0], foreign_alias => 'me',         self_result_object  => $res_args[1] )
1808     : $is_objlike[0] ? ( rel_name => $res_args[1], self_alias => 'me',         foreign_alias => $res_args[1], foreign_values      => $res_args[0] )
1809     :                  ( rel_name => $res_args[0], self_alias => $res_args[1], foreign_alias => $res_args[0]                                      )
1810     ),
1811
1812     ( $rel_name ? ( rel_name => $rel_name ) : () ),
1813   };
1814
1815   # Allowing passing relconds different than the relationshup itself is cute,
1816   # but likely dangerous. Remove that from the (still unofficial) API of
1817   # _resolve_relationship_condition, and instead make it "hard on purpose"
1818   local $self->relationship_info( $args->{rel_name} )->{cond} = $cond if defined $cond;
1819
1820 #######################
1821
1822   # now it's fucking easy isn't it?!
1823   my $rc = $self->_resolve_relationship_condition( $args );
1824
1825   my @res = (
1826     ( $rc->{join_free_condition} || $rc->{condition} ),
1827     ! $rc->{join_free_condition},
1828   );
1829
1830   # _resolve_relationship_condition always returns qualified cols even in the
1831   # case of join_free_condition, but nothing downstream expects this
1832   if ($rc->{join_free_condition} and ref $res[0] eq 'HASH') {
1833     $res[0] = { map
1834       { ($_ =~ /\.(.+)/) => $res[0]{$_} }
1835       keys %{$res[0]}
1836     };
1837   }
1838
1839   # and more legacy
1840   return wantarray ? @res : $res[0];
1841 }
1842
1843 # Keep this indefinitely. There is evidence of both CPAN and
1844 # darkpan using it, and there isn't much harm in an extra var
1845 # anyway.
1846 our $UNRESOLVABLE_CONDITION = UNRESOLVABLE_CONDITION;
1847 # YES I KNOW THIS IS EVIL
1848 # it is there to save darkpan from themselves, since internally
1849 # we are moving to a constant
1850 Internals::SvREADONLY($UNRESOLVABLE_CONDITION => 1);
1851
1852 # Resolves the passed condition to a concrete query fragment and extra
1853 # metadata
1854 #
1855 ## self-explanatory API, modeled on the custom cond coderef:
1856 # rel_name              => (scalar)
1857 # foreign_alias         => (scalar)
1858 # foreign_values        => (either not supplied, or a hashref, or a foreign ResultObject (to be ->get_columns()ed), or plain undef )
1859 # self_alias            => (scalar)
1860 # self_result_object    => (either not supplied or a result object)
1861 # require_join_free_condition => (boolean, throws on failure to construct a JF-cond)
1862 # infer_values_based_on => (either not supplied or a hashref, implies require_join_free_condition)
1863 #
1864 ## returns a hash
1865 # condition           => (a valid *likely fully qualified* sqla cond structure)
1866 # identity_map        => (a hashref of foreign-to-self *unqualified* column equality names)
1867 # join_free_condition => (a valid *fully qualified* sqla cond structure, maybe unset)
1868 # inferred_values     => (in case of an available join_free condition, this is a hashref of
1869 #                         *unqualified* column/value *EQUALITY* pairs, representing an amalgamation
1870 #                         of the JF-cond parse and infer_values_based_on
1871 #                         always either complete or unset)
1872 #
1873 sub _resolve_relationship_condition {
1874   my $self = shift;
1875
1876   my $args = { ref $_[0] eq 'HASH' ? %{ $_[0] } : @_ };
1877
1878   for ( qw( rel_name self_alias foreign_alias ) ) {
1879     $self->throw_exception("Mandatory argument '$_' to _resolve_relationship_condition() is not a plain string")
1880       if !defined $args->{$_} or length ref $args->{$_};
1881   }
1882
1883   $self->throw_exception("Arguments 'self_alias' and 'foreign_alias' may not be identical")
1884     if $args->{self_alias} eq $args->{foreign_alias};
1885
1886 # TEMP
1887   my $exception_rel_id = "relationship '$args->{rel_name}' on source '@{[ $self->source_name ]}'";
1888
1889   my $rel_info = $self->relationship_info($args->{rel_name})
1890 # TEMP
1891 #    or $self->throw_exception( "No such $exception_rel_id" );
1892     or carp_unique("Requesting resolution on non-existent relationship '$args->{rel_name}' on source '@{[ $self->source_name ]}': fix your code *soon*, as it will break with the next major version");
1893
1894 # TEMP
1895   $exception_rel_id = "relationship '$rel_info->{_original_name}' on source '@{[ $self->source_name ]}'"
1896     if $rel_info and exists $rel_info->{_original_name};
1897
1898   $self->throw_exception("No practical way to resolve $exception_rel_id between two data structures")
1899     if exists $args->{self_result_object} and exists $args->{foreign_values};
1900
1901   $self->throw_exception( "Argument to infer_values_based_on must be a hash" )
1902     if exists $args->{infer_values_based_on} and ref $args->{infer_values_based_on} ne 'HASH';
1903
1904   $args->{require_join_free_condition} ||= !!$args->{infer_values_based_on};
1905
1906   $self->throw_exception( "Argument 'self_result_object' must be an object inheriting from DBIx::Class::Row" )
1907     if (
1908       exists $args->{self_result_object}
1909         and
1910       ( ! defined blessed $args->{self_result_object} or ! $args->{self_result_object}->isa('DBIx::Class::Row') )
1911     )
1912   ;
1913
1914   my $rel_rsrc = $self->related_source($args->{rel_name});
1915   my $storage = $self->schema->storage;
1916
1917   if (exists $args->{foreign_values}) {
1918
1919     if (! defined $args->{foreign_values} ) {
1920       # fallback: undef => {}
1921       $args->{foreign_values} = {};
1922     }
1923     elsif (defined blessed $args->{foreign_values}) {
1924
1925       $self->throw_exception( "Objects supplied as 'foreign_values' ($args->{foreign_values}) must inherit from DBIx::Class::Row" )
1926         unless $args->{foreign_values}->isa('DBIx::Class::Row');
1927
1928       carp_unique(
1929         "Objects supplied as 'foreign_values' ($args->{foreign_values}) "
1930       . "usually should inherit from the related ResultClass ('@{[ $rel_rsrc->result_class ]}'), "
1931       . "perhaps you've made a mistake invoking the condition resolver?"
1932       ) unless $args->{foreign_values}->isa($rel_rsrc->result_class);
1933
1934       $args->{foreign_values} = { $args->{foreign_values}->get_columns };
1935     }
1936     elsif ( ref $args->{foreign_values} eq 'HASH' ) {
1937
1938       # re-build {foreign_values} excluding identically named rels
1939       if( keys %{$args->{foreign_values}} ) {
1940
1941         my ($col_idx, $rel_idx) = map
1942           { { map { $_ => 1 } $rel_rsrc->$_ } }
1943           qw( columns relationships )
1944         ;
1945
1946         my $equivalencies = $storage->_extract_fixed_condition_columns(
1947           $args->{foreign_values},
1948           'consider nulls',
1949         );
1950
1951         $args->{foreign_values} = { map {
1952           # skip if relationship *and* a non-literal ref
1953           # this means a multicreate stub was passed in
1954           (
1955             $rel_idx->{$_}
1956               and
1957             length ref $args->{foreign_values}{$_}
1958               and
1959             ! is_literal_value($args->{foreign_values}{$_})
1960           )
1961             ? ()
1962             : ( $_ => (
1963                 ! $col_idx->{$_}
1964                   ? $self->throw_exception( "Key '$_' supplied as 'foreign_values' is not a column on related source '@{[ $rel_rsrc->source_name ]}'" )
1965               : ( !exists $equivalencies->{$_} or ($equivalencies->{$_}||'') eq UNRESOLVABLE_CONDITION )
1966                   ? $self->throw_exception( "Value supplied for '...{foreign_values}{$_}' is not a direct equivalence expression" )
1967               : $args->{foreign_values}{$_}
1968             ))
1969         } keys %{$args->{foreign_values}} };
1970       }
1971     }
1972     else {
1973       $self->throw_exception(
1974         "Argument 'foreign_values' must be either an object inheriting from '@{[ $rel_rsrc->result_class ]}', "
1975       . "or a hash reference, or undef"
1976       );
1977     }
1978   }
1979
1980   my $ret;
1981
1982   if (ref $rel_info->{cond} eq 'CODE') {
1983
1984     my $cref_args = {
1985       rel_name => $args->{rel_name},
1986       self_resultsource => $self,
1987       self_alias => $args->{self_alias},
1988       foreign_alias => $args->{foreign_alias},
1989       ( map
1990         { (exists $args->{$_}) ? ( $_ => $args->{$_} ) : () }
1991         qw( self_result_object foreign_values )
1992       ),
1993     };
1994
1995     # legacy - never remove these!!!
1996     $cref_args->{foreign_relname} = $cref_args->{rel_name};
1997
1998     $cref_args->{self_rowobj} = $cref_args->{self_result_object}
1999       if exists $cref_args->{self_result_object};
2000
2001     ($ret->{condition}, $ret->{join_free_condition}, my @extra) = $rel_info->{cond}->($cref_args);
2002
2003     # sanity check
2004     $self->throw_exception("A custom condition coderef can return at most 2 conditions, but $exception_rel_id returned extra values: @extra")
2005       if @extra;
2006
2007     if (my $jfc = $ret->{join_free_condition}) {
2008
2009       $self->throw_exception (
2010         "The join-free condition returned for $exception_rel_id must be a hash reference"
2011       ) unless ref $jfc eq 'HASH';
2012
2013       my ($joinfree_alias, $joinfree_source);
2014       if (defined $args->{self_result_object}) {
2015         $joinfree_alias = $args->{foreign_alias};
2016         $joinfree_source = $rel_rsrc;
2017       }
2018       elsif (defined $args->{foreign_values}) {
2019         $joinfree_alias = $args->{self_alias};
2020         $joinfree_source = $self;
2021       }
2022
2023       # FIXME sanity check until things stabilize, remove at some point
2024       $self->throw_exception (
2025         "A join-free condition returned for $exception_rel_id without a result object to chain from"
2026       ) unless $joinfree_alias;
2027
2028       my $fq_col_list = { map
2029         { ( "$joinfree_alias.$_" => 1 ) }
2030         $joinfree_source->columns
2031       };
2032
2033       exists $fq_col_list->{$_} or $self->throw_exception (
2034         "The join-free condition returned for $exception_rel_id may only "
2035       . 'contain keys that are fully qualified column names of the corresponding source '
2036       . "'$joinfree_alias' (instead it returned '$_')"
2037       ) for keys %$jfc;
2038
2039       (
2040         length ref $_
2041           and
2042         defined blessed($_)
2043           and
2044         $_->isa('DBIx::Class::Row')
2045           and
2046         $self->throw_exception (
2047           "The join-free condition returned for $exception_rel_id may not "
2048         . 'contain result objects as values - perhaps instead of invoking '
2049         . '->$something you meant to return ->get_column($something)'
2050         )
2051       ) for values %$jfc;
2052
2053     }
2054   }
2055   elsif (ref $rel_info->{cond} eq 'HASH') {
2056
2057     # the condition is static - use parallel arrays
2058     # for a "pivot" depending on which side of the
2059     # rel did we get as an object
2060     my (@f_cols, @l_cols);
2061     for my $fc (keys %{ $rel_info->{cond} }) {
2062       my $lc = $rel_info->{cond}{$fc};
2063
2064       # FIXME STRICTMODE should probably check these are valid columns
2065       $fc =~ s/^foreign\.// ||
2066         $self->throw_exception("Invalid rel cond key '$fc'");
2067
2068       $lc =~ s/^self\.// ||
2069         $self->throw_exception("Invalid rel cond val '$lc'");
2070
2071       push @f_cols, $fc;
2072       push @l_cols, $lc;
2073     }
2074
2075     # construct the crosstable condition and the identity map
2076     for  (0..$#f_cols) {
2077       $ret->{condition}{"$args->{foreign_alias}.$f_cols[$_]"} = { -ident => "$args->{self_alias}.$l_cols[$_]" };
2078       $ret->{identity_map}{$l_cols[$_]} = $f_cols[$_];
2079     };
2080
2081     if ($args->{foreign_values}) {
2082       $ret->{join_free_condition}{"$args->{self_alias}.$l_cols[$_]"} = $args->{foreign_values}{$f_cols[$_]}
2083         for 0..$#f_cols;
2084     }
2085     elsif (defined $args->{self_result_object}) {
2086
2087       for my $i (0..$#l_cols) {
2088         if ( $args->{self_result_object}->has_column_loaded($l_cols[$i]) ) {
2089           $ret->{join_free_condition}{"$args->{foreign_alias}.$f_cols[$i]"} = $args->{self_result_object}->get_column($l_cols[$i]);
2090         }
2091         else {
2092           $self->throw_exception(sprintf
2093             "Unable to resolve relationship '%s' from object '%s': column '%s' not "
2094           . 'loaded from storage (or not passed to new() prior to insert()). You '
2095           . 'probably need to call ->discard_changes to get the server-side defaults '
2096           . 'from the database.',
2097             $args->{rel_name},
2098             $args->{self_result_object},
2099             $l_cols[$i],
2100           ) if $args->{self_result_object}->in_storage;
2101
2102           # FIXME - temporarly force-override
2103           delete $args->{require_join_free_condition};
2104           $ret->{join_free_condition} = UNRESOLVABLE_CONDITION;
2105           last;
2106         }
2107       }
2108     }
2109   }
2110   elsif (ref $rel_info->{cond} eq 'ARRAY') {
2111     if (@{ $rel_info->{cond} } == 0) {
2112       $ret = {
2113         condition => UNRESOLVABLE_CONDITION,
2114         join_free_condition => UNRESOLVABLE_CONDITION,
2115       };
2116     }
2117     else {
2118       my @subconds = map {
2119         local $rel_info->{cond} = $_;
2120         $self->_resolve_relationship_condition( $args );
2121       } @{ $rel_info->{cond} };
2122
2123       if( @{ $rel_info->{cond} } == 1 ) {
2124         $ret = $subconds[0];
2125       }
2126       else {
2127         # we are discarding inferred values here... likely incorrect...
2128         # then again - the entire thing is an OR, so we *can't* use them anyway
2129         for my $subcond ( @subconds ) {
2130           $self->throw_exception('Either all or none of the OR-condition members must resolve to a join-free condition')
2131             if ( $ret and ( $ret->{join_free_condition} xor $subcond->{join_free_condition} ) );
2132
2133           $subcond->{$_} and push @{$ret->{$_}}, $subcond->{$_} for (qw(condition join_free_condition));
2134         }
2135       }
2136     }
2137   }
2138   else {
2139     $self->throw_exception ("Can't handle condition $rel_info->{cond} for $exception_rel_id yet :(");
2140   }
2141
2142   if (
2143     $args->{require_join_free_condition}
2144       and
2145     ( ! $ret->{join_free_condition} or $ret->{join_free_condition} eq UNRESOLVABLE_CONDITION )
2146   ) {
2147     $self->throw_exception(
2148       ucfirst sprintf "$exception_rel_id does not resolve to a %sjoin-free condition fragment",
2149         exists $args->{foreign_values}
2150           ? "'foreign_values'-based reversed-"
2151           : ''
2152     );
2153   }
2154
2155   # we got something back - sanity check and infer values if we can
2156   my @nonvalues;
2157   if (
2158     $ret->{join_free_condition}
2159       and
2160     $ret->{join_free_condition} ne UNRESOLVABLE_CONDITION
2161       and
2162     my $jfc = $storage->_collapse_cond( $ret->{join_free_condition} )
2163   ) {
2164
2165     my $jfc_eqs = $storage->_extract_fixed_condition_columns($jfc, 'consider_nulls');
2166
2167     if (keys %$jfc_eqs) {
2168
2169       for (keys %$jfc) {
2170         # $jfc is fully qualified by definition
2171         my ($col) = $_ =~ /\.(.+)/;
2172
2173         if (exists $jfc_eqs->{$_} and ($jfc_eqs->{$_}||'') ne UNRESOLVABLE_CONDITION) {
2174           $ret->{inferred_values}{$col} = $jfc_eqs->{$_};
2175         }
2176         elsif ( !$args->{infer_values_based_on} or ! exists $args->{infer_values_based_on}{$col} ) {
2177           push @nonvalues, $col;
2178         }
2179       }
2180
2181       # all or nothing
2182       delete $ret->{inferred_values} if @nonvalues;
2183     }
2184   }
2185
2186   # did the user explicitly ask
2187   if ($args->{infer_values_based_on}) {
2188
2189     $self->throw_exception(sprintf (
2190       "Unable to complete value inferrence - custom $exception_rel_id returns conditions instead of values for column(s): %s",
2191       map { "'$_'" } @nonvalues
2192     )) if @nonvalues;
2193
2194
2195     $ret->{inferred_values} ||= {};
2196
2197     $ret->{inferred_values}{$_} = $args->{infer_values_based_on}{$_}
2198       for keys %{$args->{infer_values_based_on}};
2199   }
2200
2201   # add the identities based on the main condition
2202   # (may already be there, since easy to calculate on the fly in the HASH case)
2203   if ( ! $ret->{identity_map} ) {
2204
2205     my $col_eqs = $storage->_extract_fixed_condition_columns($ret->{condition});
2206
2207     my $colinfos;
2208     for my $lhs (keys %$col_eqs) {
2209
2210       next if $col_eqs->{$lhs} eq UNRESOLVABLE_CONDITION;
2211
2212       # there is no way to know who is right and who is left in a cref
2213       # therefore a full blown resolution call, and figure out the
2214       # direction a bit further below
2215       $colinfos ||= $storage->_resolve_column_info([
2216         { -alias => $args->{self_alias}, -rsrc => $self },
2217         { -alias => $args->{foreign_alias}, -rsrc => $rel_rsrc },
2218       ]);
2219
2220       next unless $colinfos->{$lhs};  # someone is engaging in witchcraft
2221
2222       if ( my $rhs_ref = is_literal_value( $col_eqs->{$lhs} ) ) {
2223
2224         if (
2225           $colinfos->{$rhs_ref->[0]}
2226             and
2227           $colinfos->{$lhs}{-source_alias} ne $colinfos->{$rhs_ref->[0]}{-source_alias}
2228         ) {
2229           ( $colinfos->{$lhs}{-source_alias} eq $args->{self_alias} )
2230             ? ( $ret->{identity_map}{$colinfos->{$lhs}{-colname}} = $colinfos->{$rhs_ref->[0]}{-colname} )
2231             : ( $ret->{identity_map}{$colinfos->{$rhs_ref->[0]}{-colname}} = $colinfos->{$lhs}{-colname} )
2232           ;
2233         }
2234       }
2235       elsif (
2236         $col_eqs->{$lhs} =~ /^ ( \Q$args->{self_alias}\E \. .+ ) /x
2237           and
2238         ($colinfos->{$1}||{})->{-result_source} == $rel_rsrc
2239       ) {
2240         my ($lcol, $rcol) = map
2241           { $colinfos->{$_}{-colname} }
2242           ( $lhs, $1 )
2243         ;
2244         carp_unique(
2245           "The $exception_rel_id specifies equality of column '$lcol' and the "
2246         . "*VALUE* '$rcol' (you did not use the { -ident => ... } operator)"
2247         );
2248       }
2249     }
2250   }
2251
2252   # FIXME - temporary, to fool the idiotic check in SQLMaker::_join_condition
2253   $ret->{condition} = { -and => [ $ret->{condition} ] }
2254     unless $ret->{condition} eq UNRESOLVABLE_CONDITION;
2255
2256   $ret;
2257 }
2258
2259 =head2 related_source
2260
2261 =over 4
2262
2263 =item Arguments: $rel_name
2264
2265 =item Return Value: $source
2266
2267 =back
2268
2269 Returns the result source object for the given relationship.
2270
2271 =cut
2272
2273 sub related_source {
2274   my ($self, $rel) = @_;
2275   if( !$self->has_relationship( $rel ) ) {
2276     $self->throw_exception("No such relationship '$rel' on " . $self->source_name);
2277   }
2278
2279   # if we are not registered with a schema - just use the prototype
2280   # however if we do have a schema - ask for the source by name (and
2281   # throw in the process if all fails)
2282   if (my $schema = dbic_internal_try { $self->schema }) {
2283     $schema->source($self->relationship_info($rel)->{source});
2284   }
2285   else {
2286     my $class = $self->relationship_info($rel)->{class};
2287     $self->ensure_class_loaded($class);
2288     $class->result_source_instance;
2289   }
2290 }
2291
2292 =head2 related_class
2293
2294 =over 4
2295
2296 =item Arguments: $rel_name
2297
2298 =item Return Value: $classname
2299
2300 =back
2301
2302 Returns the class name for objects in the given relationship.
2303
2304 =cut
2305
2306 sub related_class {
2307   my ($self, $rel) = @_;
2308   if( !$self->has_relationship( $rel ) ) {
2309     $self->throw_exception("No such relationship '$rel' on " . $self->source_name);
2310   }
2311   return $self->schema->class($self->relationship_info($rel)->{source});
2312 }
2313
2314 =head2 handle
2315
2316 =over 4
2317
2318 =item Arguments: none
2319
2320 =item Return Value: L<$source_handle|DBIx::Class::ResultSourceHandle>
2321
2322 =back
2323
2324 Obtain a new L<result source handle instance|DBIx::Class::ResultSourceHandle>
2325 for this source. Used as a serializable pointer to this resultsource, as it is not
2326 easy (nor advisable) to serialize CODErefs which may very well be present in e.g.
2327 relationship definitions.
2328
2329 =cut
2330
2331 sub handle {
2332   require DBIx::Class::ResultSourceHandle;
2333   return DBIx::Class::ResultSourceHandle->new({
2334     source_moniker => $_[0]->source_name,
2335
2336     # so that a detached thaw can be re-frozen
2337     $_[0]->{_detached_thaw}
2338       ? ( _detached_source  => $_[0]          )
2339       : ( schema            => $_[0]->schema  )
2340     ,
2341   });
2342 }
2343
2344 my $global_phase_destroy;
2345 sub DESTROY {
2346   ### NO detected_reinvoked_destructor check
2347   ### This code very much relies on being called multuple times
2348
2349   return if $global_phase_destroy ||= in_global_destruction;
2350
2351 ######
2352 # !!! ACHTUNG !!!!
2353 ######
2354 #
2355 # Under no circumstances shall $_[0] be stored anywhere else (like copied to
2356 # a lexical variable, or shifted, or anything else). Doing so will mess up
2357 # the refcount of this particular result source, and will allow the $schema
2358 # we are trying to save to reattach back to the source we are destroying.
2359 # The relevant code checking refcounts is in ::Schema::DESTROY()
2360
2361   # if we are not a schema instance holder - we don't matter
2362   return if(
2363     ! ref $_[0]->{schema}
2364       or
2365     isweak $_[0]->{schema}
2366   );
2367
2368   # weaken our schema hold forcing the schema to find somewhere else to live
2369   # during global destruction (if we have not yet bailed out) this will throw
2370   # which will serve as a signal to not try doing anything else
2371   # however beware - on older perls the exception seems randomly untrappable
2372   # due to some weird race condition during thread joining :(((
2373   local $SIG{__DIE__} if $SIG{__DIE__};
2374   local $@;
2375   eval {
2376     weaken $_[0]->{schema};
2377
2378     # if schema is still there reintroduce ourselves with strong refs back to us
2379     if ($_[0]->{schema}) {
2380       my $srcregs = $_[0]->{schema}->source_registrations;
2381
2382       defined $srcregs->{$_}
2383         and
2384       $srcregs->{$_} == $_[0]
2385         and
2386       $srcregs->{$_} = $_[0]
2387         and
2388       last
2389         for keys %$srcregs;
2390     }
2391
2392     1;
2393   } or do {
2394     $global_phase_destroy = 1;
2395   };
2396
2397   # Dummy NEXTSTATE ensuring the all temporaries on the stack are garbage
2398   # collected before leaving this scope. Depending on the code above, this
2399   # may very well be just a preventive measure guarding future modifications
2400   undef;
2401 }
2402
2403 sub STORABLE_freeze { Storable::nfreeze($_[0]->handle) }
2404
2405 sub STORABLE_thaw {
2406   my ($self, $cloning, $ice) = @_;
2407   %$self = %{ (Storable::thaw($ice))->resolve };
2408 }
2409
2410 =head2 throw_exception
2411
2412 See L<DBIx::Class::Schema/"throw_exception">.
2413
2414 =cut
2415
2416 sub throw_exception {
2417   my $self = shift;
2418
2419   $self->{schema}
2420     ? $self->{schema}->throw_exception(@_)
2421     : DBIx::Class::Exception->throw(@_)
2422   ;
2423 }
2424
2425 =head2 column_info_from_storage
2426
2427 =over
2428
2429 =item Arguments: 1/0 (default: 0)
2430
2431 =item Return Value: 1/0
2432
2433 =back
2434
2435   __PACKAGE__->column_info_from_storage(1);
2436
2437 Enables the on-demand automatic loading of the above column
2438 metadata from storage as necessary.  This is *deprecated*, and
2439 should not be used.  It will be removed before 1.0.
2440
2441 =head1 FURTHER QUESTIONS?
2442
2443 Check the list of L<additional DBIC resources|DBIx::Class/GETTING HELP/SUPPORT>.
2444
2445 =head1 COPYRIGHT AND LICENSE
2446
2447 This module is free software L<copyright|DBIx::Class/COPYRIGHT AND LICENSE>
2448 by the L<DBIx::Class (DBIC) authors|DBIx::Class/AUTHORS>. You can
2449 redistribute it and/or modify it under the same terms as the
2450 L<DBIx::Class library|DBIx::Class/COPYRIGHT AND LICENSE>.
2451
2452 =cut
2453
2454 1;