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