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