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