1 package DBIx::Class::ResultSource;
6 use DBIx::Class::ResultSet;
7 use DBIx::Class::ResultSourceHandle;
8 use Carp::Clan qw/^DBIx::Class/;
11 use base qw/DBIx::Class/;
13 __PACKAGE__->mk_group_accessors('simple' => qw/_ordered_columns
14 _columns _primaries _unique_constraints name resultset_attributes
15 schema from _relationships column_info_from_storage source_info
18 __PACKAGE__->mk_group_accessors('component_class' => qw/resultset_class
23 DBIx::Class::ResultSource - Result source object
29 A ResultSource is a component of a schema from which results can be directly
30 retrieved, most usually a table (see L<DBIx::Class::ResultSource::Table>)
40 $class->new({attribute_name => value});
42 Creates a new ResultSource object. Not normally called directly by end users.
47 my ($class, $attrs) = @_;
48 $class = ref $class if ref $class;
50 my $new = bless { %{$attrs || {}} }, $class;
51 $new->{resultset_class} ||= 'DBIx::Class::ResultSet';
52 $new->{resultset_attributes} = { %{$new->{resultset_attributes} || {}} };
53 $new->{_ordered_columns} = [ @{$new->{_ordered_columns}||[]}];
54 $new->{_columns} = { %{$new->{_columns}||{}} };
55 $new->{_relationships} = { %{$new->{_relationships}||{}} };
56 $new->{name} ||= "!!NAME NOT SET!!";
57 $new->{_columns_info_loaded} ||= 0;
65 Stores a hashref of per-source metadata. No specific key names
66 have yet been standardized, the examples below are purely hypothetical
67 and don't actually accomplish anything on their own:
69 __PACKAGE__->source_info({
70 "_tablespace" => 'fast_disk_array_3',
71 "_engine" => 'InnoDB',
76 $table->add_columns(qw/col1 col2 col3/);
78 $table->add_columns('col1' => \%col1_info, 'col2' => \%col2_info, ...);
80 Adds columns to the result source. If supplied key => hashref pairs, uses
81 the hashref as the column_info for that column. Repeated calls of this
82 method will add more columns, not replace them.
84 The column names given will be created as accessor methods on your
85 L<DBIx::Class::Row> objects, you can change the name of the accessor
86 by supplying an L</accessor> in the column_info hash.
88 The contents of the column_info are not set in stone. The following
89 keys are currently recognised/used by DBIx::Class:
95 Use this to set the name of the accessor method for this column. If unset,
96 the name of the column will be used.
100 This contains the column type. It is automatically filled by the
101 L<SQL::Translator::Producer::DBIx::Class::File> producer, and the
102 L<DBIx::Class::Schema::Loader> module. If you do not enter a
103 data_type, DBIx::Class will attempt to retrieve it from the
104 database for you, using L<DBI>'s column_info method. The values of this
105 key are typically upper-cased.
107 Currently there is no standard set of values for the data_type. Use
108 whatever your database supports.
112 The length of your column, if it is a column type that can have a size
113 restriction. This is currently only used by L<DBIx::Class::Schema/deploy>.
117 Set this to a true value for a columns that is allowed to contain
118 NULL values. This is currently only used by L<DBIx::Class::Schema/deploy>.
120 =item is_auto_increment
122 Set this to a true value for a column whose value is somehow
123 automatically set. This is used to determine which columns to empty
124 when cloning objects using C<copy>. It is also used by
125 L<DBIx::Class::Schema/deploy>.
129 Set this to a true value for a column that contains a key from a
130 foreign table. This is currently only used by
131 L<DBIx::Class::Schema/deploy>.
135 Set this to the default value which will be inserted into a column
136 by the database. Can contain either a value or a function. This is
137 currently only used by L<DBIx::Class::Schema/deploy>.
141 Set this on a primary key column to the name of the sequence used to
142 generate a new key value. If not specified, L<DBIx::Class::PK::Auto>
143 will attempt to retrieve the name of the sequence from the database
148 This is used by L<DBIx::Class::Schema/deploy> and L<SQL::Translator>
149 to add extra non-generic data to the column. For example: C<< extra
150 => { unsigned => 1} >> is used by the MySQL producer to set an integer
151 column to unsigned. For more details, see
152 L<SQL::Translator::Producer::MySQL>.
158 $table->add_column('col' => \%info?);
160 Convenience alias to add_columns.
165 my ($self, @cols) = @_;
166 $self->_ordered_columns(\@cols) unless $self->_ordered_columns;
169 my $columns = $self->_columns;
170 while (my $col = shift @cols) {
171 # If next entry is { ... } use that for the column info, if not
172 # use an empty hashref
173 my $column_info = ref $cols[0] ? shift(@cols) : {};
174 push(@added, $col) unless exists $columns->{$col};
175 $columns->{$col} = $column_info;
177 push @{ $self->_ordered_columns }, @added;
181 sub add_column { shift->add_columns(@_); } # DO NOT CHANGE THIS TO GLOB
185 if ($obj->has_column($col)) { ... }
187 Returns true if the source has a column of this name, false otherwise.
192 my ($self, $column) = @_;
193 return exists $self->_columns->{$column};
198 my $info = $obj->column_info($col);
200 Returns the column metadata hashref for a column. See the description
201 of add_column for information on the contents of the hashref.
206 my ($self, $column) = @_;
207 $self->throw_exception("No such column $column")
208 unless exists $self->_columns->{$column};
209 #warn $self->{_columns_info_loaded}, "\n";
210 if ( ! $self->_columns->{$column}{data_type}
211 and $self->column_info_from_storage
212 and ! $self->{_columns_info_loaded}
213 and $self->schema and $self->storage )
215 $self->{_columns_info_loaded}++;
218 # eval for the case of storage without table
219 eval { $info = $self->storage->columns_info_for( $self->from ) };
221 for my $realcol ( keys %{$info} ) {
222 $lc_info->{lc $realcol} = $info->{$realcol};
224 foreach my $col ( keys %{$self->_columns} ) {
225 $self->_columns->{$col} = {
226 %{ $self->_columns->{$col} },
227 %{ $info->{$col} || $lc_info->{lc $col} || {} }
232 return $self->_columns->{$column};
235 =head2 column_info_from_storage
237 Enables the on-demand automatic loading of the above column
238 metadata from storage as neccesary. This is *deprecated*, and
239 should not be used. It will be removed before 1.0.
241 __PACKAGE__->column_info_from_storage(1);
245 my @column_names = $obj->columns;
247 Returns all column names in the order they were declared to add_columns.
253 $self->throw_exception(
254 "columns() is a read-only accessor, did you mean add_columns()?"
256 return @{$self->{_ordered_columns}||[]};
259 =head2 remove_columns
261 $table->remove_columns(qw/col1 col2 col3/);
263 Removes columns from the result source.
267 $table->remove_column('col');
269 Convenience alias to remove_columns.
274 my ($self, @cols) = @_;
276 return unless $self->_ordered_columns;
278 my $columns = $self->_columns;
281 foreach my $col (@{$self->_ordered_columns}) {
282 push @remaining, $col unless grep(/$col/, @cols);
286 delete $columns->{$_};
289 $self->_ordered_columns(\@remaining);
292 sub remove_column { shift->remove_columns(@_); } # DO NOT CHANGE THIS TO GLOB
294 =head2 set_primary_key
298 =item Arguments: @cols
302 Defines one or more columns as primary key for this source. Should be
303 called after C<add_columns>.
305 Additionally, defines a unique constraint named C<primary>.
307 The primary key columns are used by L<DBIx::Class::PK::Auto> to
308 retrieve automatically created values from the database.
312 sub set_primary_key {
313 my ($self, @cols) = @_;
314 # check if primary key columns are valid columns
315 foreach my $col (@cols) {
316 $self->throw_exception("No such column $col on table " . $self->name)
317 unless $self->has_column($col);
319 $self->_primaries(\@cols);
321 $self->add_unique_constraint(primary => \@cols);
324 =head2 primary_columns
326 Read-only accessor which returns the list of primary keys.
330 sub primary_columns {
331 return @{shift->_primaries||[]};
334 =head2 add_unique_constraint
336 Declare a unique constraint on this source. Call once for each unique
339 # For UNIQUE (column1, column2)
340 __PACKAGE__->add_unique_constraint(
341 constraint_name => [ qw/column1 column2/ ],
344 Alternatively, you can specify only the columns:
346 __PACKAGE__->add_unique_constraint([ qw/column1 column2/ ]);
348 This will result in a unique constraint named C<table_column1_column2>, where
349 C<table> is replaced with the table name.
351 Unique constraints are used, for example, when you call
352 L<DBIx::Class::ResultSet/find>. Only columns in the constraint are searched.
356 sub add_unique_constraint {
361 $name ||= $self->name_unique_constraint($cols);
363 foreach my $col (@$cols) {
364 $self->throw_exception("No such column $col on table " . $self->name)
365 unless $self->has_column($col);
368 my %unique_constraints = $self->unique_constraints;
369 $unique_constraints{$name} = $cols;
370 $self->_unique_constraints(\%unique_constraints);
373 =head2 name_unique_constraint
375 Return a name for a unique constraint containing the specified columns. These
376 names consist of the table name and each column name, separated by underscores.
378 For example, a constraint on a table named C<cd> containing the columns
379 C<artist> and C<title> would result in a constraint name of C<cd_artist_title>.
383 sub name_unique_constraint {
384 my ($self, $cols) = @_;
386 return join '_', $self->name, @$cols;
389 =head2 unique_constraints
391 Read-only accessor which returns the list of unique constraints on this source.
395 sub unique_constraints {
396 return %{shift->_unique_constraints||{}};
399 =head2 unique_constraint_names
401 Returns the list of unique constraint names defined on this source.
405 sub unique_constraint_names {
408 my %unique_constraints = $self->unique_constraints;
410 return keys %unique_constraints;
413 =head2 unique_constraint_columns
415 Returns the list of columns that make up the specified unique constraint.
419 sub unique_constraint_columns {
420 my ($self, $constraint_name) = @_;
422 my %unique_constraints = $self->unique_constraints;
424 $self->throw_exception(
425 "Unknown unique constraint $constraint_name on '" . $self->name . "'"
426 ) unless exists $unique_constraints{$constraint_name};
428 return @{ $unique_constraints{$constraint_name} };
433 Returns an expression of the source to be supplied to storage to specify
434 retrieval from this source. In the case of a database, the required FROM
439 Returns the L<DBIx::Class::Schema> object that this result source
444 Returns the storage handle for the current schema.
446 See also: L<DBIx::Class::Storage>
450 sub storage { shift->schema->storage; }
452 =head2 add_relationship
454 $source->add_relationship('relname', 'related_source', $cond, $attrs);
456 The relationship name can be arbitrary, but must be unique for each
457 relationship attached to this result source. 'related_source' should
458 be the name with which the related result source was registered with
459 the current schema. For example:
461 $schema->source('Book')->add_relationship('reviews', 'Review', {
462 'foreign.book_id' => 'self.id',
465 The condition C<$cond> needs to be an L<SQL::Abstract>-style
466 representation of the join between the tables. For example, if you're
467 creating a rel from Author to Book,
469 { 'foreign.author_id' => 'self.id' }
471 will result in the JOIN clause
473 author me JOIN book foreign ON foreign.author_id = me.id
475 You can specify as many foreign => self mappings as necessary.
477 Valid attributes are as follows:
483 Explicitly specifies the type of join to use in the relationship. Any
484 SQL join type is valid, e.g. C<LEFT> or C<RIGHT>. It will be placed in
485 the SQL command immediately before C<JOIN>.
489 An arrayref containing a list of accessors in the foreign class to proxy in
490 the main class. If, for example, you do the following:
492 CD->might_have(liner_notes => 'LinerNotes', undef, {
493 proxy => [ qw/notes/ ],
496 Then, assuming LinerNotes has an accessor named notes, you can do:
498 my $cd = CD->find(1);
499 # set notes -- LinerNotes object is created if it doesn't exist
500 $cd->notes('Notes go here');
504 Specifies the type of accessor that should be created for the
505 relationship. Valid values are C<single> (for when there is only a single
506 related object), C<multi> (when there can be many), and C<filter> (for
507 when there is a single related object, but you also want the relationship
508 accessor to double as a column accessor). For C<multi> accessors, an
509 add_to_* method is also created, which calls C<create_related> for the
516 sub add_relationship {
517 my ($self, $rel, $f_source_name, $cond, $attrs) = @_;
518 $self->throw_exception("Can't create relationship without join condition")
522 # Check foreign and self are right in cond
523 if ( (ref $cond ||'') eq 'HASH') {
525 $self->throw_exception("Keys of condition should be of form 'foreign.col', not '$_'")
526 if /\./ && !/^foreign\./;
530 my %rels = %{ $self->_relationships };
531 $rels{$rel} = { class => $f_source_name,
532 source => $f_source_name,
535 $self->_relationships(\%rels);
539 # XXX disabled. doesn't work properly currently. skip in tests.
541 my $f_source = $self->schema->source($f_source_name);
543 $self->ensure_class_loaded($f_source_name);
544 $f_source = $f_source_name->result_source;
545 #my $s_class = ref($self->schema);
546 #$f_source_name =~ m/^${s_class}::(.*)$/;
547 #$self->schema->register_class(($1 || $f_source_name), $f_source_name);
548 #$f_source = $self->schema->source($f_source_name);
550 return unless $f_source; # Can't test rel without f_source
552 eval { $self->resolve_join($rel, 'me') };
554 if ($@) { # If the resolve failed, back out and re-throw the error
555 delete $rels{$rel}; #
556 $self->_relationships(\%rels);
557 $self->throw_exception("Error creating relationship $rel: $@");
564 Returns all relationship names for this source.
569 return keys %{shift->_relationships};
572 =head2 relationship_info
576 =item Arguments: $relname
580 Returns a hash of relationship information for the specified relationship
585 sub relationship_info {
586 my ($self, $rel) = @_;
587 return $self->_relationships->{$rel};
590 =head2 has_relationship
594 =item Arguments: $rel
598 Returns true if the source has a relationship of this name, false otherwise.
602 sub has_relationship {
603 my ($self, $rel) = @_;
604 return exists $self->_relationships->{$rel};
607 =head2 reverse_relationship_info
611 =item Arguments: $relname
615 Returns an array of hash references of relationship information for
616 the other side of the specified relationship name.
620 sub reverse_relationship_info {
621 my ($self, $rel) = @_;
622 my $rel_info = $self->relationship_info($rel);
625 return $ret unless ((ref $rel_info->{cond}) eq 'HASH');
627 my @cond = keys(%{$rel_info->{cond}});
628 my @refkeys = map {/^\w+\.(\w+)$/} @cond;
629 my @keys = map {$rel_info->{cond}->{$_} =~ /^\w+\.(\w+)$/} @cond;
631 # Get the related result source for this relationship
632 my $othertable = $self->related_source($rel);
634 # Get all the relationships for that source that related to this source
635 # whose foreign column set are our self columns on $rel and whose self
636 # columns are our foreign columns on $rel.
637 my @otherrels = $othertable->relationships();
638 my $otherrelationship;
639 foreach my $otherrel (@otherrels) {
640 my $otherrel_info = $othertable->relationship_info($otherrel);
642 my $back = $othertable->related_source($otherrel);
643 next unless $back->source_name eq $self->source_name;
647 if (ref $otherrel_info->{cond} eq 'HASH') {
648 @othertestconds = ($otherrel_info->{cond});
650 elsif (ref $otherrel_info->{cond} eq 'ARRAY') {
651 @othertestconds = @{$otherrel_info->{cond}};
657 foreach my $othercond (@othertestconds) {
658 my @other_cond = keys(%$othercond);
659 my @other_refkeys = map {/^\w+\.(\w+)$/} @other_cond;
660 my @other_keys = map {$othercond->{$_} =~ /^\w+\.(\w+)$/} @other_cond;
661 next if (!$self->compare_relationship_keys(\@refkeys, \@other_keys) ||
662 !$self->compare_relationship_keys(\@other_refkeys, \@keys));
663 $ret->{$otherrel} = $otherrel_info;
669 =head2 compare_relationship_keys
673 =item Arguments: $keys1, $keys2
677 Returns true if both sets of keynames are the same, false otherwise.
681 sub compare_relationship_keys {
682 my ($self, $keys1, $keys2) = @_;
684 # Make sure every keys1 is in keys2
686 foreach my $key (@$keys1) {
688 foreach my $prim (@$keys2) {
697 # Make sure every key2 is in key1
699 foreach my $prim (@$keys2) {
701 foreach my $key (@$keys1) {
718 =item Arguments: $relation
722 Returns the join structure required for the related result source.
727 my ($self, $join, $alias, $seen, $force_left) = @_;
729 $force_left ||= { force => 0 };
730 if (ref $join eq 'ARRAY') {
731 return map { $self->resolve_join($_, $alias, $seen) } @$join;
732 } elsif (ref $join eq 'HASH') {
735 my $as = ($seen->{$_} ? $_.'_'.($seen->{$_}+1) : $_);
736 local $force_left->{force};
738 $self->resolve_join($_, $alias, $seen, $force_left),
739 $self->related_source($_)->resolve_join(
740 $join->{$_}, $as, $seen, $force_left
744 } elsif (ref $join) {
745 $self->throw_exception("No idea how to resolve join reftype ".ref $join);
747 my $count = ++$seen->{$join};
748 #use Data::Dumper; warn Dumper($seen);
749 my $as = ($count > 1 ? "${join}_${count}" : $join);
750 my $rel_info = $self->relationship_info($join);
751 $self->throw_exception("No such relationship ${join}") unless $rel_info;
753 if ($force_left->{force}) {
756 $type = $rel_info->{attrs}{join_type} || '';
757 $force_left->{force} = 1 if lc($type) eq 'left';
759 return [ { $as => $self->related_source($join)->from,
760 -join_type => $type },
761 $self->resolve_condition($rel_info->{cond}, $as, $alias) ];
765 =head2 resolve_condition
769 =item Arguments: $cond, $as, $alias|$object
773 Resolves the passed condition to a concrete query fragment. If given an alias,
774 returns a join condition; if given an object, inverts that object to produce
775 a related conditional from that object.
779 sub resolve_condition {
780 my ($self, $cond, $as, $for) = @_;
782 if (ref $cond eq 'HASH') {
784 foreach my $k (keys %{$cond}) {
786 # XXX should probably check these are valid columns
787 $k =~ s/^foreign\.// ||
788 $self->throw_exception("Invalid rel cond key ${k}");
790 $self->throw_exception("Invalid rel cond val ${v}");
791 if (ref $for) { # Object
792 #warn "$self $k $for $v";
793 $ret{$k} = $for->get_column($v) if $for->has_column_loaded($v);
795 } elsif (!defined $for) { # undef, i.e. "no object"
797 } elsif (ref $as eq 'HASH') { # reverse hashref
798 $ret{$v} = $as->{$k};
799 } elsif (ref $as) { # reverse object
800 $ret{$v} = $as->get_column($k);
801 } elsif (!defined $as) { # undef, i.e. "no reverse object"
804 $ret{"${as}.${k}"} = "${for}.${v}";
808 } elsif (ref $cond eq 'ARRAY') {
809 return [ map { $self->resolve_condition($_, $as, $for) } @$cond ];
811 die("Can't handle this yet :(");
815 =head2 resolve_prefetch
819 =item Arguments: hashref/arrayref/scalar
823 Accepts one or more relationships for the current source and returns an
824 array of column names for each of those relationships. Column names are
825 prefixed relative to the current source, in accordance with where they appear
826 in the supplied relationships. Examples:
828 my $source = $schema->resultset('Tag')->source;
829 @columns = $source->resolve_prefetch( { cd => 'artist' } );
837 # 'cd.artist.artistid',
841 @columns = $source->resolve_prefetch( qw[/ cd /] );
851 $source = $schema->resultset('CD')->source;
852 @columns = $source->resolve_prefetch( qw[/ artist producer /] );
858 # 'producer.producerid',
864 sub resolve_prefetch {
865 my ($self, $pre, $alias, $seen, $order, $collapse) = @_;
867 #$alias ||= $self->name;
868 #warn $alias, Dumper $pre;
869 if( ref $pre eq 'ARRAY' ) {
871 map { $self->resolve_prefetch( $_, $alias, $seen, $order, $collapse ) }
874 elsif( ref $pre eq 'HASH' ) {
877 $self->resolve_prefetch($_, $alias, $seen, $order, $collapse),
878 $self->related_source($_)->resolve_prefetch(
879 $pre->{$_}, "${alias}.$_", $seen, $order, $collapse)
885 $self->throw_exception(
886 "don't know how to resolve prefetch reftype ".ref($pre));
889 my $count = ++$seen->{$pre};
890 my $as = ($count > 1 ? "${pre}_${count}" : $pre);
891 my $rel_info = $self->relationship_info( $pre );
892 $self->throw_exception( $self->name . " has no such relationship '$pre'" )
894 my $as_prefix = ($alias =~ /^.*?\.(.+)$/ ? $1.'.' : '');
895 my $rel_source = $self->related_source($pre);
897 if (exists $rel_info->{attrs}{accessor}
898 && $rel_info->{attrs}{accessor} eq 'multi') {
899 $self->throw_exception(
900 "Can't prefetch has_many ${pre} (join cond too complex)")
901 unless ref($rel_info->{cond}) eq 'HASH';
902 #my @col = map { (/^self\.(.+)$/ ? ("${as_prefix}.$1") : ()); }
903 # values %{$rel_info->{cond}};
904 $collapse->{".${as_prefix}${pre}"} = [ $rel_source->primary_columns ];
905 # action at a distance. prepending the '.' allows simpler code
906 # in ResultSet->_collapse_result
907 my @key = map { (/^foreign\.(.+)$/ ? ($1) : ()); }
908 keys %{$rel_info->{cond}};
909 my @ord = (ref($rel_info->{attrs}{order_by}) eq 'ARRAY'
910 ? @{$rel_info->{attrs}{order_by}}
911 : (defined $rel_info->{attrs}{order_by}
912 ? ($rel_info->{attrs}{order_by})
914 push(@$order, map { "${as}.$_" } (@key, @ord));
917 return map { [ "${as}.$_", "${as_prefix}${pre}.$_", ] }
918 $rel_source->columns;
919 #warn $alias, Dumper (\@ret);
924 =head2 related_source
928 =item Arguments: $relname
932 Returns the result source object for the given relationship.
937 my ($self, $rel) = @_;
938 if( !$self->has_relationship( $rel ) ) {
939 $self->throw_exception("No such relationship '$rel'");
941 return $self->schema->source($self->relationship_info($rel)->{source});
948 =item Arguments: $relname
952 Returns the class name for objects in the given relationship.
957 my ($self, $rel) = @_;
958 if( !$self->has_relationship( $rel ) ) {
959 $self->throw_exception("No such relationship '$rel'");
961 return $self->schema->class($self->relationship_info($rel)->{source});
966 Returns a resultset for the given source. This will initially be created
969 $self->resultset_class->new($self, $self->resultset_attributes)
971 but is cached from then on unless resultset_class changes.
973 =head2 resultset_class
975 ` package My::ResultSetClass;
976 use base 'DBIx::Class::ResultSet';
979 $source->resultset_class('My::ResultSet::Class');
981 Set the class of the resultset, this is useful if you want to create your
982 own resultset methods. Create your own class derived from
983 L<DBIx::Class::ResultSet>, and set it here. If called with no arguments,
984 this method returns the name of the existing resultset class, if one
987 =head2 resultset_attributes
989 $source->resultset_attributes({ order_by => [ 'id' ] });
991 Specify here any attributes you wish to pass to your specialised
992 resultset. For a full list of these, please see
993 L<DBIx::Class::ResultSet/ATTRIBUTES>.
999 $self->throw_exception(
1000 'resultset does not take any arguments. If you want another resultset, '.
1001 'call it on the schema instead.'
1004 return $self->resultset_class->new(
1007 %{$self->{resultset_attributes}},
1008 %{$self->schema->default_resultset_attributes}
1017 =item Arguments: $source_name
1021 Set the name of the result source when it is loaded into a schema.
1022 This is usefull if you want to refer to a result source by a name other than
1025 package ArchivedBooks;
1026 use base qw/DBIx::Class/;
1027 __PACKAGE__->table('books_archive');
1028 __PACKAGE__->source_name('Books');
1030 # from your schema...
1031 $schema->resultset('Books')->find(1);
1035 Obtain a new handle to this source. Returns an instance of a
1036 L<DBIx::Class::ResultSourceHandle>.
1041 return new DBIx::Class::ResultSourceHandle({
1042 schema => $_[0]->schema,
1043 source_moniker => $_[0]->source_name
1047 =head2 throw_exception
1049 See L<DBIx::Class::Schema/"throw_exception">.
1053 sub throw_exception {
1055 if (defined $self->schema) {
1056 $self->schema->throw_exception(@_);
1062 =head2 sqlt_deploy_hook($sqlt_table)
1064 An optional sub which you can declare in your own Schema class that will get
1065 passed the L<SQL::Translator::Schema::Table> object when you deploy the schema
1066 via L</create_ddl_dir> or L</deploy>.
1068 For an example of what you can do with this, see
1069 L<DBIx::Class::Manual::Cookbook/Adding Indexes And Functions To Your SQL>.
1073 Matt S. Trout <mst@shadowcatsystems.co.uk>
1077 You may distribute this code under the same terms as Perl itself.