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