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