Added Globals filter.
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator / Filter / Globals.pm
1 package SQL::Translator::Filter::Globals;
2
3 # -------------------------------------------------------------------
4 # $Id: Globals.pm,v 1.1 2006-03-06 17:46:57 grommit Exp $
5 # -------------------------------------------------------------------
6 # Copyright (C) 2002-4 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         },
49       ],
50   ) || die "SQLFairy error : ".SQL::Translator->error;
51   my $sql = $sqlt->translate || die "SQLFairy error : ".$sqlt->error;
52
53 =cut
54
55 use strict;
56 use vars qw/$VERSION/;
57 $VERSION=0.1;
58
59 sub filter {
60     my $schema = shift;
61     my %args = @_;
62     my $global_table = $args{global_table} ||= '_GLOBAL_';
63
64     my (@global_fields, @global_indices);
65     push @global_fields, @{ $args{fields} }   if $args{fields};
66     push @global_indices, @{ $args{indices} } if $args{indices};
67
68     # Pull fields and indices off global table and then remove it.
69     if ( my $gtbl = $schema->get_table( $global_table ) ) {
70
71         foreach ( $gtbl->get_fields ) {
72             # We don't copy the order attrib so the added fields should get
73             # pushed on the end of each table.
74             push @global_fields, {
75                 name                  => $_->name,
76                 comments              => "".$_->comments,
77                 data_type             => $_->data_type,
78                 default_value         => $_->default_value,
79                 size                  => [$_->size],
80                 extra                 => scalar($_->extra),
81                 foreign_key_reference => $_->foreign_key_reference,
82                 is_auto_increment     => $_->is_auto_increment,
83                 is_foreign_key        => $_->is_foreign_key,
84                 is_nullable           => $_->is_nullable,
85                 is_primary_key        => $_->is_primary_key,
86                 is_unique             => $_->is_unique,
87                 is_valid              => $_->is_valid,
88             };
89         }
90
91         foreach ( $gtbl->get_indices ) {
92             push @global_indices, {
93                 name    => $_->name,
94                 type    => $_->type,
95                 fields  => [$_->fields],
96                 options => [$_->options],
97             };
98         }
99
100         $schema->drop_table($gtbl);
101     }
102
103     # Add globalis to tables
104     foreach my $tbl ( $schema->get_tables ) {
105
106         foreach my $new_fld ( @global_fields ) {
107             # Don't add if field already there
108             next if $tbl->get_field( $new_fld->{name} );
109             $tbl->add_field( %$new_fld );
110         }
111
112         foreach my $new_index ( @global_indices ) {
113             # Don't add if already there
114             #next if $tbl->get_index( $new_index->{name} );
115             $tbl->add_index( %$new_index );
116         }
117     }
118 }
119
120 1;
121
122 __END__
123
124 =head1 DESCRIPTION
125
126 Adds global fields and indices to all tables in the schema.
127 The globals to add can either be defined in the filter args or using a _GLOBAL_
128 table (see below).
129
130 If a table already contains a field with the same name as a global then it is
131 skipped for that table.
132
133 =head2 The _GLOBAL_ Table
134
135 An alternative to using the args is to add a table called C<_GLOBAL_> to the
136 schema and then just use the filter. Any fields and indices defined on this table
137 will be added to all the tables in the schema and the _GLOBAL_ table removed.
138
139 The name of the global can be changed using a C<global_table> arg to the
140 filter.
141
142 =head1 SEE ALSO
143
144 L<perl(1)>, L<SQL::Translator>
145
146 =head1 BUGS
147
148 Will generate duplicate indices if an index already exists on a table the same
149 as one added globally.
150
151 =head1 TODO
152
153 Global addition of constraints.
154
155 Some extra data values that can be used to control the global addition. e.g.
156 'skip_global'.
157
158 =head1 AUTHOR
159
160 Mark Addison <grommit@users.sourceforge.net>
161
162 =cut