re-word options/code/pod to be less confusing wrt ResultSource vs source-definition...
[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;
701da8c4 7use Carp::Clan qw/^DBIx::Class/;
6da5894c 8use Storable;
9
9c992ba1 10use base qw/DBIx::Class/;
11__PACKAGE__->load_components(qw/AccessorGroup/);
12
aa1088bf 13__PACKAGE__->mk_group_accessors('simple' => qw/_ordered_columns
14 _columns _primaries _unique_constraints name resultset_attributes
e92b9177 15 schema from _relationships column_info_from_storage source_name/);
aa1088bf 16
17__PACKAGE__->mk_group_accessors('component_class' => qw/resultset_class
b0dd0e03 18 result_class/);
9c992ba1 19
75d07914 20=head1 NAME
9c992ba1 21
22DBIx::Class::ResultSource - Result source object
23
24=head1 SYNOPSIS
25
26=head1 DESCRIPTION
27
28A ResultSource is a component of a schema from which results can be directly
29retrieved, most usually a table (see L<DBIx::Class::ResultSource::Table>)
30
31=head1 METHODS
32
7eb4ecc8 33=pod
34
35=head2 new
36
37 $class->new();
38
39 $class->new({attribute_name => value});
40
41Creates a new ResultSource object. Not normally called directly by end users.
42
9c992ba1 43=cut
44
45sub new {
46 my ($class, $attrs) = @_;
47 $class = ref $class if ref $class;
1225fc4d 48 my $new = bless({ %{$attrs || {}}, _resultset => undef }, $class);
9c992ba1 49 $new->{resultset_class} ||= 'DBIx::Class::ResultSet';
5ac6a044 50 $new->{resultset_attributes} = { %{$new->{resultset_attributes} || {}} };
6da5894c 51 $new->{_ordered_columns} = [ @{$new->{_ordered_columns}||[]}];
52 $new->{_columns} = { %{$new->{_columns}||{}} };
53 $new->{_relationships} = { %{$new->{_relationships}||{}} };
9c992ba1 54 $new->{name} ||= "!!NAME NOT SET!!";
5afa2a15 55 $new->{_columns_info_loaded} ||= 0;
9c992ba1 56 return $new;
57}
58
988bf309 59=pod
60
5ac6a044 61=head2 add_columns
62
63 $table->add_columns(qw/col1 col2 col3/);
64
65 $table->add_columns('col1' => \%col1_info, 'col2' => \%col2_info, ...);
66
2053ab2a 67Adds columns to the result source. If supplied key => hashref pairs, uses
68the hashref as the column_info for that column. Repeated calls of this
69method will add more columns, not replace them.
5ac6a044 70
2053ab2a 71The contents of the column_info are not set in stone. The following
72keys are currently recognised/used by DBIx::Class:
988bf309 73
74=over 4
75
75d07914 76=item accessor
988bf309 77
78Use this to set the name of the accessor for this column. If unset,
79the name of the column will be used.
80
81=item data_type
82
2053ab2a 83This contains the column type. It is automatically filled by the
988bf309 84L<SQL::Translator::Producer::DBIx::Class::File> producer, and the
2053ab2a 85L<DBIx::Class::Schema::Loader> module. If you do not enter a
988bf309 86data_type, DBIx::Class will attempt to retrieve it from the
2053ab2a 87database for you, using L<DBI>'s column_info method. The values of this
988bf309 88key are typically upper-cased.
89
2053ab2a 90Currently there is no standard set of values for the data_type. Use
91whatever your database supports.
988bf309 92
93=item size
94
95The length of your column, if it is a column type that can have a size
75d07914 96restriction. This is currently not used by DBIx::Class.
988bf309 97
98=item is_nullable
99
2053ab2a 100Set this to a true value for a columns that is allowed to contain
101NULL values. This is currently not used by DBIx::Class.
988bf309 102
103=item is_auto_increment
104
2053ab2a 105Set this to a true value for a column whose value is somehow
106automatically set. This is used to determine which columns to empty
e666492c 107when cloning objects using C<copy>.
988bf309 108
109=item is_foreign_key
110
2053ab2a 111Set this to a true value for a column that contains a key from a
988bf309 112foreign table. This is currently not used by DBIx::Class.
113
114=item default_value
115
2053ab2a 116Set this to the default value which will be inserted into a column
117by the database. Can contain either a value or a function. This is
75d07914 118currently not used by DBIx::Class.
988bf309 119
120=item sequence
121
2053ab2a 122Set this on a primary key column to the name of the sequence used to
123generate a new key value. If not specified, L<DBIx::Class::PK::Auto>
124will attempt to retrieve the name of the sequence from the database
125automatically.
988bf309 126
127=back
128
5ac6a044 129=head2 add_column
130
131 $table->add_column('col' => \%info?);
132
2053ab2a 133Convenience alias to add_columns.
5ac6a044 134
135=cut
136
9c992ba1 137sub add_columns {
138 my ($self, @cols) = @_;
8e04bf91 139 $self->_ordered_columns(\@cols) unless $self->_ordered_columns;
002a359a 140
20518cb4 141 my @added;
142 my $columns = $self->_columns;
9c992ba1 143 while (my $col = shift @cols) {
8e04bf91 144 # If next entry is { ... } use that for the column info, if not
145 # use an empty hashref
30126ac7 146 my $column_info = ref $cols[0] ? shift(@cols) : {};
20518cb4 147 push(@added, $col) unless exists $columns->{$col};
20518cb4 148 $columns->{$col} = $column_info;
9c992ba1 149 }
20518cb4 150 push @{ $self->_ordered_columns }, @added;
30126ac7 151 return $self;
9c992ba1 152}
153
154*add_column = \&add_columns;
155
3842b955 156=head2 has_column
157
988bf309 158 if ($obj->has_column($col)) { ... }
159
2053ab2a 160Returns true if the source has a column of this name, false otherwise.
988bf309 161
162=cut
9c992ba1 163
164sub has_column {
165 my ($self, $column) = @_;
166 return exists $self->_columns->{$column};
167}
168
87c4e602 169=head2 column_info
9c992ba1 170
988bf309 171 my $info = $obj->column_info($col);
9c992ba1 172
988bf309 173Returns the column metadata hashref for a column. See the description
174of add_column for information on the contents of the hashref.
9c992ba1 175
988bf309 176=cut
9c992ba1 177
178sub column_info {
179 my ($self, $column) = @_;
75d07914 180 $self->throw_exception("No such column $column")
701da8c4 181 unless exists $self->_columns->{$column};
5afa2a15 182 #warn $self->{_columns_info_loaded}, "\n";
75d07914 183 if ( ! $self->_columns->{$column}{data_type}
6eda9bcf 184 and $self->column_info_from_storage
75d07914 185 and ! $self->{_columns_info_loaded}
8e04bf91 186 and $self->schema and $self->storage )
187 {
188 $self->{_columns_info_loaded}++;
189 my $info;
0b88a5bb 190 my $lc_info;
75d07914 191 # eval for the case of storage without table
955f1590 192 eval { $info = $self->storage->columns_info_for( $self->from ) };
8e04bf91 193 unless ($@) {
0b88a5bb 194 for my $realcol ( keys %{$info} ) {
195 $lc_info->{lc $realcol} = $info->{$realcol};
196 }
8e04bf91 197 foreach my $col ( keys %{$self->_columns} ) {
416e92f7 198 $self->_columns->{$col} = { %{ $self->_columns->{$col}}, %{$info->{$col} || $lc_info->{lc $col}} };
a953d8d9 199 }
8e04bf91 200 }
a953d8d9 201 }
9c992ba1 202 return $self->_columns->{$column};
203}
204
6eda9bcf 205=head2 load_column_info_from_storage
206
207Enables the on-demand automatic loading of the above column
208metadata from storage as neccesary.
209
210=cut
211
212sub load_column_info_from_storage { shift->column_info_from_storage(1) }
213
9c992ba1 214=head2 columns
215
20518cb4 216 my @column_names = $obj->columns;
217
2053ab2a 218Returns all column names in the order they were declared to add_columns.
87f0da6a 219
220=cut
9c992ba1 221
222sub columns {
8e04bf91 223 my $self = shift;
aa1088bf 224 $self->throw_exception(
225 "columns() is a read-only accessor, did you mean add_columns()?"
226 ) if (@_ > 1);
701da8c4 227 return @{$self->{_ordered_columns}||[]};
571dced3 228}
229
002a359a 230=head2 remove_columns
231
232 $table->remove_columns(qw/col1 col2 col3/);
233
234Removes columns from the result source.
235
236=head2 remove_column
237
238 $table->remove_column('col');
239
240Convenience alias to remove_columns.
241
242=cut
243
244sub remove_columns {
245 my ($self, @cols) = @_;
246
247 return unless $self->_ordered_columns;
248
249 my $columns = $self->_columns;
250 my @remaining;
251
252 foreach my $col (@{$self->_ordered_columns}) {
253 push @remaining, $col unless grep(/$col/, @cols);
254 }
255
256 foreach (@cols) {
257 undef $columns->{$_};
258 };
259
260 $self->_ordered_columns(\@remaining);
261}
262
263*remove_column = \&remove_columns;
264
87c4e602 265=head2 set_primary_key
266
27f01d1f 267=over 4
268
ebc77b53 269=item Arguments: @cols
27f01d1f 270
271=back
87f0da6a 272
9c992ba1 273Defines one or more columns as primary key for this source. Should be
274called after C<add_columns>.
87f0da6a 275
276Additionally, defines a unique constraint named C<primary>.
277
988bf309 278The primary key columns are used by L<DBIx::Class::PK::Auto> to
75d07914 279retrieve automatically created values from the database.
988bf309 280
87f0da6a 281=cut
9c992ba1 282
283sub set_primary_key {
284 my ($self, @cols) = @_;
285 # check if primary key columns are valid columns
8e04bf91 286 foreach my $col (@cols) {
287 $self->throw_exception("No such column $col on table " . $self->name)
288 unless $self->has_column($col);
9c992ba1 289 }
290 $self->_primaries(\@cols);
87f0da6a 291
292 $self->add_unique_constraint(primary => \@cols);
9c992ba1 293}
294
87f0da6a 295=head2 primary_columns
296
9c992ba1 297Read-only accessor which returns the list of primary keys.
30126ac7 298
87f0da6a 299=cut
9c992ba1 300
301sub primary_columns {
302 return @{shift->_primaries||[]};
303}
304
87f0da6a 305=head2 add_unique_constraint
306
307Declare a unique constraint on this source. Call once for each unique
58b5bb8c 308constraint.
27f01d1f 309
310 # For UNIQUE (column1, column2)
311 __PACKAGE__->add_unique_constraint(
312 constraint_name => [ qw/column1 column2/ ],
313 );
87f0da6a 314
368a5228 315Alternatively, you can specify only the columns:
316
317 __PACKAGE__->add_unique_constraint([ qw/column1 column2/ ]);
318
319This will result in a unique constraint named C<table_column1_column2>, where
320C<table> is replaced with the table name.
321
58b5bb8c 322Unique constraints are used, for example, when you call
323L<DBIx::Class::ResultSet/find>. Only columns in the constraint are searched.
324
87f0da6a 325=cut
326
327sub add_unique_constraint {
368a5228 328 my $self = shift;
329 my $cols = pop @_;
330 my $name = shift;
331
332 $name ||= $self->name_unique_constraint($cols);
87f0da6a 333
8e04bf91 334 foreach my $col (@$cols) {
335 $self->throw_exception("No such column $col on table " . $self->name)
336 unless $self->has_column($col);
87f0da6a 337 }
338
339 my %unique_constraints = $self->unique_constraints;
340 $unique_constraints{$name} = $cols;
341 $self->_unique_constraints(\%unique_constraints);
342}
343
d9c74322 344=head2 name_unique_constraint
368a5228 345
346Return a name for a unique constraint containing the specified columns. These
347names consist of the table name and each column name, separated by underscores.
348
349For example, a constraint on a table named C<cd> containing the columns
350C<artist> and C<title> would result in a constraint name of C<cd_artist_title>.
351
352=cut
353
354sub name_unique_constraint {
355 my ($self, $cols) = @_;
356
357 return join '_', $self->name, @$cols;
358}
359
87f0da6a 360=head2 unique_constraints
361
362Read-only accessor which returns the list of unique constraints on this source.
363
364=cut
365
366sub unique_constraints {
367 return %{shift->_unique_constraints||{}};
368}
369
e6a0e17c 370=head2 unique_constraint_names
371
372Returns the list of unique constraint names defined on this source.
373
374=cut
375
376sub unique_constraint_names {
377 my ($self) = @_;
378
379 my %unique_constraints = $self->unique_constraints;
380
381 return keys %unique_constraints;
382}
383
384=head2 unique_constraint_columns
385
386Returns the list of columns that make up the specified unique constraint.
387
388=cut
389
390sub unique_constraint_columns {
391 my ($self, $constraint_name) = @_;
392
393 my %unique_constraints = $self->unique_constraints;
394
395 $self->throw_exception(
396 "Unknown unique constraint $constraint_name on '" . $self->name . "'"
397 ) unless exists $unique_constraints{$constraint_name};
398
399 return @{ $unique_constraints{$constraint_name} };
400}
401
9c992ba1 402=head2 from
403
404Returns an expression of the source to be supplied to storage to specify
2053ab2a 405retrieval from this source. In the case of a database, the required FROM
406clause contents.
9c992ba1 407
f9b7bd6e 408=head2 schema
409
410Returns the L<DBIx::Class::Schema> object that this result source
411belongs too.
9c992ba1 412
413=head2 storage
414
75d07914 415Returns the storage handle for the current schema.
988bf309 416
417See also: L<DBIx::Class::Storage>
9c992ba1 418
419=cut
420
421sub storage { shift->schema->storage; }
422
8452e496 423=head2 add_relationship
424
425 $source->add_relationship('relname', 'related_source', $cond, $attrs);
426
24d67825 427The relationship name can be arbitrary, but must be unique for each
428relationship attached to this result source. 'related_source' should
429be the name with which the related result source was registered with
430the current schema. For example:
8452e496 431
24d67825 432 $schema->source('Book')->add_relationship('reviews', 'Review', {
433 'foreign.book_id' => 'self.id',
434 });
435
2053ab2a 436The condition C<$cond> needs to be an L<SQL::Abstract>-style
24d67825 437representation of the join between the tables. For example, if you're
438creating a rel from Author to Book,
988bf309 439
440 { 'foreign.author_id' => 'self.id' }
441
442will result in the JOIN clause
443
444 author me JOIN book foreign ON foreign.author_id = me.id
445
8452e496 446You can specify as many foreign => self mappings as necessary.
447
988bf309 448Valid attributes are as follows:
449
450=over 4
451
452=item join_type
453
454Explicitly specifies the type of join to use in the relationship. Any
455SQL join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in
456the SQL command immediately before C<JOIN>.
457
458=item proxy
459
24d67825 460An arrayref containing a list of accessors in the foreign class to proxy in
461the main class. If, for example, you do the following:
002a359a 462
24d67825 463 CD->might_have(liner_notes => 'LinerNotes', undef, {
464 proxy => [ qw/notes/ ],
465 });
002a359a 466
24d67825 467Then, assuming LinerNotes has an accessor named notes, you can do:
988bf309 468
24d67825 469 my $cd = CD->find(1);
2053ab2a 470 # set notes -- LinerNotes object is created if it doesn't exist
471 $cd->notes('Notes go here');
988bf309 472
473=item accessor
474
475Specifies the type of accessor that should be created for the
75d07914 476relationship. Valid values are C<single> (for when there is only a single
477related object), C<multi> (when there can be many), and C<filter> (for
478when there is a single related object, but you also want the relationship
479accessor to double as a column accessor). For C<multi> accessors, an
480add_to_* method is also created, which calls C<create_related> for the
988bf309 481relationship.
482
8452e496 483=back
484
485=cut
486
487sub add_relationship {
488 my ($self, $rel, $f_source_name, $cond, $attrs) = @_;
27f01d1f 489 $self->throw_exception("Can't create relationship without join condition")
490 unless $cond;
8452e496 491 $attrs ||= {};
87772e46 492
8452e496 493 my %rels = %{ $self->_relationships };
494 $rels{$rel} = { class => $f_source_name,
87772e46 495 source => $f_source_name,
8452e496 496 cond => $cond,
497 attrs => $attrs };
498 $self->_relationships(\%rels);
499
30126ac7 500 return $self;
87772e46 501
953a18ef 502 # XXX disabled. doesn't work properly currently. skip in tests.
503
8452e496 504 my $f_source = $self->schema->source($f_source_name);
505 unless ($f_source) {
c037c03a 506 $self->ensure_class_loaded($f_source_name);
8452e496 507 $f_source = $f_source_name->result_source;
87772e46 508 #my $s_class = ref($self->schema);
509 #$f_source_name =~ m/^${s_class}::(.*)$/;
510 #$self->schema->register_class(($1 || $f_source_name), $f_source_name);
511 #$f_source = $self->schema->source($f_source_name);
8452e496 512 }
513 return unless $f_source; # Can't test rel without f_source
514
515 eval { $self->resolve_join($rel, 'me') };
516
517 if ($@) { # If the resolve failed, back out and re-throw the error
75d07914 518 delete $rels{$rel}; #
8452e496 519 $self->_relationships(\%rels);
701da8c4 520 $self->throw_exception("Error creating relationship $rel: $@");
8452e496 521 }
522 1;
523}
524
87c4e602 525=head2 relationships
8452e496 526
2053ab2a 527Returns all relationship names for this source.
8452e496 528
529=cut
530
531sub relationships {
532 return keys %{shift->_relationships};
533}
534
87c4e602 535=head2 relationship_info
536
27f01d1f 537=over 4
538
ebc77b53 539=item Arguments: $relname
27f01d1f 540
541=back
8452e496 542
2053ab2a 543Returns a hash of relationship information for the specified relationship
544name.
8452e496 545
546=cut
547
548sub relationship_info {
549 my ($self, $rel) = @_;
550 return $self->_relationships->{$rel};
75d07914 551}
8452e496 552
87c4e602 553=head2 has_relationship
554
27f01d1f 555=over 4
556
ebc77b53 557=item Arguments: $rel
27f01d1f 558
559=back
953a18ef 560
2053ab2a 561Returns true if the source has a relationship of this name, false otherwise.
988bf309 562
563=cut
953a18ef 564
565sub has_relationship {
566 my ($self, $rel) = @_;
567 return exists $self->_relationships->{$rel};
568}
569
de60a93d 570=head2 reverse_relationship_info
571
572=over 4
573
574=item Arguments: $relname
575
576=back
577
bab77431 578Returns an array of hash references of relationship information for
de60a93d 579the other side of the specified relationship name.
580
581=cut
582
583sub reverse_relationship_info {
584 my ($self, $rel) = @_;
585 my $rel_info = $self->relationship_info($rel);
586 my $ret = {};
587
588 return $ret unless ((ref $rel_info->{cond}) eq 'HASH');
589
590 my @cond = keys(%{$rel_info->{cond}});
591 my @refkeys = map {/^\w+\.(\w+)$/} @cond;
592 my @keys = map {$rel_info->{cond}->{$_} =~ /^\w+\.(\w+)$/} @cond;
bab77431 593
de60a93d 594 # Get the related result source for this relationship
595 my $othertable = $self->related_source($rel);
596
597 # Get all the relationships for that source that related to this source
598 # whose foreign column set are our self columns on $rel and whose self
bab77431 599 # columns are our foreign columns on $rel.
de60a93d 600 my @otherrels = $othertable->relationships();
601 my $otherrelationship;
602 foreach my $otherrel (@otherrels) {
603 my $otherrel_info = $othertable->relationship_info($otherrel);
604
605 my $back = $othertable->related_source($otherrel);
606 next unless $back->name eq $self->name;
607
608 my @othertestconds;
609
610 if (ref $otherrel_info->{cond} eq 'HASH') {
611 @othertestconds = ($otherrel_info->{cond});
612 }
613 elsif (ref $otherrel_info->{cond} eq 'ARRAY') {
614 @othertestconds = @{$otherrel_info->{cond}};
615 }
616 else {
617 next;
618 }
619
620 foreach my $othercond (@othertestconds) {
621 my @other_cond = keys(%$othercond);
622 my @other_refkeys = map {/^\w+\.(\w+)$/} @other_cond;
623 my @other_keys = map {$othercond->{$_} =~ /^\w+\.(\w+)$/} @other_cond;
bab77431 624 next if (!$self->compare_relationship_keys(\@refkeys, \@other_keys) ||
de60a93d 625 !$self->compare_relationship_keys(\@other_refkeys, \@keys));
626 $ret->{$otherrel} = $otherrel_info;
627 }
628 }
629 return $ret;
630}
631
632=head2 compare_relationship_keys
633
634=over 4
635
636=item Arguments: $keys1, $keys2
637
638=back
639
640Returns true if both sets of keynames are the same, false otherwise.
641
642=cut
643
644sub compare_relationship_keys {
645 my ($self, $keys1, $keys2) = @_;
646
647 # Make sure every keys1 is in keys2
648 my $found;
649 foreach my $key (@$keys1) {
650 $found = 0;
651 foreach my $prim (@$keys2) {
652 if ($prim eq $key) {
653 $found = 1;
654 last;
655 }
656 }
657 last unless $found;
658 }
659
660 # Make sure every key2 is in key1
661 if ($found) {
662 foreach my $prim (@$keys2) {
663 $found = 0;
664 foreach my $key (@$keys1) {
665 if ($prim eq $key) {
666 $found = 1;
667 last;
668 }
669 }
670 last unless $found;
671 }
672 }
673
674 return $found;
675}
676
87c4e602 677=head2 resolve_join
678
27f01d1f 679=over 4
680
ebc77b53 681=item Arguments: $relation
27f01d1f 682
683=back
8452e496 684
2053ab2a 685Returns the join structure required for the related result source.
8452e496 686
687=cut
688
689sub resolve_join {
489709af 690 my ($self, $join, $alias, $seen) = @_;
691 $seen ||= {};
87772e46 692 if (ref $join eq 'ARRAY') {
489709af 693 return map { $self->resolve_join($_, $alias, $seen) } @$join;
87772e46 694 } elsif (ref $join eq 'HASH') {
489709af 695 return
887ce227 696 map {
697 my $as = ($seen->{$_} ? $_.'_'.($seen->{$_}+1) : $_);
698 ($self->resolve_join($_, $alias, $seen),
699 $self->related_source($_)->resolve_join($join->{$_}, $as, $seen));
700 } keys %$join;
87772e46 701 } elsif (ref $join) {
701da8c4 702 $self->throw_exception("No idea how to resolve join reftype ".ref $join);
87772e46 703 } else {
489709af 704 my $count = ++$seen->{$join};
705 #use Data::Dumper; warn Dumper($seen);
706 my $as = ($count > 1 ? "${join}_${count}" : $join);
3842b955 707 my $rel_info = $self->relationship_info($join);
701da8c4 708 $self->throw_exception("No such relationship ${join}") unless $rel_info;
3842b955 709 my $type = $rel_info->{attrs}{join_type} || '';
489709af 710 return [ { $as => $self->related_source($join)->from,
953a18ef 711 -join_type => $type },
489709af 712 $self->resolve_condition($rel_info->{cond}, $as, $alias) ];
953a18ef 713 }
714}
715
87c4e602 716=head2 resolve_condition
717
27f01d1f 718=over 4
719
ebc77b53 720=item Arguments: $cond, $as, $alias|$object
27f01d1f 721
722=back
953a18ef 723
3842b955 724Resolves the passed condition to a concrete query fragment. If given an alias,
953a18ef 725returns a join condition; if given an object, inverts that object to produce
726a related conditional from that object.
727
728=cut
729
730sub resolve_condition {
489709af 731 my ($self, $cond, $as, $for) = @_;
953a18ef 732 #warn %$cond;
733 if (ref $cond eq 'HASH') {
734 my %ret;
bd054cb4 735 foreach my $k (keys %{$cond}) {
736 my $v = $cond->{$k};
953a18ef 737 # XXX should probably check these are valid columns
27f01d1f 738 $k =~ s/^foreign\.// ||
75d07914 739 $self->throw_exception("Invalid rel cond key ${k}");
27f01d1f 740 $v =~ s/^self\.// ||
75d07914 741 $self->throw_exception("Invalid rel cond val ${v}");
953a18ef 742 if (ref $for) { # Object
3842b955 743 #warn "$self $k $for $v";
744 $ret{$k} = $for->get_column($v);
745 #warn %ret;
2c037e6b 746 } elsif (!defined $for) { # undef, i.e. "no object"
747 $ret{$k} = undef;
fde6e28e 748 } elsif (ref $as) { # reverse object
749 $ret{$v} = $as->get_column($k);
2c037e6b 750 } elsif (!defined $as) { # undef, i.e. "no reverse object"
751 $ret{$v} = undef;
953a18ef 752 } else {
489709af 753 $ret{"${as}.${k}"} = "${for}.${v}";
953a18ef 754 }
953a18ef 755 }
756 return \%ret;
5efe4c79 757 } elsif (ref $cond eq 'ARRAY') {
489709af 758 return [ map { $self->resolve_condition($_, $as, $for) } @$cond ];
953a18ef 759 } else {
760 die("Can't handle this yet :(");
87772e46 761 }
762}
763
87c4e602 764=head2 resolve_prefetch
765
27f01d1f 766=over 4
767
ebc77b53 768=item Arguments: hashref/arrayref/scalar
27f01d1f 769
770=back
988bf309 771
b3e8ac9b 772Accepts one or more relationships for the current source and returns an
773array of column names for each of those relationships. Column names are
774prefixed relative to the current source, in accordance with where they appear
775in the supplied relationships. Examples:
776
5ac6a044 777 my $source = $schema->resultset('Tag')->source;
b3e8ac9b 778 @columns = $source->resolve_prefetch( { cd => 'artist' } );
779
780 # @columns =
781 #(
782 # 'cd.cdid',
783 # 'cd.artist',
784 # 'cd.title',
785 # 'cd.year',
786 # 'cd.artist.artistid',
787 # 'cd.artist.name'
788 #)
789
790 @columns = $source->resolve_prefetch( qw[/ cd /] );
791
792 # @columns =
793 #(
794 # 'cd.cdid',
795 # 'cd.artist',
796 # 'cd.title',
797 # 'cd.year'
798 #)
799
800 $source = $schema->resultset('CD')->source;
801 @columns = $source->resolve_prefetch( qw[/ artist producer /] );
802
803 # @columns =
804 #(
805 # 'artist.artistid',
806 # 'artist.name',
807 # 'producer.producerid',
808 # 'producer.name'
75d07914 809 #)
988bf309 810
b3e8ac9b 811=cut
812
813sub resolve_prefetch {
0f66a01b 814 my ($self, $pre, $alias, $seen, $order, $collapse) = @_;
489709af 815 $seen ||= {};
b3e8ac9b 816 #$alias ||= $self->name;
817 #warn $alias, Dumper $pre;
818 if( ref $pre eq 'ARRAY' ) {
0f66a01b 819 return
820 map { $self->resolve_prefetch( $_, $alias, $seen, $order, $collapse ) }
821 @$pre;
b3e8ac9b 822 }
823 elsif( ref $pre eq 'HASH' ) {
824 my @ret =
825 map {
0f66a01b 826 $self->resolve_prefetch($_, $alias, $seen, $order, $collapse),
489709af 827 $self->related_source($_)->resolve_prefetch(
0f66a01b 828 $pre->{$_}, "${alias}.$_", $seen, $order, $collapse)
829 } keys %$pre;
b3e8ac9b 830 #die Dumper \@ret;
831 return @ret;
832 }
833 elsif( ref $pre ) {
a86b1efe 834 $self->throw_exception(
835 "don't know how to resolve prefetch reftype ".ref($pre));
b3e8ac9b 836 }
837 else {
489709af 838 my $count = ++$seen->{$pre};
839 my $as = ($count > 1 ? "${pre}_${count}" : $pre);
b3e8ac9b 840 my $rel_info = $self->relationship_info( $pre );
a86b1efe 841 $self->throw_exception( $self->name . " has no such relationship '$pre'" )
842 unless $rel_info;
37f23589 843 my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : '');
a86b1efe 844 my $rel_source = $self->related_source($pre);
0f66a01b 845
846 if (exists $rel_info->{attrs}{accessor}
847 && $rel_info->{attrs}{accessor} eq 'multi') {
848 $self->throw_exception(
849 "Can't prefetch has_many ${pre} (join cond too complex)")
850 unless ref($rel_info->{cond}) eq 'HASH';
37f23589 851 my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); }
0f66a01b 852 keys %{$rel_info->{cond}};
853 $collapse->{"${as_prefix}${pre}"} = \@key;
5a5bec6c 854 my @ord = (ref($rel_info->{attrs}{order_by}) eq 'ARRAY'
855 ? @{$rel_info->{attrs}{order_by}}
856 : (defined $rel_info->{attrs}{order_by}
857 ? ($rel_info->{attrs}{order_by})
858 : ()));
859 push(@$order, map { "${as}.$_" } (@key, @ord));
0f66a01b 860 }
861
489709af 862 return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] }
a86b1efe 863 $rel_source->columns;
b3e8ac9b 864 #warn $alias, Dumper (\@ret);
489709af 865 #return @ret;
b3e8ac9b 866 }
867}
953a18ef 868
87c4e602 869=head2 related_source
870
27f01d1f 871=over 4
872
ebc77b53 873=item Arguments: $relname
27f01d1f 874
875=back
87772e46 876
2053ab2a 877Returns the result source object for the given relationship.
87772e46 878
879=cut
880
881sub related_source {
882 my ($self, $rel) = @_;
aea52c85 883 if( !$self->has_relationship( $rel ) ) {
701da8c4 884 $self->throw_exception("No such relationship '$rel'");
aea52c85 885 }
87772e46 886 return $self->schema->source($self->relationship_info($rel)->{source});
8452e496 887}
888
77254782 889=head2 related_class
890
27f01d1f 891=over 4
892
ebc77b53 893=item Arguments: $relname
27f01d1f 894
895=back
77254782 896
2053ab2a 897Returns the class name for objects in the given relationship.
77254782 898
899=cut
900
901sub related_class {
902 my ($self, $rel) = @_;
903 if( !$self->has_relationship( $rel ) ) {
904 $self->throw_exception("No such relationship '$rel'");
905 }
906 return $self->schema->class($self->relationship_info($rel)->{source});
907}
908
5ac6a044 909=head2 resultset
910
bcc5a210 911Returns a resultset for the given source. This will initially be created
912on demand by calling
5ac6a044 913
988bf309 914 $self->resultset_class->new($self, $self->resultset_attributes)
5ac6a044 915
bcc5a210 916but is cached from then on unless resultset_class changes.
917
5ac6a044 918=head2 resultset_class
919
988bf309 920Set the class of the resultset, this is useful if you want to create your
921own resultset methods. Create your own class derived from
922L<DBIx::Class::ResultSet>, and set it here.
5ac6a044 923
924=head2 resultset_attributes
925
988bf309 926Specify here any attributes you wish to pass to your specialised resultset.
5ac6a044 927
928=cut
929
930sub resultset {
931 my $self = shift;
27f01d1f 932 $self->throw_exception(
933 'resultset does not take any arguments. If you want another resultset, '.
934 'call it on the schema instead.'
935 ) if scalar @_;
428c2b82 936
937 # disabled until we can figure out a way to do it without consistency issues
938 #
939 #return $self->{_resultset}
940 # if ref $self->{_resultset} eq $self->resultset_class;
941 #return $self->{_resultset} =
942
943 return $self->resultset_class->new(
27f01d1f 944 $self, $self->{resultset_attributes}
945 );
5ac6a044 946}
947
bab77431 948=head2 source_name
949
950=over 4
951
952=item Arguments: $source_name
953
954=back
955
956Set the name of the result source when it is loaded into a schema.
957This is usefull if you want to refer to a result source by a name other than
958its class name.
959
960 package ArchivedBooks;
961 use base qw/DBIx::Class/;
962 __PACKAGE__->table('books_archive');
963 __PACKAGE__->source_name('Books');
964
965 # from your schema...
966 $schema->resultset('Books')->find(1);
967
701da8c4 968=head2 throw_exception
969
2053ab2a 970See L<DBIx::Class::Schema/"throw_exception">.
701da8c4 971
972=cut
973
974sub throw_exception {
975 my $self = shift;
75d07914 976 if (defined $self->schema) {
701da8c4 977 $self->schema->throw_exception(@_);
978 } else {
979 croak(@_);
980 }
981}
982
9c992ba1 983=head1 AUTHORS
984
985Matt S. Trout <mst@shadowcatsystems.co.uk>
986
987=head1 LICENSE
988
989You may distribute this code under the same terms as Perl itself.
990
991=cut
992