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