X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FSQL%2FTranslator%2FProducer%2FMySQL.pm;h=6c20e566cf2acca05f098c57bd35aff7d33721bd;hb=1c680eb9aac43c469260f89be06027951722402e;hp=4fd5cee6b4fe14faba5ae8cc1e8db9d431e089e6;hpb=4d4385499fa84e31f78abe4cacf517e4a11c7b8f;p=dbsrgits%2FSQL-Translator.git diff --git a/lib/SQL/Translator/Producer/MySQL.pm b/lib/SQL/Translator/Producer/MySQL.pm index 4fd5cee..6c20e56 100644 --- a/lib/SQL/Translator/Producer/MySQL.pm +++ b/lib/SQL/Translator/Producer/MySQL.pm @@ -124,6 +124,80 @@ my %translate = ( 'datetime' => 'datetime', ); + +sub preprocess_schema { + my ($class, $schema) = @_; + + # extra->{mysql_table_type} used to be the type. It belongs in options, so + # move it if we find it. Return Engine type if found in extra or options + my $mysql_table_type_to_options = sub { + my ($table) = @_; + + my $extra = $table->extra; + + my $extra_type = delete $extra->{mysql_table_type}; + + # Now just to find if there is already an Engine or Type option... + # and lets normalize it to ENGINE since: + # + # The ENGINE table option specifies the storage engine for the table. + # TYPE is a synonym, but ENGINE is the preferred option name. + # + + # We have to use the hash directly here since otherwise there is no way + # to remove options. + my $options = ( $table->{options} ||= []); + + # This assumes that there isn't both a Type and an Engine option. + for my $idx ( 0..$#{$options} ) { + my ($key, $value) = %{ $options->[$idx] }; + + next unless uc $key eq 'ENGINE' || uc $key eq 'TYPE'; + + # if the extra.mysql_table_type is given, use that + delete $options->[$idx]{$key}; + return $options->[$idx]{ENGINE} = $value || $extra_type; + + } + + if ($extra_type) { + push @$options, { ENGINE => $extra_type }; + return $extra_type; + } + + }; + + # Names are only specific to a given schema + local %used_names = (); + + # + # Work out which tables need to be InnoDB to support foreign key + # constraints. We do this first as we need InnoDB at both ends. + # + foreach my $table ( $schema->get_tables ) { + + $mysql_table_type_to_options->($table); + + foreach my $c( $table->get_constraints ) { + next unless $c->type eq FOREIGN_KEY; + + # Normalize constraint names here. + my $c_name = $c->name; + # Give the constraint a name if it doesn't have one, so it doens't feel + # left out + $c_name = $table->name . '_fk' unless length $c_name; + + $c->name( next_unused_name($c_name) ); + + for my $meth (qw/table reference_table/) { + my $table = $schema->get_table($c->$meth) || next; + next if $mysql_table_type_to_options->($table); + $table->options( { 'ENGINE' => 'InnoDB' } ); + } + } + } +} + sub produce { my $translator = shift; local $DEBUG = $translator->debug; @@ -144,18 +218,7 @@ sub produce { # \todo Don't set if MySQL 3.x is set on command line $create .= "SET foreign_key_checks=0;\n\n"; - # - # Work out which tables need to be InnoDB to support foreign key - # constraints. We do this first as we need InnoDB at both ends. - # - foreach ( map { $_->get_constraints } $schema->get_tables ) { - next unless $_->type eq FOREIGN_KEY; - foreach my $meth (qw/table reference_table/) { - my $table = $schema->get_table($_->$meth) || next; - next if $table->extra('mysql_table_type'); - $table->extra( 'mysql_table_type' => 'InnoDB'); - } - } + __PACKAGE__->preprocess_schema($schema); # # Generate sql @@ -257,8 +320,9 @@ sub generate_table_options if uc $key eq 'ENGINE' or uc $key eq 'TYPE'; $create .= " $key=$value"; } + my $mysql_table_type = $table->extra('mysql_table_type'); - $create .= " Type=$mysql_table_type" + $create .= " ENGINE=$mysql_table_type" if $mysql_table_type && !$table_type_defined; my $charset = $table->extra('mysql_charset'); my $collate = $table->extra('mysql_collate'); @@ -458,7 +522,6 @@ sub create_constraint my $qf = $options->{quote_field_names} || ''; my $qt = $options->{quote_table_names} || ''; my $leave_name = $options->{leave_name} || undef; - my $counter = ($options->{fk_name_counter} ||= {}); my @fields = $c->fields or next; @@ -479,18 +542,10 @@ sub create_constraint my $table = $c->table; my $c_name = $c->name; - # Give the constraint a name if it doesn't have one, so it doens't feel - # left out - unless ( $c_name ){ - $c_name = $table->name . '_fk'; - } - - $counter->{$table} ||= {}; my $def = join(' ', map { $_ || () } 'CONSTRAINT', - $qt . join('_', next_unused_name($c_name) - ) . $qt, + $qt . $c_name . $qt, 'FOREIGN KEY' ); @@ -636,7 +691,6 @@ sub drop_table { my ($table) = @_; # Drop (foreign key) constraints so table drops cleanly - $DB::single = 1; my @sql = batch_alter_table($table, { alter_drop_constraint => [ grep { $_->type eq 'FOREIGN KEY' } $table->get_constraints ] }); return join("\n", @sql, "DROP TABLE $table;");