X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FSQL%2FTranslator%2FParser%2FDDL%2FMySQL.pm;h=2a23fdaf5749f7f3163fd9d50ef251abd3ff86db;hb=refs%2Fheads%2Fmaster;hp=4e8ce748f9a08667625bc65e8db47b1fa1094abb;hpb=02989ef4c6530af87802703da118538712bc4976;p=dbsrgits%2FSQL-Translator-2.0-ish.git diff --git a/lib/SQL/Translator/Parser/DDL/MySQL.pm b/lib/SQL/Translator/Parser/DDL/MySQL.pm index 4e8ce74..2a23fda 100644 --- a/lib/SQL/Translator/Parser/DDL/MySQL.pm +++ b/lib/SQL/Translator/Parser/DDL/MySQL.pm @@ -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,12 +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 => $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 ], @@ -82,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} } ) { @@ -108,165 +107,66 @@ role SQL::Translator::Parser::DDL::MySQL { } -# 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 $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); + } + for my $view_name ( keys %{ $result->{'views'} } ) { + my $view = View->new({ + name => $view_name, + sql => $result->{'views'}->{$view_name}->{sql}, + }); + $schema->add_view($view); + } + for my $table_name (@tables) { + my $table = $schema->get_table($table_name); + my $tdata = $result->{tables}{ $table_name }; for my $cdata ( @{ $tdata->{constraints} || [] } ) { my $constraint; if (uc $cdata->{type} eq 'PRIMARY_KEY') { - $constraint = PrimaryKey->new({ name => $cdata->{name} || 'primary_key', table => $table }); - $constraint->add_column($table->get_column($_)) for @{$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}, table => $table }); - $constraint->add_column($table->get_column($_)) for @{$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]; - } - } - - if ( $type =~ /^tiny(text|blob)$/i ) { - $changed = $size != 255; - $size = 255; - } - 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; } }