From: Mark Addison Date: Mon, 6 Mar 2006 17:46:57 +0000 (+0000) Subject: Added Globals filter. X-Git-Tag: v0.11008~463 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=8dc6a4a31380a1a53c9f50041620ef20337f849c;p=dbsrgits%2FSQL-Translator.git Added Globals filter. --- diff --git a/Changes b/Changes index b58efd1..ac76a7f 100644 --- a/Changes +++ b/Changes @@ -1,6 +1,6 @@ * Added mysql_character_set for 4.1+ -mda -* Two experimental filters (DefaultExtra, Names). -mda +* New filters, Names and Globals. -mda * Added the initial work on a template based Dia UML producer. -mda # ----------------------------------------------------------- diff --git a/lib/SQL/Translator/Filter/Globals.pm b/lib/SQL/Translator/Filter/Globals.pm new file mode 100644 index 0000000..9262590 --- /dev/null +++ b/lib/SQL/Translator/Filter/Globals.pm @@ -0,0 +1,162 @@ +package SQL::Translator::Filter::Globals; + +# ------------------------------------------------------------------- +# $Id: Globals.pm,v 1.1 2006-03-06 17:46:57 grommit Exp $ +# ------------------------------------------------------------------- +# Copyright (C) 2002-4 SQLFairy Authors +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; version 2. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA +# ------------------------------------------------------------------- + +=head1 NAME + +SQL::Translator::Filter::Globals - Add global fields and indices to all tables. + +=head1 SYNOPSIS + + # e.g. Add timestamp field to all tables. + use SQL::Translator; + + my $sqlt = SQL::Translator->new( + from => 'MySQL', + to => 'MySQL', + filters => [ + Globals => { + fields => [ + { + name => 'modified' + data_type => 'TIMESTAMP' + } + ], + indices => [ + { + fields => 'modifed', + }, + ] + }, + ], + ) || die "SQLFairy error : ".SQL::Translator->error; + my $sql = $sqlt->translate || die "SQLFairy error : ".$sqlt->error; + +=cut + +use strict; +use vars qw/$VERSION/; +$VERSION=0.1; + +sub filter { + my $schema = shift; + my %args = @_; + my $global_table = $args{global_table} ||= '_GLOBAL_'; + + my (@global_fields, @global_indices); + push @global_fields, @{ $args{fields} } if $args{fields}; + push @global_indices, @{ $args{indices} } if $args{indices}; + + # Pull fields and indices off global table and then remove it. + if ( my $gtbl = $schema->get_table( $global_table ) ) { + + foreach ( $gtbl->get_fields ) { + # We don't copy the order attrib so the added fields should get + # pushed on the end of each table. + push @global_fields, { + name => $_->name, + comments => "".$_->comments, + data_type => $_->data_type, + default_value => $_->default_value, + size => [$_->size], + extra => scalar($_->extra), + foreign_key_reference => $_->foreign_key_reference, + is_auto_increment => $_->is_auto_increment, + is_foreign_key => $_->is_foreign_key, + is_nullable => $_->is_nullable, + is_primary_key => $_->is_primary_key, + is_unique => $_->is_unique, + is_valid => $_->is_valid, + }; + } + + foreach ( $gtbl->get_indices ) { + push @global_indices, { + name => $_->name, + type => $_->type, + fields => [$_->fields], + options => [$_->options], + }; + } + + $schema->drop_table($gtbl); + } + + # Add globalis to tables + foreach my $tbl ( $schema->get_tables ) { + + foreach my $new_fld ( @global_fields ) { + # Don't add if field already there + next if $tbl->get_field( $new_fld->{name} ); + $tbl->add_field( %$new_fld ); + } + + foreach my $new_index ( @global_indices ) { + # Don't add if already there + #next if $tbl->get_index( $new_index->{name} ); + $tbl->add_index( %$new_index ); + } + } +} + +1; + +__END__ + +=head1 DESCRIPTION + +Adds global fields and indices to all tables in the schema. +The globals to add can either be defined in the filter args or using a _GLOBAL_ +table (see below). + +If a table already contains a field with the same name as a global then it is +skipped for that table. + +=head2 The _GLOBAL_ Table + +An alternative to using the args is to add a table called C<_GLOBAL_> to the +schema and then just use the filter. Any fields and indices defined on this table +will be added to all the tables in the schema and the _GLOBAL_ table removed. + +The name of the global can be changed using a C arg to the +filter. + +=head1 SEE ALSO + +L, L + +=head1 BUGS + +Will generate duplicate indices if an index already exists on a table the same +as one added globally. + +=head1 TODO + +Global addition of constraints. + +Some extra data values that can be used to control the global addition. e.g. +'skip_global'. + +=head1 AUTHOR + +Mark Addison + +=cut diff --git a/t/39-filter-globals.t b/t/39-filter-globals.t new file mode 100644 index 0000000..4bc19c1 --- /dev/null +++ b/t/39-filter-globals.t @@ -0,0 +1,149 @@ +#!/usr/bin/perl -w +# vim:filetype=perl + +# Before `make install' is performed this script should be runnable with +# `make test'. After `make install' it should work as `perl test.pl' + +use strict; +use Test::More; +use Test::Exception; +use Test::SQL::Translator qw(maybe_plan); + +use Data::Dumper; + +BEGIN { + maybe_plan(4, 'YAML', 'Test::Differences') +} +use Test::Differences; +use SQL::Translator; + +# The _GLOBAL_ table should be removed and its fields copied onto all other +# tables. +my $in_yaml = qq{--- +schema: + tables: + _GLOBAL_: + name: _GLOBAL_ + fields: + modified: + name: modified + data_type: timestamp + indices: + - fields: + - modified + Person: + name: Person + fields: + first_name: + data_type: foovar + name: first_name +}; + +my $ans_yaml = qq{--- +schema: + procedures: {} + tables: + Person: + comments: '' + constraints: [] + fields: + created: + comments: '' + data_type: timestamp + default_value: ~ + extra: {} + is_nullable: 0 + is_primary_key: 0 + is_unique: 0 + name: created + order: 3 + size: + - 0 + first_name: + comments: '' + data_type: foovar + default_value: ~ + extra: {} + is_nullable: 1 + is_primary_key: 0 + is_unique: 0 + name: first_name + order: 2 + size: + - 0 + modified: + comments: '' + data_type: timestamp + default_value: ~ + extra: {} + is_nullable: 1 + is_primary_key: 0 + is_unique: 0 + name: modified + order: 4 + size: + - 0 + indices: + - fields: + - created + name: '' + options: [] + type: NORMAL + - fields: + - modified + name: '' + options: [] + type: NORMAL + name: Person + options: [] + order: 2 + triggers: {} + views: {} +translator: + add_drop_table: 0 + filename: ~ + no_comments: 0 + parser_args: {} + parser_type: SQL::Translator::Parser::YAML + producer_args: {} + producer_type: SQL::Translator::Producer::YAML + show_warnings: 1 + trace: 0 + version: 0.07 +}; + +# Parse the test XML schema +my $obj; +$obj = SQL::Translator->new( + debug => 0, + show_warnings => 1, + from => "YAML", + to => "YAML", + data => $in_yaml, + filters => [ + # Filter from SQL::Translator::Filter::* + [ 'Globals', + # A global field to add given in the args + fields => [ + { + name => 'created', + data_type => 'timestamp', + is_nullable => 0, + } + ], + indices => [ + { + fields => 'created', + } + ], + ], + ], + +) or die "Failed to create translator object: ".SQL::Translator->error; + +my $out; +lives_ok { $out = $obj->translate; } "Translate ran"; +is $obj->error, '' ,"No errors"; +ok $out ne "" ,"Produced something!"; +eq_or_diff $out, $ans_yaml ,"Output looks right"; +#print "$out\n";