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