Upped version numbers, cleaned up code, fixed my name.
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator / Filter / Globals.pm
1 package SQL::Translator::Filter::Globals;
2
3 # -------------------------------------------------------------------
4 # Copyright (C) 2002-2009 SQLFairy Authors
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License as
8 # published by the Free Software Foundation; version 2.
9 #
10 # This program is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 # 02111-1307  USA
19 # -------------------------------------------------------------------
20
21 =head1 NAME
22
23 SQL::Translator::Filter::Globals - Add global fields and indices to all tables.
24
25 =head1 SYNOPSIS
26
27   # e.g. Add timestamp field to all tables.
28   use SQL::Translator;
29
30   my $sqlt = SQL::Translator->new(
31       from => 'MySQL',
32       to   => 'MySQL',
33       filters => [
34         Globals => {
35             fields => [
36                 {
37                     name => 'modified'
38                     data_type => 'TIMESTAMP'
39                 }
40             ],
41             indices => [
42                 { 
43                     fields => 'modifed',
44                 },
45             ]
46             constraints => [
47                 {
48                 }
49             ]
50         },
51       ],
52   ) || die "SQLFairy error : ".SQL::Translator->error;
53   my $sql = $sqlt->translate || die "SQLFairy error : ".$sqlt->error;
54
55 =cut
56
57 use strict;
58 use vars qw/$VERSION/;
59 $VERSION = '1.60';
60
61 sub filter {
62     my $schema = shift;
63     my %args = @_;
64     my $global_table = $args{global_table} ||= '_GLOBAL_';
65
66     my (@global_fields, @global_indices, @global_constraints);
67     push @global_fields,      @{ $args{fields} }      if $args{fields};
68     push @global_indices,     @{ $args{indices} }     if $args{indices};
69     push @global_constraints, @{ $args{constraints} } if $args{constraints};
70
71     # Pull fields and indices off global table and then remove it.
72     if ( my $gtbl = $schema->get_table( $global_table ) ) {
73
74         foreach ( $gtbl->get_fields ) {
75             # We don't copy the order attrib so the added fields should get
76             # pushed on the end of each table.
77             push @global_fields, {
78                 name                  => $_->name,
79                 comments              => "".$_->comments,
80                 data_type             => $_->data_type,
81                 default_value         => $_->default_value,
82                 size                  => [$_->size],
83                 extra                 => scalar($_->extra),
84                 foreign_key_reference => $_->foreign_key_reference,
85                 is_auto_increment     => $_->is_auto_increment,
86                 is_foreign_key        => $_->is_foreign_key,
87                 is_nullable           => $_->is_nullable,
88                 is_primary_key        => $_->is_primary_key,
89                 is_unique             => $_->is_unique,
90                 is_valid              => $_->is_valid,
91             };
92         }
93
94         foreach ( $gtbl->get_indices ) {
95             push @global_indices, {
96                 name    => $_->name,
97                 type    => $_->type,
98                 fields  => [$_->fields],
99                 options => [$_->options],
100                 extra   => scalar($_->extra),
101             };
102         }
103
104         foreach ( $gtbl->get_constraints ) {
105             push @global_constraints, {
106                 name             => $_->name,
107                 fields           => [$_->fields],
108                 deferrable       => $_->deferrable,
109                 expression       => $_->expression,
110                 match_type       => $_->match_type,
111                 options          => [$_->options],
112                 on_delete        => $_->on_delete,
113                 on_update        => $_->on_update,
114                 reference_fields => [$_->reference_fields],
115                 reference_table  => $_->reference_table,
116                 table            => $_->table,
117                 type             => $_->type,
118                 extra            => scalar($_->extra),
119             };
120         }
121
122         $schema->drop_table($gtbl);
123     }
124
125     # Add globalis to tables
126     foreach my $tbl ( $schema->get_tables ) {
127
128         foreach my $new_fld ( @global_fields ) {
129             # Don't add if field already there
130             next if $tbl->get_field( $new_fld->{name} );
131             $tbl->add_field( %$new_fld );
132         }
133
134         foreach my $new_index ( @global_indices ) {
135             $tbl->add_index( %$new_index );
136         }
137
138         foreach my $new_constraint ( @global_constraints ) {
139             $tbl->add_constraint( %$new_constraint );
140         }
141     }
142 }
143
144 1;
145
146 __END__
147
148 =head1 DESCRIPTION
149
150 Adds global fields, indices and constraints to all tables in the
151 schema.  The globals to add can either be defined in the filter args
152 or using a _GLOBAL_ table (see below).
153
154 If a table already contains a field with the same name as a global
155 then it is skipped for that table.
156
157 =head2 The _GLOBAL_ Table
158
159 An alternative to using the args is to add a table called C<_GLOBAL_>
160 to the schema and then just use the filter. Any fields and indices
161 defined on this table will be added to all the tables in the schema
162 and the _GLOBAL_ table removed.
163
164 The name of the global can be changed using a C<global_table> arg to
165 the filter.
166
167 =head1 SEE ALSO
168
169 L<perl(1)>, L<SQL::Translator>
170
171 =head1 BUGS
172
173 Will generate duplicate indices if an index already exists on a table
174 the same as one added globally.
175
176 Will generate duplicate constraints if a constraint already exists on
177 a table the same as one added globally.
178
179 =head1 TODO
180
181 Some extra data values that can be used to control the global
182 addition. e.g.  'skip_global'.
183
184 =head1 AUTHOR
185
186 Mark Addison <grommit@users.sourceforge.net>
187
188 =cut