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