First stab at properly documenting the new sqlt_hook for resultsources
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / ResultSource.pm
1 package DBIx::Class::ResultSource;
2
3 use strict;
4 use warnings;
5
6 use DBIx::Class::ResultSet;
7 use DBIx::Class::ResultSourceHandle;
8 use Carp::Clan qw/^DBIx::Class/;
9 use Storable;
10
11 use base qw/DBIx::Class/;
12
13 __PACKAGE__->mk_group_accessors('simple' => qw/_ordered_columns
14   _columns _primaries _unique_constraints name resultset_attributes
15   schema from _relationships column_info_from_storage source_info
16   source_name sqlt_deploy_callback/);
17
18 __PACKAGE__->mk_group_accessors('component_class' => qw/resultset_class
19   result_class/);
20
21 =head1 NAME
22
23 DBIx::Class::ResultSource - Result source object
24
25 =head1 SYNOPSIS
26
27 =head1 DESCRIPTION
28
29 A ResultSource is a component of a schema from which results can be directly
30 retrieved, most usually a table (see L<DBIx::Class::ResultSource::Table>)
31
32 =head1 METHODS
33
34 =pod
35
36 =cut
37
38 sub new {
39   my ($class, $attrs) = @_;
40   $class = ref $class if ref $class;
41
42   my $new = bless { %{$attrs || {}} }, $class;
43   $new->{resultset_class} ||= 'DBIx::Class::ResultSet';
44   $new->{resultset_attributes} = { %{$new->{resultset_attributes} || {}} };
45   $new->{_ordered_columns} = [ @{$new->{_ordered_columns}||[]}];
46   $new->{_columns} = { %{$new->{_columns}||{}} };
47   $new->{_relationships} = { %{$new->{_relationships}||{}} };
48   $new->{name} ||= "!!NAME NOT SET!!";
49   $new->{_columns_info_loaded} ||= 0;
50   $new->{sqlt_deploy_callback} ||= "default_sqlt_deploy_hook";
51   return $new;
52 }
53
54 =pod
55
56 =head2 add_columns
57
58 =over
59
60 =item Arguments: @columns
61
62 =item Return value: The ResultSource object
63
64 =back
65
66   $source->add_columns(qw/col1 col2 col3/);
67
68   $source->add_columns('col1' => \%col1_info, 'col2' => \%col2_info, ...);
69
70 Adds columns to the result source. If supplied key => hashref pairs, uses
71 the hashref as the column_info for that column. Repeated calls of this
72 method will add more columns, not replace them.
73
74 The column names given will be created as accessor methods on your
75 L<DBIx::Class::Row> objects, you can change the name of the accessor
76 by supplying an L</accessor> in the column_info hash.
77
78 The contents of the column_info are not set in stone. The following
79 keys are currently recognised/used by DBIx::Class:
80
81 =over 4
82
83 =item accessor
84
85 Use this to set the name of the accessor method for this column. If unset,
86 the name of the column will be used.
87
88 =item data_type
89
90 This contains the column type. It is automatically filled by the
91 L<SQL::Translator::Producer::DBIx::Class::File> producer, and the
92 L<DBIx::Class::Schema::Loader> module. If you do not enter a
93 data_type, DBIx::Class will attempt to retrieve it from the
94 database for you, using L<DBI>'s column_info method. The values of this
95 key are typically upper-cased.
96
97 Currently there is no standard set of values for the data_type. Use
98 whatever your database supports.
99
100 =item size
101
102 The length of your column, if it is a column type that can have a size
103 restriction. This is currently only used by L<DBIx::Class::Schema/deploy>.
104
105 =item is_nullable
106
107 Set this to a true value for a columns that is allowed to contain
108 NULL values. This is currently only used by L<DBIx::Class::Schema/deploy>.
109
110 =item is_auto_increment
111
112 Set this to a true value for a column whose value is somehow
113 automatically set. This is used to determine which columns to empty
114 when cloning objects using C<copy>. It is also used by
115 L<DBIx::Class::Schema/deploy>.
116
117 =item is_foreign_key
118
119 Set this to a true value for a column that contains a key from a
120 foreign table. This is currently only used by
121 L<DBIx::Class::Schema/deploy>.
122
123 =item default_value
124
125 Set this to the default value which will be inserted into a column
126 by the database. Can contain either a value or a function. This is
127 currently only used by L<DBIx::Class::Schema/deploy>.
128
129 =item sequence
130
131 Set this on a primary key column to the name of the sequence used to
132 generate a new key value. If not specified, L<DBIx::Class::PK::Auto>
133 will attempt to retrieve the name of the sequence from the database
134 automatically.
135
136 =item auto_nextval
137
138 Set this to a true value for a column whose value is retrieved
139 automatically from an oracle sequence. If you do not use an oracle
140 trigger to get the nextval, you have to set sequence as well.
141
142 =item extra
143
144 This is used by L<DBIx::Class::Schema/deploy> and L<SQL::Translator>
145 to add extra non-generic data to the column. For example: C<< extra
146 => { unsigned => 1} >> is used by the MySQL producer to set an integer
147 column to unsigned. For more details, see
148 L<SQL::Translator::Producer::MySQL>.
149
150 =back
151
152 =head2 add_column
153
154 =over
155
156 =item Arguments: $colname, [ \%columninfo ]
157
158 =item Return value: 1/0 (true/false)
159
160 =back
161
162   $source->add_column('col' => \%info?);
163
164 Add a single column and optional column info. Uses the same column
165 info keys as L</add_columns>.
166
167 =cut
168
169 sub add_columns {
170   my ($self, @cols) = @_;
171   $self->_ordered_columns(\@cols) unless $self->_ordered_columns;
172
173   my @added;
174   my $columns = $self->_columns;
175   while (my $col = shift @cols) {
176     # If next entry is { ... } use that for the column info, if not
177     # use an empty hashref
178     my $column_info = ref $cols[0] ? shift(@cols) : {};
179     push(@added, $col) unless exists $columns->{$col};
180     $columns->{$col} = $column_info;
181   }
182   push @{ $self->_ordered_columns }, @added;
183   return $self;
184 }
185
186 sub add_column { shift->add_columns(@_); } # DO NOT CHANGE THIS TO GLOB
187
188 =head2 has_column
189
190 =over
191
192 =item Arguments: $colname
193
194 =item Return value: 1/0 (true/false)
195
196 =back
197
198   if ($source->has_column($colname)) { ... }
199
200 Returns true if the source has a column of this name, false otherwise.
201
202 =cut
203
204 sub has_column {
205   my ($self, $column) = @_;
206   return exists $self->_columns->{$column};
207 }
208
209 =head2 column_info
210
211 =over
212
213 =item Arguments: $colname
214
215 =item Return value: Hashref of info
216
217 =back
218
219   my $info = $source->column_info($col);
220
221 Returns the column metadata hashref for a column, as originally passed
222 to L</add_columns>. See the description of L</add_columns> for information
223 on the contents of the hashref.
224
225 =cut
226
227 sub column_info {
228   my ($self, $column) = @_;
229   $self->throw_exception("No such column $column")
230     unless exists $self->_columns->{$column};
231   #warn $self->{_columns_info_loaded}, "\n";
232   if ( ! $self->_columns->{$column}{data_type}
233        and $self->column_info_from_storage
234        and ! $self->{_columns_info_loaded}
235        and $self->schema and $self->storage )
236   {
237     $self->{_columns_info_loaded}++;
238     my $info = {};
239     my $lc_info = {};
240     # eval for the case of storage without table
241     eval { $info = $self->storage->columns_info_for( $self->from ) };
242     unless ($@) {
243       for my $realcol ( keys %{$info} ) {
244         $lc_info->{lc $realcol} = $info->{$realcol};
245       }
246       foreach my $col ( keys %{$self->_columns} ) {
247         $self->_columns->{$col} = {
248           %{ $self->_columns->{$col} },
249           %{ $info->{$col} || $lc_info->{lc $col} || {} }
250         };
251       }
252     }
253   }
254   return $self->_columns->{$column};
255 }
256
257 =head2 columns
258
259 =over
260
261 =item Arguments: None
262
263 =item Return value: Ordered list of column names
264
265 =back
266
267   my @column_names = $source->columns;
268
269 Returns all column names in the order they were declared to L</add_columns>.
270
271 =cut
272
273 sub columns {
274   my $self = shift;
275   $self->throw_exception(
276     "columns() is a read-only accessor, did you mean add_columns()?"
277   ) if (@_ > 1);
278   return @{$self->{_ordered_columns}||[]};
279 }
280
281 =head2 remove_columns
282
283 =over
284
285 =item Arguments: @colnames
286
287 =item Return value: undefined
288
289 =back
290
291   $source->remove_columns(qw/col1 col2 col3/);
292
293 Removes the given list of columns by name, from the result source.
294
295 B<Warning>: Removing a column that is also used in the sources primary
296 key, or in one of the sources unique constraints, B<will> result in a
297 broken result source.
298
299 =head2 remove_column
300
301 =over
302
303 =item Arguments: $colname
304
305 =item Return value: undefined
306
307 =back
308
309   $source->remove_column('col');
310
311 Remove a single column by name from the result source, similar to
312 L</remove_columns>.
313
314 B<Warning>: Removing a column that is also used in the sources primary
315 key, or in one of the sources unique constraints, B<will> result in a
316 broken result source.
317
318 =cut
319
320 sub remove_columns {
321   my ($self, @to_remove) = @_;
322
323   my $columns = $self->_columns
324     or return;
325
326   my %to_remove;
327   for (@to_remove) {
328     delete $columns->{$_};
329     ++$to_remove{$_};
330   }
331
332   $self->_ordered_columns([ grep { not $to_remove{$_} } @{$self->_ordered_columns} ]);
333 }
334
335 sub remove_column { shift->remove_columns(@_); } # DO NOT CHANGE THIS TO GLOB
336
337 =head2 set_primary_key
338
339 =over 4
340
341 =item Arguments: @cols
342
343 =item Return value: undefined
344
345 =back
346
347 Defines one or more columns as primary key for this source. Should be
348 called after L</add_columns>.
349
350 Additionally, defines a L<unique constraint|add_unique_constraint>
351 named C<primary>.
352
353 The primary key columns are used by L<DBIx::Class::PK::Auto> to
354 retrieve automatically created values from the database.
355
356 =cut
357
358 sub set_primary_key {
359   my ($self, @cols) = @_;
360   # check if primary key columns are valid columns
361   foreach my $col (@cols) {
362     $self->throw_exception("No such column $col on table " . $self->name)
363       unless $self->has_column($col);
364   }
365   $self->_primaries(\@cols);
366
367   $self->add_unique_constraint(primary => \@cols);
368 }
369
370 =head2 primary_columns
371
372 =over 4
373
374 =item Arguments: None
375
376 =item Return value: Ordered list of primary column names
377
378 =back
379
380 Read-only accessor which returns the list of primary keys, supplied by
381 L</set_primary_key>.
382
383 =cut
384
385 sub primary_columns {
386   return @{shift->_primaries||[]};
387 }
388
389 =head2 add_unique_constraint
390
391 =over 4
392
393 =item Arguments: [ $name ], \@colnames
394
395 =item Return value: undefined
396
397 =back
398
399 Declare a unique constraint on this source. Call once for each unique
400 constraint.
401
402   # For UNIQUE (column1, column2)
403   __PACKAGE__->add_unique_constraint(
404     constraint_name => [ qw/column1 column2/ ],
405   );
406
407 Alternatively, you can specify only the columns:
408
409   __PACKAGE__->add_unique_constraint([ qw/column1 column2/ ]);
410
411 This will result in a unique constraint named C<table_column1_column2>, where
412 C<table> is replaced with the table name.
413
414 Unique constraints are used, for example, when you call
415 L<DBIx::Class::ResultSet/find>. Only columns in the constraint are searched.
416
417 Throws an error if any of the given column names do not yet exist on
418 the result source.
419
420 =cut
421
422 sub add_unique_constraint {
423   my $self = shift;
424   my $cols = pop @_;
425   my $name = shift;
426
427   $name ||= $self->name_unique_constraint($cols);
428
429   foreach my $col (@$cols) {
430     $self->throw_exception("No such column $col on table " . $self->name)
431       unless $self->has_column($col);
432   }
433
434   my %unique_constraints = $self->unique_constraints;
435   $unique_constraints{$name} = $cols;
436   $self->_unique_constraints(\%unique_constraints);
437 }
438
439 =head2 name_unique_constraint
440
441 =over 4
442
443 =item Arguments: @colnames
444
445 =item Return value: Constraint name
446
447 =back
448
449   $source->table('mytable');
450   $source->name_unique_constraint('col1', 'col2');
451   # returns
452   'mytable_col1_col2'
453
454 Return a name for a unique constraint containing the specified
455 columns. The name is created by joining the table name and each column
456 name, using an underscore character.
457
458 For example, a constraint on a table named C<cd> containing the columns
459 C<artist> and C<title> would result in a constraint name of C<cd_artist_title>.
460
461 This is used by L</add_unique_constraint> if you do not specify the
462 optional constraint name.
463
464 =cut
465
466 sub name_unique_constraint {
467   my ($self, $cols) = @_;
468
469   return join '_', $self->name, @$cols;
470 }
471
472 =head2 unique_constraints
473
474 =over 4
475
476 =item Arguments: None
477
478 =item Return value: Hash of unique constraint data
479
480 =back
481
482   $source->unique_constraints();
483
484 Read-only accessor which returns a hash of unique constraints on this source.
485
486 The hash is keyed by constraint name, and contains an arrayref of
487 column names as values.
488
489 =cut
490
491 sub unique_constraints {
492   return %{shift->_unique_constraints||{}};
493 }
494
495 =head2 unique_constraint_names
496
497 =over 4
498
499 =item Arguments: None
500
501 =item Return value: Unique constraint names
502
503 =back
504
505   $source->unique_constraint_names();
506
507 Returns the list of unique constraint names defined on this source.
508
509 =cut
510
511 sub unique_constraint_names {
512   my ($self) = @_;
513
514   my %unique_constraints = $self->unique_constraints;
515
516   return keys %unique_constraints;
517 }
518
519 =head2 unique_constraint_columns
520
521 =over 4
522
523 =item Arguments: $constraintname
524
525 =item Return value: List of constraint columns
526
527 =back
528
529   $source->unique_constraint_columns('myconstraint');
530
531 Returns the list of columns that make up the specified unique constraint.
532
533 =cut
534
535 sub unique_constraint_columns {
536   my ($self, $constraint_name) = @_;
537
538   my %unique_constraints = $self->unique_constraints;
539
540   $self->throw_exception(
541     "Unknown unique constraint $constraint_name on '" . $self->name . "'"
542   ) unless exists $unique_constraints{$constraint_name};
543
544   return @{ $unique_constraints{$constraint_name} };
545 }
546
547 =head2 resultset
548
549 =over 4
550
551 =item Arguments: None
552
553 =item Return value: $resultset
554
555 =back
556
557 Returns a resultset for the given source. This will initially be created
558 on demand by calling
559
560   $self->resultset_class->new($self, $self->resultset_attributes)
561
562 but is cached from then on unless resultset_class changes.
563
564 =head2 resultset_class
565
566 =over 4
567
568 =item Arguments: $classname
569
570 =item Return value: $classname
571
572 =back
573
574   package My::ResultSetClass;
575   use base 'DBIx::Class::ResultSet';
576   ...
577
578   $source->resultset_class('My::ResultSet::Class');
579
580 Set the class of the resultset, this is useful if you want to create your
581 own resultset methods. Create your own class derived from
582 L<DBIx::Class::ResultSet>, and set it here. If called with no arguments,
583 this method returns the name of the existing resultset class, if one
584 exists.
585
586 =head2 resultset_attributes
587
588 =over 4
589
590 =item Arguments: \%attrs
591
592 =item Return value: \%attrs
593
594 =back
595
596   $source->resultset_attributes({ order_by => [ 'id' ] });
597
598 Store a collection of resultset attributes, that will be set on every
599 L<DBIx::Class::ResultSet> produced from this result source. For a full
600 list see L<DBIx::Class::ResultSet/ATTRIBUTES>.
601
602 =cut
603
604 sub resultset {
605   my $self = shift;
606   $self->throw_exception(
607     'resultset does not take any arguments. If you want another resultset, '.
608     'call it on the schema instead.'
609   ) if scalar @_;
610
611   return $self->resultset_class->new(
612     $self,
613     {
614       %{$self->{resultset_attributes}},
615       %{$self->schema->default_resultset_attributes}
616     },
617   );
618 }
619
620 =head2 source_name
621
622 =over 4
623
624 =item Arguments: $source_name
625
626 =item Result value: $source_name
627
628 =back
629
630 Set an alternate name for the result source when it is loaded into a schema.
631 This is useful if you want to refer to a result source by a name other than
632 its class name.
633
634   package ArchivedBooks;
635   use base qw/DBIx::Class/;
636   __PACKAGE__->table('books_archive');
637   __PACKAGE__->source_name('Books');
638
639   # from your schema...
640   $schema->resultset('Books')->find(1);
641
642 =head2 from
643
644 =over 4
645
646 =item Arguments: None
647
648 =item Return value: FROM clause
649
650 =back
651
652   my $from_clause = $source->from();
653
654 Returns an expression of the source to be supplied to storage to specify
655 retrieval from this source. In the case of a database, the required FROM
656 clause contents.
657
658 =head2 schema
659
660 =over 4
661
662 =item Arguments: None
663
664 =item Return value: A schema object
665
666 =back
667
668   my $schema = $source->schema();
669
670 Returns the L<DBIx::Class::Schema> object that this result source 
671 belongs to.
672
673 =head2 storage
674
675 =over 4
676
677 =item Arguments: None
678
679 =item Return value: A Storage object
680
681 =back
682
683   $source->storage->debug(1);
684
685 Returns the storage handle for the current schema.
686
687 See also: L<DBIx::Class::Storage>
688
689 =cut
690
691 sub storage { shift->schema->storage; }
692
693 =head2 add_relationship
694
695 =over 4
696
697 =item Arguments: $relname, $related_source_name, \%cond, [ \%attrs ]
698
699 =item Return value: 1/true if it succeeded
700
701 =back
702
703   $source->add_relationship('relname', 'related_source', $cond, $attrs);
704
705 L<DBIx::Class::Relationship> describes a series of methods which
706 create pre-defined useful types of relationships. Look there first
707 before using this method directly.
708
709 The relationship name can be arbitrary, but must be unique for each
710 relationship attached to this result source. 'related_source' should
711 be the name with which the related result source was registered with
712 the current schema. For example:
713
714   $schema->source('Book')->add_relationship('reviews', 'Review', {
715     'foreign.book_id' => 'self.id',
716   });
717
718 The condition C<$cond> needs to be an L<SQL::Abstract>-style
719 representation of the join between the tables. For example, if you're
720 creating a relation from Author to Book,
721
722   { 'foreign.author_id' => 'self.id' }
723
724 will result in the JOIN clause
725
726   author me JOIN book foreign ON foreign.author_id = me.id
727
728 You can specify as many foreign => self mappings as necessary.
729
730 Valid attributes are as follows:
731
732 =over 4
733
734 =item join_type
735
736 Explicitly specifies the type of join to use in the relationship. Any
737 SQL join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in
738 the SQL command immediately before C<JOIN>.
739
740 =item proxy
741
742 An arrayref containing a list of accessors in the foreign class to proxy in
743 the main class. If, for example, you do the following:
744
745   CD->might_have(liner_notes => 'LinerNotes', undef, {
746     proxy => [ qw/notes/ ],
747   });
748
749 Then, assuming LinerNotes has an accessor named notes, you can do:
750
751   my $cd = CD->find(1);
752   # set notes -- LinerNotes object is created if it doesn't exist
753   $cd->notes('Notes go here');
754
755 =item accessor
756
757 Specifies the type of accessor that should be created for the
758 relationship. Valid values are C<single> (for when there is only a single
759 related object), C<multi> (when there can be many), and C<filter> (for
760 when there is a single related object, but you also want the relationship
761 accessor to double as a column accessor). For C<multi> accessors, an
762 add_to_* method is also created, which calls C<create_related> for the
763 relationship.
764
765 =back
766
767 Throws an exception if the condition is improperly supplied, or cannot
768 be resolved using L</resolve_join>.
769
770 =cut
771
772 sub add_relationship {
773   my ($self, $rel, $f_source_name, $cond, $attrs) = @_;
774   $self->throw_exception("Can't create relationship without join condition")
775     unless $cond;
776   $attrs ||= {};
777
778   # Check foreign and self are right in cond
779   if ( (ref $cond ||'') eq 'HASH') {
780     for (keys %$cond) {
781       $self->throw_exception("Keys of condition should be of form 'foreign.col', not '$_'")
782         if /\./ && !/^foreign\./;
783     }
784   }
785
786   my %rels = %{ $self->_relationships };
787   $rels{$rel} = { class => $f_source_name,
788                   source => $f_source_name,
789                   cond  => $cond,
790                   attrs => $attrs };
791   $self->_relationships(\%rels);
792
793   return $self;
794
795   # XXX disabled. doesn't work properly currently. skip in tests.
796
797   my $f_source = $self->schema->source($f_source_name);
798   unless ($f_source) {
799     $self->ensure_class_loaded($f_source_name);
800     $f_source = $f_source_name->result_source;
801     #my $s_class = ref($self->schema);
802     #$f_source_name =~ m/^${s_class}::(.*)$/;
803     #$self->schema->register_class(($1 || $f_source_name), $f_source_name);
804     #$f_source = $self->schema->source($f_source_name);
805   }
806   return unless $f_source; # Can't test rel without f_source
807
808   eval { $self->resolve_join($rel, 'me') };
809
810   if ($@) { # If the resolve failed, back out and re-throw the error
811     delete $rels{$rel}; #
812     $self->_relationships(\%rels);
813     $self->throw_exception("Error creating relationship $rel: $@");
814   }
815   1;
816 }
817
818 =head2 relationships
819
820 =over 4
821
822 =item Arguments: None
823
824 =item Return value: List of relationship names
825
826 =back
827
828   my @relnames = $source->relationships();
829
830 Returns all relationship names for this source.
831
832 =cut
833
834 sub relationships {
835   return keys %{shift->_relationships};
836 }
837
838 =head2 relationship_info
839
840 =over 4
841
842 =item Arguments: $relname
843
844 =item Return value: Hashref of relation data,
845
846 =back
847
848 Returns a hash of relationship information for the specified relationship
849 name. The keys/values are as specified for L</add_relationship>.
850
851 =cut
852
853 sub relationship_info {
854   my ($self, $rel) = @_;
855   return $self->_relationships->{$rel};
856 }
857
858 =head2 has_relationship
859
860 =over 4
861
862 =item Arguments: $rel
863
864 =item Return value: 1/0 (true/false)
865
866 =back
867
868 Returns true if the source has a relationship of this name, false otherwise.
869
870 =cut
871
872 sub has_relationship {
873   my ($self, $rel) = @_;
874   return exists $self->_relationships->{$rel};
875 }
876
877 =head2 reverse_relationship_info
878
879 =over 4
880
881 =item Arguments: $relname
882
883 =item Return value: Hashref of relationship data
884
885 =back
886
887 Looks through all the relationships on the source this relationship
888 points to, looking for one whose condition is the reverse of the
889 condition on this relationship.
890
891 A common use of this is to find the name of the C<belongs_to> relation
892 opposing a C<has_many> relation. For definition of these look in
893 L<DBIx::Class::Relationship>.
894
895 The returned hashref is keyed by the name of the opposing
896 relationship, and contains it's data in the same manner as
897 L</relationship_info>.
898
899 =cut
900
901 sub reverse_relationship_info {
902   my ($self, $rel) = @_;
903   my $rel_info = $self->relationship_info($rel);
904   my $ret = {};
905
906   return $ret unless ((ref $rel_info->{cond}) eq 'HASH');
907
908   my @cond = keys(%{$rel_info->{cond}});
909   my @refkeys = map {/^\w+\.(\w+)$/} @cond;
910   my @keys = map {$rel_info->{cond}->{$_} =~ /^\w+\.(\w+)$/} @cond;
911
912   # Get the related result source for this relationship
913   my $othertable = $self->related_source($rel);
914
915   # Get all the relationships for that source that related to this source
916   # whose foreign column set are our self columns on $rel and whose self
917   # columns are our foreign columns on $rel.
918   my @otherrels = $othertable->relationships();
919   my $otherrelationship;
920   foreach my $otherrel (@otherrels) {
921     my $otherrel_info = $othertable->relationship_info($otherrel);
922
923     my $back = $othertable->related_source($otherrel);
924     next unless $back->source_name eq $self->source_name;
925
926     my @othertestconds;
927
928     if (ref $otherrel_info->{cond} eq 'HASH') {
929       @othertestconds = ($otherrel_info->{cond});
930     }
931     elsif (ref $otherrel_info->{cond} eq 'ARRAY') {
932       @othertestconds = @{$otherrel_info->{cond}};
933     }
934     else {
935       next;
936     }
937
938     foreach my $othercond (@othertestconds) {
939       my @other_cond = keys(%$othercond);
940       my @other_refkeys = map {/^\w+\.(\w+)$/} @other_cond;
941       my @other_keys = map {$othercond->{$_} =~ /^\w+\.(\w+)$/} @other_cond;
942       next if (!$self->compare_relationship_keys(\@refkeys, \@other_keys) ||
943                !$self->compare_relationship_keys(\@other_refkeys, \@keys));
944       $ret->{$otherrel} =  $otherrel_info;
945     }
946   }
947   return $ret;
948 }
949
950 =head2 compare_relationship_keys
951
952 =over 4
953
954 =item Arguments: \@keys1, \@keys2
955
956 =item Return value: 1/0 (true/false)
957
958 =back
959
960 Returns true if both sets of keynames are the same, false otherwise.
961
962 =cut
963
964 sub compare_relationship_keys {
965   my ($self, $keys1, $keys2) = @_;
966
967   # Make sure every keys1 is in keys2
968   my $found;
969   foreach my $key (@$keys1) {
970     $found = 0;
971     foreach my $prim (@$keys2) {
972       if ($prim eq $key) {
973         $found = 1;
974         last;
975       }
976     }
977     last unless $found;
978   }
979
980   # Make sure every key2 is in key1
981   if ($found) {
982     foreach my $prim (@$keys2) {
983       $found = 0;
984       foreach my $key (@$keys1) {
985         if ($prim eq $key) {
986           $found = 1;
987           last;
988         }
989       }
990       last unless $found;
991     }
992   }
993
994   return $found;
995 }
996
997 =head2 resolve_join
998
999 =over 4
1000
1001 =item Arguments: $relation
1002
1003 =item Return value: Join condition arrayref
1004
1005 =back
1006
1007 Returns the join structure required for the related result source.
1008
1009 =cut
1010
1011 sub resolve_join {
1012   my ($self, $join, $alias, $seen, $force_left) = @_;
1013   $seen ||= {};
1014   $force_left ||= { force => 0 };
1015   if (ref $join eq 'ARRAY') {
1016     return map { $self->resolve_join($_, $alias, $seen) } @$join;
1017   } elsif (ref $join eq 'HASH') {
1018     return
1019       map {
1020         my $as = ($seen->{$_} ? $_.'_'.($seen->{$_}+1) : $_);
1021         local $force_left->{force};
1022         (
1023           $self->resolve_join($_, $alias, $seen, $force_left),
1024           $self->related_source($_)->resolve_join(
1025             $join->{$_}, $as, $seen, $force_left
1026           )
1027         );
1028       } keys %$join;
1029   } elsif (ref $join) {
1030     $self->throw_exception("No idea how to resolve join reftype ".ref $join);
1031   } else {
1032     my $count = ++$seen->{$join};
1033     #use Data::Dumper; warn Dumper($seen);
1034     my $as = ($count > 1 ? "${join}_${count}" : $join);
1035     my $rel_info = $self->relationship_info($join);
1036     $self->throw_exception("No such relationship ${join}") unless $rel_info;
1037     my $type;
1038     if ($force_left->{force}) {
1039       $type = 'left';
1040     } else {
1041       $type = $rel_info->{attrs}{join_type} || '';
1042       $force_left->{force} = 1 if lc($type) eq 'left';
1043     }
1044     return [ { $as => $self->related_source($join)->from,
1045                -join_type => $type },
1046              $self->resolve_condition($rel_info->{cond}, $as, $alias) ];
1047   }
1048 }
1049
1050 =head2 pk_depends_on
1051
1052 =over 4
1053
1054 =item Arguments: $relname, $rel_data
1055
1056 =item Return value: 1/0 (true/false)
1057
1058 =back
1059
1060 Determines whether a relation is dependent on an object from this source
1061 having already been inserted. Takes the name of the relationship and a
1062 hashref of columns of the related object.
1063
1064 =cut
1065
1066 sub pk_depends_on {
1067   my ($self, $relname, $rel_data) = @_;
1068   my $cond = $self->relationship_info($relname)->{cond};
1069
1070   return 0 unless ref($cond) eq 'HASH';
1071
1072   # map { foreign.foo => 'self.bar' } to { bar => 'foo' }
1073
1074   my $keyhash = { map { my $x = $_; $x =~ s/.*\.//; $x; } reverse %$cond };
1075
1076   # assume anything that references our PK probably is dependent on us
1077   # rather than vice versa, unless the far side is (a) defined or (b)
1078   # auto-increment
1079
1080   my $rel_source = $self->related_source($relname);
1081
1082   foreach my $p ($self->primary_columns) {
1083     if (exists $keyhash->{$p}) {
1084       unless (defined($rel_data->{$keyhash->{$p}})
1085               || $rel_source->column_info($keyhash->{$p})
1086                             ->{is_auto_increment}) {
1087         return 0;
1088       }
1089     }
1090   }
1091
1092   return 1;
1093 }
1094
1095 =head2 resolve_condition
1096
1097 =over 4
1098
1099 =item Arguments: $cond, $as, $alias|$object
1100
1101 =back
1102
1103 Resolves the passed condition to a concrete query fragment. If given an alias,
1104 returns a join condition; if given an object, inverts that object to produce
1105 a related conditional from that object.
1106
1107 =cut
1108
1109 our $UNRESOLVABLE_CONDITION = \'1 = 0';
1110
1111 sub resolve_condition {
1112   my ($self, $cond, $as, $for) = @_;
1113   #warn %$cond;
1114   if (ref $cond eq 'HASH') {
1115     my %ret;
1116     foreach my $k (keys %{$cond}) {
1117       my $v = $cond->{$k};
1118       # XXX should probably check these are valid columns
1119       $k =~ s/^foreign\.// ||
1120         $self->throw_exception("Invalid rel cond key ${k}");
1121       $v =~ s/^self\.// ||
1122         $self->throw_exception("Invalid rel cond val ${v}");
1123       if (ref $for) { # Object
1124         #warn "$self $k $for $v";
1125         unless ($for->has_column_loaded($v)) {
1126           if ($for->in_storage) {
1127             $self->throw_exception("Column ${v} not loaded on ${for} trying to resolve relationship");
1128           }
1129           return $UNRESOLVABLE_CONDITION;
1130         }
1131         $ret{$k} = $for->get_column($v);
1132         #$ret{$k} = $for->get_column($v) if $for->has_column_loaded($v);
1133         #warn %ret;
1134       } elsif (!defined $for) { # undef, i.e. "no object"
1135         $ret{$k} = undef;
1136       } elsif (ref $as eq 'HASH') { # reverse hashref
1137         $ret{$v} = $as->{$k};
1138       } elsif (ref $as) { # reverse object
1139         $ret{$v} = $as->get_column($k);
1140       } elsif (!defined $as) { # undef, i.e. "no reverse object"
1141         $ret{$v} = undef;
1142       } else {
1143         $ret{"${as}.${k}"} = "${for}.${v}";
1144       }
1145     }
1146     return \%ret;
1147   } elsif (ref $cond eq 'ARRAY') {
1148     return [ map { $self->resolve_condition($_, $as, $for) } @$cond ];
1149   } else {
1150    die("Can't handle this yet :(");
1151   }
1152 }
1153
1154 =head2 resolve_prefetch
1155
1156 =over 4
1157
1158 =item Arguments: hashref/arrayref/scalar
1159
1160 =back
1161
1162 Accepts one or more relationships for the current source and returns an
1163 array of column names for each of those relationships. Column names are
1164 prefixed relative to the current source, in accordance with where they appear
1165 in the supplied relationships. Examples:
1166
1167   my $source = $schema->resultset('Tag')->source;
1168   @columns = $source->resolve_prefetch( { cd => 'artist' } );
1169
1170   # @columns =
1171   #(
1172   #  'cd.cdid',
1173   #  'cd.artist',
1174   #  'cd.title',
1175   #  'cd.year',
1176   #  'cd.artist.artistid',
1177   #  'cd.artist.name'
1178   #)
1179
1180   @columns = $source->resolve_prefetch( qw[/ cd /] );
1181
1182   # @columns =
1183   #(
1184   #   'cd.cdid',
1185   #   'cd.artist',
1186   #   'cd.title',
1187   #   'cd.year'
1188   #)
1189
1190   $source = $schema->resultset('CD')->source;
1191   @columns = $source->resolve_prefetch( qw[/ artist producer /] );
1192
1193   # @columns =
1194   #(
1195   #  'artist.artistid',
1196   #  'artist.name',
1197   #  'producer.producerid',
1198   #  'producer.name'
1199   #)
1200
1201 =cut
1202
1203 sub resolve_prefetch {
1204   my ($self, $pre, $alias, $seen, $order, $collapse) = @_;
1205   $seen ||= {};
1206   #$alias ||= $self->name;
1207   #warn $alias, Dumper $pre;
1208   if( ref $pre eq 'ARRAY' ) {
1209     return
1210       map { $self->resolve_prefetch( $_, $alias, $seen, $order, $collapse ) }
1211         @$pre;
1212   }
1213   elsif( ref $pre eq 'HASH' ) {
1214     my @ret =
1215     map {
1216       $self->resolve_prefetch($_, $alias, $seen, $order, $collapse),
1217       $self->related_source($_)->resolve_prefetch(
1218                $pre->{$_}, "${alias}.$_", $seen, $order, $collapse)
1219     } keys %$pre;
1220     #die Dumper \@ret;
1221     return @ret;
1222   }
1223   elsif( ref $pre ) {
1224     $self->throw_exception(
1225       "don't know how to resolve prefetch reftype ".ref($pre));
1226   }
1227   else {
1228     my $count = ++$seen->{$pre};
1229     my $as = ($count > 1 ? "${pre}_${count}" : $pre);
1230     my $rel_info = $self->relationship_info( $pre );
1231     $self->throw_exception( $self->name . " has no such relationship '$pre'" )
1232       unless $rel_info;
1233     my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : '');
1234     my $rel_source = $self->related_source($pre);
1235
1236     if (exists $rel_info->{attrs}{accessor}
1237          && $rel_info->{attrs}{accessor} eq 'multi') {
1238       $self->throw_exception(
1239         "Can't prefetch has_many ${pre} (join cond too complex)")
1240         unless ref($rel_info->{cond}) eq 'HASH';
1241       my $dots = @{[$as_prefix =~ m/\./g]} + 1; # +1 to match the ".${as_prefix}"
1242       if (my ($fail) = grep { @{[$_ =~ m/\./g]} == $dots }
1243                          keys %{$collapse}) {
1244         my ($last) = ($fail =~ /([^\.]+)$/);
1245         carp (
1246           "Prefetching multiple has_many rels ${last} and ${pre} "
1247           .(length($as_prefix)
1248             ? "at the same level (${as_prefix}) "
1249             : "at top level "
1250           )
1251           . 'will currently disrupt both the functionality of $rs->count(), '
1252           . 'and the amount of objects retrievable via $rs->next(). '
1253           . 'Use at your own risk.'
1254         );
1255       }
1256       #my @col = map { (/^self\.(.+)$/ ? ("${as_prefix}.$1") : ()); }
1257       #              values %{$rel_info->{cond}};
1258       $collapse->{".${as_prefix}${pre}"} = [ $rel_source->primary_columns ];
1259         # action at a distance. prepending the '.' allows simpler code
1260         # in ResultSet->_collapse_result
1261       my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); }
1262                     keys %{$rel_info->{cond}};
1263       my @ord = (ref($rel_info->{attrs}{order_by}) eq 'ARRAY'
1264                    ? @{$rel_info->{attrs}{order_by}}
1265                    : (defined $rel_info->{attrs}{order_by}
1266                        ? ($rel_info->{attrs}{order_by})
1267                        : ()));
1268       push(@$order, map { "${as}.$_" } (@key, @ord));
1269     }
1270
1271     return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] }
1272       $rel_source->columns;
1273     #warn $alias, Dumper (\@ret);
1274     #return @ret;
1275   }
1276 }
1277
1278 =head2 related_source
1279
1280 =over 4
1281
1282 =item Arguments: $relname
1283
1284 =item Return value: $source
1285
1286 =back
1287
1288 Returns the result source object for the given relationship.
1289
1290 =cut
1291
1292 sub related_source {
1293   my ($self, $rel) = @_;
1294   if( !$self->has_relationship( $rel ) ) {
1295     $self->throw_exception("No such relationship '$rel'");
1296   }
1297   return $self->schema->source($self->relationship_info($rel)->{source});
1298 }
1299
1300 =head2 related_class
1301
1302 =over 4
1303
1304 =item Arguments: $relname
1305
1306 =item Return value: $classname
1307
1308 =back
1309
1310 Returns the class name for objects in the given relationship.
1311
1312 =cut
1313
1314 sub related_class {
1315   my ($self, $rel) = @_;
1316   if( !$self->has_relationship( $rel ) ) {
1317     $self->throw_exception("No such relationship '$rel'");
1318   }
1319   return $self->schema->class($self->relationship_info($rel)->{source});
1320 }
1321
1322 =head2 handle
1323
1324 Obtain a new handle to this source. Returns an instance of a 
1325 L<DBIx::Class::ResultSourceHandle>.
1326
1327 =cut
1328
1329 sub handle {
1330     return new DBIx::Class::ResultSourceHandle({
1331         schema         => $_[0]->schema,
1332         source_moniker => $_[0]->source_name
1333     });
1334 }
1335
1336 =head2 throw_exception
1337
1338 See L<DBIx::Class::Schema/"throw_exception">.
1339
1340 =cut
1341
1342 sub throw_exception {
1343   my $self = shift;
1344   if (defined $self->schema) {
1345     $self->schema->throw_exception(@_);
1346   } else {
1347     croak(@_);
1348   }
1349 }
1350
1351 =head2 source_info
1352
1353 Stores a hashref of per-source metadata.  No specific key names
1354 have yet been standardized, the examples below are purely hypothetical
1355 and don't actually accomplish anything on their own:
1356
1357   __PACKAGE__->source_info({
1358     "_tablespace" => 'fast_disk_array_3',
1359     "_engine" => 'InnoDB',
1360   });
1361
1362 =head2 new
1363
1364   $class->new();
1365
1366   $class->new({attribute_name => value});
1367
1368 Creates a new ResultSource object.  Not normally called directly by end users.
1369
1370 =cut
1371
1372 =head2 column_info_from_storage
1373
1374 =over
1375
1376 =item Arguments: 1/0 (default: 0)
1377
1378 =item Return value: 1/0
1379
1380 =back
1381
1382 Enables the on-demand automatic loading of the above column
1383 metadata from storage as neccesary.  This is *deprecated*, and
1384 should not be used.  It will be removed before 1.0.
1385
1386   __PACKAGE__->column_info_from_storage(1);
1387
1388 =cut
1389
1390 =head2 sqlt_deploy_hook
1391
1392 =over 4
1393
1394 =item Arguments: $source, $sqlt_table
1395
1396 =item Return value: undefined
1397
1398 =back
1399
1400 An optional sub which you can declare in your own Result class that will get 
1401 passed the L<SQL::Translator::Schema::Table> object when you deploy the schema
1402 via L</create_ddl_dir> or L</deploy>.
1403
1404 This is useful to make L<SQL::Translator> create non-unique indexes, or set
1405 table options such as C<Engine=INNODB>. For an example of what you can do with
1406 this, see
1407 L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To Your SQL>.
1408
1409 Note that sqlt_deploy_hook is called by 
1410 L<DBIx::Class::Schema/deployment_statements>, which in turn is called before
1411 L<DBIx::Class::Schema/deploy>. Therefore the hook can be used only to manipulate
1412 the L<SQL::Translator::Table> object before it is turned into SQL fed to the
1413 database. If you want to execute post-deploy statements which can not be generated
1414 by L<SQL::Translator>, the currently suggested method is to overload
1415 L<DBIx::Class::Storage/deploy> and use L<dbh_do|DBIx::Class::Storage::DBI/dbh_do>.
1416
1417 Starting from DBIC 0.08100 a simple hook is inherited by all result sources, which
1418 invokes the method or coderef specified in L</sqlt_deploy_callback>. You can still
1419 overload this method like in older DBIC versions without any compatibility issues.
1420
1421 =cut
1422
1423 sub sqlt_deploy_hook {
1424   my $self = shift;
1425   if ( my $hook = $self->sqlt_deploy_callback) {
1426     $self->$hook(@_);
1427   }
1428 }
1429
1430 =head2 sqlt_deploy_callback
1431
1432 An attribute which contains the callback to trigger on C<sqlt_deploy_hook>.
1433 Defaults to C<default_sqlt_deploy_hook>. Can be a code reference or the name
1434 of a method in a result class. You would change the default value in case you
1435 want to share a hook between several result sources, or if you want to use a
1436 result source without a declared result class.
1437
1438 =head2 default_sqlt_deploy_hook($table)
1439
1440 Delegates to a an optional C<sqlt_deploy_hook> method on the C<result_class>.
1441
1442 This will get passed the L<SQL::Translator::Schema::Table> object when you
1443 deploy the schema via L</create_ddl_dir> or L</deploy>.
1444
1445 For an example of what you can do with this, see 
1446 L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To Your SQL>.
1447
1448 =cut
1449
1450 sub default_sqlt_deploy_hook {
1451   my $self = shift;
1452
1453   my $class = $self->result_class;
1454
1455   if ($class and $class->can('sqlt_deploy_hook')) {
1456     $class->sqlt_deploy_hook(@_);
1457   }
1458 }
1459
1460
1461 =head1 AUTHORS
1462
1463 Matt S. Trout <mst@shadowcatsystems.co.uk>
1464
1465 =head1 LICENSE
1466
1467 You may distribute this code under the same terms as Perl itself.
1468
1469 =cut
1470
1471 1;