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