Storable sanification
[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 9
9c992ba1 10use base qw/DBIx::Class/;
9c992ba1 11
aa1088bf 12__PACKAGE__->mk_group_accessors('simple' => qw/_ordered_columns
13 _columns _primaries _unique_constraints name resultset_attributes
acbe81cf 14 schema from _relationships column_info_from_storage source_info
f89bb832 15 source_name sqlt_deploy_callback/);
aa1088bf 16
fac560c2 17__PACKAGE__->mk_group_accessors('component_class' => qw/resultset_class
b0dd0e03 18 result_class/);
9c992ba1 19
75d07914 20=head1 NAME
9c992ba1 21
22DBIx::Class::ResultSource - Result source object
23
24=head1 SYNOPSIS
25
16ccb4fe 26 # Create a table based result source, in a result class.
27
28 package MyDB::Schema::Result::Artist;
29 use base qw/DBIx::Class/;
30
31 __PACKAGE__->load_components(qw/Core/);
32 __PACKAGE__->table('artist');
33 __PACKAGE__->add_columns(qw/ artistid name /);
34 __PACKAGE__->set_primary_key('artistid');
35 __PACKAGE__->has_many(cds => 'MyDB::Schema::Result::CD');
36
37 1;
38
39 # Create a query (view) based result source, in a result class
40 package MyDB::Schema::Result::Year2000CDs;
41
16ccb4fe 42 __PACKAGE__->load_components('Core');
43 __PACKAGE__->table_class('DBIx::Class::ResultSource::View');
44
45 __PACKAGE__->table('year2000cds');
46 __PACKAGE__->result_source_instance->is_virtual(1);
47 __PACKAGE__->result_source_instance->view_definition(
48 "SELECT cdid, artist, title FROM cd WHERE year ='2000'"
49 );
50
51
9c992ba1 52=head1 DESCRIPTION
53
16ccb4fe 54A ResultSource is an object that represents a source of data for querying.
55
56This class is a base class for various specialised types of result
57sources, for example L<DBIx::Class::ResultSource::Table>. Table is the
58default result source type, so one is created for you when defining a
59result class as described in the synopsis above.
60
61More specifically, the L<DBIx::Class::Core> component pulls in the
62L<DBIx::Class::ResultSourceProxy::Table> as a base class, which
63defines the L<table|DBIx::Class::ResultSourceProxy::Table/table>
64method. When called, C<table> creates and stores an instance of
65L<DBIx::Class::ResultSoure::Table>. Luckily, to use tables as result
66sources, you don't need to remember any of this.
67
68Result sources representing select queries, or views, can also be
69created, see L<DBIx::Class::ResultSource::View> for full details.
70
71=head2 Finding result source objects
72
73As mentioned above, a result source instance is created and stored for
74you when you define a L<Result Class|DBIx::Class::Manual::Glossary/Result Class>.
75
76You can retrieve the result source at runtime in the following ways:
77
78=over
79
80=item From a Schema object:
81
82 $schema->source($source_name);
83
84=item From a Row object:
9c992ba1 85
16ccb4fe 86 $row->result_source;
87
88=item From a ResultSet object:
89
90 $rs->result_source;
91
92=back
00be2e0b 93
9c992ba1 94=head1 METHODS
95
7eb4ecc8 96=pod
97
9c992ba1 98=cut
99
100sub new {
101 my ($class, $attrs) = @_;
102 $class = ref $class if ref $class;
04786a4c 103
6b051e14 104 my $new = bless { %{$attrs || {}} }, $class;
9c992ba1 105 $new->{resultset_class} ||= 'DBIx::Class::ResultSet';
5ac6a044 106 $new->{resultset_attributes} = { %{$new->{resultset_attributes} || {}} };
6da5894c 107 $new->{_ordered_columns} = [ @{$new->{_ordered_columns}||[]}];
108 $new->{_columns} = { %{$new->{_columns}||{}} };
109 $new->{_relationships} = { %{$new->{_relationships}||{}} };
9c992ba1 110 $new->{name} ||= "!!NAME NOT SET!!";
5afa2a15 111 $new->{_columns_info_loaded} ||= 0;
f89bb832 112 $new->{sqlt_deploy_callback} ||= "default_sqlt_deploy_hook";
9c992ba1 113 return $new;
114}
115
988bf309 116=pod
117
5ac6a044 118=head2 add_columns
119
391ccf38 120=over
121
122=item Arguments: @columns
123
124=item Return value: The ResultSource object
125
126=back
127
843f6bc1 128 $source->add_columns(qw/col1 col2 col3/);
5ac6a044 129
843f6bc1 130 $source->add_columns('col1' => \%col1_info, 'col2' => \%col2_info, ...);
5ac6a044 131
16ccb4fe 132Adds columns to the result source. If supplied colname => hashref
133pairs, uses the hashref as the L</column_info> for that column. Repeated
134calls of this method will add more columns, not replace them.
5ac6a044 135
5d9d9e87 136The column names given will be created as accessor methods on your
7e51afbf 137L<DBIx::Class::Row> objects. You can change the name of the accessor
5d9d9e87 138by supplying an L</accessor> in the column_info hash.
139
2053ab2a 140The contents of the column_info are not set in stone. The following
141keys are currently recognised/used by DBIx::Class:
988bf309 142
143=over 4
144
75d07914 145=item accessor
988bf309 146
16ccb4fe 147 { accessor => '_name' }
148
149 # example use, replace standard accessor with one of your own:
150 sub name {
151 my ($self, $value) = @_;
152
153 die "Name cannot contain digits!" if($value =~ /\d/);
154 $self->_name($value);
155
156 return $self->_name();
157 }
158
5d9d9e87 159Use this to set the name of the accessor method for this column. If unset,
988bf309 160the name of the column will be used.
161
162=item data_type
163
16ccb4fe 164 { data_type => 'integer' }
165
166This contains the column type. It is automatically filled if you use the
167L<SQL::Translator::Producer::DBIx::Class::File> producer, or the
168L<DBIx::Class::Schema::Loader> module.
988bf309 169
2053ab2a 170Currently there is no standard set of values for the data_type. Use
171whatever your database supports.
988bf309 172
173=item size
174
16ccb4fe 175 { size => 20 }
176
988bf309 177The length of your column, if it is a column type that can have a size
16ccb4fe 178restriction. This is currently only used to create tables from your
179schema, see L<DBIx::Class::Schema/deploy>.
988bf309 180
181=item is_nullable
182
16ccb4fe 183 { is_nullable => 1 }
184
185Set this to a true value for a columns that is allowed to contain NULL
186values, default is false. This is currently only used to create tables
187from your schema, see L<DBIx::Class::Schema/deploy>.
988bf309 188
189=item is_auto_increment
190
16ccb4fe 191 { is_auto_increment => 1 }
192
2053ab2a 193Set this to a true value for a column whose value is somehow
16ccb4fe 194automatically set, defaults to false. This is used to determine which
195columns to empty when cloning objects using
196L<DBIx::Class::Row/copy>. It is also used by
d7be2784 197L<DBIx::Class::Schema/deploy>.
988bf309 198
26a29815 199=item is_numeric
200
16ccb4fe 201 { is_numeric => 1 }
202
26a29815 203Set this to a true or false value (not C<undef>) to explicitly specify
204if this column contains numeric data. This controls how set_column
205decides whether to consider a column dirty after an update: if
0bad1823 206C<is_numeric> is true a numeric comparison C<< != >> will take place
26a29815 207instead of the usual C<eq>
208
209If not specified the storage class will attempt to figure this out on
210first access to the column, based on the column C<data_type>. The
211result will be cached in this attribute.
212
988bf309 213=item is_foreign_key
214
16ccb4fe 215 { is_foreign_key => 1 }
216
2053ab2a 217Set this to a true value for a column that contains a key from a
16ccb4fe 218foreign table, defaults to false. This is currently only used to
219create tables from your schema, see L<DBIx::Class::Schema/deploy>.
988bf309 220
221=item default_value
222
16ccb4fe 223 { default_value => \'now()' }
224
225Set this to the default value which will be inserted into a column by
226the database. Can contain either a value or a function (use a
4858fea7 227reference to a scalar e.g. C<\'now()'> if you want a function). This
16ccb4fe 228is currently only used to create tables from your schema, see
229L<DBIx::Class::Schema/deploy>.
988bf309 230
a4fcda00 231See the note on L<DBIx::Class::Row/new> for more information about possible
232issues related to db-side default values.
233
988bf309 234=item sequence
235
16ccb4fe 236 { sequence => 'my_table_seq' }
237
2053ab2a 238Set this on a primary key column to the name of the sequence used to
239generate a new key value. If not specified, L<DBIx::Class::PK::Auto>
240will attempt to retrieve the name of the sequence from the database
241automatically.
988bf309 242
838ef78d 243=item auto_nextval
244
ca791b95 245Set this to a true value for a column whose value is retrieved automatically
246from a sequence or function (if supported by your Storage driver.) For a
247sequence, if you do not use a trigger to get the nextval, you have to set the
248L</sequence> value as well.
249
250Also set this for MSSQL columns with the 'uniqueidentifier'
251L<DBIx::Class::ResultSource/data_type> whose values you want to automatically
252generate using C<NEWID()>, unless they are a primary key in which case this will
253be done anyway.
838ef78d 254
190615a7 255=item extra
d7be2784 256
257This is used by L<DBIx::Class::Schema/deploy> and L<SQL::Translator>
190615a7 258to add extra non-generic data to the column. For example: C<< extra
d7be2784 259=> { unsigned => 1} >> is used by the MySQL producer to set an integer
260column to unsigned. For more details, see
261L<SQL::Translator::Producer::MySQL>.
262
988bf309 263=back
264
5ac6a044 265=head2 add_column
266
391ccf38 267=over
268
16ccb4fe 269=item Arguments: $colname, \%columninfo?
391ccf38 270
271=item Return value: 1/0 (true/false)
272
273=back
274
16ccb4fe 275 $source->add_column('col' => \%info);
5ac6a044 276
391ccf38 277Add a single column and optional column info. Uses the same column
278info keys as L</add_columns>.
5ac6a044 279
280=cut
281
9c992ba1 282sub add_columns {
283 my ($self, @cols) = @_;
8e04bf91 284 $self->_ordered_columns(\@cols) unless $self->_ordered_columns;
002a359a 285
20518cb4 286 my @added;
287 my $columns = $self->_columns;
9c992ba1 288 while (my $col = shift @cols) {
8e04bf91 289 # If next entry is { ... } use that for the column info, if not
290 # use an empty hashref
30126ac7 291 my $column_info = ref $cols[0] ? shift(@cols) : {};
20518cb4 292 push(@added, $col) unless exists $columns->{$col};
20518cb4 293 $columns->{$col} = $column_info;
9c992ba1 294 }
20518cb4 295 push @{ $self->_ordered_columns }, @added;
30126ac7 296 return $self;
9c992ba1 297}
298
b25e9fa0 299sub add_column { shift->add_columns(@_); } # DO NOT CHANGE THIS TO GLOB
9c992ba1 300
3842b955 301=head2 has_column
302
391ccf38 303=over
304
305=item Arguments: $colname
306
307=item Return value: 1/0 (true/false)
308
309=back
310
843f6bc1 311 if ($source->has_column($colname)) { ... }
988bf309 312
2053ab2a 313Returns true if the source has a column of this name, false otherwise.
988bf309 314
315=cut
9c992ba1 316
317sub has_column {
318 my ($self, $column) = @_;
319 return exists $self->_columns->{$column};
320}
321
87c4e602 322=head2 column_info
9c992ba1 323
391ccf38 324=over
325
326=item Arguments: $colname
327
328=item Return value: Hashref of info
329
330=back
331
843f6bc1 332 my $info = $source->column_info($col);
9c992ba1 333
391ccf38 334Returns the column metadata hashref for a column, as originally passed
16ccb4fe 335to L</add_columns>. See L</add_columns> above for information on the
336contents of the hashref.
9c992ba1 337
988bf309 338=cut
9c992ba1 339
340sub column_info {
341 my ($self, $column) = @_;
75d07914 342 $self->throw_exception("No such column $column")
701da8c4 343 unless exists $self->_columns->{$column};
5afa2a15 344 #warn $self->{_columns_info_loaded}, "\n";
75d07914 345 if ( ! $self->_columns->{$column}{data_type}
6eda9bcf 346 and $self->column_info_from_storage
75d07914 347 and ! $self->{_columns_info_loaded}
8e04bf91 348 and $self->schema and $self->storage )
349 {
350 $self->{_columns_info_loaded}++;
d51f93c8 351 my $info = {};
352 my $lc_info = {};
75d07914 353 # eval for the case of storage without table
955f1590 354 eval { $info = $self->storage->columns_info_for( $self->from ) };
8e04bf91 355 unless ($@) {
0b88a5bb 356 for my $realcol ( keys %{$info} ) {
357 $lc_info->{lc $realcol} = $info->{$realcol};
358 }
8e04bf91 359 foreach my $col ( keys %{$self->_columns} ) {
d51f93c8 360 $self->_columns->{$col} = {
361 %{ $self->_columns->{$col} },
362 %{ $info->{$col} || $lc_info->{lc $col} || {} }
363 };
a953d8d9 364 }
8e04bf91 365 }
a953d8d9 366 }
9c992ba1 367 return $self->_columns->{$column};
368}
369
370=head2 columns
371
391ccf38 372=over
373
374=item Arguments: None
375
376=item Return value: Ordered list of column names
377
378=back
379
380 my @column_names = $source->columns;
20518cb4 381
391ccf38 382Returns all column names in the order they were declared to L</add_columns>.
87f0da6a 383
384=cut
9c992ba1 385
386sub columns {
8e04bf91 387 my $self = shift;
aa1088bf 388 $self->throw_exception(
389 "columns() is a read-only accessor, did you mean add_columns()?"
390 ) if (@_ > 1);
701da8c4 391 return @{$self->{_ordered_columns}||[]};
571dced3 392}
393
002a359a 394=head2 remove_columns
395
391ccf38 396=over
002a359a 397
391ccf38 398=item Arguments: @colnames
399
400=item Return value: undefined
401
402=back
403
404 $source->remove_columns(qw/col1 col2 col3/);
405
406Removes the given list of columns by name, from the result source.
407
408B<Warning>: Removing a column that is also used in the sources primary
409key, or in one of the sources unique constraints, B<will> result in a
410broken result source.
002a359a 411
412=head2 remove_column
413
391ccf38 414=over
415
416=item Arguments: $colname
417
418=item Return value: undefined
419
420=back
002a359a 421
391ccf38 422 $source->remove_column('col');
423
424Remove a single column by name from the result source, similar to
425L</remove_columns>.
426
427B<Warning>: Removing a column that is also used in the sources primary
428key, or in one of the sources unique constraints, B<will> result in a
429broken result source.
002a359a 430
431=cut
432
433sub remove_columns {
4738027b 434 my ($self, @to_remove) = @_;
002a359a 435
4738027b 436 my $columns = $self->_columns
437 or return;
002a359a 438
4738027b 439 my %to_remove;
440 for (@to_remove) {
a918d901 441 delete $columns->{$_};
4738027b 442 ++$to_remove{$_};
443 }
002a359a 444
4738027b 445 $self->_ordered_columns([ grep { not $to_remove{$_} } @{$self->_ordered_columns} ]);
002a359a 446}
447
b25e9fa0 448sub remove_column { shift->remove_columns(@_); } # DO NOT CHANGE THIS TO GLOB
002a359a 449
87c4e602 450=head2 set_primary_key
451
27f01d1f 452=over 4
453
ebc77b53 454=item Arguments: @cols
27f01d1f 455
391ccf38 456=item Return value: undefined
457
27f01d1f 458=back
87f0da6a 459
16ccb4fe 460Defines one or more columns as primary key for this source. Must be
391ccf38 461called after L</add_columns>.
87f0da6a 462
391ccf38 463Additionally, defines a L<unique constraint|add_unique_constraint>
464named C<primary>.
87f0da6a 465
988bf309 466The primary key columns are used by L<DBIx::Class::PK::Auto> to
16ccb4fe 467retrieve automatically created values from the database. They are also
468used as default joining columns when specifying relationships, see
469L<DBIx::Class::Relationship>.
988bf309 470
87f0da6a 471=cut
9c992ba1 472
473sub set_primary_key {
474 my ($self, @cols) = @_;
475 # check if primary key columns are valid columns
8e04bf91 476 foreach my $col (@cols) {
477 $self->throw_exception("No such column $col on table " . $self->name)
478 unless $self->has_column($col);
9c992ba1 479 }
480 $self->_primaries(\@cols);
87f0da6a 481
482 $self->add_unique_constraint(primary => \@cols);
9c992ba1 483}
484
87f0da6a 485=head2 primary_columns
486
391ccf38 487=over 4
488
489=item Arguments: None
490
491=item Return value: Ordered list of primary column names
492
493=back
494
495Read-only accessor which returns the list of primary keys, supplied by
496L</set_primary_key>.
30126ac7 497
87f0da6a 498=cut
9c992ba1 499
500sub primary_columns {
501 return @{shift->_primaries||[]};
502}
503
87f0da6a 504=head2 add_unique_constraint
505
391ccf38 506=over 4
507
16ccb4fe 508=item Arguments: $name?, \@colnames
391ccf38 509
510=item Return value: undefined
511
512=back
513
87f0da6a 514Declare a unique constraint on this source. Call once for each unique
58b5bb8c 515constraint.
27f01d1f 516
517 # For UNIQUE (column1, column2)
518 __PACKAGE__->add_unique_constraint(
519 constraint_name => [ qw/column1 column2/ ],
520 );
87f0da6a 521
368a5228 522Alternatively, you can specify only the columns:
523
524 __PACKAGE__->add_unique_constraint([ qw/column1 column2/ ]);
525
16ccb4fe 526This will result in a unique constraint named
527C<table_column1_column2>, where C<table> is replaced with the table
528name.
368a5228 529
16ccb4fe 530Unique constraints are used, for example, when you pass the constraint
531name as the C<key> attribute to L<DBIx::Class::ResultSet/find>. Then
532only columns in the constraint are searched.
58b5bb8c 533
391ccf38 534Throws an error if any of the given column names do not yet exist on
535the result source.
536
87f0da6a 537=cut
538
539sub add_unique_constraint {
368a5228 540 my $self = shift;
541 my $cols = pop @_;
542 my $name = shift;
543
544 $name ||= $self->name_unique_constraint($cols);
87f0da6a 545
8e04bf91 546 foreach my $col (@$cols) {
547 $self->throw_exception("No such column $col on table " . $self->name)
548 unless $self->has_column($col);
87f0da6a 549 }
550
551 my %unique_constraints = $self->unique_constraints;
552 $unique_constraints{$name} = $cols;
553 $self->_unique_constraints(\%unique_constraints);
554}
555
d9c74322 556=head2 name_unique_constraint
368a5228 557
391ccf38 558=over 4
559
560=item Arguments: @colnames
561
562=item Return value: Constraint name
563
564=back
565
566 $source->table('mytable');
567 $source->name_unique_constraint('col1', 'col2');
568 # returns
569 'mytable_col1_col2'
570
571Return a name for a unique constraint containing the specified
572columns. The name is created by joining the table name and each column
573name, using an underscore character.
368a5228 574
575For example, a constraint on a table named C<cd> containing the columns
576C<artist> and C<title> would result in a constraint name of C<cd_artist_title>.
577
391ccf38 578This is used by L</add_unique_constraint> if you do not specify the
579optional constraint name.
580
368a5228 581=cut
582
583sub name_unique_constraint {
584 my ($self, $cols) = @_;
585
3e6c1131 586 my $name = $self->name;
4678e9da 587 $name = $$name if (ref $name eq 'SCALAR');
3e6c1131 588
589 return join '_', $name, @$cols;
368a5228 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';
243ddc4a 1239 }
1240 else {
1241 $type = $rel_info->{attrs}{join_type};
1242 $force_left = 1 if lc($type||'') eq 'left';
24010dd8 1243 }
ba61fa2a 1244
1245 my $rel_src = $self->related_source($join);
1246 return [ { $as => $rel_src->from,
35ec0366 1247 -source_handle => $rel_src->handle,
1979278e 1248 -join_type => $type,
1249 -join_path => [@$jpath, $join],
ba61fa2a 1250 -alias => $as,
1979278e 1251 -relation_chain_depth => $seen->{-relation_chain_depth} || 0,
1252 },
6d0ee587 1253 $self->_resolve_condition($rel_info->{cond}, $as, $alias) ];
953a18ef 1254 }
1255}
1256
370f2ba2 1257sub pk_depends_on {
6d0ee587 1258 carp 'pk_depends_on is a private method, stop calling it';
1259 my $self = shift;
1260 $self->_pk_depends_on (@_);
1261}
1262
1263# Determines whether a relation is dependent on an object from this source
1264# having already been inserted. Takes the name of the relationship and a
1265# hashref of columns of the related object.
1266sub _pk_depends_on {
370f2ba2 1267 my ($self, $relname, $rel_data) = @_;
370f2ba2 1268
c39b48e5 1269 my $relinfo = $self->relationship_info($relname);
1270
1271 # don't assume things if the relationship direction is specified
1272 return $relinfo->{attrs}{is_foreign_key_constraint}
1273 if exists ($relinfo->{attrs}{is_foreign_key_constraint});
1274
1275 my $cond = $relinfo->{cond};
370f2ba2 1276 return 0 unless ref($cond) eq 'HASH';
1277
1278 # map { foreign.foo => 'self.bar' } to { bar => 'foo' }
370f2ba2 1279 my $keyhash = { map { my $x = $_; $x =~ s/.*\.//; $x; } reverse %$cond };
1280
1281 # assume anything that references our PK probably is dependent on us
1282 # rather than vice versa, unless the far side is (a) defined or (b)
1283 # auto-increment
370f2ba2 1284 my $rel_source = $self->related_source($relname);
1285
1286 foreach my $p ($self->primary_columns) {
1287 if (exists $keyhash->{$p}) {
1288 unless (defined($rel_data->{$keyhash->{$p}})
1289 || $rel_source->column_info($keyhash->{$p})
1290 ->{is_auto_increment}) {
1291 return 0;
1292 }
1293 }
1294 }
1295
1296 return 1;
1297}
1298
6d0ee587 1299sub resolve_condition {
1300 carp 'resolve_condition is a private method, stop calling it';
1301 my $self = shift;
1302 $self->_resolve_condition (@_);
1303}
953a18ef 1304
6d0ee587 1305# Resolves the passed condition to a concrete query fragment. If given an alias,
1306# returns a join condition; if given an object, inverts that object to produce
1307# a related conditional from that object.
8c368cf3 1308our $UNRESOLVABLE_CONDITION = \'1 = 0';
1309
6d0ee587 1310sub _resolve_condition {
489709af 1311 my ($self, $cond, $as, $for) = @_;
953a18ef 1312 if (ref $cond eq 'HASH') {
1313 my %ret;
bd054cb4 1314 foreach my $k (keys %{$cond}) {
1315 my $v = $cond->{$k};
953a18ef 1316 # XXX should probably check these are valid columns
27f01d1f 1317 $k =~ s/^foreign\.// ||
75d07914 1318 $self->throw_exception("Invalid rel cond key ${k}");
27f01d1f 1319 $v =~ s/^self\.// ||
75d07914 1320 $self->throw_exception("Invalid rel cond val ${v}");
953a18ef 1321 if (ref $for) { # Object
3842b955 1322 #warn "$self $k $for $v";
370f2ba2 1323 unless ($for->has_column_loaded($v)) {
1324 if ($for->in_storage) {
a4fcda00 1325 $self->throw_exception(
1326 "Column ${v} not loaded or not passed to new() prior to insert()"
1327 ." on ${for} trying to resolve relationship (maybe you forgot "
286fa9c5 1328 ."to call ->discard_changes to get defaults from the db)"
a4fcda00 1329 );
370f2ba2 1330 }
68f3b0dd 1331 return $UNRESOLVABLE_CONDITION;
370f2ba2 1332 }
1333 $ret{$k} = $for->get_column($v);
1334 #$ret{$k} = $for->get_column($v) if $for->has_column_loaded($v);
3842b955 1335 #warn %ret;
2c037e6b 1336 } elsif (!defined $for) { # undef, i.e. "no object"
1337 $ret{$k} = undef;
2ec8e594 1338 } elsif (ref $as eq 'HASH') { # reverse hashref
1339 $ret{$v} = $as->{$k};
fde6e28e 1340 } elsif (ref $as) { # reverse object
1341 $ret{$v} = $as->get_column($k);
2c037e6b 1342 } elsif (!defined $as) { # undef, i.e. "no reverse object"
1343 $ret{$v} = undef;
953a18ef 1344 } else {
489709af 1345 $ret{"${as}.${k}"} = "${for}.${v}";
953a18ef 1346 }
953a18ef 1347 }
1348 return \%ret;
5efe4c79 1349 } elsif (ref $cond eq 'ARRAY') {
6d0ee587 1350 return [ map { $self->_resolve_condition($_, $as, $for) } @$cond ];
953a18ef 1351 } else {
35c77aa3 1352 die("Can't handle condition $cond yet :(");
87772e46 1353 }
1354}
1355
3bb4eb8f 1356# Legacy code, needs to go entirely away (fully replaced by _resolve_prefetch)
6d0ee587 1357sub resolve_prefetch {
1358 carp 'resolve_prefetch is a private method, stop calling it';
3bb4eb8f 1359
1360 my ($self, $pre, $alias, $seen, $order, $collapse) = @_;
1361 $seen ||= {};
1362 if( ref $pre eq 'ARRAY' ) {
1363 return
1364 map { $self->resolve_prefetch( $_, $alias, $seen, $order, $collapse ) }
1365 @$pre;
1366 }
1367 elsif( ref $pre eq 'HASH' ) {
1368 my @ret =
1369 map {
1370 $self->resolve_prefetch($_, $alias, $seen, $order, $collapse),
1371 $self->related_source($_)->resolve_prefetch(
1372 $pre->{$_}, "${alias}.$_", $seen, $order, $collapse)
1373 } keys %$pre;
1374 return @ret;
1375 }
1376 elsif( ref $pre ) {
1377 $self->throw_exception(
1378 "don't know how to resolve prefetch reftype ".ref($pre));
1379 }
1380 else {
1381 my $count = ++$seen->{$pre};
1382 my $as = ($count > 1 ? "${pre}_${count}" : $pre);
1383 my $rel_info = $self->relationship_info( $pre );
1384 $self->throw_exception( $self->name . " has no such relationship '$pre'" )
1385 unless $rel_info;
1386 my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : '');
1387 my $rel_source = $self->related_source($pre);
1388
1389 if (exists $rel_info->{attrs}{accessor}
1390 && $rel_info->{attrs}{accessor} eq 'multi') {
1391 $self->throw_exception(
1392 "Can't prefetch has_many ${pre} (join cond too complex)")
1393 unless ref($rel_info->{cond}) eq 'HASH';
1394 my $dots = @{[$as_prefix =~ m/\./g]} + 1; # +1 to match the ".${as_prefix}"
1395 if (my ($fail) = grep { @{[$_ =~ m/\./g]} == $dots }
1396 keys %{$collapse}) {
1397 my ($last) = ($fail =~ /([^\.]+)$/);
1398 carp (
1399 "Prefetching multiple has_many rels ${last} and ${pre} "
1400 .(length($as_prefix)
1401 ? "at the same level (${as_prefix}) "
1402 : "at top level "
1403 )
2e251255 1404 . 'will explode the number of row objects retrievable via ->next or ->all. '
3bb4eb8f 1405 . 'Use at your own risk.'
1406 );
1407 }
1408 #my @col = map { (/^self\.(.+)$/ ? ("${as_prefix}.$1") : ()); }
1409 # values %{$rel_info->{cond}};
1410 $collapse->{".${as_prefix}${pre}"} = [ $rel_source->primary_columns ];
1411 # action at a distance. prepending the '.' allows simpler code
1412 # in ResultSet->_collapse_result
1413 my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); }
1414 keys %{$rel_info->{cond}};
1415 my @ord = (ref($rel_info->{attrs}{order_by}) eq 'ARRAY'
1416 ? @{$rel_info->{attrs}{order_by}}
1417 : (defined $rel_info->{attrs}{order_by}
1418 ? ($rel_info->{attrs}{order_by})
1419 : ()));
1420 push(@$order, map { "${as}.$_" } (@key, @ord));
1421 }
1422
1423 return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] }
1424 $rel_source->columns;
1425 }
6d0ee587 1426}
988bf309 1427
6d0ee587 1428# Accepts one or more relationships for the current source and returns an
1429# array of column names for each of those relationships. Column names are
1430# prefixed relative to the current source, in accordance with where they appear
1431# in the supplied relationships. Needs an alias_map generated by
1432# $rs->_joinpath_aliases
b3e8ac9b 1433
6d0ee587 1434sub _resolve_prefetch {
1979278e 1435 my ($self, $pre, $alias, $alias_map, $order, $collapse, $pref_path) = @_;
1436 $pref_path ||= [];
1437
b3e8ac9b 1438 if( ref $pre eq 'ARRAY' ) {
0f66a01b 1439 return
6d0ee587 1440 map { $self->_resolve_prefetch( $_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ) }
0f66a01b 1441 @$pre;
b3e8ac9b 1442 }
1443 elsif( ref $pre eq 'HASH' ) {
1444 my @ret =
1445 map {
6d0ee587 1446 $self->_resolve_prefetch($_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ),
1447 $self->related_source($_)->_resolve_prefetch(
1979278e 1448 $pre->{$_}, "${alias}.$_", $alias_map, $order, $collapse, [ @$pref_path, $_] )
0f66a01b 1449 } keys %$pre;
b3e8ac9b 1450 return @ret;
1451 }
1452 elsif( ref $pre ) {
a86b1efe 1453 $self->throw_exception(
1454 "don't know how to resolve prefetch reftype ".ref($pre));
b3e8ac9b 1455 }
1456 else {
1979278e 1457 my $p = $alias_map;
1458 $p = $p->{$_} for (@$pref_path, $pre);
1459
1460 $self->throw_exception (
88a66388 1461 "Unable to resolve prefetch $pre - join alias map does not contain an entry for path: "
1979278e 1462 . join (' -> ', @$pref_path, $pre)
1463 ) if (ref $p->{-join_aliases} ne 'ARRAY' or not @{$p->{-join_aliases}} );
88a66388 1464
1979278e 1465 my $as = shift @{$p->{-join_aliases}};
1466
b3e8ac9b 1467 my $rel_info = $self->relationship_info( $pre );
a86b1efe 1468 $self->throw_exception( $self->name . " has no such relationship '$pre'" )
1469 unless $rel_info;
37f23589 1470 my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : '');
a86b1efe 1471 my $rel_source = $self->related_source($pre);
0f66a01b 1472
1473 if (exists $rel_info->{attrs}{accessor}
1474 && $rel_info->{attrs}{accessor} eq 'multi') {
1475 $self->throw_exception(
1476 "Can't prefetch has_many ${pre} (join cond too complex)")
1477 unless ref($rel_info->{cond}) eq 'HASH';
cb136e67 1478 my $dots = @{[$as_prefix =~ m/\./g]} + 1; # +1 to match the ".${as_prefix}"
1479 if (my ($fail) = grep { @{[$_ =~ m/\./g]} == $dots }
1480 keys %{$collapse}) {
1481 my ($last) = ($fail =~ /([^\.]+)$/);
616b461d 1482 carp (
1483 "Prefetching multiple has_many rels ${last} and ${pre} "
1484 .(length($as_prefix)
1485 ? "at the same level (${as_prefix}) "
1486 : "at top level "
1487 )
2e251255 1488 . 'will explode the number of row objects retrievable via ->next or ->all. '
616b461d 1489 . 'Use at your own risk.'
1490 );
cb136e67 1491 }
b25e9fa0 1492 #my @col = map { (/^self\.(.+)$/ ? ("${as_prefix}.$1") : ()); }
1493 # values %{$rel_info->{cond}};
1494 $collapse->{".${as_prefix}${pre}"} = [ $rel_source->primary_columns ];
1495 # action at a distance. prepending the '.' allows simpler code
1496 # in ResultSet->_collapse_result
37f23589 1497 my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); }
0f66a01b 1498 keys %{$rel_info->{cond}};
5a5bec6c 1499 my @ord = (ref($rel_info->{attrs}{order_by}) eq 'ARRAY'
1500 ? @{$rel_info->{attrs}{order_by}}
1501 : (defined $rel_info->{attrs}{order_by}
1502 ? ($rel_info->{attrs}{order_by})
1503 : ()));
1504 push(@$order, map { "${as}.$_" } (@key, @ord));
0f66a01b 1505 }
1506
489709af 1507 return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] }
a86b1efe 1508 $rel_source->columns;
b3e8ac9b 1509 }
1510}
953a18ef 1511
87c4e602 1512=head2 related_source
1513
27f01d1f 1514=over 4
1515
ebc77b53 1516=item Arguments: $relname
27f01d1f 1517
391ccf38 1518=item Return value: $source
1519
27f01d1f 1520=back
87772e46 1521
2053ab2a 1522Returns the result source object for the given relationship.
87772e46 1523
1524=cut
1525
1526sub related_source {
1527 my ($self, $rel) = @_;
aea52c85 1528 if( !$self->has_relationship( $rel ) ) {
701da8c4 1529 $self->throw_exception("No such relationship '$rel'");
aea52c85 1530 }
87772e46 1531 return $self->schema->source($self->relationship_info($rel)->{source});
8452e496 1532}
1533
77254782 1534=head2 related_class
1535
27f01d1f 1536=over 4
1537
ebc77b53 1538=item Arguments: $relname
27f01d1f 1539
391ccf38 1540=item Return value: $classname
1541
27f01d1f 1542=back
77254782 1543
2053ab2a 1544Returns the class name for objects in the given relationship.
77254782 1545
1546=cut
1547
1548sub related_class {
1549 my ($self, $rel) = @_;
1550 if( !$self->has_relationship( $rel ) ) {
1551 $self->throw_exception("No such relationship '$rel'");
1552 }
1553 return $self->schema->class($self->relationship_info($rel)->{source});
1554}
1555
aec3eff1 1556=head2 handle
1557
1558Obtain a new handle to this source. Returns an instance of a
1559L<DBIx::Class::ResultSourceHandle>.
1560
1561=cut
1562
1563sub handle {
1564 return new DBIx::Class::ResultSourceHandle({
1565 schema => $_[0]->schema,
3441fd57 1566 source_moniker => $_[0]->source_name
aec3eff1 1567 });
1568}
1569
701da8c4 1570=head2 throw_exception
1571
2053ab2a 1572See L<DBIx::Class::Schema/"throw_exception">.
701da8c4 1573
1574=cut
1575
1576sub throw_exception {
1577 my $self = shift;
75d07914 1578 if (defined $self->schema) {
701da8c4 1579 $self->schema->throw_exception(@_);
1580 } else {
1581 croak(@_);
1582 }
1583}
1584
843f6bc1 1585=head2 source_info
d2f3e87b 1586
843f6bc1 1587Stores a hashref of per-source metadata. No specific key names
1588have yet been standardized, the examples below are purely hypothetical
1589and don't actually accomplish anything on their own:
391ccf38 1590
843f6bc1 1591 __PACKAGE__->source_info({
1592 "_tablespace" => 'fast_disk_array_3',
1593 "_engine" => 'InnoDB',
1594 });
391ccf38 1595
843f6bc1 1596=head2 new
391ccf38 1597
843f6bc1 1598 $class->new();
391ccf38 1599
843f6bc1 1600 $class->new({attribute_name => value});
d2f3e87b 1601
843f6bc1 1602Creates a new ResultSource object. Not normally called directly by end users.
391ccf38 1603
843f6bc1 1604=head2 column_info_from_storage
1605
1606=over
1607
1608=item Arguments: 1/0 (default: 0)
1609
1610=item Return value: 1/0
1611
1612=back
1613
880c075b 1614 __PACKAGE__->column_info_from_storage(1);
1615
843f6bc1 1616Enables the on-demand automatic loading of the above column
1617metadata from storage as neccesary. This is *deprecated*, and
1618should not be used. It will be removed before 1.0.
1619
f89bb832 1620
9c992ba1 1621=head1 AUTHORS
1622
1623Matt S. Trout <mst@shadowcatsystems.co.uk>
1624
1625=head1 LICENSE
1626
1627You may distribute this code under the same terms as Perl itself.
1628
1629=cut
1630
b25e9fa0 16311;