Fix up is_auto_increment doc
[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;
701da8c4 7use Carp::Clan qw/^DBIx::Class/;
6da5894c 8use Storable;
9
9c992ba1 10use base qw/DBIx::Class/;
11__PACKAGE__->load_components(qw/AccessorGroup/);
12
13__PACKAGE__->mk_group_accessors('simple' =>
fc969005 14 qw/_ordered_columns _columns _primaries _unique_constraints name resultset_attributes schema from _relationships/);
15__PACKAGE__->mk_group_accessors('component_class' => qw/resultset_class result_class/);
9c992ba1 16
17=head1 NAME
18
19DBIx::Class::ResultSource - Result source object
20
21=head1 SYNOPSIS
22
23=head1 DESCRIPTION
24
25A ResultSource is a component of a schema from which results can be directly
26retrieved, most usually a table (see L<DBIx::Class::ResultSource::Table>)
27
28=head1 METHODS
29
30=cut
31
32sub new {
33 my ($class, $attrs) = @_;
34 $class = ref $class if ref $class;
1225fc4d 35 my $new = bless({ %{$attrs || {}}, _resultset => undef }, $class);
9c992ba1 36 $new->{resultset_class} ||= 'DBIx::Class::ResultSet';
5ac6a044 37 $new->{resultset_attributes} = { %{$new->{resultset_attributes} || {}} };
6da5894c 38 $new->{_ordered_columns} = [ @{$new->{_ordered_columns}||[]}];
39 $new->{_columns} = { %{$new->{_columns}||{}} };
40 $new->{_relationships} = { %{$new->{_relationships}||{}} };
9c992ba1 41 $new->{name} ||= "!!NAME NOT SET!!";
5afa2a15 42 $new->{_columns_info_loaded} ||= 0;
9c992ba1 43 return $new;
44}
45
988bf309 46=pod
47
5ac6a044 48=head2 add_columns
49
50 $table->add_columns(qw/col1 col2 col3/);
51
52 $table->add_columns('col1' => \%col1_info, 'col2' => \%col2_info, ...);
53
54Adds columns to the result source. If supplied key => hashref pairs uses
55the hashref as the column_info for that column.
56
988bf309 57Repeated calls of this method will add more columns, not replace them.
58
59The contents of the column_info are not set in stone, the following
60keys are currently recognised/used by DBIx::Class.
61
62=over 4
63
64=item accessor
65
66Use this to set the name of the accessor for this column. If unset,
67the name of the column will be used.
68
69=item data_type
70
71This contains the column type, it is automatically filled by the
72L<SQL::Translator::Producer::DBIx::Class::File> producer, and the
73L<DBIx::Class::Schema::Loader> module. If you do not enter the
74data_type, DBIx::Class will attempt to retrieve it from the
75database for you, using L<DBI>s column_info method. The values of this
76key are typically upper-cased.
77
78Currently there is no standard set of values for the data_type, use
79whatever your database(s) support.
80
81=item size
82
83The length of your column, if it is a column type that can have a size
84restriction. This is currently not used by DBIx::Class.
85
86=item is_nullable
87
88If the column is allowed to contain NULL values, set a true value
89(typically 1), here. This is currently not used by DBIx::Class.
90
91=item is_auto_increment
92
93Set this to a true value if this is a column that is somehow
e666492c 94automatically filled. This is used to determine which columns to empty
95when cloning objects using C<copy>.
988bf309 96
97=item is_foreign_key
98
99Set this to a true value if this column represents a key from a
100foreign table. This is currently not used by DBIx::Class.
101
102=item default_value
103
104Set this to the default value which will be inserted into this column
105by the database. Can contain either values or functions. This is
106currently not used by DBIx::Class.
107
108=item sequence
109
110If your column is using a sequence to create it's values, set the name
111of the sequence here, to allow the values to be retrieved
112automatically by the L<DBIx::Class::PK::Auto> module. PK::Auto will
113attempt to retrieve the sequence name from the database, if this value
114is left unset.
115
116=back
117
5ac6a044 118=head2 add_column
119
120 $table->add_column('col' => \%info?);
121
122Convenience alias to add_columns
123
124=cut
125
9c992ba1 126sub add_columns {
127 my ($self, @cols) = @_;
8e04bf91 128 $self->_ordered_columns(\@cols) unless $self->_ordered_columns;
129
20518cb4 130 my @added;
131 my $columns = $self->_columns;
9c992ba1 132 while (my $col = shift @cols) {
8e04bf91 133 # If next entry is { ... } use that for the column info, if not
134 # use an empty hashref
30126ac7 135 my $column_info = ref $cols[0] ? shift(@cols) : {};
20518cb4 136 push(@added, $col) unless exists $columns->{$col};
20518cb4 137 $columns->{$col} = $column_info;
9c992ba1 138 }
20518cb4 139 push @{ $self->_ordered_columns }, @added;
30126ac7 140 return $self;
9c992ba1 141}
142
143*add_column = \&add_columns;
144
3842b955 145=head2 has_column
146
988bf309 147 if ($obj->has_column($col)) { ... }
148
9c992ba1 149Returns 1 if the source has a column of this name, 0 otherwise.
988bf309 150
151=cut
9c992ba1 152
153sub has_column {
154 my ($self, $column) = @_;
155 return exists $self->_columns->{$column};
156}
157
87c4e602 158=head2 column_info
9c992ba1 159
988bf309 160 my $info = $obj->column_info($col);
9c992ba1 161
988bf309 162Returns the column metadata hashref for a column. See the description
163of add_column for information on the contents of the hashref.
9c992ba1 164
988bf309 165=cut
9c992ba1 166
167sub column_info {
168 my ($self, $column) = @_;
701da8c4 169 $self->throw_exception("No such column $column")
170 unless exists $self->_columns->{$column};
5afa2a15 171 #warn $self->{_columns_info_loaded}, "\n";
8e04bf91 172 if ( ! $self->_columns->{$column}{data_type}
173 and ! $self->{_columns_info_loaded}
174 and $self->schema and $self->storage )
175 {
176 $self->{_columns_info_loaded}++;
177 my $info;
178 # eval for the case of storage without table
179 eval { $info = $self->storage->columns_info_for($self->from) };
180 unless ($@) {
181 foreach my $col ( keys %{$self->_columns} ) {
182 foreach my $i ( keys %{$info->{$col}} ) {
183 $self->_columns->{$col}{$i} = $info->{$col}{$i};
184 }
a953d8d9 185 }
8e04bf91 186 }
a953d8d9 187 }
9c992ba1 188 return $self->_columns->{$column};
189}
190
191=head2 columns
192
20518cb4 193 my @column_names = $obj->columns;
194
195Returns all column names in the order they were declared to add_columns
87f0da6a 196
197=cut
9c992ba1 198
199sub columns {
8e04bf91 200 my $self = shift;
701da8c4 201 $self->throw_exception("columns() is a read-only accessor, did you mean add_columns()?") if (@_ > 1);
202 return @{$self->{_ordered_columns}||[]};
571dced3 203}
204
87c4e602 205=head2 set_primary_key
206
207=head3 Arguments: (@cols)
87f0da6a 208
9c992ba1 209Defines one or more columns as primary key for this source. Should be
210called after C<add_columns>.
87f0da6a 211
212Additionally, defines a unique constraint named C<primary>.
213
988bf309 214The primary key columns are used by L<DBIx::Class::PK::Auto> to
215retrieve automatically created values from the database.
216
87f0da6a 217=cut
9c992ba1 218
219sub set_primary_key {
220 my ($self, @cols) = @_;
221 # check if primary key columns are valid columns
8e04bf91 222 foreach my $col (@cols) {
223 $self->throw_exception("No such column $col on table " . $self->name)
224 unless $self->has_column($col);
9c992ba1 225 }
226 $self->_primaries(\@cols);
87f0da6a 227
228 $self->add_unique_constraint(primary => \@cols);
9c992ba1 229}
230
87f0da6a 231=head2 primary_columns
232
9c992ba1 233Read-only accessor which returns the list of primary keys.
30126ac7 234
87f0da6a 235=cut
9c992ba1 236
237sub primary_columns {
238 return @{shift->_primaries||[]};
239}
240
87f0da6a 241=head2 add_unique_constraint
242
243Declare a unique constraint on this source. Call once for each unique
988bf309 244constraint. Unique constraints are used when you call C<find> on a
958916aa 245L<DBIx::Class::ResultSet>, only columns in the constraint are searched,
87f0da6a 246
247 # For e.g. UNIQUE (column1, column2)
248 __PACKAGE__->add_unique_constraint(constraint_name => [ qw/column1 column2/ ]);
249
250=cut
251
252sub add_unique_constraint {
253 my ($self, $name, $cols) = @_;
254
8e04bf91 255 foreach my $col (@$cols) {
256 $self->throw_exception("No such column $col on table " . $self->name)
257 unless $self->has_column($col);
87f0da6a 258 }
259
260 my %unique_constraints = $self->unique_constraints;
261 $unique_constraints{$name} = $cols;
262 $self->_unique_constraints(\%unique_constraints);
263}
264
265=head2 unique_constraints
266
267Read-only accessor which returns the list of unique constraints on this source.
268
269=cut
270
271sub unique_constraints {
272 return %{shift->_unique_constraints||{}};
273}
274
9c992ba1 275=head2 from
276
277Returns an expression of the source to be supplied to storage to specify
278retrieval from this source; in the case of a database the required FROM clause
279contents.
280
281=cut
282
283=head2 storage
284
988bf309 285Returns the storage handle for the current schema.
286
287See also: L<DBIx::Class::Storage>
9c992ba1 288
289=cut
290
291sub storage { shift->schema->storage; }
292
8452e496 293=head2 add_relationship
294
295 $source->add_relationship('relname', 'related_source', $cond, $attrs);
296
24d67825 297The relationship name can be arbitrary, but must be unique for each
298relationship attached to this result source. 'related_source' should
299be the name with which the related result source was registered with
300the current schema. For example:
8452e496 301
24d67825 302 $schema->source('Book')->add_relationship('reviews', 'Review', {
303 'foreign.book_id' => 'self.id',
304 });
305
306The condition C<$cond> needs to be an SQL::Abstract-style
307representation of the join between the tables. For example, if you're
308creating a rel from Author to Book,
988bf309 309
310 { 'foreign.author_id' => 'self.id' }
311
312will result in the JOIN clause
313
314 author me JOIN book foreign ON foreign.author_id = me.id
315
8452e496 316You can specify as many foreign => self mappings as necessary.
317
988bf309 318Valid attributes are as follows:
319
320=over 4
321
322=item join_type
323
324Explicitly specifies the type of join to use in the relationship. Any
325SQL join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in
326the SQL command immediately before C<JOIN>.
327
328=item proxy
329
24d67825 330An arrayref containing a list of accessors in the foreign class to proxy in
331the main class. If, for example, you do the following:
332
333 CD->might_have(liner_notes => 'LinerNotes', undef, {
334 proxy => [ qw/notes/ ],
335 });
336
337Then, assuming LinerNotes has an accessor named notes, you can do:
988bf309 338
24d67825 339 my $cd = CD->find(1);
340 $cd->notes('Notes go here'); # set notes -- LinerNotes object is
341 # created if it doesn't exist
988bf309 342
343=item accessor
344
345Specifies the type of accessor that should be created for the
346relationship. Valid values are C<single> (for when there is only a single
347related object), C<multi> (when there can be many), and C<filter> (for
348when there is a single related object, but you also want the relationship
349accessor to double as a column accessor). For C<multi> accessors, an
350add_to_* method is also created, which calls C<create_related> for the
351relationship.
352
8452e496 353=back
354
355=cut
356
357sub add_relationship {
358 my ($self, $rel, $f_source_name, $cond, $attrs) = @_;
701da8c4 359 $self->throw_exception("Can't create relationship without join condition") unless $cond;
8452e496 360 $attrs ||= {};
87772e46 361
8452e496 362 my %rels = %{ $self->_relationships };
363 $rels{$rel} = { class => $f_source_name,
87772e46 364 source => $f_source_name,
8452e496 365 cond => $cond,
366 attrs => $attrs };
367 $self->_relationships(\%rels);
368
30126ac7 369 return $self;
87772e46 370
953a18ef 371 # XXX disabled. doesn't work properly currently. skip in tests.
372
8452e496 373 my $f_source = $self->schema->source($f_source_name);
374 unless ($f_source) {
375 eval "require $f_source_name;";
376 if ($@) {
377 die $@ unless $@ =~ /Can't locate/;
378 }
379 $f_source = $f_source_name->result_source;
87772e46 380 #my $s_class = ref($self->schema);
381 #$f_source_name =~ m/^${s_class}::(.*)$/;
382 #$self->schema->register_class(($1 || $f_source_name), $f_source_name);
383 #$f_source = $self->schema->source($f_source_name);
8452e496 384 }
385 return unless $f_source; # Can't test rel without f_source
386
387 eval { $self->resolve_join($rel, 'me') };
388
389 if ($@) { # If the resolve failed, back out and re-throw the error
390 delete $rels{$rel}; #
391 $self->_relationships(\%rels);
701da8c4 392 $self->throw_exception("Error creating relationship $rel: $@");
8452e496 393 }
394 1;
395}
396
87c4e602 397=head2 relationships
8452e496 398
399Returns all valid relationship names for this source
400
401=cut
402
403sub relationships {
404 return keys %{shift->_relationships};
405}
406
87c4e602 407=head2 relationship_info
408
409=head3 Arguments: ($relname)
8452e496 410
411Returns the relationship information for the specified relationship name
412
413=cut
414
415sub relationship_info {
416 my ($self, $rel) = @_;
417 return $self->_relationships->{$rel};
418}
419
87c4e602 420=head2 has_relationship
421
422=head3 Arguments: ($rel)
953a18ef 423
424Returns 1 if the source has a relationship of this name, 0 otherwise.
988bf309 425
426=cut
953a18ef 427
428sub has_relationship {
429 my ($self, $rel) = @_;
430 return exists $self->_relationships->{$rel};
431}
432
87c4e602 433=head2 resolve_join
434
435=head3 Arguments: ($relation)
8452e496 436
437Returns the join structure required for the related result source
438
439=cut
440
441sub resolve_join {
489709af 442 my ($self, $join, $alias, $seen) = @_;
443 $seen ||= {};
87772e46 444 if (ref $join eq 'ARRAY') {
489709af 445 return map { $self->resolve_join($_, $alias, $seen) } @$join;
87772e46 446 } elsif (ref $join eq 'HASH') {
489709af 447 return
887ce227 448 map {
449 my $as = ($seen->{$_} ? $_.'_'.($seen->{$_}+1) : $_);
450 ($self->resolve_join($_, $alias, $seen),
451 $self->related_source($_)->resolve_join($join->{$_}, $as, $seen));
452 } keys %$join;
87772e46 453 } elsif (ref $join) {
701da8c4 454 $self->throw_exception("No idea how to resolve join reftype ".ref $join);
87772e46 455 } else {
489709af 456 my $count = ++$seen->{$join};
457 #use Data::Dumper; warn Dumper($seen);
458 my $as = ($count > 1 ? "${join}_${count}" : $join);
3842b955 459 my $rel_info = $self->relationship_info($join);
701da8c4 460 $self->throw_exception("No such relationship ${join}") unless $rel_info;
3842b955 461 my $type = $rel_info->{attrs}{join_type} || '';
489709af 462 return [ { $as => $self->related_source($join)->from,
953a18ef 463 -join_type => $type },
489709af 464 $self->resolve_condition($rel_info->{cond}, $as, $alias) ];
953a18ef 465 }
466}
467
87c4e602 468=head2 resolve_condition
469
470=head3 Arguments: ($cond, $as, $alias|$object)
953a18ef 471
3842b955 472Resolves the passed condition to a concrete query fragment. If given an alias,
953a18ef 473returns a join condition; if given an object, inverts that object to produce
474a related conditional from that object.
475
476=cut
477
478sub resolve_condition {
489709af 479 my ($self, $cond, $as, $for) = @_;
953a18ef 480 #warn %$cond;
481 if (ref $cond eq 'HASH') {
482 my %ret;
483 while (my ($k, $v) = each %{$cond}) {
484 # XXX should probably check these are valid columns
701da8c4 485 $k =~ s/^foreign\.// || $self->throw_exception("Invalid rel cond key ${k}");
486 $v =~ s/^self\.// || $self->throw_exception("Invalid rel cond val ${v}");
953a18ef 487 if (ref $for) { # Object
3842b955 488 #warn "$self $k $for $v";
489 $ret{$k} = $for->get_column($v);
490 #warn %ret;
fde6e28e 491 } elsif (ref $as) { # reverse object
492 $ret{$v} = $as->get_column($k);
953a18ef 493 } else {
489709af 494 $ret{"${as}.${k}"} = "${for}.${v}";
953a18ef 495 }
953a18ef 496 }
497 return \%ret;
5efe4c79 498 } elsif (ref $cond eq 'ARRAY') {
489709af 499 return [ map { $self->resolve_condition($_, $as, $for) } @$cond ];
953a18ef 500 } else {
501 die("Can't handle this yet :(");
87772e46 502 }
503}
504
87c4e602 505=head2 resolve_prefetch
506
507=head3 Arguments: (hashref/arrayref/scalar)
988bf309 508
b3e8ac9b 509Accepts one or more relationships for the current source and returns an
510array of column names for each of those relationships. Column names are
511prefixed relative to the current source, in accordance with where they appear
512in the supplied relationships. Examples:
513
5ac6a044 514 my $source = $schema->resultset('Tag')->source;
b3e8ac9b 515 @columns = $source->resolve_prefetch( { cd => 'artist' } );
516
517 # @columns =
518 #(
519 # 'cd.cdid',
520 # 'cd.artist',
521 # 'cd.title',
522 # 'cd.year',
523 # 'cd.artist.artistid',
524 # 'cd.artist.name'
525 #)
526
527 @columns = $source->resolve_prefetch( qw[/ cd /] );
528
529 # @columns =
530 #(
531 # 'cd.cdid',
532 # 'cd.artist',
533 # 'cd.title',
534 # 'cd.year'
535 #)
536
537 $source = $schema->resultset('CD')->source;
538 @columns = $source->resolve_prefetch( qw[/ artist producer /] );
539
540 # @columns =
541 #(
542 # 'artist.artistid',
543 # 'artist.name',
544 # 'producer.producerid',
545 # 'producer.name'
546 #)
988bf309 547
b3e8ac9b 548=cut
549
550sub resolve_prefetch {
0f66a01b 551 my ($self, $pre, $alias, $seen, $order, $collapse) = @_;
489709af 552 $seen ||= {};
b3e8ac9b 553 #$alias ||= $self->name;
554 #warn $alias, Dumper $pre;
555 if( ref $pre eq 'ARRAY' ) {
0f66a01b 556 return
557 map { $self->resolve_prefetch( $_, $alias, $seen, $order, $collapse ) }
558 @$pre;
b3e8ac9b 559 }
560 elsif( ref $pre eq 'HASH' ) {
561 my @ret =
562 map {
0f66a01b 563 $self->resolve_prefetch($_, $alias, $seen, $order, $collapse),
489709af 564 $self->related_source($_)->resolve_prefetch(
0f66a01b 565 $pre->{$_}, "${alias}.$_", $seen, $order, $collapse)
566 } keys %$pre;
b3e8ac9b 567 #die Dumper \@ret;
568 return @ret;
569 }
570 elsif( ref $pre ) {
a86b1efe 571 $self->throw_exception(
572 "don't know how to resolve prefetch reftype ".ref($pre));
b3e8ac9b 573 }
574 else {
489709af 575 my $count = ++$seen->{$pre};
576 my $as = ($count > 1 ? "${pre}_${count}" : $pre);
b3e8ac9b 577 my $rel_info = $self->relationship_info( $pre );
a86b1efe 578 $self->throw_exception( $self->name . " has no such relationship '$pre'" )
579 unless $rel_info;
37f23589 580 my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : '');
a86b1efe 581 my $rel_source = $self->related_source($pre);
0f66a01b 582
583 if (exists $rel_info->{attrs}{accessor}
584 && $rel_info->{attrs}{accessor} eq 'multi') {
585 $self->throw_exception(
586 "Can't prefetch has_many ${pre} (join cond too complex)")
587 unless ref($rel_info->{cond}) eq 'HASH';
37f23589 588 my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); }
0f66a01b 589 keys %{$rel_info->{cond}};
590 $collapse->{"${as_prefix}${pre}"} = \@key;
5a5bec6c 591 my @ord = (ref($rel_info->{attrs}{order_by}) eq 'ARRAY'
592 ? @{$rel_info->{attrs}{order_by}}
593 : (defined $rel_info->{attrs}{order_by}
594 ? ($rel_info->{attrs}{order_by})
595 : ()));
596 push(@$order, map { "${as}.$_" } (@key, @ord));
0f66a01b 597 }
598
489709af 599 return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] }
a86b1efe 600 $rel_source->columns;
b3e8ac9b 601 #warn $alias, Dumper (\@ret);
489709af 602 #return @ret;
b3e8ac9b 603 }
604}
953a18ef 605
87c4e602 606=head2 related_source
607
608=head3 Arguments: ($relname)
87772e46 609
988bf309 610Returns the result source object for the given relationship
87772e46 611
612=cut
613
614sub related_source {
615 my ($self, $rel) = @_;
aea52c85 616 if( !$self->has_relationship( $rel ) ) {
701da8c4 617 $self->throw_exception("No such relationship '$rel'");
aea52c85 618 }
87772e46 619 return $self->schema->source($self->relationship_info($rel)->{source});
8452e496 620}
621
77254782 622=head2 related_class
623
624=head3 Arguments: ($relname)
625
626Returns the class object for the given relationship
627
628=cut
629
630sub related_class {
631 my ($self, $rel) = @_;
632 if( !$self->has_relationship( $rel ) ) {
633 $self->throw_exception("No such relationship '$rel'");
634 }
635 return $self->schema->class($self->relationship_info($rel)->{source});
636}
637
5ac6a044 638=head2 resultset
639
bcc5a210 640Returns a resultset for the given source. This will initially be created
641on demand by calling
5ac6a044 642
988bf309 643 $self->resultset_class->new($self, $self->resultset_attributes)
5ac6a044 644
bcc5a210 645but is cached from then on unless resultset_class changes.
646
5ac6a044 647=head2 resultset_class
648
988bf309 649Set the class of the resultset, this is useful if you want to create your
650own resultset methods. Create your own class derived from
651L<DBIx::Class::ResultSet>, and set it here.
5ac6a044 652
653=head2 resultset_attributes
654
988bf309 655Specify here any attributes you wish to pass to your specialised resultset.
5ac6a044 656
657=cut
658
659sub resultset {
660 my $self = shift;
e0f56292 661 $self->throw_exception('resultset does not take any arguments. If you want another resultset, call it on the schema instead.') if scalar @_;
1225fc4d 662 return $self->{_resultset} if ref $self->{_resultset} eq $self->resultset_class;
bcd26419 663 return $self->{_resultset} = $self->resultset_class->new($self, $self->{resultset_attributes});
5ac6a044 664}
665
701da8c4 666=head2 throw_exception
667
988bf309 668See throw_exception in L<DBIx::Class::Schema>.
701da8c4 669
670=cut
671
672sub throw_exception {
673 my $self = shift;
674 if (defined $self->schema) {
675 $self->schema->throw_exception(@_);
676 } else {
677 croak(@_);
678 }
679}
680
681
9c992ba1 682=head1 AUTHORS
683
684Matt S. Trout <mst@shadowcatsystems.co.uk>
685
686=head1 LICENSE
687
688You may distribute this code under the same terms as Perl itself.
689
690=cut
691