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