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