Dynamically load necessary table classes
[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
587 return join '_', $self->name, @$cols;
588}
589
87f0da6a 590=head2 unique_constraints
591
391ccf38 592=over 4
593
594=item Arguments: None
595
596=item Return value: Hash of unique constraint data
597
598=back
599
600 $source->unique_constraints();
601
16ccb4fe 602Read-only accessor which returns a hash of unique constraints on this
603source.
391ccf38 604
605The hash is keyed by constraint name, and contains an arrayref of
606column names as values.
87f0da6a 607
608=cut
609
610sub unique_constraints {
611 return %{shift->_unique_constraints||{}};
612}
613
e6a0e17c 614=head2 unique_constraint_names
615
391ccf38 616=over 4
617
618=item Arguments: None
619
620=item Return value: Unique constraint names
621
622=back
623
624 $source->unique_constraint_names();
625
e6a0e17c 626Returns the list of unique constraint names defined on this source.
627
628=cut
629
630sub unique_constraint_names {
631 my ($self) = @_;
632
633 my %unique_constraints = $self->unique_constraints;
634
635 return keys %unique_constraints;
636}
637
638=head2 unique_constraint_columns
639
391ccf38 640=over 4
641
642=item Arguments: $constraintname
643
644=item Return value: List of constraint columns
645
646=back
647
648 $source->unique_constraint_columns('myconstraint');
649
e6a0e17c 650Returns the list of columns that make up the specified unique constraint.
651
652=cut
653
654sub unique_constraint_columns {
655 my ($self, $constraint_name) = @_;
656
657 my %unique_constraints = $self->unique_constraints;
658
659 $self->throw_exception(
660 "Unknown unique constraint $constraint_name on '" . $self->name . "'"
661 ) unless exists $unique_constraints{$constraint_name};
662
663 return @{ $unique_constraints{$constraint_name} };
664}
665
880c075b 666=head2 sqlt_deploy_callback
667
668=over
669
670=item Arguments: $callback
671
672=back
673
674 __PACKAGE__->sqlt_deploy_callback('mycallbackmethod');
675
676An accessor to set a callback to be called during deployment of
677the schema via L<DBIx::Class::Schema/create_ddl_dir> or
678L<DBIx::Class::Schema/deploy>.
679
680The callback can be set as either a code reference or the name of a
681method in the current result class.
682
683If not set, the L</default_sqlt_deploy_hook> is called.
684
685Your callback will be passed the $source object representing the
686ResultSource instance being deployed, and the
687L<SQL::Translator::Schema::Table> object being created from it. The
688callback can be used to manipulate the table object or add your own
689customised indexes. If you need to manipulate a non-table object, use
690the L<DBIx::Class::Schema/sqlt_deploy_hook>.
691
692See L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To
693Your SQL> for examples.
694
695This sqlt deployment callback can only be used to manipulate
696SQL::Translator objects as they get turned into SQL. To execute
697post-deploy statements which SQL::Translator does not currently
698handle, override L<DBIx::Class::Schema/deploy> in your Schema class
699and call L<dbh_do|DBIx::Class::Storage::DBI/dbh_do>.
700
701=head2 default_sqlt_deploy_hook
702
703=over
704
705=item Arguments: $source, $sqlt_table
706
707=item Return value: undefined
708
709=back
710
711This is the sensible default for L</sqlt_deploy_callback>.
712
713If a method named C<sqlt_deploy_hook> exists in your Result class, it
714will be called and passed the current C<$source> and the
715C<$sqlt_table> being deployed.
716
717=cut
718
719sub default_sqlt_deploy_hook {
720 my $self = shift;
721
722 my $class = $self->result_class;
723
724 if ($class and $class->can('sqlt_deploy_hook')) {
725 $class->sqlt_deploy_hook(@_);
726 }
727}
728
729sub _invoke_sqlt_deploy_hook {
730 my $self = shift;
731 if ( my $hook = $self->sqlt_deploy_callback) {
732 $self->$hook(@_);
733 }
734}
735
843f6bc1 736=head2 resultset
737
738=over 4
739
740=item Arguments: None
741
742=item Return value: $resultset
743
744=back
745
746Returns a resultset for the given source. This will initially be created
747on demand by calling
748
749 $self->resultset_class->new($self, $self->resultset_attributes)
750
751but is cached from then on unless resultset_class changes.
752
753=head2 resultset_class
754
755=over 4
756
757=item Arguments: $classname
758
759=item Return value: $classname
760
761=back
762
16ccb4fe 763 package My::Schema::ResultSet::Artist;
843f6bc1 764 use base 'DBIx::Class::ResultSet';
765 ...
766
16ccb4fe 767 # In the result class
768 __PACKAGE__->resultset_class('My::Schema::ResultSet::Artist');
769
770 # Or in code
771 $source->resultset_class('My::Schema::ResultSet::Artist');
843f6bc1 772
7e51afbf 773Set the class of the resultset. This is useful if you want to create your
843f6bc1 774own resultset methods. Create your own class derived from
775L<DBIx::Class::ResultSet>, and set it here. If called with no arguments,
776this method returns the name of the existing resultset class, if one
777exists.
778
779=head2 resultset_attributes
780
781=over 4
782
783=item Arguments: \%attrs
784
785=item Return value: \%attrs
786
787=back
788
16ccb4fe 789 # In the result class
790 __PACKAGE__->resultset_attributes({ order_by => [ 'id' ] });
791
792 # Or in code
843f6bc1 793 $source->resultset_attributes({ order_by => [ 'id' ] });
794
795Store a collection of resultset attributes, that will be set on every
796L<DBIx::Class::ResultSet> produced from this result source. For a full
797list see L<DBIx::Class::ResultSet/ATTRIBUTES>.
798
799=cut
800
801sub resultset {
802 my $self = shift;
803 $self->throw_exception(
804 'resultset does not take any arguments. If you want another resultset, '.
805 'call it on the schema instead.'
806 ) if scalar @_;
807
808 return $self->resultset_class->new(
809 $self,
810 {
811 %{$self->{resultset_attributes}},
812 %{$self->schema->default_resultset_attributes}
813 },
814 );
815}
816
817=head2 source_name
818
819=over 4
820
821=item Arguments: $source_name
822
823=item Result value: $source_name
824
825=back
826
827Set an alternate name for the result source when it is loaded into a schema.
828This is useful if you want to refer to a result source by a name other than
829its class name.
830
831 package ArchivedBooks;
832 use base qw/DBIx::Class/;
833 __PACKAGE__->table('books_archive');
834 __PACKAGE__->source_name('Books');
835
836 # from your schema...
837 $schema->resultset('Books')->find(1);
838
9c992ba1 839=head2 from
840
391ccf38 841=over 4
842
843=item Arguments: None
844
845=item Return value: FROM clause
846
847=back
848
849 my $from_clause = $source->from();
850
9c992ba1 851Returns an expression of the source to be supplied to storage to specify
2053ab2a 852retrieval from this source. In the case of a database, the required FROM
853clause contents.
9c992ba1 854
f9b7bd6e 855=head2 schema
856
391ccf38 857=over 4
858
859=item Arguments: None
860
861=item Return value: A schema object
862
863=back
864
865 my $schema = $source->schema();
866
f9b7bd6e 867Returns the L<DBIx::Class::Schema> object that this result source
391ccf38 868belongs to.
9c992ba1 869
870=head2 storage
871
391ccf38 872=over 4
873
874=item Arguments: None
875
876=item Return value: A Storage object
877
878=back
879
880 $source->storage->debug(1);
881
75d07914 882Returns the storage handle for the current schema.
988bf309 883
884See also: L<DBIx::Class::Storage>
9c992ba1 885
886=cut
887
888sub storage { shift->schema->storage; }
889
8452e496 890=head2 add_relationship
891
391ccf38 892=over 4
893
894=item Arguments: $relname, $related_source_name, \%cond, [ \%attrs ]
895
896=item Return value: 1/true if it succeeded
897
898=back
899
8452e496 900 $source->add_relationship('relname', 'related_source', $cond, $attrs);
901
391ccf38 902L<DBIx::Class::Relationship> describes a series of methods which
903create pre-defined useful types of relationships. Look there first
904before using this method directly.
905
24d67825 906The relationship name can be arbitrary, but must be unique for each
907relationship attached to this result source. 'related_source' should
908be the name with which the related result source was registered with
909the current schema. For example:
8452e496 910
24d67825 911 $schema->source('Book')->add_relationship('reviews', 'Review', {
912 'foreign.book_id' => 'self.id',
913 });
914
2053ab2a 915The condition C<$cond> needs to be an L<SQL::Abstract>-style
24d67825 916representation of the join between the tables. For example, if you're
391ccf38 917creating a relation from Author to Book,
988bf309 918
919 { 'foreign.author_id' => 'self.id' }
920
921will result in the JOIN clause
922
923 author me JOIN book foreign ON foreign.author_id = me.id
924
8452e496 925You can specify as many foreign => self mappings as necessary.
926
988bf309 927Valid attributes are as follows:
928
929=over 4
930
931=item join_type
932
933Explicitly specifies the type of join to use in the relationship. Any
934SQL join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in
935the SQL command immediately before C<JOIN>.
936
937=item proxy
938
24d67825 939An arrayref containing a list of accessors in the foreign class to proxy in
940the main class. If, for example, you do the following:
002a359a 941
24d67825 942 CD->might_have(liner_notes => 'LinerNotes', undef, {
943 proxy => [ qw/notes/ ],
944 });
002a359a 945
24d67825 946Then, assuming LinerNotes has an accessor named notes, you can do:
988bf309 947
24d67825 948 my $cd = CD->find(1);
2053ab2a 949 # set notes -- LinerNotes object is created if it doesn't exist
950 $cd->notes('Notes go here');
988bf309 951
952=item accessor
953
954Specifies the type of accessor that should be created for the
75d07914 955relationship. Valid values are C<single> (for when there is only a single
956related object), C<multi> (when there can be many), and C<filter> (for
957when there is a single related object, but you also want the relationship
958accessor to double as a column accessor). For C<multi> accessors, an
959add_to_* method is also created, which calls C<create_related> for the
988bf309 960relationship.
961
8452e496 962=back
963
391ccf38 964Throws an exception if the condition is improperly supplied, or cannot
6d0ee587 965be resolved.
391ccf38 966
8452e496 967=cut
968
969sub add_relationship {
970 my ($self, $rel, $f_source_name, $cond, $attrs) = @_;
27f01d1f 971 $self->throw_exception("Can't create relationship without join condition")
972 unless $cond;
8452e496 973 $attrs ||= {};
87772e46 974
eba322a7 975 # Check foreign and self are right in cond
976 if ( (ref $cond ||'') eq 'HASH') {
977 for (keys %$cond) {
978 $self->throw_exception("Keys of condition should be of form 'foreign.col', not '$_'")
979 if /\./ && !/^foreign\./;
980 }
981 }
982
8452e496 983 my %rels = %{ $self->_relationships };
984 $rels{$rel} = { class => $f_source_name,
87772e46 985 source => $f_source_name,
8452e496 986 cond => $cond,
987 attrs => $attrs };
988 $self->_relationships(\%rels);
989
30126ac7 990 return $self;
87772e46 991
953a18ef 992 # XXX disabled. doesn't work properly currently. skip in tests.
993
8452e496 994 my $f_source = $self->schema->source($f_source_name);
995 unless ($f_source) {
c037c03a 996 $self->ensure_class_loaded($f_source_name);
8452e496 997 $f_source = $f_source_name->result_source;
87772e46 998 #my $s_class = ref($self->schema);
999 #$f_source_name =~ m/^${s_class}::(.*)$/;
1000 #$self->schema->register_class(($1 || $f_source_name), $f_source_name);
1001 #$f_source = $self->schema->source($f_source_name);
8452e496 1002 }
1003 return unless $f_source; # Can't test rel without f_source
1004
88a66388 1005 eval { $self->_resolve_join($rel, 'me', {}, []) };
8452e496 1006
1007 if ($@) { # If the resolve failed, back out and re-throw the error
75d07914 1008 delete $rels{$rel}; #
8452e496 1009 $self->_relationships(\%rels);
701da8c4 1010 $self->throw_exception("Error creating relationship $rel: $@");
8452e496 1011 }
1012 1;
1013}
1014
87c4e602 1015=head2 relationships
8452e496 1016
391ccf38 1017=over 4
1018
1019=item Arguments: None
1020
1021=item Return value: List of relationship names
1022
1023=back
1024
1025 my @relnames = $source->relationships();
1026
2053ab2a 1027Returns all relationship names for this source.
8452e496 1028
1029=cut
1030
1031sub relationships {
1032 return keys %{shift->_relationships};
1033}
1034
87c4e602 1035=head2 relationship_info
1036
27f01d1f 1037=over 4
1038
ebc77b53 1039=item Arguments: $relname
27f01d1f 1040
391ccf38 1041=item Return value: Hashref of relation data,
1042
27f01d1f 1043=back
8452e496 1044
2053ab2a 1045Returns a hash of relationship information for the specified relationship
391ccf38 1046name. The keys/values are as specified for L</add_relationship>.
8452e496 1047
1048=cut
1049
1050sub relationship_info {
1051 my ($self, $rel) = @_;
1052 return $self->_relationships->{$rel};
75d07914 1053}
8452e496 1054
87c4e602 1055=head2 has_relationship
1056
27f01d1f 1057=over 4
1058
ebc77b53 1059=item Arguments: $rel
27f01d1f 1060
391ccf38 1061=item Return value: 1/0 (true/false)
1062
27f01d1f 1063=back
953a18ef 1064
2053ab2a 1065Returns true if the source has a relationship of this name, false otherwise.
988bf309 1066
1067=cut
953a18ef 1068
1069sub has_relationship {
1070 my ($self, $rel) = @_;
1071 return exists $self->_relationships->{$rel};
1072}
1073
de60a93d 1074=head2 reverse_relationship_info
1075
1076=over 4
1077
1078=item Arguments: $relname
1079
391ccf38 1080=item Return value: Hashref of relationship data
1081
de60a93d 1082=back
1083
391ccf38 1084Looks through all the relationships on the source this relationship
1085points to, looking for one whose condition is the reverse of the
1086condition on this relationship.
1087
1088A common use of this is to find the name of the C<belongs_to> relation
1089opposing a C<has_many> relation. For definition of these look in
1090L<DBIx::Class::Relationship>.
1091
1092The returned hashref is keyed by the name of the opposing
faaba25f 1093relationship, and contains its data in the same manner as
391ccf38 1094L</relationship_info>.
de60a93d 1095
1096=cut
1097
1098sub reverse_relationship_info {
1099 my ($self, $rel) = @_;
1100 my $rel_info = $self->relationship_info($rel);
1101 my $ret = {};
1102
1103 return $ret unless ((ref $rel_info->{cond}) eq 'HASH');
1104
1105 my @cond = keys(%{$rel_info->{cond}});
1106 my @refkeys = map {/^\w+\.(\w+)$/} @cond;
1107 my @keys = map {$rel_info->{cond}->{$_} =~ /^\w+\.(\w+)$/} @cond;
bab77431 1108
de60a93d 1109 # Get the related result source for this relationship
1110 my $othertable = $self->related_source($rel);
1111
1112 # Get all the relationships for that source that related to this source
1113 # whose foreign column set are our self columns on $rel and whose self
bab77431 1114 # columns are our foreign columns on $rel.
de60a93d 1115 my @otherrels = $othertable->relationships();
1116 my $otherrelationship;
1117 foreach my $otherrel (@otherrels) {
1118 my $otherrel_info = $othertable->relationship_info($otherrel);
1119
1120 my $back = $othertable->related_source($otherrel);
f3fb2641 1121 next unless $back->source_name eq $self->source_name;
de60a93d 1122
1123 my @othertestconds;
1124
1125 if (ref $otherrel_info->{cond} eq 'HASH') {
1126 @othertestconds = ($otherrel_info->{cond});
1127 }
1128 elsif (ref $otherrel_info->{cond} eq 'ARRAY') {
1129 @othertestconds = @{$otherrel_info->{cond}};
1130 }
1131 else {
1132 next;
1133 }
1134
1135 foreach my $othercond (@othertestconds) {
1136 my @other_cond = keys(%$othercond);
1137 my @other_refkeys = map {/^\w+\.(\w+)$/} @other_cond;
1138 my @other_keys = map {$othercond->{$_} =~ /^\w+\.(\w+)$/} @other_cond;
6d0ee587 1139 next if (!$self->_compare_relationship_keys(\@refkeys, \@other_keys) ||
1140 !$self->_compare_relationship_keys(\@other_refkeys, \@keys));
de60a93d 1141 $ret->{$otherrel} = $otherrel_info;
1142 }
1143 }
1144 return $ret;
1145}
1146
de60a93d 1147sub compare_relationship_keys {
6d0ee587 1148 carp 'compare_relationship_keys is a private method, stop calling it';
1149 my $self = shift;
1150 $self->_compare_relationship_keys (@_);
1151}
1152
1153# Returns true if both sets of keynames are the same, false otherwise.
1154sub _compare_relationship_keys {
de60a93d 1155 my ($self, $keys1, $keys2) = @_;
1156
1157 # Make sure every keys1 is in keys2
1158 my $found;
1159 foreach my $key (@$keys1) {
1160 $found = 0;
1161 foreach my $prim (@$keys2) {
1162 if ($prim eq $key) {
1163 $found = 1;
1164 last;
1165 }
1166 }
1167 last unless $found;
1168 }
1169
1170 # Make sure every key2 is in key1
1171 if ($found) {
1172 foreach my $prim (@$keys2) {
1173 $found = 0;
1174 foreach my $key (@$keys1) {
1175 if ($prim eq $key) {
1176 $found = 1;
1177 last;
1178 }
1179 }
1180 last unless $found;
1181 }
1182 }
1183
1184 return $found;
1185}
1186
8452e496 1187sub resolve_join {
6d0ee587 1188 carp 'resolve_join is a private method, stop calling it';
1189 my $self = shift;
1190 $self->_resolve_join (@_);
1191}
1192
1193# Returns the {from} structure used to express JOIN conditions
1194sub _resolve_join {
b230b4be 1195 my ($self, $join, $alias, $seen, $jpath, $force_left) = @_;
1979278e 1196
1197 # we need a supplied one, because we do in-place modifications, no returns
6d0ee587 1198 $self->throw_exception ('You must supply a seen hashref as the 3rd argument to _resolve_join')
88a66388 1199 unless ref $seen eq 'HASH';
1979278e 1200
88a66388 1201 $self->throw_exception ('You must supply a joinpath arrayref as the 4th argument to _resolve_join')
1202 unless ref $jpath eq 'ARRAY';
1203
1204 $jpath = [@$jpath];
1979278e 1205
87772e46 1206 if (ref $join eq 'ARRAY') {
caac1708 1207 return
1208 map {
88a66388 1209 $self->_resolve_join($_, $alias, $seen, $jpath, $force_left);
caac1708 1210 } @$join;
87772e46 1211 } elsif (ref $join eq 'HASH') {
489709af 1212 return
887ce227 1213 map {
1979278e 1214 my $as = ($seen->{$_} ? join ('_', $_, $seen->{$_} + 1) : $_); # the actual seen value will be incremented below
caac1708 1215 local $force_left->{force} = $force_left->{force};
24010dd8 1216 (
b230b4be 1217 $self->_resolve_join($_, $alias, $seen, [@$jpath], $force_left),
6d0ee587 1218 $self->related_source($_)->_resolve_join(
b230b4be 1219 $join->{$_}, $as, $seen, [@$jpath, $_], $force_left
24010dd8 1220 )
1221 );
887ce227 1222 } keys %$join;
87772e46 1223 } elsif (ref $join) {
701da8c4 1224 $self->throw_exception("No idea how to resolve join reftype ".ref $join);
87772e46 1225 } else {
1979278e 1226
096395af 1227 return() unless defined $join;
1228
489709af 1229 my $count = ++$seen->{$join};
489709af 1230 my $as = ($count > 1 ? "${join}_${count}" : $join);
1979278e 1231
3842b955 1232 my $rel_info = $self->relationship_info($join);
701da8c4 1233 $self->throw_exception("No such relationship ${join}") unless $rel_info;
24010dd8 1234 my $type;
b230b4be 1235 if ($force_left) {
24010dd8 1236 $type = 'left';
1237 } else {
1238 $type = $rel_info->{attrs}{join_type} || '';
b230b4be 1239 $force_left = 1 if lc($type) eq 'left';
24010dd8 1240 }
ba61fa2a 1241
1242 my $rel_src = $self->related_source($join);
1243 return [ { $as => $rel_src->from,
35ec0366 1244 -source_handle => $rel_src->handle,
1979278e 1245 -join_type => $type,
1246 -join_path => [@$jpath, $join],
ba61fa2a 1247 -alias => $as,
1979278e 1248 -relation_chain_depth => $seen->{-relation_chain_depth} || 0,
1249 },
6d0ee587 1250 $self->_resolve_condition($rel_info->{cond}, $as, $alias) ];
953a18ef 1251 }
1252}
1253
370f2ba2 1254sub pk_depends_on {
6d0ee587 1255 carp 'pk_depends_on is a private method, stop calling it';
1256 my $self = shift;
1257 $self->_pk_depends_on (@_);
1258}
1259
1260# Determines whether a relation is dependent on an object from this source
1261# having already been inserted. Takes the name of the relationship and a
1262# hashref of columns of the related object.
1263sub _pk_depends_on {
370f2ba2 1264 my ($self, $relname, $rel_data) = @_;
1265 my $cond = $self->relationship_info($relname)->{cond};
1266
1267 return 0 unless ref($cond) eq 'HASH';
1268
1269 # map { foreign.foo => 'self.bar' } to { bar => 'foo' }
1270
1271 my $keyhash = { map { my $x = $_; $x =~ s/.*\.//; $x; } reverse %$cond };
1272
1273 # assume anything that references our PK probably is dependent on us
1274 # rather than vice versa, unless the far side is (a) defined or (b)
1275 # auto-increment
1276
1277 my $rel_source = $self->related_source($relname);
1278
1279 foreach my $p ($self->primary_columns) {
1280 if (exists $keyhash->{$p}) {
1281 unless (defined($rel_data->{$keyhash->{$p}})
1282 || $rel_source->column_info($keyhash->{$p})
1283 ->{is_auto_increment}) {
1284 return 0;
1285 }
1286 }
1287 }
1288
1289 return 1;
1290}
1291
6d0ee587 1292sub resolve_condition {
1293 carp 'resolve_condition is a private method, stop calling it';
1294 my $self = shift;
1295 $self->_resolve_condition (@_);
1296}
953a18ef 1297
6d0ee587 1298# Resolves the passed condition to a concrete query fragment. If given an alias,
1299# returns a join condition; if given an object, inverts that object to produce
1300# a related conditional from that object.
8c368cf3 1301our $UNRESOLVABLE_CONDITION = \'1 = 0';
1302
6d0ee587 1303sub _resolve_condition {
489709af 1304 my ($self, $cond, $as, $for) = @_;
953a18ef 1305 if (ref $cond eq 'HASH') {
1306 my %ret;
bd054cb4 1307 foreach my $k (keys %{$cond}) {
1308 my $v = $cond->{$k};
953a18ef 1309 # XXX should probably check these are valid columns
27f01d1f 1310 $k =~ s/^foreign\.// ||
75d07914 1311 $self->throw_exception("Invalid rel cond key ${k}");
27f01d1f 1312 $v =~ s/^self\.// ||
75d07914 1313 $self->throw_exception("Invalid rel cond val ${v}");
953a18ef 1314 if (ref $for) { # Object
3842b955 1315 #warn "$self $k $for $v";
370f2ba2 1316 unless ($for->has_column_loaded($v)) {
1317 if ($for->in_storage) {
a4fcda00 1318 $self->throw_exception(
1319 "Column ${v} not loaded or not passed to new() prior to insert()"
1320 ." on ${for} trying to resolve relationship (maybe you forgot "
286fa9c5 1321 ."to call ->discard_changes to get defaults from the db)"
a4fcda00 1322 );
370f2ba2 1323 }
68f3b0dd 1324 return $UNRESOLVABLE_CONDITION;
370f2ba2 1325 }
1326 $ret{$k} = $for->get_column($v);
1327 #$ret{$k} = $for->get_column($v) if $for->has_column_loaded($v);
3842b955 1328 #warn %ret;
2c037e6b 1329 } elsif (!defined $for) { # undef, i.e. "no object"
1330 $ret{$k} = undef;
2ec8e594 1331 } elsif (ref $as eq 'HASH') { # reverse hashref
1332 $ret{$v} = $as->{$k};
fde6e28e 1333 } elsif (ref $as) { # reverse object
1334 $ret{$v} = $as->get_column($k);
2c037e6b 1335 } elsif (!defined $as) { # undef, i.e. "no reverse object"
1336 $ret{$v} = undef;
953a18ef 1337 } else {
489709af 1338 $ret{"${as}.${k}"} = "${for}.${v}";
953a18ef 1339 }
953a18ef 1340 }
1341 return \%ret;
5efe4c79 1342 } elsif (ref $cond eq 'ARRAY') {
6d0ee587 1343 return [ map { $self->_resolve_condition($_, $as, $for) } @$cond ];
953a18ef 1344 } else {
35c77aa3 1345 die("Can't handle condition $cond yet :(");
87772e46 1346 }
1347}
1348
3bb4eb8f 1349# Legacy code, needs to go entirely away (fully replaced by _resolve_prefetch)
6d0ee587 1350sub resolve_prefetch {
1351 carp 'resolve_prefetch is a private method, stop calling it';
3bb4eb8f 1352
1353 my ($self, $pre, $alias, $seen, $order, $collapse) = @_;
1354 $seen ||= {};
1355 if( ref $pre eq 'ARRAY' ) {
1356 return
1357 map { $self->resolve_prefetch( $_, $alias, $seen, $order, $collapse ) }
1358 @$pre;
1359 }
1360 elsif( ref $pre eq 'HASH' ) {
1361 my @ret =
1362 map {
1363 $self->resolve_prefetch($_, $alias, $seen, $order, $collapse),
1364 $self->related_source($_)->resolve_prefetch(
1365 $pre->{$_}, "${alias}.$_", $seen, $order, $collapse)
1366 } keys %$pre;
1367 return @ret;
1368 }
1369 elsif( ref $pre ) {
1370 $self->throw_exception(
1371 "don't know how to resolve prefetch reftype ".ref($pre));
1372 }
1373 else {
1374 my $count = ++$seen->{$pre};
1375 my $as = ($count > 1 ? "${pre}_${count}" : $pre);
1376 my $rel_info = $self->relationship_info( $pre );
1377 $self->throw_exception( $self->name . " has no such relationship '$pre'" )
1378 unless $rel_info;
1379 my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : '');
1380 my $rel_source = $self->related_source($pre);
1381
1382 if (exists $rel_info->{attrs}{accessor}
1383 && $rel_info->{attrs}{accessor} eq 'multi') {
1384 $self->throw_exception(
1385 "Can't prefetch has_many ${pre} (join cond too complex)")
1386 unless ref($rel_info->{cond}) eq 'HASH';
1387 my $dots = @{[$as_prefix =~ m/\./g]} + 1; # +1 to match the ".${as_prefix}"
1388 if (my ($fail) = grep { @{[$_ =~ m/\./g]} == $dots }
1389 keys %{$collapse}) {
1390 my ($last) = ($fail =~ /([^\.]+)$/);
1391 carp (
1392 "Prefetching multiple has_many rels ${last} and ${pre} "
1393 .(length($as_prefix)
1394 ? "at the same level (${as_prefix}) "
1395 : "at top level "
1396 )
2e251255 1397 . 'will explode the number of row objects retrievable via ->next or ->all. '
3bb4eb8f 1398 . 'Use at your own risk.'
1399 );
1400 }
1401 #my @col = map { (/^self\.(.+)$/ ? ("${as_prefix}.$1") : ()); }
1402 # values %{$rel_info->{cond}};
1403 $collapse->{".${as_prefix}${pre}"} = [ $rel_source->primary_columns ];
1404 # action at a distance. prepending the '.' allows simpler code
1405 # in ResultSet->_collapse_result
1406 my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); }
1407 keys %{$rel_info->{cond}};
1408 my @ord = (ref($rel_info->{attrs}{order_by}) eq 'ARRAY'
1409 ? @{$rel_info->{attrs}{order_by}}
1410 : (defined $rel_info->{attrs}{order_by}
1411 ? ($rel_info->{attrs}{order_by})
1412 : ()));
1413 push(@$order, map { "${as}.$_" } (@key, @ord));
1414 }
1415
1416 return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] }
1417 $rel_source->columns;
1418 }
6d0ee587 1419}
988bf309 1420
6d0ee587 1421# Accepts one or more relationships for the current source and returns an
1422# array of column names for each of those relationships. Column names are
1423# prefixed relative to the current source, in accordance with where they appear
1424# in the supplied relationships. Needs an alias_map generated by
1425# $rs->_joinpath_aliases
b3e8ac9b 1426
6d0ee587 1427sub _resolve_prefetch {
1979278e 1428 my ($self, $pre, $alias, $alias_map, $order, $collapse, $pref_path) = @_;
1429 $pref_path ||= [];
1430
b3e8ac9b 1431 if( ref $pre eq 'ARRAY' ) {
0f66a01b 1432 return
6d0ee587 1433 map { $self->_resolve_prefetch( $_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ) }
0f66a01b 1434 @$pre;
b3e8ac9b 1435 }
1436 elsif( ref $pre eq 'HASH' ) {
1437 my @ret =
1438 map {
6d0ee587 1439 $self->_resolve_prefetch($_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ),
1440 $self->related_source($_)->_resolve_prefetch(
1979278e 1441 $pre->{$_}, "${alias}.$_", $alias_map, $order, $collapse, [ @$pref_path, $_] )
0f66a01b 1442 } keys %$pre;
b3e8ac9b 1443 return @ret;
1444 }
1445 elsif( ref $pre ) {
a86b1efe 1446 $self->throw_exception(
1447 "don't know how to resolve prefetch reftype ".ref($pre));
b3e8ac9b 1448 }
1449 else {
1979278e 1450 my $p = $alias_map;
1451 $p = $p->{$_} for (@$pref_path, $pre);
1452
1453 $self->throw_exception (
88a66388 1454 "Unable to resolve prefetch $pre - join alias map does not contain an entry for path: "
1979278e 1455 . join (' -> ', @$pref_path, $pre)
1456 ) if (ref $p->{-join_aliases} ne 'ARRAY' or not @{$p->{-join_aliases}} );
88a66388 1457
1979278e 1458 my $as = shift @{$p->{-join_aliases}};
1459
b3e8ac9b 1460 my $rel_info = $self->relationship_info( $pre );
a86b1efe 1461 $self->throw_exception( $self->name . " has no such relationship '$pre'" )
1462 unless $rel_info;
37f23589 1463 my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : '');
a86b1efe 1464 my $rel_source = $self->related_source($pre);
0f66a01b 1465
1466 if (exists $rel_info->{attrs}{accessor}
1467 && $rel_info->{attrs}{accessor} eq 'multi') {
1468 $self->throw_exception(
1469 "Can't prefetch has_many ${pre} (join cond too complex)")
1470 unless ref($rel_info->{cond}) eq 'HASH';
cb136e67 1471 my $dots = @{[$as_prefix =~ m/\./g]} + 1; # +1 to match the ".${as_prefix}"
1472 if (my ($fail) = grep { @{[$_ =~ m/\./g]} == $dots }
1473 keys %{$collapse}) {
1474 my ($last) = ($fail =~ /([^\.]+)$/);
616b461d 1475 carp (
1476 "Prefetching multiple has_many rels ${last} and ${pre} "
1477 .(length($as_prefix)
1478 ? "at the same level (${as_prefix}) "
1479 : "at top level "
1480 )
2e251255 1481 . 'will explode the number of row objects retrievable via ->next or ->all. '
616b461d 1482 . 'Use at your own risk.'
1483 );
cb136e67 1484 }
b25e9fa0 1485 #my @col = map { (/^self\.(.+)$/ ? ("${as_prefix}.$1") : ()); }
1486 # values %{$rel_info->{cond}};
1487 $collapse->{".${as_prefix}${pre}"} = [ $rel_source->primary_columns ];
1488 # action at a distance. prepending the '.' allows simpler code
1489 # in ResultSet->_collapse_result
37f23589 1490 my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); }
0f66a01b 1491 keys %{$rel_info->{cond}};
5a5bec6c 1492 my @ord = (ref($rel_info->{attrs}{order_by}) eq 'ARRAY'
1493 ? @{$rel_info->{attrs}{order_by}}
1494 : (defined $rel_info->{attrs}{order_by}
1495 ? ($rel_info->{attrs}{order_by})
1496 : ()));
1497 push(@$order, map { "${as}.$_" } (@key, @ord));
0f66a01b 1498 }
1499
489709af 1500 return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] }
a86b1efe 1501 $rel_source->columns;
b3e8ac9b 1502 }
1503}
953a18ef 1504
87c4e602 1505=head2 related_source
1506
27f01d1f 1507=over 4
1508
ebc77b53 1509=item Arguments: $relname
27f01d1f 1510
391ccf38 1511=item Return value: $source
1512
27f01d1f 1513=back
87772e46 1514
2053ab2a 1515Returns the result source object for the given relationship.
87772e46 1516
1517=cut
1518
1519sub related_source {
1520 my ($self, $rel) = @_;
aea52c85 1521 if( !$self->has_relationship( $rel ) ) {
701da8c4 1522 $self->throw_exception("No such relationship '$rel'");
aea52c85 1523 }
87772e46 1524 return $self->schema->source($self->relationship_info($rel)->{source});
8452e496 1525}
1526
77254782 1527=head2 related_class
1528
27f01d1f 1529=over 4
1530
ebc77b53 1531=item Arguments: $relname
27f01d1f 1532
391ccf38 1533=item Return value: $classname
1534
27f01d1f 1535=back
77254782 1536
2053ab2a 1537Returns the class name for objects in the given relationship.
77254782 1538
1539=cut
1540
1541sub related_class {
1542 my ($self, $rel) = @_;
1543 if( !$self->has_relationship( $rel ) ) {
1544 $self->throw_exception("No such relationship '$rel'");
1545 }
1546 return $self->schema->class($self->relationship_info($rel)->{source});
1547}
1548
aec3eff1 1549=head2 handle
1550
1551Obtain a new handle to this source. Returns an instance of a
1552L<DBIx::Class::ResultSourceHandle>.
1553
1554=cut
1555
1556sub handle {
1557 return new DBIx::Class::ResultSourceHandle({
1558 schema => $_[0]->schema,
3441fd57 1559 source_moniker => $_[0]->source_name
aec3eff1 1560 });
1561}
1562
701da8c4 1563=head2 throw_exception
1564
2053ab2a 1565See L<DBIx::Class::Schema/"throw_exception">.
701da8c4 1566
1567=cut
1568
1569sub throw_exception {
1570 my $self = shift;
75d07914 1571 if (defined $self->schema) {
701da8c4 1572 $self->schema->throw_exception(@_);
1573 } else {
1574 croak(@_);
1575 }
1576}
1577
843f6bc1 1578=head2 source_info
d2f3e87b 1579
843f6bc1 1580Stores a hashref of per-source metadata. No specific key names
1581have yet been standardized, the examples below are purely hypothetical
1582and don't actually accomplish anything on their own:
391ccf38 1583
843f6bc1 1584 __PACKAGE__->source_info({
1585 "_tablespace" => 'fast_disk_array_3',
1586 "_engine" => 'InnoDB',
1587 });
391ccf38 1588
843f6bc1 1589=head2 new
391ccf38 1590
843f6bc1 1591 $class->new();
391ccf38 1592
843f6bc1 1593 $class->new({attribute_name => value});
d2f3e87b 1594
843f6bc1 1595Creates a new ResultSource object. Not normally called directly by end users.
391ccf38 1596
843f6bc1 1597=head2 column_info_from_storage
1598
1599=over
1600
1601=item Arguments: 1/0 (default: 0)
1602
1603=item Return value: 1/0
1604
1605=back
1606
880c075b 1607 __PACKAGE__->column_info_from_storage(1);
1608
843f6bc1 1609Enables the on-demand automatic loading of the above column
1610metadata from storage as neccesary. This is *deprecated*, and
1611should not be used. It will be removed before 1.0.
1612
f89bb832 1613
9c992ba1 1614=head1 AUTHORS
1615
1616Matt S. Trout <mst@shadowcatsystems.co.uk>
1617
1618=head1 LICENSE
1619
1620You may distribute this code under the same terms as Perl itself.
1621
1622=cut
1623
b25e9fa0 16241;