X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FResultSource.pm;h=fd7da0f3c26177888b28bae0622dc8034d863e58;hb=f89bb832;hp=83ad7ccacd14c1ade731b5192814039c774d749a;hpb=6bf6ba2f2c58514c065a95019cd23b10bd4770ff;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/ResultSource.pm b/lib/DBIx/Class/ResultSource.pm index 83ad7cc..fd7da0f 100644 --- a/lib/DBIx/Class/ResultSource.pm +++ b/lib/DBIx/Class/ResultSource.pm @@ -13,7 +13,7 @@ use base qw/DBIx::Class/; __PACKAGE__->mk_group_accessors('simple' => qw/_ordered_columns _columns _primaries _unique_constraints name resultset_attributes schema from _relationships column_info_from_storage source_info - source_name/); + source_name sqlt_deploy_callback/); __PACKAGE__->mk_group_accessors('component_class' => qw/resultset_class result_class/); @@ -33,14 +33,6 @@ retrieved, most usually a table (see L) =pod -=head2 new - - $class->new(); - - $class->new({attribute_name => value}); - -Creates a new ResultSource object. Not normally called directly by end users. - =cut sub new { @@ -55,27 +47,25 @@ sub new { $new->{_relationships} = { %{$new->{_relationships}||{}} }; $new->{name} ||= "!!NAME NOT SET!!"; $new->{_columns_info_loaded} ||= 0; + $new->{sqlt_deploy_callback} ||= "default_sqlt_deploy_hook"; return $new; } =pod -=head2 source_info +=head2 add_columns -Stores a hashref of per-source metadata. No specific key names -have yet been standardized, the examples below are purely hypothetical -and don't actually accomplish anything on their own: +=over - __PACKAGE__->source_info({ - "_tablespace" => 'fast_disk_array_3', - "_engine" => 'InnoDB', - }); +=item Arguments: @columns -=head2 add_columns +=item Return value: The ResultSource object - $table->add_columns(qw/col1 col2 col3/); +=back + + $source->add_columns(qw/col1 col2 col3/); - $table->add_columns('col1' => \%col1_info, 'col2' => \%col2_info, ...); + $source->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 @@ -161,9 +151,18 @@ L. =head2 add_column - $table->add_column('col' => \%info?); +=over + +=item Arguments: $colname, [ \%columninfo ] -Convenience alias to add_columns. +=item Return value: 1/0 (true/false) + +=back + + $source->add_column('col' => \%info?); + +Add a single column and optional column info. Uses the same column +info keys as L. =cut @@ -188,7 +187,15 @@ sub add_column { shift->add_columns(@_); } # DO NOT CHANGE THIS TO GLOB =head2 has_column - if ($obj->has_column($col)) { ... } +=over + +=item Arguments: $colname + +=item Return value: 1/0 (true/false) + +=back + + if ($source->has_column($colname)) { ... } Returns true if the source has a column of this name, false otherwise. @@ -201,10 +208,19 @@ sub has_column { =head2 column_info - my $info = $obj->column_info($col); +=over + +=item Arguments: $colname + +=item Return value: Hashref of info + +=back + + my $info = $source->column_info($col); -Returns the column metadata hashref for a column. See the description -of add_column for information on the contents of the hashref. +Returns the column metadata hashref for a column, as originally passed +to L. See the description of L for information +on the contents of the hashref. =cut @@ -238,19 +254,19 @@ sub column_info { return $self->_columns->{$column}; } -=head2 column_info_from_storage +=head2 columns -Enables the on-demand automatic loading of the above column -metadata from storage as neccesary. This is *deprecated*, and -should not be used. It will be removed before 1.0. +=over - __PACKAGE__->column_info_from_storage(1); +=item Arguments: None -=head2 columns +=item Return value: Ordered list of column names - my @column_names = $obj->columns; +=back -Returns all column names in the order they were declared to add_columns. + my @column_names = $source->columns; + +Returns all column names in the order they were declared to L. =cut @@ -264,15 +280,40 @@ sub columns { =head2 remove_columns - $table->remove_columns(qw/col1 col2 col3/); +=over + +=item Arguments: @colnames -Removes columns from the result source. +=item Return value: undefined + +=back + + $source->remove_columns(qw/col1 col2 col3/); + +Removes the given list of columns by name, from the result source. + +B: Removing a column that is also used in the sources primary +key, or in one of the sources unique constraints, B result in a +broken result source. =head2 remove_column - $table->remove_column('col'); +=over + +=item Arguments: $colname -Convenience alias to remove_columns. +=item Return value: undefined + +=back + + $source->remove_column('col'); + +Remove a single column by name from the result source, similar to +L. + +B: Removing a column that is also used in the sources primary +key, or in one of the sources unique constraints, B result in a +broken result source. =cut @@ -303,12 +344,15 @@ sub remove_column { shift->remove_columns(@_); } # DO NOT CHANGE THIS TO GLOB =item Arguments: @cols +=item Return value: undefined + =back Defines one or more columns as primary key for this source. Should be -called after C. +called after L. -Additionally, defines a unique constraint named C. +Additionally, defines a L +named C. The primary key columns are used by L to retrieve automatically created values from the database. @@ -329,7 +373,16 @@ sub set_primary_key { =head2 primary_columns -Read-only accessor which returns the list of primary keys. +=over 4 + +=item Arguments: None + +=item Return value: Ordered list of primary column names + +=back + +Read-only accessor which returns the list of primary keys, supplied by +L. =cut @@ -339,6 +392,14 @@ sub primary_columns { =head2 add_unique_constraint +=over 4 + +=item Arguments: [ $name ], \@colnames + +=item Return value: undefined + +=back + Declare a unique constraint on this source. Call once for each unique constraint. @@ -357,6 +418,9 @@ C is replaced with the table name. Unique constraints are used, for example, when you call L. Only columns in the constraint are searched. +Throws an error if any of the given column names do not yet exist on +the result source. + =cut sub add_unique_constraint { @@ -378,12 +442,29 @@ sub add_unique_constraint { =head2 name_unique_constraint -Return a name for a unique constraint containing the specified columns. These -names consist of the table name and each column name, separated by underscores. +=over 4 + +=item Arguments: @colnames + +=item Return value: Constraint name + +=back + + $source->table('mytable'); + $source->name_unique_constraint('col1', 'col2'); + # returns + 'mytable_col1_col2' + +Return a name for a unique constraint containing the specified +columns. The name is created by joining the table name and each column +name, using an underscore character. For example, a constraint on a table named C containing the columns C and C would result in a constraint name of C<cd_artist_title>. +This is used by L</add_unique_constraint> if you do not specify the +optional constraint name. + =cut sub name_unique_constraint { @@ -394,7 +475,20 @@ sub name_unique_constraint { =head2 unique_constraints -Read-only accessor which returns the list of unique constraints on this source. +=over 4 + +=item Arguments: None + +=item Return value: Hash of unique constraint data + +=back + + $source->unique_constraints(); + +Read-only accessor which returns a hash of unique constraints on this source. + +The hash is keyed by constraint name, and contains an arrayref of +column names as values. =cut @@ -404,6 +498,16 @@ sub unique_constraints { =head2 unique_constraint_names +=over 4 + +=item Arguments: None + +=item Return value: Unique constraint names + +=back + + $source->unique_constraint_names(); + Returns the list of unique constraint names defined on this source. =cut @@ -418,6 +522,16 @@ sub unique_constraint_names { =head2 unique_constraint_columns +=over 4 + +=item Arguments: $constraintname + +=item Return value: List of constraint columns + +=back + + $source->unique_constraint_columns('myconstraint'); + Returns the list of columns that make up the specified unique constraint. =cut @@ -434,19 +548,144 @@ sub unique_constraint_columns { return @{ $unique_constraints{$constraint_name} }; } +=head2 resultset + +=over 4 + +=item Arguments: None + +=item Return value: $resultset + +=back + +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 + +=over 4 + +=item Arguments: $classname + +=item Return value: $classname + +=back + + package My::ResultSetClass; + use base 'DBIx::Class::ResultSet'; + ... + + $source->resultset_class('My::ResultSet::Class'); + +Set the class of the resultset, this is useful if you want to create your +own resultset methods. Create your own class derived from +L<DBIx::Class::ResultSet>, and set it here. If called with no arguments, +this method returns the name of the existing resultset class, if one +exists. + +=head2 resultset_attributes + +=over 4 + +=item Arguments: \%attrs + +=item Return value: \%attrs + +=back + + $source->resultset_attributes({ order_by => [ 'id' ] }); + +Store a collection of resultset attributes, that will be set on every +L<DBIx::Class::ResultSet> produced from this result source. For a full +list see L<DBIx::Class::ResultSet/ATTRIBUTES>. + +=cut + +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_class->new( + $self, + { + %{$self->{resultset_attributes}}, + %{$self->schema->default_resultset_attributes} + }, + ); +} + +=head2 source_name + +=over 4 + +=item Arguments: $source_name + +=item Result value: $source_name + +=back + +Set an alternate name for the result source when it is loaded into a schema. +This is useful if you want to refer to a result source by a name other than +its class name. + + package ArchivedBooks; + use base qw/DBIx::Class/; + __PACKAGE__->table('books_archive'); + __PACKAGE__->source_name('Books'); + + # from your schema... + $schema->resultset('Books')->find(1); + =head2 from +=over 4 + +=item Arguments: None + +=item Return value: FROM clause + +=back + + my $from_clause = $source->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. =head2 schema +=over 4 + +=item Arguments: None + +=item Return value: A schema object + +=back + + my $schema = $source->schema(); + Returns the L<DBIx::Class::Schema> object that this result source -belongs too. +belongs to. =head2 storage +=over 4 + +=item Arguments: None + +=item Return value: A Storage object + +=back + + $source->storage->debug(1); + Returns the storage handle for the current schema. See also: L<DBIx::Class::Storage> @@ -457,8 +696,20 @@ sub storage { shift->schema->storage; } =head2 add_relationship +=over 4 + +=item Arguments: $relname, $related_source_name, \%cond, [ \%attrs ] + +=item Return value: 1/true if it succeeded + +=back + $source->add_relationship('relname', 'related_source', $cond, $attrs); +L<DBIx::Class::Relationship> describes a series of methods which +create pre-defined useful types of relationships. Look there first +before using this method directly. + The relationship name can be arbitrary, but must be unique for each relationship attached to this result source. 'related_source' should be the name with which the related result source was registered with @@ -470,7 +721,7 @@ the current schema. For example: The condition C<$cond> needs to be an L<SQL::Abstract>-style representation of the join between the tables. For example, if you're -creating a rel from Author to Book, +creating a relation from Author to Book, { 'foreign.author_id' => 'self.id' } @@ -517,6 +768,9 @@ relationship. =back +Throws an exception if the condition is improperly supplied, or cannot +be resolved using L</resolve_join>. + =cut sub add_relationship { @@ -567,6 +821,16 @@ sub add_relationship { =head2 relationships +=over 4 + +=item Arguments: None + +=item Return value: List of relationship names + +=back + + my @relnames = $source->relationships(); + Returns all relationship names for this source. =cut @@ -581,10 +845,12 @@ sub relationships { =item Arguments: $relname +=item Return value: Hashref of relation data, + =back Returns a hash of relationship information for the specified relationship -name. +name. The keys/values are as specified for L</add_relationship>. =cut @@ -599,6 +865,8 @@ sub relationship_info { =item Arguments: $rel +=item Return value: 1/0 (true/false) + =back Returns true if the source has a relationship of this name, false otherwise. @@ -616,10 +884,21 @@ sub has_relationship { =item Arguments: $relname +=item Return value: Hashref of relationship data + =back -Returns an array of hash references of relationship information for -the other side of the specified relationship name. +Looks through all the relationships on the source this relationship +points to, looking for one whose condition is the reverse of the +condition on this relationship. + +A common use of this is to find the name of the C<belongs_to> relation +opposing a C<has_many> relation. For definition of these look in +L<DBIx::Class::Relationship>. + +The returned hashref is keyed by the name of the opposing +relationship, and contains it's data in the same manner as +L</relationship_info>. =cut @@ -676,7 +955,9 @@ sub reverse_relationship_info { =over 4 -=item Arguments: $keys1, $keys2 +=item Arguments: \@keys1, \@keys2 + +=item Return value: 1/0 (true/false) =back @@ -717,12 +998,36 @@ sub compare_relationship_keys { return $found; } +=head2 sqlt_deploy_hook + +=over 4 + +=item Arguments: $source, $sqlt_table + +=item Return value: undefined + +=back + +This is NOT a method of C<ResultSource>. + +An optional sub which you can declare in your own Result class that will get +passed the L<SQL::Translator::Schema::Table> object when you deploy the schema +via L</create_ddl_dir> or L</deploy>. + +This is useful to make L<SQL::Translator> create non-unique indexes, +or set table options such as C<Engine=INNOFB>. + +For an example of what you can do with this, see +L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To Your SQL>. + =head2 resolve_join =over 4 =item Arguments: $relation +=item Return value: Join condition arrayref + =back Returns the join structure required for the related result source. @@ -774,6 +1079,8 @@ sub resolve_join { =item Arguments: $relname, $rel_data +=item Return value: 1/0 (true/false) + =back Determines whether a relation is dependent on an object from this source @@ -1000,6 +1307,8 @@ sub resolve_prefetch { =item Arguments: $relname +=item Return value: $source + =back Returns the result source object for the given relationship. @@ -1020,6 +1329,8 @@ sub related_source { =item Arguments: $relname +=item Return value: $classname + =back Returns the class name for objects in the given relationship. @@ -1034,113 +1345,115 @@ sub related_class { return $self->schema->class($self->relationship_info($rel)->{source}); } -=head2 resultset +=head2 handle -Returns a resultset for the given source. This will initially be created -on demand by calling +Obtain a new handle to this source. Returns an instance of a +L<DBIx::Class::ResultSourceHandle>. - $self->resultset_class->new($self, $self->resultset_attributes) +=cut -but is cached from then on unless resultset_class changes. +sub handle { + return new DBIx::Class::ResultSourceHandle({ + schema => $_[0]->schema, + source_moniker => $_[0]->source_name + }); +} -=head2 resultset_class +=head2 throw_exception -` package My::ResultSetClass; - use base 'DBIx::Class::ResultSet'; - ... +See L<DBIx::Class::Schema/"throw_exception">. - $source->resultset_class('My::ResultSet::Class'); +=cut -Set the class of the resultset, this is useful if you want to create your -own resultset methods. Create your own class derived from -L<DBIx::Class::ResultSet>, and set it here. If called with no arguments, -this method returns the name of the existing resultset class, if one -exists. +sub throw_exception { + my $self = shift; + if (defined $self->schema) { + $self->schema->throw_exception(@_); + } else { + croak(@_); + } +} -=head2 resultset_attributes +=head2 source_info - $source->resultset_attributes({ order_by => [ 'id' ] }); +Stores a hashref of per-source metadata. No specific key names +have yet been standardized, the examples below are purely hypothetical +and don't actually accomplish anything on their own: -Specify here any attributes you wish to pass to your specialised -resultset. For a full list of these, please see -L<DBIx::Class::ResultSet/ATTRIBUTES>. + __PACKAGE__->source_info({ + "_tablespace" => 'fast_disk_array_3', + "_engine" => 'InnoDB', + }); -=cut +=head2 new -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 @_; + $class->new(); - return $self->resultset_class->new( - $self, - { - %{$self->{resultset_attributes}}, - %{$self->schema->default_resultset_attributes} - }, - ); -} + $class->new({attribute_name => value}); -=head2 source_name +Creates a new ResultSource object. Not normally called directly by end users. -=over 4 +=cut -=item Arguments: $source_name +=head2 column_info_from_storage -=back +=over -Set the name of the result source when it is loaded into a schema. -This is usefull if you want to refer to a result source by a name other than -its class name. +=item Arguments: 1/0 (default: 0) - package ArchivedBooks; - use base qw/DBIx::Class/; - __PACKAGE__->table('books_archive'); - __PACKAGE__->source_name('Books'); +=item Return value: 1/0 - # from your schema... - $schema->resultset('Books')->find(1); +=back -=head2 handle +Enables the on-demand automatic loading of the above column +metadata from storage as neccesary. This is *deprecated*, and +should not be used. It will be removed before 1.0. -Obtain a new handle to this source. Returns an instance of a -L<DBIx::Class::ResultSourceHandle>. + __PACKAGE__->column_info_from_storage(1); =cut -sub handle { - return new DBIx::Class::ResultSourceHandle({ - schema => $_[0]->schema, - source_moniker => $_[0]->source_name - }); -} - -=head2 throw_exception +=head2 sqlt_deploy_hook($sqlt_table) -See L<DBIx::Class::Schema/"throw_exception">. +Triggers C<sqlt_deploy_callback>. =cut -sub throw_exception { +sub sqlt_deploy_hook { my $self = shift; - if (defined $self->schema) { - $self->schema->throw_exception(@_); - } else { - croak(@_); + if ( my $hook = $self->sqlt_deploy_callback) { + $self->$hook(@_); } } -=head2 sqlt_deploy_hook($sqlt_table) +=head2 default_sqlt_deploy_hook($table) -An optional sub which you can declare in your own Schema class that will get -passed the L<SQL::Translator::Schema::Table> object when you deploy the schema -via L</create_ddl_dir> or L</deploy>. +Delegates to a an optional C<sqlt_deploy_hook> method on the C<result_class>. + +This will get passed the L<SQL::Translator::Schema::Table> object when you +deploy the schema via L</create_ddl_dir> or L</deploy>. For an example of what you can do with this, see L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To Your SQL>. +=cut + +sub default_sqlt_deploy_hook { + my $self = shift; + + my $class = $self->result_class; + + if ($class and $class->can('sqlt_deploy_hook')) { + $class->sqlt_deploy_hook(@_); + } +} + +=head2 sqlt_deploy_callback + +An attribute which contains the callback to trigger on C<sqlt_deploy_hook>. +Defaults to C<default_sqlt_deploy_hook>. Can be a code reference or a method +name. + =head1 AUTHORS Matt S. Trout <mst@shadowcatsystems.co.uk>