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