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