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