primary key fix
[dbsrgits/SQL-Translator-2.0-ish.git] / lib / SQL / Translator / Parser / DDL / MySQL.pm
index 574aa5e..e577f33 100644 (file)
@@ -8,8 +8,10 @@ role SQL::Translator::Parser::DDL::MySQL {
     use aliased 'SQL::Translator::Object::ForeignKey';
     use aliased 'SQL::Translator::Object::Index';
     use aliased 'SQL::Translator::Object::PrimaryKey';
+    use aliased 'SQL::Translator::Object::Procedure';
     use aliased 'SQL::Translator::Object::Schema';
     use aliased 'SQL::Translator::Object::Table';
+    use aliased 'SQL::Translator::Object::View';
 
     around _build_data_type_mapping {
         my $data_type_mapping = $self->$orig;
@@ -28,17 +30,17 @@ role SQL::Translator::Parser::DDL::MySQL {
                 "instance: Bad grammar");
         }
 
-#    my $parser_version = parse_mysql_version(
-#        $translator->parser_args->{mysql_parser_version}, 'mysql'
-#    ) || DEFAULT_PARSER_VERSION;
-        my $parser_version = 30000;
+        my $translator = $self->translator;
+
+        my $parser_version = $translator->has_parser_args
+                             ? $translator->engine_version($translator->parser_args->{mysql_parser_version}, 'mysql') || DEFAULT_PARSER_VERSION
+                             : DEFAULT_PARSER_VERSION;
     
         while ($data =~ s#/\*!(\d{5})?(.*?)\*/#($1 && $1 > $parser_version ? '' : $2)#es) { }
 
         my $result = $parser->startrule($data);
         die "Parse failed" unless defined $result;
     
-        my $translator = $self->translator;
         my $schema = $translator->schema;
         $schema->name($result->{'database_name'}) if $result->{'database_name'};
     
@@ -63,11 +65,12 @@ role SQL::Translator::Parser::DDL::MySQL {
                     is_auto_increment => $fdata->{is_auto_inc},
                     is_nullable       => $fdata->{null},
                     is_primary_key    => $fdata->{is_primary_key} ? 1 : 0,
-                    comments          => (join "\n", @{$fdata->{comments}}) || '',
+                    table             => $table,
                 });
+                $field->comments($fdata->{comments});
                 $table->add_column($field);
     
-                $table->primary_key( $field->name ) if $fdata->{'is_primary_key'};
+                $field->is_primary_key(1) if $fdata->{is_primary_key};
 
                 my %extra;
                 for my $qual ( qw[ binary unsigned zerofill list collate ],
@@ -81,16 +84,13 @@ role SQL::Translator::Parser::DDL::MySQL {
                 $field->extra(\%extra);
 
                 if ( $fdata->{has_index} ) {
-                    my $index = Index->new({ name => '', type => 'NORMAL' });
+                    my $index = Index->new({ name => '', type => 'NORMAL', table => $table });
                     $index->add_column($table->get_column($fdata->{name}));
                     $table->add_index($index);
                 }
     
                 if ( $fdata->{is_unique} ) {
                     push @{ $tdata->{constraints} }, { name => '', type => 'UNIQUE', fields => [ $fdata->{name} ] };
-#                     my $constraint = Constraint->new({ name => '', type => 'UNIQUE' });
-#                     $constraint->add_column($table->get_column($fdata->{name}));
-#                     $table->add_constraint($constraint);
                 }
     
                 for my $cdata ( @{ $fdata->{constraints} } ) {
@@ -101,170 +101,69 @@ role SQL::Translator::Parser::DDL::MySQL {
             }
     
             for my $idata ( @{ $tdata->{indices} || [] } ) {
-                my $index = Index->new({ name => $idata->{name} || '', type => uc($idata->{type}) });
+                my $index = Index->new({ name => $idata->{name} || '', type => uc($idata->{type}), table => $table });
                 map { $index->add_column($table->get_column($_)) } @{$idata->{fields}};
                 $table->add_index($index);
             }
             
     
-#            if ( my @options = @{ $tdata->{'table_options'} || [] } ) {
-#                my @cleaned_options;
-#                my @ignore_opts = $self->parser_args->{'ignore_opts'}
-#                    ? split( /,/, $self->parser_args->{'ignore_opts'} )
-#                    : ();
-#                if (@ignore_opts) {
-#                    my $ignores = { map { $_ => 1 } @ignore_opts };
-#                    foreach my $option (@options) {
-#                        # make sure the option isn't in ignore list
-#                        my ($option_key) = keys %$option;
-#                        if ( !exists $ignores->{$option_key} ) {
-#                            push @cleaned_options, $option;
-#                        }
-#                    }
-#                } else {
-#                    @cleaned_options = @options;
-#                }
-#                $table->options( \@cleaned_options ) or die $table->error;
-#            }
+            if ( my @options = @{ $tdata->{'table_options'} || [] } ) {
+                my @cleaned_options;
+                my @ignore_opts = $translator->has_parser_args && $translator->parser_args->{'ignore_opts'}
+                    ? split( /,/, $translator->parser_args->{'ignore_opts'} )
+                    : ();
+                if (@ignore_opts) {
+                    my $ignores = { map { $_ => 1 } @ignore_opts };
+                    foreach my $option (@options) {
+                        # make sure the option isn't in ignore list
+                        my ($option_key) = keys %$option;
+                        if ( !exists $ignores->{$option_key} ) {
+                            push @cleaned_options, $option;
+                        }
+                    }
+                } else {
+                    @cleaned_options = @options;
+                }
+                $table->options( \@cleaned_options ); # or die $table->error;
+            }
     
             for my $cdata ( @{ $tdata->{constraints} || [] } ) {
                 my $constraint;
                 if (uc $cdata->{type} eq 'PRIMARY_KEY') {
-                    $constraint = PrimaryKey->new({ name => $cdata->{name} || 'primary_key' });
-                map { $constraint->add_column($table->get_column($_)) } @{$cdata->{fields}};
-                $table->get_column($_)->is_primary_key(1) for @{$cdata->{fields}};
+                    $constraint = PrimaryKey->new({ name => $cdata->{name} || '', table => $table });
+                    $table->get_column($_)->is_primary_key(1) for @{$cdata->{fields}};
                 } elsif (uc $cdata->{type} eq 'FOREIGN_KEY') {
-                    $constraint = ForeignKey->new({ name => $cdata->{name} || 'foreign_key',
+                    $constraint = ForeignKey->new({ name => $cdata->{name} || '',
+                                                    table => $table,
                                                     reference_table => $cdata->{reference_table},
-                                                    reference_columns => $cdata->{reference_fields},
+                                                    defined $cdata->{reference_fields} ? (reference_columns => $cdata->{reference_fields}) : (),
                                                     on_delete => $cdata->{on_delete} || $cdata->{on_delete_do},
                                                     on_update => $cdata->{on_update} || $cdata->{on_update_do} });
                     $table->get_column($_)->is_foreign_key(1) for @{$cdata->{fields}};
                     $table->get_column($_)->foreign_key_reference($constraint) for @{$cdata->{fields}};
                 } else {
-                    $constraint = Constraint->new({ name => $cdata->{name} || 'constraint', type => uc $cdata->{type} });
-                map { $constraint->add_column($table->get_column($_)) } @{$cdata->{fields}};
+                    $constraint = Constraint->new({ name => $cdata->{name} || '', type => uc $cdata->{type}, table => $table });
                 }
+                $constraint->add_column($table->get_column($_)) for @{$cdata->{fields}};
                 $table->add_constraint($constraint);
-
-#                my $constraint       =  $table->add_constraint(
-#                    name             => $cdata->{'name'},
-#                    type             => $cdata->{'type'},
-#                    fields           => $cdata->{'fields'},
-#                    reference_table  => $cdata->{'reference_table'},
-#                    reference_fields => $cdata->{'reference_fields'},
-#                    match_type       => $cdata->{'match_type'} || '',
-#                    on_delete        => $cdata->{'on_delete'} 
-#                                     || $cdata->{'on_delete_do'},
-#                    on_update        => $cdata->{'on_update'} 
-#                                     || $cdata->{'on_update_do'},
-#                ) or die $table->error;
             }
-    
-            # After the constrains and PK/idxs have been created, 
-            # we normalize fields
-            normalize_field($_) for $table->get_fields;
         }
         
-#        my @procedures = sort { $result->{procedures}->{ $a }->{'order'} <=> $result->{procedures}->{ $b }->{'order'} } keys %{ $result->{procedures} };
-    
-#        for my $proc_name ( @procedures ) {
-#            $schema->add_procedure(
-#                name  => $proc_name,
-#                owner => $result->{procedures}->{$proc_name}->{owner},
-#                sql   => $result->{procedures}->{$proc_name}->{sql},
-#            );
-#        }
-    
-#        my @views = sort { $result->{views}->{ $a }->{'order'} <=> $result->{views}->{ $b }->{'order'} } keys %{ $result->{views} };
-    
-#        for my $view_name ( keys %{ $result->{'views'} } ) {
-#            $schema->add_view(
-#                name => $view_name,
-#                sql  => $result->{'views'}->{$view_name}->{sql},
-#            );
-#        }
-        return $schema;
-    }
-    
-    # Takes a field, and returns 
-    method normalize_field {
-        my ($size, $type, $list, $changed); # = @_;
-      
-        $size = $self->size || 0;
-        $type = $self->data_type;
-        $list = $self->extra->{list} || [];
-
-        if ( !ref $size && $size == 0 ) {
-            if ( lc $type eq 'tinyint' ) {
-                $changed = $size != 4;
-                $size = 4;
-            }
-            elsif ( lc $type eq 'smallint' ) {
-                $changed = $size != 6;
-                $size = 6;
-            }
-            elsif ( lc $type eq 'mediumint' ) {
-                $changed = $size != 9;
-                $size = 9;
-            }
-            elsif ( $type =~ /^int(eger)?$/i ) {
-                $changed = $size != 11 || $type ne 'int';
-                $type = 'int';
-                $size = 11;
-            }
-            elsif ( lc $type eq 'bigint' ) {
-                $changed = $size != 20;
-                $size = 20;
-            }
-            elsif ( lc $type =~ /(float|double|decimal|numeric|real|fixed|dec)/ ) {
-                my $old_size = (ref $size || '') eq 'ARRAY' ? $size : [];
-                $changed     = @$old_size != 2 
-                            || $old_size->[0] != 8 
-                            || $old_size->[1] != 2;
-                $size        = [8,2];
-            }
+        for my $proc_name ( keys %{ $result->{procedures} } ) {
+            my $procedure = Procedure->new({ name  => $proc_name,
+                                             owner => $result->{procedures}->{$proc_name}->{owner},
+                                             sql   => $result->{procedures}->{$proc_name}->{sql}
+            });
+            $schema->add_procedure($procedure);
         }
     
-        if ( $type =~ /^tiny(text|blob)$/i ) {
-            $changed = $size != 255;
-            $size = 255;
+        for my $view_name ( keys %{ $result->{'views'} } ) {
+            my $view = View->new({ 
+                name => $view_name,
+                sql  => $result->{'views'}->{$view_name}->{sql},
+            });
+            $schema->add_view($view);
         }
-        elsif ( $type =~ /^(blob|text)$/i ) {
-            $changed = $size != 65_535;
-            $size = 65_535;
-        }
-        elsif ( $type =~ /^medium(blob|text)$/i ) {
-            $changed = $size != 16_777_215;
-            $size = 16_777_215;
-        }
-        elsif ( $type =~ /^long(blob|text)$/i ) {
-            $changed = $size != 4_294_967_295;
-            $size = 4_294_967_295;
-        }
-    
-        if ( $type =~ /(set|enum)/i && !$size ) {
-            my %extra = $self->extra;
-            my $longest = 0;
-            for my $len ( map { length } @{ $extra{'list'} || [] } ) {
-                $longest = $len if $len > $longest;
-            }
-            $changed = 1;
-            $size = $longest if $longest;
-        }
-    
-#        if ( $changed ) {
-            # We only want to clone the field, not *everything*
-#            {
-#                local $field->{table} = undef;
-#                $field->parsed_field( dclone( $field ) );
-#                $field->parsed_field->{table} = $field->table;
-#            }
-            $self->size( $size );
-            $self->data_type( $type );
-#            $column->sql_data_type( $self->data_type_mapping->{$type} || -99999 );
-            $self->extra->{list} = $list if @$list;
-#        }
         return 1;
     }
 }