From: Jess Robinson Date: Wed, 24 May 2006 22:06:56 +0000 (+0000) Subject: More DB2 producing X-Git-Tag: v0.11008~434 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=a0ea6c87dfbb871007b6f455dbd74ff739276755;p=dbsrgits%2FSQL-Translator.git More DB2 producing --- diff --git a/lib/SQL/Translator/Producer/DB2.pm b/lib/SQL/Translator/Producer/DB2.pm index c394201..e59704e 100644 --- a/lib/SQL/Translator/Producer/DB2.pm +++ b/lib/SQL/Translator/Producer/DB2.pm @@ -1,7 +1,7 @@ package SQL::Translator::Producer::DB2; # ------------------------------------------------------------------- -# $Id: DB2.pm,v 1.1 2005-09-18 20:06:31 schiffbruechige Exp $ +# $Id: DB2.pm,v 1.2 2006-05-24 22:06:56 schiffbruechige Exp $ # ------------------------------------------------------------------- # Copyright (C) 2002-4 SQLFairy Authors # @@ -19,7 +19,6 @@ package SQL::Translator::Producer::DB2; # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA # 02111-1307 USA # ------------------------------------------------------------------- - =head1 NAME SQL::Translator::Producer::DB2 - DB2 SQL producer @@ -33,13 +32,14 @@ SQL::Translator::Producer::DB2 - DB2 SQL producer =head1 DESCRIPTION -Creates an SQL DDL suitable for DB. +Creates an SQL DDL suitable for DB2. =cut +use warnings; use strict; use vars qw[ $VERSION $DEBUG $WARN ]; -$VERSION = sprintf "%d.%02d", q$Revision: 1.1 $ =~ /(\d+)\.(\d+)/; +$VERSION = sprintf "%d.%02d", q$Revision: 1.2 $ =~ /(\d+)\.(\d+)/; $DEBUG = 0 unless defined $DEBUG; use SQL::Translator::Schema::Constants; @@ -52,7 +52,7 @@ use SQL::Translator::Utils qw(header_comment); # of SQL data types, with field->extra entries being used to convert back to # weird types like "polygon" if needed (IMO anyway) -my %translate = ( +my %dt_translate = ( # # MySQL types # @@ -64,9 +64,9 @@ my %translate = ( mediumblob => 'blob', longblob => 'long varchar for bit data', tinytext => 'varchar', - text => 'clob', - longtext => 'clob', - mediumtext => 'clob', + text => 'varchar', + longtext => 'varchar', + mediumtext => 'varchar', enum => 'varchar', set => 'varchar', date => 'date', @@ -202,42 +202,31 @@ sub produce my $indent = ' '; $output .= header_comment unless($no_comments); - my (@table_defs); + my (@table_defs, @index_defs); foreach my $table ($schema->get_tables) { - my $table_name = check_name($table->name, 'tables', 18); + push @table_defs, 'DROP TABLE ' . $table->name . ";\n" if $add_drop_table; + push @table_defs, create_table($table, { + no_comments => $no_comments}); - my (@field_defs, @comments); - push @comments, "--\n-- Table: $table_name\n--" unless $no_comments; - foreach my $field ($table->get_fields) + foreach my $index ($table->get_indices) { - my $field_name = check_name($field->name, 'fields', 30); - my $data_type = uc($translate{lc($field->data_type)} || $field->data_type); - my $size = $field->size(); - - my $field_def = "$field_name $data_type"; - $field_def .= $field->is_auto_increment ? - ' GENERATED BY DEFAULT AS IDENTITY' : ''; - $field_def .= $data_type =~ /CHAR/i ? "(${size})" : ''; - $field_def .= !$field->is_nullable ? ' NOT NULL':''; - $field_def .= $field->is_primary_key ? ' PRIMARY KEY':''; - $field_def .= $field->default_value ? ' DEFAULT ' . $field->default_value : ''; - - push @field_defs, "${indent}${field_def}"; + push @index_defs, create_index($index); } - - - my $tablespace = $table->extra()->{'TABLESPACE'} || ''; - my $table_def = "CREATE TABLE $table_name (\n"; - $table_def .= join (",\n", @field_defs); - $table_def .= "\n)"; - $table_def .= $tablespace ? "IN $tablespace;" : ';'; - - push @table_defs, "DROP TABLE $table_name;\n" if $add_drop_table; - push @table_defs, $table_def; + } + my (@view_defs); + foreach my $view ( $schema->get_views ) + { + push @view_defs, create_view($view); + } + my (@trigger_defs); + foreach my $trigger ( $schema->get_triggers ) + { + push @trigger_defs, create_trigger($trigger); + } - $output .= join("\n\n", @table_defs); + $output .= join("\n\n", @table_defs, @index_defs, @view_defs, @trigger_defs) . "\n"; } { my %objnames; @@ -250,13 +239,13 @@ sub produce if(length($name) > $length) ## Maximum table name length is 18 { warn "Table name $name is longer than $length characters, truncated" if $WARN; - if(grep {$_ eq substr($name, 0, $length) } - values(%{$objnames{$type}})) - { - die "Got multiple matching table names when truncated"; - } - $objnames{$type}{$name} = substr($name, 0,$length); - $newname = $objnames{$type}{$name}; +# if(grep {$_ eq substr($name, 0, $length) } +# values(%{$objnames{$type}})) +# { +# die "Got multiple matching table names when truncated"; +# } +# $objnames{$type}{$name} = substr($name, 0,$length); +# $newname = $objnames{$type}{$name}; } if($db2_reserved{uc($newname)}) @@ -268,4 +257,148 @@ sub produce } } +sub create_table +{ + my ($table, $options) = @_; + + my $table_name = check_name($table->name, 'tables', 128); + # this limit is 18 in older DB2s ! (<= 8) + + my (@field_defs, @comments); + push @comments, "--\n-- Table: $table_name\n--" unless $options->{no_comments}; + foreach my $field ($table->get_fields) + { + push @field_defs, create_field($field); + } + my @con_defs; + foreach my $con ($table->get_constraints) + { + push @con_defs, create_constraint($con); + } + my $pkey = join(", ", $table->primary_key()->fields); + + my $tablespace = $table->extra()->{'TABLESPACE'} || ''; + my $table_def = "CREATE TABLE $table_name (\n"; + $table_def .= join (",\n", @field_defs); + $table_def .= join (",\n", @con_defs); + $table_def .= ",\n PRIMARY KEY($pkey)"; + $table_def .= "\n)"; + $table_def .= $tablespace ? "IN $tablespace;" : ';'; + + return $table_def; +} + +sub create_field +{ + my ($field) = @_; + + my $field_name = check_name($field->name, 'fields', 30); +# use Data::Dumper; +# print Dumper(\%dt_translate); +# print $field->data_type, " ", $dt_translate{lc($field->data_type)}, "\n"; + my $data_type = uc($dt_translate{lc($field->data_type)} || $field->data_type); + my $size = $field->size(); + + my $field_def = "$field_name $data_type"; + $field_def .= $field->is_auto_increment ? + ' GENERATED BY DEFAULT AS IDENTITY' : ''; + $field_def .= $data_type =~ /CHAR/i ? "(${size})" : ''; + $field_def .= !$field->is_nullable ? ' NOT NULL':''; +# $field_def .= $field->is_primary_key ? ' PRIMARY KEY':''; + $field_def .= !defined $field->default_value ? '' : + $field->default_value =~ /current( |_)timestamp/i || + $field->default_value =~ /\Qnow()\E/i ? + 'DEFAULT CURRENT TIMESTAMP' : defined $field->default_value ? + (" DEFAULT '" . $field->default_value . "'") : ''; + +} + +sub create_index +{ + my ($index) = @_; + + my $out = sprintf('CREATE %sINDEX %s ON %s ( %s );', + $index->type() =~ /^UNIQUE$/i ? 'UNIQUE' : '', + $index->name, + $index->table->name, + join(', ', $index->fields) ); + + return $out; +} + +sub create_constraint +{ + my ($constraint) = @_; + + return '' if($constraint->type =~ /^PRIMARY(_|\s)KEY$/i); + + my $ctype = $constraint->type =~ /^PRIMARY(_|\s)KEY$/i ? 'PRIMARY KEY' : + $constraint->type =~ /^UNIQUE$/i ? 'UNIQUE' : + $constraint->type =~ /^CHECK_C$/i ? 'CHECK' : + $constraint->type =~ /^FOREIGN_KEY$/i ? 'FOREIGN KEY' : ''; + + my $expr = $constraint->type =~ /^CHECK_C$/i ? $constraint->expression : + ''; + my $ref = $constraint->type =~ /^FOREIGN_KEY$/i ? ('REFERENCES ' . $constraint->reference_table . '(' . join(', ', $constraint->reference_fields) . ')') : ''; + my $update = $constraint->on_update ? $constraint->on_update : ''; + my $delete = $constraint->on_delete ? $constraint->on_delete : ''; + + my $out = sprintf('%s %s %s %s %s %s', + $constraint->name ? ('CONSTRAINT ' . $constraint->name) : '', + $ctype, + '(' . join (', ', $constraint->fields) . ')', + $expr ? $expr : $ref, + $update, + $delete); + + + return $out; + +} + +sub create_view +{ + my ($view) = @_; + + my $out = sprintf("CREATE VIEW %s AS\n%s;", + $view->name, + $view->sql); + + return $out; +} + +sub create_trigger +{ + my ($trigger) = @_; +# create: CREATE TRIGGER trigger_name before type /ON/i table_name reference_b(?) /FOR EACH ROW/i 'MODE DB2SQL' triggered_action + + my $out = sprintf('CREATE TRIGGER %s %s %s ON %s %s %s MODE DB2SQL %s', + $trigger->name, + $trigger->perform_action_when || 'AFTER', + $trigger->database_event =~ /update_on/i ? + ('UPDATE OF '. join(', ', $trigger->fields)) : + $trigger->database_event || 'UPDATE', + $trigger->on_table->name, + $trigger->extra->{reference} || 'REFERENCING OLD AS oldrow NEW AS newrow', + $trigger->extra->{granularity} || 'FOR EACH ROW', + $trigger->action ); + + return $out; + +} + +sub alter_field +{ + my ($from_field, $to_field) = @_; +} + +sub add_field +{ + my ($field) = @_; +} + +sub drop_field +{ + my ($field) = @_; +} 1;