1 package SQL::Translator::Parser::MySQL;
3 # -------------------------------------------------------------------
4 # $Id: MySQL.pm,v 1.5 2002-11-20 04:03:04 kycl4rk Exp $
5 # -------------------------------------------------------------------
6 # Copyright (C) 2002 Ken Y. Clark <kycl4rk@users.sourceforge.net>,
7 # darren chamberlain <darren@cpan.org>
9 # This program is free software; you can redistribute it and/or
10 # modify it under the terms of the GNU General Public License as
11 # published by the Free Software Foundation; version 2.
13 # This program is distributed in the hope that it will be useful, but
14 # WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 # General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
22 # -------------------------------------------------------------------
25 use vars qw($VERSION $GRAMMAR @EXPORT_OK);
26 $VERSION = sprintf "%d.%02d", q$Revision: 1.5 $ =~ /(\d+)\.(\d+)/;
28 #use SQL::Translator::Parser; # This is not necessary!
29 use Parse::RecDescent;
31 use base qw(Exporter);
33 @EXPORT_OK = qw(parse);
35 my $parser; # should we do this? There's no programmic way to
36 # change the grammar, so I think this is safe.
38 my ( $translator, $data ) = @_;
39 $parser ||= Parse::RecDescent->new($GRAMMAR);
41 unless (defined $parser) {
42 return $translator->error("Error instantiating Parse::RecDescent ".
43 "instance: Bad grammer");
46 # Is this right? It was $parser->parse before, but that didn't
47 # work; Parse::RecDescent appears to need the name of a rule
48 # with which to begin, so I chose the first rule in the grammar.
49 return $parser->file($data);
56 file : statement(s) { \%tables }
62 create : create_table table_name '(' line(s /,/) ')' table_type(?) ';'
65 for my $line ( @{ $item[4] } ) {
66 if ( $line->{'type'} eq 'field' ) {
67 my $field_name = $line->{'name'};
68 $tables{ $item{'table_name'} }
69 {'fields'}{$field_name} =
70 { %$line, order => $i };
73 if ( $line->{'is_primary_key'} ) {
75 @{ $tables{ $item{'table_name'} }{'indices'} },
77 type => 'primary_key',
78 fields => [ $field_name ],
83 push @{ $tables{ $item{'table_name'} }{'indices'} },
86 $tables{ $item{'table_name'} }{'type'} =
87 $item{'table_type'}[0];
92 create : create_index index_name /on/i table_name '(' field_name(s /,/) ')' ';'
93 # create : create_index index_name keyword_on table_name '(' field_name ')' ';'
106 comment : /^\s*[#-]+.*\n/
111 field : field_name data_type field_qualifier(s?)
114 map {%$_} @{$item{'field_qualifier'} || []};
115 my $null = defined $item{'not_null'}
116 ? $item{'not_null'} : 1 ;
117 delete $qualifier_h{'not_null'};
120 name => $item{'field_name'},
121 data_type => $item{'data_type'}{'type'},
128 field_qualifier : not_null
131 null => $item{'not_null'},
135 field_qualifier : default_val
138 default => $item{default_val},
142 field_qualifier : auto_inc
145 is_auto_inc => $item{auto_inc},
149 field_qualifier : primary_key
152 is_primary_key => $item{primary_key},
156 field_qualifier : unsigned
159 is_unsigned => $item{unsigned},
163 index : primary_key_index
173 data_type : WORD field_size(?)
183 field_size : '(' num_range ')' { $item{'num_range'} }
185 num_range : DIGITS ',' DIGITS
186 { $return = $item[1].','.$item[3] }
188 { $return = $item[1] }
191 create_table : /create/i /table/i
193 create_index : /create/i /index/i
195 not_null : /not/i /null/i { $return = 0 }
197 unsigned : /unsigned/i { $return = 0 }
199 default_val : /default/i /(?:')?[\w\d.-]*(?:')?/ { $item[2]=~s/'//g; $return=$item[2] }
201 auto_inc : /auto_increment/i { 1 }
203 primary_key : /primary/i /key/i { 1 }
205 primary_key_index : primary_key index_name(?) '(' field_name(s /,/) ')'
208 name => $item{'index_name'}[0],
209 type => 'primary_key',
214 normal_index : key index_name(?) '(' field_name(s /,/) ')'
217 name => $item{'index_name'}[0],
223 unique_index : /unique/i key(?) index_name(?) '(' field_name(s /,/) ')'
226 name => $item{'index_name'}[0],
235 table_type : /TYPE=/i /\w+/ { $item[2] }
247 #-----------------------------------------------------
248 # Where man is not nature is barren.
250 #-----------------------------------------------------
254 SQL::Translator::Parser::MySQL - parser for MySQL
259 use SQL::Translator::Parser::MySQL;
261 my $translator = SQL::Translator->new;
262 $translator->parser("SQL::Translator::Parser::MySQL");
270 Ken Y. Clark, kclark@logsoft.com