Patch from jgoulah for mysqls UNION (merge engine) option
Jess Robinson [Wed, 22 Oct 2008 21:19:45 +0000 (21:19 +0000)]
Changes
lib/SQL/Translator/Parser/MySQL.pm
lib/SQL/Translator/Producer/MySQL.pm
t/02mysql-parser.t

diff --git a/Changes b/Changes
index ecade0b..e514881 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,6 +1,7 @@
 # ----------------------------------------------------------
 # 
 # ----------------------------------------------------------
+* Applied patch from jgoulah to support mysql's MERGE option
 * Applied patch from rbo to add support of multiple database events on a trigger
 * Applied patch from lukes to allow drop if exists in sqlite producer, with version >= 3.3
 * Applied patch from rjbs with minor changes, now we support scalar refs in default values!
index a8793f6..e132ee4 100644 (file)
@@ -713,6 +713,10 @@ table_option : /comment/i /=/ /'.*?'/
     {
         $return = { 'COLLATE' => $item[2] }
     }
+    | /union/i /\s*=\s*/ '(' table_name(s /,/) ')'
+    { 
+        $return = { $item[1] => $item[4] };
+    }
     | WORD /\s*=\s*/ WORD
     { 
         $return = { $item[1] => $item[3] };
@@ -765,7 +769,6 @@ END_OF_GRAMMAR
 sub parse {
     my ( $translator, $data ) = @_;
     my $parser = Parse::RecDescent->new($GRAMMAR);
-
     local $::RD_TRACE  = $translator->trace ? 1 : undef;
     local $DEBUG       = $translator->debug;
 
index 9121160..86b32bf 100644 (file)
@@ -419,7 +419,7 @@ sub create_table
     # Footer
     #
     $create .= "\n)";
-    $create .= generate_table_options($table) || '';
+    $create .= generate_table_options($table, $options) || '';
 #    $create .= ";\n\n";
 
     return $drop ? ($drop,$create) : $create;
@@ -427,12 +427,14 @@ sub create_table
 
 sub generate_table_options 
 {
-  my ($table) = @_;
+  my ($table, $options) = @_;
   my $create;
 
   my $table_type_defined = 0;
+  my $qf               = $options->{quote_field_names} ||= '';
   my $charset          = $table->extra('mysql_charset');
   my $collate          = $table->extra('mysql_collate');
+  my $union            = undef;
   for my $t1_option_ref ( $table->options ) {
     my($key, $value) = %{$t1_option_ref};
     $table_type_defined = 1
@@ -443,6 +445,9 @@ sub generate_table_options
     } elsif (uc $key eq 'COLLATE') {
       $collate = $value;
       next;
+    } elsif (uc $key eq 'UNION') {
+      $union = "($qf". join("$qf, $qf", @$value) ."$qf)";
+      next;
     }
     $create .= " $key=$value";
   }
@@ -454,6 +459,7 @@ sub generate_table_options
 
   $create .= " DEFAULT CHARACTER SET $charset" if $charset;
   $create .= " COLLATE $collate" if $collate;
+  $create .= " UNION=$union" if $union;
   $create .= qq[ comment='$comments'] if $comments;
   return $create;
 }
@@ -730,7 +736,7 @@ sub alter_table
 
     my $qt = $options->{quote_table_names} || '';
 
-    my $table_options = generate_table_options($to_table) || '';
+    my $table_options = generate_table_options($to_table, $options) || '';
     my $out = sprintf('ALTER TABLE %s%s',
                       $qt . $to_table->name . $qt,
                       $table_options);
index 585bd05..1ed7001 100644 (file)
@@ -11,7 +11,7 @@ use SQL::Translator::Utils qw//;
 use Test::SQL::Translator qw(maybe_plan);
 
 BEGIN {
-    maybe_plan(244, "SQL::Translator::Parser::MySQL");
+    maybe_plan(265, "SQL::Translator::Parser::MySQL");
     SQL::Translator::Parser::MySQL->import('parse');
 }
 
@@ -660,3 +660,65 @@ for my $target (keys %$parse_as) {
 
 eval { SQL::Translator::Utils::parse_mysql_version ('bogus5.1') };
 ok ($@, 'Exception thrown on invalid version string');
+
+{
+    my $tr = SQL::Translator->new;
+    my $data = q|create table merge_example (
+       id int(11) NOT NULL auto_increment,
+       shape_field geometry NOT NULL,
+       PRIMARY KEY (id),
+       SPATIAL KEY shape_field (shape_field)
+    ) ENGINE=MRG_MyISAM UNION=(`sometable_0`,`sometable_1`,`sometable_2`);|;
+
+    my $val = parse($tr, $data);
+    my $schema = $tr->schema;
+    is( $schema->is_valid, 1, 'Schema is valid' );
+    my @tables = $schema->get_tables;
+    is( scalar @tables, 1, 'Right number of tables (1)' );
+    my $table  = shift @tables;
+    is( $table->name, 'merge_example', 'Found "merge_example" table' );
+
+    my $tableTypeFound = 0;
+    my $unionFound = 0;
+    for my $t_option_ref ( $table->options ) {
+      my($key, $value) = %{$t_option_ref};
+      if ( $key eq 'ENGINE' ) {
+        is($value, 'MRG_MyISAM', 'Table has right table engine option' );
+        $tableTypeFound = 1;
+      } elsif ( $key eq 'UNION' ) {
+        is_deeply($value, [ 'sometable_0','sometable_1','sometable_2' ],
+          "UNION option has correct set");
+        $unionFound = 1;
+      }
+    }
+
+    fail('Table did not have a type option') unless $tableTypeFound;
+    fail('Table did not have a union option') unless $unionFound;
+
+    my @fields = $table->get_fields;
+    is( scalar @fields, 2, 'Right number of fields (2)' );
+    my $f1 = shift @fields;
+    my $f2 = shift @fields;
+    is( $f1->name, 'id', 'First field name is "id"' );
+    is( $f1->data_type, 'int', 'Type is "int"' );
+    is( $f1->size, 11, 'Size is "11"' );
+    is( $f1->is_nullable, 0, 'Field cannot be null' );
+    is( $f1->is_primary_key, 1, 'Field is PK' );
+
+    is( $f2->name, 'shape_field', 'Second field name is "shape_field"' );
+    is( $f2->data_type, 'geometry', 'Type is "geometry"' );
+    is( $f2->is_nullable, 0, 'Field cannot be null' );
+    is( $f2->is_primary_key, 0, 'Field is not PK' );
+
+    my @indices = $table->get_indices;
+    is( scalar @indices, 1, 'Right number of indices (1)' );
+    my $i1 = shift @indices;
+    is( $i1->name, 'shape_field', 'No name on index' );
+    is( $i1->type, SPATIAL, 'Spatial index' );
+
+    my @constraints = $table->get_constraints;
+    is( scalar @constraints, 1, 'Right number of constraints (1)' );
+    my $c = shift @constraints;
+    is( $c->type, PRIMARY_KEY, 'Constraint is a PK' );
+    is( join(',', $c->fields), 'id', 'Constraint is on "id"' );
+}