From: Ken Youens-Clark Date: Tue, 3 Jun 2003 22:11:55 +0000 (+0000) Subject: Changed grammar to bring it more inline with the official MySQL YACC X-Git-Tag: v0.02~106 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=40c1ade147af9b3aa320b937f4315350d2239848;p=dbsrgits%2FSQL-Translator.git Changed grammar to bring it more inline with the official MySQL YACC grammar, added better support for FK references. --- diff --git a/lib/SQL/Translator/Parser/MySQL.pm b/lib/SQL/Translator/Parser/MySQL.pm index 6b5e631..7f684b0 100644 --- a/lib/SQL/Translator/Parser/MySQL.pm +++ b/lib/SQL/Translator/Parser/MySQL.pm @@ -1,7 +1,7 @@ package SQL::Translator::Parser::MySQL; # ------------------------------------------------------------------- -# $Id: MySQL.pm,v 1.18 2003-05-09 19:51:04 kycl4rk Exp $ +# $Id: MySQL.pm,v 1.19 2003-06-03 22:11:55 kycl4rk Exp $ # ------------------------------------------------------------------- # Copyright (C) 2003 Ken Y. Clark , # darren chamberlain , @@ -123,7 +123,7 @@ Here's the word from the MySQL site use strict; use vars qw[ $DEBUG $VERSION $GRAMMAR @EXPORT_OK ]; -$VERSION = sprintf "%d.%02d", q$Revision: 1.18 $ =~ /(\d+)\.(\d+)/; +$VERSION = sprintf "%d.%02d", q$Revision: 1.19 $ =~ /(\d+)\.(\d+)/; $DEBUG = 0 unless defined $DEBUG; use Data::Dumper; @@ -138,9 +138,6 @@ $::RD_ERRORS = 1; # Make sure the parser dies when it encounters an error $::RD_WARN = 1; # Enable warnings. This will warn on unused rules &c. $::RD_HINT = 1; # Give out hints to help fix problems. -my $parser; # should we do this? There's no programmic way to - # change the grammar, so I think this is safe. - $GRAMMAR = q! { @@ -164,14 +161,14 @@ statement : comment drop : /drop/i WORD(s) ';' -create : create_table table_name '(' create_definition(s /,/) ')' table_option(s?) ';' +create : CREATE TEMPORARY(?) TABLE opt_if_not_exists(?) table_name '(' create_definition(s /,/) ')' table_option(s?) ';' { my $table_name = $item{'table_name'}; $tables{ $table_name }{'order'} = ++$table_order; $tables{ $table_name }{'table_name'} = $table_name; my $i = 1; - for my $definition ( @{ $item[4] } ) { + for my $definition ( @{ $item[7] } ) { if ( $definition->{'type'} eq 'field' ) { my $field_name = $definition->{'name'}; $tables{ $table_name }{'fields'}{ $field_name } = @@ -187,6 +184,14 @@ create : create_table table_name '(' create_definition(s /,/) ')' table_option(s ; } } + elsif ( $definition->{'type'} eq 'foreign_key' ) { + for my $field ( @{ $definition->{'fields'} } ) { + push @{ + $tables{$table_name}{'fields'}{$field}{'constraints'} + }, + $definition; + } + } else { push @{ $tables{ $table_name }{'indices'} }, $definition; @@ -202,6 +207,8 @@ create : create_table table_name '(' create_definition(s /,/) ')' table_option(s 1; } +opt_if_not_exists : /if not exists/i + create : /CREATE/i unique(?) /(INDEX|KEY)/i index_name /on/i table_name '(' field_name(s /,/) ')' ';' { push @{ $tables{ $item{'table_name'} }{'indices'} }, @@ -214,6 +221,7 @@ create : /CREATE/i unique(?) /(INDEX|KEY)/i index_name /on/i table_name '(' fiel } create_definition : index + | foreign_key | field | @@ -280,7 +288,7 @@ field_qualifier : unsigned reference_definition : /references/i table_name parens_field_list(?) match_type(?) on_delete_do(?) on_update_do(?) { - $return = { + $return = { type => 'foreign_key', reference_table => $item[2], reference_fields => $item[3][0], @@ -290,6 +298,7 @@ reference_definition : /references/i table_name parens_field_list(?) match_type( } } + match_type : /match full/i { 'match_full' } | /match partial/i { 'match_partial' } @@ -360,8 +369,6 @@ num_range : DIGITS ',' DIGITS | DIGITS { $return = $item[1] } -create_table : /create/i /table/i - create_index : /create/i /index/i not_null : /not/i /null/i { $return = 0 } @@ -378,6 +385,18 @@ auto_inc : /auto_increment/i { 1 } primary_key : /primary/i /key/i { 1 } +foreign_key : opt_constraint(?) /foreign key/i WORD(?) parens_field_list reference_definition + { + $return = { + type => 'foreign_key', + name => $item[3][0], + fields => $item[4], + %{ $item{'reference_definition'} }, + } + } + +opt_constraint : /constraint/i WORD + primary_key_index : primary_key index_name(?) '(' field_name(s /,/) ')' { $return = { @@ -428,6 +447,12 @@ table_option : /[^\s;]*/ $return = { split /=/, $item[1] } } +CREATE : /create/i + +TEMPORARY : /temporary/i + +TABLE : /table/i + WORD : /\w+/ DIGITS : /\d+/ @@ -457,7 +482,7 @@ VALUE : /[-+]?\.?\d+(?:[eE]\d+)?/ # ------------------------------------------------------------------- sub parse { my ( $translator, $data ) = @_; - $parser ||= Parse::RecDescent->new($GRAMMAR); + my $parser = Parse::RecDescent->new($GRAMMAR); local $::RD_TRACE = $translator->trace ? 1 : undef; local $DEBUG = $translator->debug; @@ -468,7 +493,7 @@ sub parse { } my $result = $parser->startrule($data); - die "Parse failed.\n" unless defined $result; + return $translator->error( "Parse failed." ) unless defined $result; warn Dumper( $result ) if $DEBUG; my $schema = $translator->schema; @@ -476,7 +501,7 @@ sub parse { my $tdata = $result->{ $table_name }; my $table = $schema->add_table( name => $tdata->{'table_name'}, - ); + ) or die $schema->error; my @fields = sort { $tdata->{'fields'}->{$a}->{'order'} @@ -493,7 +518,7 @@ sub parse { default_value => $fdata->{'default'}, is_auto_increment => $fdata->{'is_auto_inc'}, is_nullable => $fdata->{'null'}, - ); + ) or die $table->error; } }