checks if the complex conditions are overriden in set_from_related
[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 },
cf320fd7 1496 $self->_resolve_condition($rel_info->{cond}, $as, $alias, $join) ];
953a18ef 1497 }
1498}
1499
370f2ba2 1500sub pk_depends_on {
6d0ee587 1501 carp 'pk_depends_on is a private method, stop calling it';
1502 my $self = shift;
1503 $self->_pk_depends_on (@_);
1504}
1505
1506# Determines whether a relation is dependent on an object from this source
1507# having already been inserted. Takes the name of the relationship and a
1508# hashref of columns of the related object.
1509sub _pk_depends_on {
370f2ba2 1510 my ($self, $relname, $rel_data) = @_;
370f2ba2 1511
c39b48e5 1512 my $relinfo = $self->relationship_info($relname);
1513
1514 # don't assume things if the relationship direction is specified
1515 return $relinfo->{attrs}{is_foreign_key_constraint}
1516 if exists ($relinfo->{attrs}{is_foreign_key_constraint});
1517
1518 my $cond = $relinfo->{cond};
370f2ba2 1519 return 0 unless ref($cond) eq 'HASH';
1520
1521 # map { foreign.foo => 'self.bar' } to { bar => 'foo' }
370f2ba2 1522 my $keyhash = { map { my $x = $_; $x =~ s/.*\.//; $x; } reverse %$cond };
1523
1524 # assume anything that references our PK probably is dependent on us
1525 # rather than vice versa, unless the far side is (a) defined or (b)
1526 # auto-increment
370f2ba2 1527 my $rel_source = $self->related_source($relname);
1528
1529 foreach my $p ($self->primary_columns) {
1530 if (exists $keyhash->{$p}) {
1531 unless (defined($rel_data->{$keyhash->{$p}})
1532 || $rel_source->column_info($keyhash->{$p})
1533 ->{is_auto_increment}) {
1534 return 0;
1535 }
1536 }
1537 }
1538
1539 return 1;
1540}
1541
6d0ee587 1542sub resolve_condition {
1543 carp 'resolve_condition is a private method, stop calling it';
1544 my $self = shift;
1545 $self->_resolve_condition (@_);
1546}
953a18ef 1547
6d0ee587 1548# Resolves the passed condition to a concrete query fragment. If given an alias,
1549# returns a join condition; if given an object, inverts that object to produce
1550# a related conditional from that object.
8c368cf3 1551our $UNRESOLVABLE_CONDITION = \'1 = 0';
1552
6d0ee587 1553sub _resolve_condition {
cf320fd7 1554 my ($self, $cond, $as, $for, $rel) = @_;
1555 if (ref $cond eq 'CODE') {
1556
1557 # heuristic for the actual relname
1558 if (! defined $rel) {
1559 if (!ref $as) {
1560 $rel = $as;
1561 }
1562 elsif (!ref $for) {
1563 $rel = $for;
1564 }
1565 }
1566
1567 if (! defined $rel) {
1568 $self->throw_exception ('Unable to determine relationship name for condition resolution');
1569 }
1570
6c4f4d69 1571 return $cond->({
1572 self_alias => ref $for ? $as : $for,
1573 foreign_alias => ref $for ? $self->related_source($rel)->resultset->current_source_alias : $as,
1574 self_resultsource => $self,
1575 foreign_relname => $rel,
1576 self_rowobj => ref $for ? $for : undef
1577 });
cf320fd7 1578
1579 } elsif (ref $cond eq 'HASH') {
953a18ef 1580 my %ret;
bd054cb4 1581 foreach my $k (keys %{$cond}) {
1582 my $v = $cond->{$k};
953a18ef 1583 # XXX should probably check these are valid columns
27f01d1f 1584 $k =~ s/^foreign\.// ||
75d07914 1585 $self->throw_exception("Invalid rel cond key ${k}");
27f01d1f 1586 $v =~ s/^self\.// ||
75d07914 1587 $self->throw_exception("Invalid rel cond val ${v}");
953a18ef 1588 if (ref $for) { # Object
3842b955 1589 #warn "$self $k $for $v";
370f2ba2 1590 unless ($for->has_column_loaded($v)) {
1591 if ($for->in_storage) {
8bbfe6b2 1592 $self->throw_exception(sprintf
5c89c897 1593 "Unable to resolve relationship '%s' from object %s: column '%s' not "
1594 . 'loaded from storage (or not passed to new() prior to insert()). You '
1595 . 'probably need to call ->discard_changes to get the server-side defaults '
1596 . 'from the database.',
8bbfe6b2 1597 $as,
971beb94 1598 $for,
5c89c897 1599 $v,
a4fcda00 1600 );
370f2ba2 1601 }
68f3b0dd 1602 return $UNRESOLVABLE_CONDITION;
370f2ba2 1603 }
1604 $ret{$k} = $for->get_column($v);
1605 #$ret{$k} = $for->get_column($v) if $for->has_column_loaded($v);
3842b955 1606 #warn %ret;
2c037e6b 1607 } elsif (!defined $for) { # undef, i.e. "no object"
1608 $ret{$k} = undef;
2ec8e594 1609 } elsif (ref $as eq 'HASH') { # reverse hashref
1610 $ret{$v} = $as->{$k};
fde6e28e 1611 } elsif (ref $as) { # reverse object
1612 $ret{$v} = $as->get_column($k);
2c037e6b 1613 } elsif (!defined $as) { # undef, i.e. "no reverse object"
1614 $ret{$v} = undef;
953a18ef 1615 } else {
489709af 1616 $ret{"${as}.${k}"} = "${for}.${v}";
953a18ef 1617 }
953a18ef 1618 }
1619 return \%ret;
5efe4c79 1620 } elsif (ref $cond eq 'ARRAY') {
6d0ee587 1621 return [ map { $self->_resolve_condition($_, $as, $for) } @$cond ];
953a18ef 1622 } else {
cf320fd7 1623 $self->throw_exception ("Can't handle condition $cond yet :(");
87772e46 1624 }
1625}
1626
988bf309 1627
6d0ee587 1628# Accepts one or more relationships for the current source and returns an
1629# array of column names for each of those relationships. Column names are
1630# prefixed relative to the current source, in accordance with where they appear
38f42d85 1631# in the supplied relationships.
b3e8ac9b 1632
6d0ee587 1633sub _resolve_prefetch {
1979278e 1634 my ($self, $pre, $alias, $alias_map, $order, $collapse, $pref_path) = @_;
1635 $pref_path ||= [];
1636
8a3fa4ae 1637 if (not defined $pre) {
1638 return ();
1639 }
1640 elsif( ref $pre eq 'ARRAY' ) {
0f66a01b 1641 return
6d0ee587 1642 map { $self->_resolve_prefetch( $_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ) }
0f66a01b 1643 @$pre;
b3e8ac9b 1644 }
1645 elsif( ref $pre eq 'HASH' ) {
1646 my @ret =
1647 map {
6d0ee587 1648 $self->_resolve_prefetch($_, $alias, $alias_map, $order, $collapse, [ @$pref_path ] ),
1649 $self->related_source($_)->_resolve_prefetch(
1979278e 1650 $pre->{$_}, "${alias}.$_", $alias_map, $order, $collapse, [ @$pref_path, $_] )
0f66a01b 1651 } keys %$pre;
b3e8ac9b 1652 return @ret;
1653 }
1654 elsif( ref $pre ) {
a86b1efe 1655 $self->throw_exception(
1656 "don't know how to resolve prefetch reftype ".ref($pre));
b3e8ac9b 1657 }
1658 else {
1979278e 1659 my $p = $alias_map;
1660 $p = $p->{$_} for (@$pref_path, $pre);
1661
1662 $self->throw_exception (
5e8cb53c 1663 "Unable to resolve prefetch '$pre' - join alias map does not contain an entry for path: "
1979278e 1664 . join (' -> ', @$pref_path, $pre)
1665 ) if (ref $p->{-join_aliases} ne 'ARRAY' or not @{$p->{-join_aliases}} );
88a66388 1666
1979278e 1667 my $as = shift @{$p->{-join_aliases}};
1668
b3e8ac9b 1669 my $rel_info = $self->relationship_info( $pre );
455a33cb 1670 $self->throw_exception( $self->source_name . " has no such relationship '$pre'" )
a86b1efe 1671 unless $rel_info;
37f23589 1672 my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : '');
a86b1efe 1673 my $rel_source = $self->related_source($pre);
0f66a01b 1674
b82c8a28 1675 if ($rel_info->{attrs}{accessor} && $rel_info->{attrs}{accessor} eq 'multi') {
0f66a01b 1676 $self->throw_exception(
1677 "Can't prefetch has_many ${pre} (join cond too complex)")
1678 unless ref($rel_info->{cond}) eq 'HASH';
cb136e67 1679 my $dots = @{[$as_prefix =~ m/\./g]} + 1; # +1 to match the ".${as_prefix}"
d5a14c53 1680
cb136e67 1681 if (my ($fail) = grep { @{[$_ =~ m/\./g]} == $dots }
1682 keys %{$collapse}) {
1683 my ($last) = ($fail =~ /([^\.]+)$/);
616b461d 1684 carp (
1685 "Prefetching multiple has_many rels ${last} and ${pre} "
1686 .(length($as_prefix)
1687 ? "at the same level (${as_prefix}) "
1688 : "at top level "
1689 )
2e251255 1690 . 'will explode the number of row objects retrievable via ->next or ->all. '
616b461d 1691 . 'Use at your own risk.'
1692 );
cb136e67 1693 }
d5a14c53 1694
b25e9fa0 1695 #my @col = map { (/^self\.(.+)$/ ? ("${as_prefix}.$1") : ()); }
1696 # values %{$rel_info->{cond}};
b1d8e3fd 1697 $collapse->{".${as_prefix}${pre}"} = [ $rel_source->_pri_cols ];
b25e9fa0 1698 # action at a distance. prepending the '.' allows simpler code
1699 # in ResultSet->_collapse_result
37f23589 1700 my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); }
0f66a01b 1701 keys %{$rel_info->{cond}};
d2fcb9b3 1702 push @$order, map { "${as}.$_" } @key;
fd323bf1 1703
d2fcb9b3 1704 if (my $rel_order = $rel_info->{attrs}{order_by}) {
1705 # this is kludgy and incomplete, I am well aware
1706 # but the parent method is going away entirely anyway
1707 # so sod it
1708 my $sql_maker = $self->storage->sql_maker;
1709 my ($orig_ql, $orig_qr) = $sql_maker->_quote_chars;
1710 my $sep = $sql_maker->name_sep;
1711
1712 # install our own quoter, so we can catch unqualified stuff
1713 local $sql_maker->{quote_char} = ["\x00", "\xFF"];
1714
1715 my $quoted_prefix = "\x00${as}\xFF";
1716
1717 for my $chunk ( $sql_maker->_order_by_chunks ($rel_order) ) {
1718 my @bind;
1719 ($chunk, @bind) = @$chunk if ref $chunk;
1720
1721 $chunk = "${quoted_prefix}${sep}${chunk}"
1722 unless $chunk =~ /\Q$sep/;
1723
1724 $chunk =~ s/\x00/$orig_ql/g;
1725 $chunk =~ s/\xFF/$orig_qr/g;
1726 push @$order, \[$chunk, @bind];
1727 }
1728 }
0f66a01b 1729 }
1730
489709af 1731 return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] }
a86b1efe 1732 $rel_source->columns;
b3e8ac9b 1733 }
1734}
953a18ef 1735
87c4e602 1736=head2 related_source
1737
27f01d1f 1738=over 4
1739
ebc77b53 1740=item Arguments: $relname
27f01d1f 1741
391ccf38 1742=item Return value: $source
1743
27f01d1f 1744=back
87772e46 1745
2053ab2a 1746Returns the result source object for the given relationship.
87772e46 1747
1748=cut
1749
1750sub related_source {
1751 my ($self, $rel) = @_;
aea52c85 1752 if( !$self->has_relationship( $rel ) ) {
455a33cb 1753 $self->throw_exception("No such relationship '$rel' on " . $self->source_name);
aea52c85 1754 }
87772e46 1755 return $self->schema->source($self->relationship_info($rel)->{source});
8452e496 1756}
1757
77254782 1758=head2 related_class
1759
27f01d1f 1760=over 4
1761
ebc77b53 1762=item Arguments: $relname
27f01d1f 1763
391ccf38 1764=item Return value: $classname
1765
27f01d1f 1766=back
77254782 1767
2053ab2a 1768Returns the class name for objects in the given relationship.
77254782 1769
1770=cut
1771
1772sub related_class {
1773 my ($self, $rel) = @_;
1774 if( !$self->has_relationship( $rel ) ) {
455a33cb 1775 $self->throw_exception("No such relationship '$rel' on " . $self->source_name);
77254782 1776 }
1777 return $self->schema->class($self->relationship_info($rel)->{source});
1778}
1779
aec3eff1 1780=head2 handle
1781
4376a157 1782=over 4
1783
1784=item Arguments: None
1785
1786=item Return value: $source_handle
1787
1788=back
1789
1790Obtain a new L<result source handle instance|DBIx::Class::ResultSourceHandle>
1791for this source. Used as a serializable pointer to this resultsource, as it is not
1792easy (nor advisable) to serialize CODErefs which may very well be present in e.g.
1793relationship definitions.
aec3eff1 1794
1795=cut
1796
1797sub handle {
4376a157 1798 return DBIx::Class::ResultSourceHandle->new({
1799 source_moniker => $_[0]->source_name,
1800
1801 # so that a detached thaw can be re-frozen
1802 $_[0]->{_detached_thaw}
1803 ? ( _detached_source => $_[0] )
1804 : ( schema => $_[0]->schema )
1805 ,
1806 });
aec3eff1 1807}
1808
50261284 1809{
1810 my $global_phase_destroy;
1811
1812 END { $global_phase_destroy++ }
1813
1814 sub DESTROY {
1815 return if $global_phase_destroy;
1816
1817######
1818# !!! ACHTUNG !!!!
1819######
1820#
1821# Under no circumstances shall $_[0] be stored anywhere else (like copied to
1822# a lexical variable, or shifted, or anything else). Doing so will mess up
1823# the refcount of this particular result source, and will allow the $schema
1824# we are trying to save to reattach back to the source we are destroying.
1825# The relevant code checking refcounts is in ::Schema::DESTROY()
1826
1827 # if we are not a schema instance holder - we don't matter
1828 return if(
1829 ! ref $_[0]->{schema}
1830 or
1831 isweak $_[0]->{schema}
1832 );
1833
1834 # weaken our schema hold forcing the schema to find somewhere else to live
1835 weaken $_[0]->{schema};
1836
1837 # if schema is still there reintroduce ourselves with strong refs back
1838 if ($_[0]->{schema}) {
1839 my $srcregs = $_[0]->{schema}->source_registrations;
1840 for (keys %$srcregs) {
1841 $srcregs->{$_} = $_[0] if $srcregs->{$_} == $_[0];
1842 }
1843 }
1844 }
1845}
1846
4376a157 1847sub STORABLE_freeze { nfreeze($_[0]->handle) }
50261284 1848
1849sub STORABLE_thaw {
1850 my ($self, $cloning, $ice) = @_;
1851 %$self = %{ (thaw $ice)->resolve };
1852}
1853
701da8c4 1854=head2 throw_exception
1855
2053ab2a 1856See L<DBIx::Class::Schema/"throw_exception">.
701da8c4 1857
1858=cut
1859
1860sub throw_exception {
1861 my $self = shift;
1a58752c 1862
4376a157 1863 $self->{schema}
1864 ? $self->{schema}->throw_exception(@_)
1865 : DBIx::Class::Exception->throw(@_)
1866 ;
701da8c4 1867}
1868
843f6bc1 1869=head2 source_info
d2f3e87b 1870
843f6bc1 1871Stores a hashref of per-source metadata. No specific key names
1872have yet been standardized, the examples below are purely hypothetical
1873and don't actually accomplish anything on their own:
391ccf38 1874
843f6bc1 1875 __PACKAGE__->source_info({
1876 "_tablespace" => 'fast_disk_array_3',
1877 "_engine" => 'InnoDB',
1878 });
391ccf38 1879
843f6bc1 1880=head2 new
391ccf38 1881
843f6bc1 1882 $class->new();
391ccf38 1883
843f6bc1 1884 $class->new({attribute_name => value});
d2f3e87b 1885
843f6bc1 1886Creates a new ResultSource object. Not normally called directly by end users.
391ccf38 1887
843f6bc1 1888=head2 column_info_from_storage
1889
1890=over
1891
1892=item Arguments: 1/0 (default: 0)
1893
1894=item Return value: 1/0
1895
1896=back
1897
880c075b 1898 __PACKAGE__->column_info_from_storage(1);
1899
843f6bc1 1900Enables the on-demand automatic loading of the above column
c1300297 1901metadata from storage as necessary. This is *deprecated*, and
843f6bc1 1902should not be used. It will be removed before 1.0.
1903
f89bb832 1904
9c992ba1 1905=head1 AUTHORS
1906
1907Matt S. Trout <mst@shadowcatsystems.co.uk>
1908
1909=head1 LICENSE
1910
1911You may distribute this code under the same terms as Perl itself.
1912
1913=cut
1914
b25e9fa0 19151;