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