Improve trigger 'scope' attribute support (RT#119997)
[dbsrgits/SQL-Translator.git] / lib / SQL / Translator / Parser / SQLServer.pm
index dcfec05..c4191fd 100644 (file)
@@ -19,22 +19,18 @@ should probably be considered a work in progress.
 use strict;
 use warnings;
 
-use vars qw[ $DEBUG $VERSION $GRAMMAR @EXPORT_OK ];
-$VERSION = '1.59';
+our $VERSION = '1.59';
+
+our $DEBUG;
 $DEBUG   = 0 unless defined $DEBUG;
 
 use Data::Dumper;
-use Parse::RecDescent;
-use Exporter;
-use base qw(Exporter);
-
-@EXPORT_OK = qw(parse);
+use SQL::Translator::Utils qw/ddl_parser_instance/;
 
-$::RD_ERRORS = 1;
-$::RD_WARN   = 1;
-$::RD_HINT   = 1;
+use base qw(Exporter);
+our @EXPORT_OK = qw(parse);
 
-$GRAMMAR = q{
+our $GRAMMAR = <<'END_OF_GRAMMAR';
 
 {
     my ( %tables, @table_comments, $table_order, %procedures, $proc_order, %views, $view_order );
@@ -77,10 +73,10 @@ statement : create_table
     | exec
     | /^\Z/ | { _err ($thisline, $text) }
 
-use : /use/i WORD GO
+use : /use/i NAME GO
     { @table_comments = () }
 
-setuser : /setuser/i NAME GO
+setuser : /setuser/i USERNAME GO
 
 if : /if/i object_not_null begin if_command end GO
 
@@ -88,7 +84,7 @@ if_command : grant
     | create_index
     | create_constraint
 
-object_not_null : /object_id/i '(' ident ')' /is not null/i
+object_not_null : /object_id/i '(' SQSTRING ')' /is not null/i
 
 field_not_null : /where/i field_name /is \s+ not \s+ null/ix
 
@@ -179,7 +175,7 @@ create_table : /create/i /table/i ident '(' create_def(s /,/) ')' lock(?) on_sys
 
 disable_constraints : if_exists(?) /alter/i /table/i ident /nocheck/i /constraint/i /all/i END_STATEMENT
 
-# this is for the normal case 
+# this is for the normal case
 create_constraint : /create/i constraint END_STATEMENT
     {
         @table_comments = ();
@@ -296,20 +292,11 @@ constraint : primary_key_constraint
     | foreign_key_constraint
     | unique_constraint
 
-field_name : WORD
-   { $return = $item[1] }
-   | LQUOTE WORD RQUOTE
-   { $return = $item[2] }
+field_name : NAME
 
-index_name : WORD
-   { $return = $item[1] }
-   | LQUOTE WORD RQUOTE
-   { $return = $item[2] }
+index_name : NAME
 
-table_name : WORD
- { $return = $item[1] }
- | LQUOTE WORD RQUOTE
- { $return = $item[2] }
+table_name : NAME
 
 data_type : WORD field_size(?)
     {
@@ -338,8 +325,8 @@ nullable : /not/i /null/i
 
 default_val : /default/i /null/i
     { $return = 'null' }
-   | /default/i /'[^']*'/
-    { $item[2]=~ s/'//g; $return = $item[2] }
+   | /default/i SQSTRING
+    { $return = $item[2] }
    | /default/i WORD
     { $return = $item[2] }
 
@@ -430,15 +417,9 @@ index : clustered(?) INDEX index_name(?) on_table(?) parens_field_list END_STATE
 parens_field_list : '(' field_name(s /,/) ')'
     { $item[2] }
 
-ident : QUOTE WORD '.' WORD QUOTE | LQUOTE WORD '.' WORD RQUOTE
-    { $return = { owner => $item[2], name => $item[4] } }
-    | LQUOTE WORD RQUOTE '.' LQUOTE WORD RQUOTE
-    { $return = { owner => $item[2], name => $item[6] } }
-    | LQUOTE WORD RQUOTE
-    { $return = { name  => $item[2] } }
-    | WORD '.' WORD
+ident : NAME '.' NAME
     { $return = { owner => $item[1], name => $item[3] } }
-    | WORD
+    | NAME
     { $return = { name  => $item[1] } }
 
 END_STATEMENT : ';'
@@ -446,8 +427,12 @@ END_STATEMENT : ';'
 
 GO : /^go/i
 
-NAME : QUOTE(?) /\w+/ QUOTE(?)
-    { $item[2] }
+USERNAME : WORD
+    | SQSTRING
+
+NAME : WORD
+    | DQSTRING
+    | BQSTRING
 
 WORD : /[\w#]+/
 
@@ -455,25 +440,29 @@ DIGITS : /\d+/
 
 COMMA : ','
 
-QUOTE : /'/
+SQSTRING : "'" <skip: ''> /(?:[^']|'')*/ "'"
+    { ($return = $item[3]) =~ s/''/'/g }
 
-LQUOTE : '['
+DQSTRING : '"' <skip: ''> /(?:[^"]|"")+/ '"'
+    { ($return = $item[3]) =~ s/""/"/g }
 
-RQUOTE : ']'
+BQSTRING : '[' <skip: ''> /(?:[^]]|]])+/ ']'
+    { ($return = $item[3]) =~ s/]]/]/g; }
 
-};
+END_OF_GRAMMAR
 
 sub parse {
     my ( $translator, $data ) = @_;
-    my $parser = Parse::RecDescent->new($GRAMMAR);
+
+    # Enable warnings within the Parse::RecDescent module.
+    local $::RD_ERRORS = 1 unless defined $::RD_ERRORS; # Make sure the parser dies when it encounters an error
+    local $::RD_WARN   = 1 unless defined $::RD_WARN; # Enable warnings. This will warn on unused rules &c.
+    local $::RD_HINT   = 1 unless defined $::RD_HINT; # Give out hints to help fix problems.
 
     local $::RD_TRACE  = $translator->trace ? 1 : undef;
     local $DEBUG       = $translator->debug;
 
-    unless (defined $parser) {
-        return $translator->error("Error instantiating Parse::RecDescent ".
-            "instance: Bad grammer");
-    }
+    my $parser = ddl_parser_instance('SQLServer');
 
     my $result = $parser->startrule($data);
     return $translator->error( "Parse failed." ) unless defined $result;