X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FResultSource.pm;h=53da27b8831beb1d64441289d717e306eaef21c3;hb=002a359a8e58e2ffdc2b571231a8a6f209056ffe;hp=e4ba46faa888affa49e5389265b7e843d119a4ab;hpb=24d67825c6b2e604a349ccd5de0df1956c0d98dc;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/ResultSource.pm b/lib/DBIx/Class/ResultSource.pm index e4ba46f..53da27b 100644 --- a/lib/DBIx/Class/ResultSource.pm +++ b/lib/DBIx/Class/ResultSource.pm @@ -10,11 +10,14 @@ use Storable; use base qw/DBIx::Class/; __PACKAGE__->load_components(qw/AccessorGroup/); -__PACKAGE__->mk_group_accessors('simple' => - qw/_ordered_columns _columns _primaries _unique_constraints name resultset_attributes schema from _relationships/); -__PACKAGE__->mk_group_accessors('component_class' => qw/resultset_class result_class/); +__PACKAGE__->mk_group_accessors('simple' => qw/_ordered_columns + _columns _primaries _unique_constraints name resultset_attributes + schema from _relationships/); -=head1 NAME +__PACKAGE__->mk_group_accessors('component_class' => qw/resultset_class + result_class/); + +=head1 NAME DBIx::Class::ResultSource - Result source object @@ -51,66 +54,65 @@ sub new { $table->add_columns('col1' => \%col1_info, 'col2' => \%col2_info, ...); -Adds columns to the result source. If supplied key => hashref pairs uses -the hashref as the column_info for that column. - -Repeated calls of this method will add more columns, not replace them. +Adds columns to the result source. If supplied key => hashref pairs, uses +the hashref as the column_info for that column. Repeated calls of this +method will add more columns, not replace them. -The contents of the column_info are not set in stone, the following -keys are currently recognised/used by DBIx::Class. +The contents of the column_info are not set in stone. The following +keys are currently recognised/used by DBIx::Class: =over 4 -=item accessor +=item accessor Use this to set the name of the accessor for this column. If unset, the name of the column will be used. =item data_type -This contains the column type, it is automatically filled by the +This contains the column type. It is automatically filled by the L producer, and the -L module. If you do not enter the +L module. If you do not enter a data_type, DBIx::Class will attempt to retrieve it from the -database for you, using Ls column_info method. The values of this +database for you, using L's column_info method. The values of this key are typically upper-cased. -Currently there is no standard set of values for the data_type, use -whatever your database(s) support. +Currently there is no standard set of values for the data_type. Use +whatever your database supports. =item size The length of your column, if it is a column type that can have a size -restriction. This is currently not used by DBIx::Class. +restriction. This is currently not used by DBIx::Class. =item is_nullable -If the column is allowed to contain NULL values, set a true value -(typically 1), here. This is currently not used by DBIx::Class. +Set this to a true value for a columns that is allowed to contain +NULL values. This is currently not used by DBIx::Class. =item is_auto_increment -Set this to a true value if this is a column that is somehow -automatically filled. This is currently not used by DBIx::Class. +Set this to a true value for a column whose value is somehow +automatically set. This is used to determine which columns to empty +when cloning objects using C. =item is_foreign_key -Set this to a true value if this column represents a key from a +Set this to a true value for a column that contains a key from a foreign table. This is currently not used by DBIx::Class. =item default_value -Set this to the default value which will be inserted into this column -by the database. Can contain either values or functions. This is -currently not used by DBIx::Class. +Set this to the default value which will be inserted into a column +by the database. Can contain either a value or a function. This is +currently not used by DBIx::Class. =item sequence -If your column is using a sequence to create it's values, set the name -of the sequence here, to allow the values to be retrieved -automatically by the L module. PK::Auto will -attempt to retrieve the sequence name from the database, if this value -is left unset. +Set this on a primary key column to the name of the sequence used to +generate a new key value. If not specified, L +will attempt to retrieve the name of the sequence from the database +automatically. =back @@ -118,14 +120,14 @@ is left unset. $table->add_column('col' => \%info?); -Convenience alias to add_columns +Convenience alias to add_columns. =cut sub add_columns { my ($self, @cols) = @_; $self->_ordered_columns(\@cols) unless $self->_ordered_columns; - + my @added; my $columns = $self->_columns; while (my $col = shift @cols) { @@ -145,7 +147,7 @@ sub add_columns { if ($obj->has_column($col)) { ... } -Returns 1 if the source has a column of this name, 0 otherwise. +Returns true if the source has a column of this name, false otherwise. =cut @@ -165,16 +167,16 @@ of add_column for information on the contents of the hashref. sub column_info { my ($self, $column) = @_; - $self->throw_exception("No such column $column") + $self->throw_exception("No such column $column") unless exists $self->_columns->{$column}; #warn $self->{_columns_info_loaded}, "\n"; - if ( ! $self->_columns->{$column}{data_type} - and ! $self->{_columns_info_loaded} + if ( ! $self->_columns->{$column}{data_type} + and ! $self->{_columns_info_loaded} and $self->schema and $self->storage ) { $self->{_columns_info_loaded}++; my $info; - # eval for the case of storage without table + # eval for the case of storage without table eval { $info = $self->storage->columns_info_for($self->from) }; unless ($@) { foreach my $col ( keys %{$self->_columns} ) { @@ -191,19 +193,60 @@ sub column_info { my @column_names = $obj->columns; -Returns all column names in the order they were declared to add_columns +Returns all column names in the order they were declared to add_columns. =cut sub columns { my $self = shift; - $self->throw_exception("columns() is a read-only accessor, did you mean add_columns()?") if (@_ > 1); + $self->throw_exception( + "columns() is a read-only accessor, did you mean add_columns()?" + ) if (@_ > 1); return @{$self->{_ordered_columns}||[]}; } +=head2 remove_columns + + $table->remove_columns(qw/col1 col2 col3/); + +Removes columns from the result source. + +=head2 remove_column + + $table->remove_column('col'); + +Convenience alias to remove_columns. + +=cut + +sub remove_columns { + my ($self, @cols) = @_; + + return unless $self->_ordered_columns; + + my $columns = $self->_columns; + my @remaining; + + foreach my $col (@{$self->_ordered_columns}) { + push @remaining, $col unless grep(/$col/, @cols); + } + + foreach (@cols) { + undef $columns->{$_}; + }; + + $self->_ordered_columns(\@remaining); +} + +*remove_column = \&remove_columns; + =head2 set_primary_key -=head3 Arguments: (@cols) +=over 4 + +=item Arguments: @cols + +=back Defines one or more columns as primary key for this source. Should be called after C. @@ -211,7 +254,7 @@ called after C. Additionally, defines a unique constraint named C. The primary key columns are used by L to -retrieve automatically created values from the database. +retrieve automatically created values from the database. =cut @@ -241,10 +284,13 @@ sub primary_columns { Declare a unique constraint on this source. Call once for each unique constraint. Unique constraints are used when you call C on a -L, only columns in the constraint are searched, +L. Only columns in the constraint are searched, +for example: - # For e.g. UNIQUE (column1, column2) - __PACKAGE__->add_unique_constraint(constraint_name => [ qw/column1 column2/ ]); + # For UNIQUE (column1, column2) + __PACKAGE__->add_unique_constraint( + constraint_name => [ qw/column1 column2/ ], + ); =cut @@ -274,14 +320,14 @@ sub unique_constraints { =head2 from Returns an expression of the source to be supplied to storage to specify -retrieval from this source; in the case of a database the required FROM clause -contents. +retrieval from this source. In the case of a database, the required FROM +clause contents. =cut =head2 storage -Returns the storage handle for the current schema. +Returns the storage handle for the current schema. See also: L @@ -302,7 +348,7 @@ the current schema. For example: 'foreign.book_id' => 'self.id', }); -The condition C<$cond> needs to be an SQL::Abstract-style +The condition C<$cond> needs to be an L-style representation of the join between the tables. For example, if you're creating a rel from Author to Book, @@ -328,25 +374,25 @@ the SQL command immediately before C. An arrayref containing a list of accessors in the foreign class to proxy in the main class. If, for example, you do the following: - + CD->might_have(liner_notes => 'LinerNotes', undef, { proxy => [ qw/notes/ ], }); - + Then, assuming LinerNotes has an accessor named notes, you can do: my $cd = CD->find(1); - $cd->notes('Notes go here'); # set notes -- LinerNotes object is - # created if it doesn't exist + # set notes -- LinerNotes object is created if it doesn't exist + $cd->notes('Notes go here'); =item accessor Specifies the type of accessor that should be created for the -relationship. Valid values are C (for when there is only a single -related object), C (when there can be many), and C (for -when there is a single related object, but you also want the relationship -accessor to double as a column accessor). For C accessors, an -add_to_* method is also created, which calls C for the +relationship. Valid values are C (for when there is only a single +related object), C (when there can be many), and C (for +when there is a single related object, but you also want the relationship +accessor to double as a column accessor). For C accessors, an +add_to_* method is also created, which calls C for the relationship. =back @@ -355,7 +401,8 @@ relationship. sub add_relationship { my ($self, $rel, $f_source_name, $cond, $attrs) = @_; - $self->throw_exception("Can't create relationship without join condition") unless $cond; + $self->throw_exception("Can't create relationship without join condition") + unless $cond; $attrs ||= {}; my %rels = %{ $self->_relationships }; @@ -386,7 +433,7 @@ sub add_relationship { eval { $self->resolve_join($rel, 'me') }; if ($@) { # If the resolve failed, back out and re-throw the error - delete $rels{$rel}; # + delete $rels{$rel}; # $self->_relationships(\%rels); $self->throw_exception("Error creating relationship $rel: $@"); } @@ -395,7 +442,7 @@ sub add_relationship { =head2 relationships -Returns all valid relationship names for this source +Returns all relationship names for this source. =cut @@ -405,22 +452,31 @@ sub relationships { =head2 relationship_info -=head3 Arguments: ($relname) +=over 4 -Returns the relationship information for the specified relationship name +=item Arguments: $relname + +=back + +Returns a hash of relationship information for the specified relationship +name. =cut sub relationship_info { my ($self, $rel) = @_; return $self->_relationships->{$rel}; -} +} =head2 has_relationship -=head3 Arguments: ($rel) +=over 4 + +=item Arguments: $rel -Returns 1 if the source has a relationship of this name, 0 otherwise. +=back + +Returns true if the source has a relationship of this name, false otherwise. =cut @@ -431,9 +487,13 @@ sub has_relationship { =head2 resolve_join -=head3 Arguments: ($relation) +=over 4 -Returns the join structure required for the related result source +=item Arguments: $relation + +=back + +Returns the join structure required for the related result source. =cut @@ -466,7 +526,11 @@ sub resolve_join { =head2 resolve_condition -=head3 Arguments: ($cond, $as, $alias|$object) +=over 4 + +=item Arguments: $cond, $as, $alias|$object + +=back Resolves the passed condition to a concrete query fragment. If given an alias, returns a join condition; if given an object, inverts that object to produce @@ -481,8 +545,10 @@ sub resolve_condition { my %ret; while (my ($k, $v) = each %{$cond}) { # XXX should probably check these are valid columns - $k =~ s/^foreign\.// || $self->throw_exception("Invalid rel cond key ${k}"); - $v =~ s/^self\.// || $self->throw_exception("Invalid rel cond val ${v}"); + $k =~ s/^foreign\.// || + $self->throw_exception("Invalid rel cond key ${k}"); + $v =~ s/^self\.// || + $self->throw_exception("Invalid rel cond val ${v}"); if (ref $for) { # Object #warn "$self $k $for $v"; $ret{$k} = $for->get_column($v); @@ -503,7 +569,11 @@ sub resolve_condition { =head2 resolve_prefetch -=head3 Arguments: (hashref/arrayref/scalar) +=over 4 + +=item Arguments: hashref/arrayref/scalar + +=back Accepts one or more relationships for the current source and returns an array of column names for each of those relationships. Column names are @@ -542,7 +612,7 @@ in the supplied relationships. Examples: # 'artist.name', # 'producer.producerid', # 'producer.name' - #) + #) =cut @@ -604,9 +674,13 @@ sub resolve_prefetch { =head2 related_source -=head3 Arguments: ($relname) +=over 4 + +=item Arguments: $relname + +=back -Returns the result source object for the given relationship +Returns the result source object for the given relationship. =cut @@ -618,12 +692,35 @@ sub related_source { return $self->schema->source($self->relationship_info($rel)->{source}); } +=head2 related_class + +=over 4 + +=item Arguments: $relname + +=back + +Returns the class name for objects in the given relationship. + +=cut + +sub related_class { + my ($self, $rel) = @_; + if( !$self->has_relationship( $rel ) ) { + $self->throw_exception("No such relationship '$rel'"); + } + return $self->schema->class($self->relationship_info($rel)->{source}); +} + =head2 resultset -Returns a resultset for the given source, by calling: +Returns a resultset for the given source. This will initially be created +on demand by calling $self->resultset_class->new($self, $self->resultset_attributes) +but is cached from then on unless resultset_class changes. + =head2 resultset_class Set the class of the resultset, this is useful if you want to create your @@ -638,27 +735,32 @@ Specify here any attributes you wish to pass to your specialised resultset. sub resultset { my $self = shift; - $self->throw_exception('resultset does not take any arguments. If you want another resultset, call it on the schema instead.') if scalar @_; - return $self->{_resultset} if ref $self->{_resultset} eq $self->resultset_class; - return $self->{_resultset} = $self->resultset_class->new($self, $self->{resultset_attributes}); + $self->throw_exception( + 'resultset does not take any arguments. If you want another resultset, '. + 'call it on the schema instead.' + ) if scalar @_; + return $self->{_resultset} + if ref $self->{_resultset} eq $self->resultset_class; + return $self->{_resultset} = $self->resultset_class->new( + $self, $self->{resultset_attributes} + ); } =head2 throw_exception -See throw_exception in L. +See L. =cut sub throw_exception { my $self = shift; - if (defined $self->schema) { + if (defined $self->schema) { $self->schema->throw_exception(@_); } else { croak(@_); } } - =head1 AUTHORS Matt S. Trout