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