1 package DBIx::Class::ResultSource;
6 use DBIx::Class::ResultSet;
7 use Carp::Clan qw/^DBIx::Class/;
10 use base qw/DBIx::Class/;
11 __PACKAGE__->load_components(qw/AccessorGroup/);
13 __PACKAGE__->mk_group_accessors('simple' => qw/_ordered_columns
14 _columns _primaries _unique_constraints name resultset_attributes
15 schema from _relationships/);
17 __PACKAGE__->mk_group_accessors('component_class' => qw/resultset_class
18 result_class source_name/);
22 DBIx::Class::ResultSource - Result source object
28 A ResultSource is a component of a schema from which results can be directly
29 retrieved, most usually a table (see L<DBIx::Class::ResultSource::Table>)
39 $class->new({attribute_name => value});
41 Creates a new ResultSource object. Not normally called directly by end users.
46 my ($class, $attrs) = @_;
47 $class = ref $class if ref $class;
48 my $new = bless({ %{$attrs || {}}, _resultset => undef }, $class);
49 $new->{resultset_class} ||= 'DBIx::Class::ResultSet';
50 $new->{resultset_attributes} = { %{$new->{resultset_attributes} || {}} };
51 $new->{_ordered_columns} = [ @{$new->{_ordered_columns}||[]}];
52 $new->{_columns} = { %{$new->{_columns}||{}} };
53 $new->{_relationships} = { %{$new->{_relationships}||{}} };
54 $new->{name} ||= "!!NAME NOT SET!!";
55 $new->{_columns_info_loaded} ||= 0;
63 $table->add_columns(qw/col1 col2 col3/);
65 $table->add_columns('col1' => \%col1_info, 'col2' => \%col2_info, ...);
67 Adds columns to the result source. If supplied key => hashref pairs, uses
68 the hashref as the column_info for that column. Repeated calls of this
69 method will add more columns, not replace them.
71 The contents of the column_info are not set in stone. The following
72 keys are currently recognised/used by DBIx::Class:
78 Use this to set the name of the accessor for this column. If unset,
79 the name of the column will be used.
83 This contains the column type. It is automatically filled by the
84 L<SQL::Translator::Producer::DBIx::Class::File> producer, and the
85 L<DBIx::Class::Schema::Loader> module. If you do not enter a
86 data_type, DBIx::Class will attempt to retrieve it from the
87 database for you, using L<DBI>'s column_info method. The values of this
88 key are typically upper-cased.
90 Currently there is no standard set of values for the data_type. Use
91 whatever your database supports.
95 The length of your column, if it is a column type that can have a size
96 restriction. This is currently not used by DBIx::Class.
100 Set this to a true value for a columns that is allowed to contain
101 NULL values. This is currently not used by DBIx::Class.
103 =item is_auto_increment
105 Set this to a true value for a column whose value is somehow
106 automatically set. This is used to determine which columns to empty
107 when cloning objects using C<copy>.
111 Set this to a true value for a column that contains a key from a
112 foreign table. This is currently not used by DBIx::Class.
116 Set this to the default value which will be inserted into a column
117 by the database. Can contain either a value or a function. This is
118 currently not used by DBIx::Class.
122 Set this on a primary key column to the name of the sequence used to
123 generate a new key value. If not specified, L<DBIx::Class::PK::Auto>
124 will attempt to retrieve the name of the sequence from the database
131 $table->add_column('col' => \%info?);
133 Convenience alias to add_columns.
138 my ($self, @cols) = @_;
139 $self->_ordered_columns(\@cols) unless $self->_ordered_columns;
142 my $columns = $self->_columns;
143 while (my $col = shift @cols) {
144 # If next entry is { ... } use that for the column info, if not
145 # use an empty hashref
146 my $column_info = ref $cols[0] ? shift(@cols) : {};
147 push(@added, $col) unless exists $columns->{$col};
148 $columns->{$col} = $column_info;
150 push @{ $self->_ordered_columns }, @added;
154 *add_column = \&add_columns;
158 if ($obj->has_column($col)) { ... }
160 Returns true if the source has a column of this name, false otherwise.
165 my ($self, $column) = @_;
166 return exists $self->_columns->{$column};
171 my $info = $obj->column_info($col);
173 Returns the column metadata hashref for a column. See the description
174 of add_column for information on the contents of the hashref.
179 my ($self, $column) = @_;
180 $self->throw_exception("No such column $column")
181 unless exists $self->_columns->{$column};
182 #warn $self->{_columns_info_loaded}, "\n";
183 if ( ! $self->_columns->{$column}{data_type}
184 and ! $self->{_columns_info_loaded}
185 and $self->schema and $self->storage )
187 $self->{_columns_info_loaded}++;
190 # eval for the case of storage without table
191 eval { $info = $self->storage->columns_info_for( $self->from, keys %{$self->_columns} ) };
193 for my $realcol ( keys %{$info} ) {
194 $lc_info->{lc $realcol} = $info->{$realcol};
196 foreach my $col ( keys %{$self->_columns} ) {
197 $self->_columns->{$col} = { %{ $self->_columns->{$col}}, %{$info->{$col} || $lc_info->{lc $col}} };
201 return $self->_columns->{$column};
206 my @column_names = $obj->columns;
208 Returns all column names in the order they were declared to add_columns.
214 $self->throw_exception(
215 "columns() is a read-only accessor, did you mean add_columns()?"
217 return @{$self->{_ordered_columns}||[]};
220 =head2 remove_columns
222 $table->remove_columns(qw/col1 col2 col3/);
224 Removes columns from the result source.
228 $table->remove_column('col');
230 Convenience alias to remove_columns.
235 my ($self, @cols) = @_;
237 return unless $self->_ordered_columns;
239 my $columns = $self->_columns;
242 foreach my $col (@{$self->_ordered_columns}) {
243 push @remaining, $col unless grep(/$col/, @cols);
247 undef $columns->{$_};
250 $self->_ordered_columns(\@remaining);
253 *remove_column = \&remove_columns;
255 =head2 set_primary_key
259 =item Arguments: @cols
263 Defines one or more columns as primary key for this source. Should be
264 called after C<add_columns>.
266 Additionally, defines a unique constraint named C<primary>.
268 The primary key columns are used by L<DBIx::Class::PK::Auto> to
269 retrieve automatically created values from the database.
273 sub set_primary_key {
274 my ($self, @cols) = @_;
275 # check if primary key columns are valid columns
276 foreach my $col (@cols) {
277 $self->throw_exception("No such column $col on table " . $self->name)
278 unless $self->has_column($col);
280 $self->_primaries(\@cols);
282 $self->add_unique_constraint(primary => \@cols);
285 =head2 primary_columns
287 Read-only accessor which returns the list of primary keys.
291 sub primary_columns {
292 return @{shift->_primaries||[]};
295 =head2 add_unique_constraint
297 Declare a unique constraint on this source. Call once for each unique
300 # For UNIQUE (column1, column2)
301 __PACKAGE__->add_unique_constraint(
302 constraint_name => [ qw/column1 column2/ ],
305 Alternatively, you can specify only the columns:
307 __PACKAGE__->add_unique_constraint([ qw/column1 column2/ ]);
309 This will result in a unique constraint named C<table_column1_column2>, where
310 C<table> is replaced with the table name.
312 Unique constraints are used, for example, when you call
313 L<DBIx::Class::ResultSet/find>. Only columns in the constraint are searched.
317 sub add_unique_constraint {
322 $name ||= $self->name_unique_constraint($cols);
324 foreach my $col (@$cols) {
325 $self->throw_exception("No such column $col on table " . $self->name)
326 unless $self->has_column($col);
329 my %unique_constraints = $self->unique_constraints;
330 $unique_constraints{$name} = $cols;
331 $self->_unique_constraints(\%unique_constraints);
334 =head2 name_unique_constraint
336 Return a name for a unique constraint containing the specified columns. These
337 names consist of the table name and each column name, separated by underscores.
339 For example, a constraint on a table named C<cd> containing the columns
340 C<artist> and C<title> would result in a constraint name of C<cd_artist_title>.
344 sub name_unique_constraint {
345 my ($self, $cols) = @_;
347 return join '_', $self->name, @$cols;
350 =head2 unique_constraints
352 Read-only accessor which returns the list of unique constraints on this source.
356 sub unique_constraints {
357 return %{shift->_unique_constraints||{}};
360 =head2 unique_constraint_names
362 Returns the list of unique constraint names defined on this source.
366 sub unique_constraint_names {
369 my %unique_constraints = $self->unique_constraints;
371 return keys %unique_constraints;
374 =head2 unique_constraint_columns
376 Returns the list of columns that make up the specified unique constraint.
380 sub unique_constraint_columns {
381 my ($self, $constraint_name) = @_;
383 my %unique_constraints = $self->unique_constraints;
385 $self->throw_exception(
386 "Unknown unique constraint $constraint_name on '" . $self->name . "'"
387 ) unless exists $unique_constraints{$constraint_name};
389 return @{ $unique_constraints{$constraint_name} };
394 Returns an expression of the source to be supplied to storage to specify
395 retrieval from this source. In the case of a database, the required FROM
400 Returns the L<DBIx::Class::Schema> object that this result source
405 Returns the storage handle for the current schema.
407 See also: L<DBIx::Class::Storage>
411 sub storage { shift->schema->storage; }
413 =head2 add_relationship
415 $source->add_relationship('relname', 'related_source', $cond, $attrs);
417 The relationship name can be arbitrary, but must be unique for each
418 relationship attached to this result source. 'related_source' should
419 be the name with which the related result source was registered with
420 the current schema. For example:
422 $schema->source('Book')->add_relationship('reviews', 'Review', {
423 'foreign.book_id' => 'self.id',
426 The condition C<$cond> needs to be an L<SQL::Abstract>-style
427 representation of the join between the tables. For example, if you're
428 creating a rel from Author to Book,
430 { 'foreign.author_id' => 'self.id' }
432 will result in the JOIN clause
434 author me JOIN book foreign ON foreign.author_id = me.id
436 You can specify as many foreign => self mappings as necessary.
438 Valid attributes are as follows:
444 Explicitly specifies the type of join to use in the relationship. Any
445 SQL join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in
446 the SQL command immediately before C<JOIN>.
450 An arrayref containing a list of accessors in the foreign class to proxy in
451 the main class. If, for example, you do the following:
453 CD->might_have(liner_notes => 'LinerNotes', undef, {
454 proxy => [ qw/notes/ ],
457 Then, assuming LinerNotes has an accessor named notes, you can do:
459 my $cd = CD->find(1);
460 # set notes -- LinerNotes object is created if it doesn't exist
461 $cd->notes('Notes go here');
465 Specifies the type of accessor that should be created for the
466 relationship. Valid values are C<single> (for when there is only a single
467 related object), C<multi> (when there can be many), and C<filter> (for
468 when there is a single related object, but you also want the relationship
469 accessor to double as a column accessor). For C<multi> accessors, an
470 add_to_* method is also created, which calls C<create_related> for the
477 sub add_relationship {
478 my ($self, $rel, $f_source_name, $cond, $attrs) = @_;
479 $self->throw_exception("Can't create relationship without join condition")
483 my %rels = %{ $self->_relationships };
484 $rels{$rel} = { class => $f_source_name,
485 source => $f_source_name,
488 $self->_relationships(\%rels);
492 # XXX disabled. doesn't work properly currently. skip in tests.
494 my $f_source = $self->schema->source($f_source_name);
496 $self->ensure_class_loaded($f_source_name);
497 $f_source = $f_source_name->result_source;
498 #my $s_class = ref($self->schema);
499 #$f_source_name =~ m/^${s_class}::(.*)$/;
500 #$self->schema->register_class(($1 || $f_source_name), $f_source_name);
501 #$f_source = $self->schema->source($f_source_name);
503 return unless $f_source; # Can't test rel without f_source
505 eval { $self->resolve_join($rel, 'me') };
507 if ($@) { # If the resolve failed, back out and re-throw the error
508 delete $rels{$rel}; #
509 $self->_relationships(\%rels);
510 $self->throw_exception("Error creating relationship $rel: $@");
517 Returns all relationship names for this source.
522 return keys %{shift->_relationships};
525 =head2 relationship_info
529 =item Arguments: $relname
533 Returns a hash of relationship information for the specified relationship
538 sub relationship_info {
539 my ($self, $rel) = @_;
540 return $self->_relationships->{$rel};
543 =head2 has_relationship
547 =item Arguments: $rel
551 Returns true if the source has a relationship of this name, false otherwise.
555 sub has_relationship {
556 my ($self, $rel) = @_;
557 return exists $self->_relationships->{$rel};
560 =head2 reverse_relationship_info
564 =item Arguments: $relname
568 Returns an array of hash references of relationship information for
569 the other side of the specified relationship name.
573 sub reverse_relationship_info {
574 my ($self, $rel) = @_;
575 my $rel_info = $self->relationship_info($rel);
578 return $ret unless ((ref $rel_info->{cond}) eq 'HASH');
580 my @cond = keys(%{$rel_info->{cond}});
581 my @refkeys = map {/^\w+\.(\w+)$/} @cond;
582 my @keys = map {$rel_info->{cond}->{$_} =~ /^\w+\.(\w+)$/} @cond;
584 # Get the related result source for this relationship
585 my $othertable = $self->related_source($rel);
587 # Get all the relationships for that source that related to this source
588 # whose foreign column set are our self columns on $rel and whose self
589 # columns are our foreign columns on $rel.
590 my @otherrels = $othertable->relationships();
591 my $otherrelationship;
592 foreach my $otherrel (@otherrels) {
593 my $otherrel_info = $othertable->relationship_info($otherrel);
595 my $back = $othertable->related_source($otherrel);
596 next unless $back->name eq $self->name;
600 if (ref $otherrel_info->{cond} eq 'HASH') {
601 @othertestconds = ($otherrel_info->{cond});
603 elsif (ref $otherrel_info->{cond} eq 'ARRAY') {
604 @othertestconds = @{$otherrel_info->{cond}};
610 foreach my $othercond (@othertestconds) {
611 my @other_cond = keys(%$othercond);
612 my @other_refkeys = map {/^\w+\.(\w+)$/} @other_cond;
613 my @other_keys = map {$othercond->{$_} =~ /^\w+\.(\w+)$/} @other_cond;
614 next if (!$self->compare_relationship_keys(\@refkeys, \@other_keys) ||
615 !$self->compare_relationship_keys(\@other_refkeys, \@keys));
616 $ret->{$otherrel} = $otherrel_info;
622 =head2 compare_relationship_keys
626 =item Arguments: $keys1, $keys2
630 Returns true if both sets of keynames are the same, false otherwise.
634 sub compare_relationship_keys {
635 my ($self, $keys1, $keys2) = @_;
637 # Make sure every keys1 is in keys2
639 foreach my $key (@$keys1) {
641 foreach my $prim (@$keys2) {
650 # Make sure every key2 is in key1
652 foreach my $prim (@$keys2) {
654 foreach my $key (@$keys1) {
671 =item Arguments: $relation
675 Returns the join structure required for the related result source.
680 my ($self, $join, $alias, $seen) = @_;
682 if (ref $join eq 'ARRAY') {
683 return map { $self->resolve_join($_, $alias, $seen) } @$join;
684 } elsif (ref $join eq 'HASH') {
687 my $as = ($seen->{$_} ? $_.'_'.($seen->{$_}+1) : $_);
688 ($self->resolve_join($_, $alias, $seen),
689 $self->related_source($_)->resolve_join($join->{$_}, $as, $seen));
691 } elsif (ref $join) {
692 $self->throw_exception("No idea how to resolve join reftype ".ref $join);
694 my $count = ++$seen->{$join};
695 #use Data::Dumper; warn Dumper($seen);
696 my $as = ($count > 1 ? "${join}_${count}" : $join);
697 my $rel_info = $self->relationship_info($join);
698 $self->throw_exception("No such relationship ${join}") unless $rel_info;
699 my $type = $rel_info->{attrs}{join_type} || '';
700 return [ { $as => $self->related_source($join)->from,
701 -join_type => $type },
702 $self->resolve_condition($rel_info->{cond}, $as, $alias) ];
706 =head2 resolve_condition
710 =item Arguments: $cond, $as, $alias|$object
714 Resolves the passed condition to a concrete query fragment. If given an alias,
715 returns a join condition; if given an object, inverts that object to produce
716 a related conditional from that object.
720 sub resolve_condition {
721 my ($self, $cond, $as, $for) = @_;
723 if (ref $cond eq 'HASH') {
725 foreach my $k (keys %{$cond}) {
727 # XXX should probably check these are valid columns
728 $k =~ s/^foreign\.// ||
729 $self->throw_exception("Invalid rel cond key ${k}");
731 $self->throw_exception("Invalid rel cond val ${v}");
732 if (ref $for) { # Object
733 #warn "$self $k $for $v";
734 $ret{$k} = $for->get_column($v);
736 } elsif (!defined $for) { # undef, i.e. "no object"
738 } elsif (ref $as) { # reverse object
739 $ret{$v} = $as->get_column($k);
740 } elsif (!defined $as) { # undef, i.e. "no reverse object"
743 $ret{"${as}.${k}"} = "${for}.${v}";
747 } elsif (ref $cond eq 'ARRAY') {
748 return [ map { $self->resolve_condition($_, $as, $for) } @$cond ];
750 die("Can't handle this yet :(");
754 =head2 resolve_prefetch
758 =item Arguments: hashref/arrayref/scalar
762 Accepts one or more relationships for the current source and returns an
763 array of column names for each of those relationships. Column names are
764 prefixed relative to the current source, in accordance with where they appear
765 in the supplied relationships. Examples:
767 my $source = $schema->resultset('Tag')->source;
768 @columns = $source->resolve_prefetch( { cd => 'artist' } );
776 # 'cd.artist.artistid',
780 @columns = $source->resolve_prefetch( qw[/ cd /] );
790 $source = $schema->resultset('CD')->source;
791 @columns = $source->resolve_prefetch( qw[/ artist producer /] );
797 # 'producer.producerid',
803 sub resolve_prefetch {
804 my ($self, $pre, $alias, $seen, $order, $collapse) = @_;
806 #$alias ||= $self->name;
807 #warn $alias, Dumper $pre;
808 if( ref $pre eq 'ARRAY' ) {
810 map { $self->resolve_prefetch( $_, $alias, $seen, $order, $collapse ) }
813 elsif( ref $pre eq 'HASH' ) {
816 $self->resolve_prefetch($_, $alias, $seen, $order, $collapse),
817 $self->related_source($_)->resolve_prefetch(
818 $pre->{$_}, "${alias}.$_", $seen, $order, $collapse)
824 $self->throw_exception(
825 "don't know how to resolve prefetch reftype ".ref($pre));
828 my $count = ++$seen->{$pre};
829 my $as = ($count > 1 ? "${pre}_${count}" : $pre);
830 my $rel_info = $self->relationship_info( $pre );
831 $self->throw_exception( $self->name . " has no such relationship '$pre'" )
833 my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : '');
834 my $rel_source = $self->related_source($pre);
836 if (exists $rel_info->{attrs}{accessor}
837 && $rel_info->{attrs}{accessor} eq 'multi') {
838 $self->throw_exception(
839 "Can't prefetch has_many ${pre} (join cond too complex)")
840 unless ref($rel_info->{cond}) eq 'HASH';
841 my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); }
842 keys %{$rel_info->{cond}};
843 $collapse->{"${as_prefix}${pre}"} = \@key;
844 my @ord = (ref($rel_info->{attrs}{order_by}) eq 'ARRAY'
845 ? @{$rel_info->{attrs}{order_by}}
846 : (defined $rel_info->{attrs}{order_by}
847 ? ($rel_info->{attrs}{order_by})
849 push(@$order, map { "${as}.$_" } (@key, @ord));
852 return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] }
853 $rel_source->columns;
854 #warn $alias, Dumper (\@ret);
859 =head2 related_source
863 =item Arguments: $relname
867 Returns the result source object for the given relationship.
872 my ($self, $rel) = @_;
873 if( !$self->has_relationship( $rel ) ) {
874 $self->throw_exception("No such relationship '$rel'");
876 return $self->schema->source($self->relationship_info($rel)->{source});
883 =item Arguments: $relname
887 Returns the class name for objects in the given relationship.
892 my ($self, $rel) = @_;
893 if( !$self->has_relationship( $rel ) ) {
894 $self->throw_exception("No such relationship '$rel'");
896 return $self->schema->class($self->relationship_info($rel)->{source});
901 Returns a resultset for the given source. This will initially be created
904 $self->resultset_class->new($self, $self->resultset_attributes)
906 but is cached from then on unless resultset_class changes.
908 =head2 resultset_class
910 Set the class of the resultset, this is useful if you want to create your
911 own resultset methods. Create your own class derived from
912 L<DBIx::Class::ResultSet>, and set it here.
914 =head2 resultset_attributes
916 Specify here any attributes you wish to pass to your specialised resultset.
922 $self->throw_exception(
923 'resultset does not take any arguments. If you want another resultset, '.
924 'call it on the schema instead.'
927 # disabled until we can figure out a way to do it without consistency issues
929 #return $self->{_resultset}
930 # if ref $self->{_resultset} eq $self->resultset_class;
931 #return $self->{_resultset} =
933 return $self->resultset_class->new(
934 $self, $self->{resultset_attributes}
942 =item Arguments: $source_name
946 Set the name of the result source when it is loaded into a schema.
947 This is usefull if you want to refer to a result source by a name other than
950 package ArchivedBooks;
951 use base qw/DBIx::Class/;
952 __PACKAGE__->table('books_archive');
953 __PACKAGE__->source_name('Books');
955 # from your schema...
956 $schema->resultset('Books')->find(1);
958 =head2 throw_exception
960 See L<DBIx::Class::Schema/"throw_exception">.
964 sub throw_exception {
966 if (defined $self->schema) {
967 $self->schema->throw_exception(@_);
975 Matt S. Trout <mst@shadowcatsystems.co.uk>
979 You may distribute this code under the same terms as Perl itself.