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