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