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