Change parser to not eagerly slurp RHS expressions it doesn't recognize
Peter Rabbitson [Tue, 4 Jun 2013 16:08:25 +0000 (18:08 +0200)]
Changes
lib/SQL/Abstract/Tree.pm
t/11parser.t

diff --git a/Changes b/Changes
index ca58b59..c178f5b 100644 (file)
--- a/Changes
+++ b/Changes
@@ -3,6 +3,7 @@ Revision history for SQL::Abstract
     - Fix insufficient parenthesis unroll during operator comparison
     - 'ORDER BY foo' and 'ORDER BY foo ASC' are now considered equal
       by default (with a switch to reenable old behavior when necessary)
+    - Change parser to not eagerly slurp RHS expressions it doesn't recognize
 
 revision 1.73  2012-07-10
 ----------------------------
index 8e743a6..c3e1555 100644 (file)
@@ -447,13 +447,16 @@ sub _recurse_parse {
     }
 
     # we're now in "unknown token" land - start eating tokens until
-    # we see something familiar
+    # we see something familiar, OR in the case of RHS (binop) stop
+    # after the first token
     else {
       my @lits = [ -LITERAL => [$token] ];
 
-      while (@$tokens and $tokens->[0] !~ $all_std_keywords_re) {
-        push @lits, [ -LITERAL => [ shift @$tokens ] ];
-       }
+      unless ( $state == PARSE_RHS ) {
+        while (@$tokens and $tokens->[0] !~ $all_std_keywords_re) {
+          push @lits, [ -LITERAL => [ shift @$tokens ] ];
+         }
+      }
 
       if (@left == 1) {
         unshift @lits, pop @left;
@@ -465,10 +468,13 @@ sub _recurse_parse {
     }
 
     if (@$tokens) {
-      # asc/desc
+
+      # deal with post-fix operators (asc/desc)
       if ($tokens->[0] =~ $asc_desc_re) {
         @left = [ ('-' . uc (shift @$tokens)) => [ @left ] ];
       }
+
+      return @left if $state == PARSE_RHS and $left[-1][0] eq '-LITERAL';
     }
   }
 }
index 202e5fa..8e1ee05 100644 (file)
@@ -800,8 +800,13 @@ is_deeply($sqlat->parse('SELECT foo FROM bar ORDER BY x + ? DESC, oomph, y - ? D
   ]
 ], 'Crazy ORDER BY parsed correctly');
 
-
-is_deeply($sqlat->parse("SELECT * * FROM (SELECT *, FROM foobar baz buzz) foo bar WHERE NOT NOT NOT EXISTS (SELECT 'cr,ap') AND foo.a = ? and not (foo.b LIKE 'station') and x = y and a = b and GROUP BY , ORDER BY x x1 x2 y asc, max(y) desc x z desc"), [
+is_deeply( $sqlat->parse("META SELECT * * FROM (SELECT *, FROM foobar baz buzz) foo bar WHERE NOT NOT NOT EXISTS (SELECT 'cr,ap') AND foo.a = ? STUFF and not (foo.b LIKE 'station') and x = y and a = b and GROUP BY , ORDER BY x x1 x2 y asc, max(y) desc x z desc"), [
+  [
+    "-LITERAL",
+    [
+      "META"
+    ]
+  ],
   [
     "SELECT",
     [
@@ -952,10 +957,21 @@ is_deeply($sqlat->parse("SELECT * * FROM (SELECT *, FROM foobar baz buzz) foo ba
                 ]
               ],
               [
-                "-PLACEHOLDER",
+                "-MISC",
                 [
-                  "?"
-                ]
+                  [
+                    "-PLACEHOLDER",
+                    [
+                      "?"
+                    ]
+                  ],
+                  [
+                    "-LITERAL",
+                    [
+                      "STUFF"
+                    ]
+                  ]
+                ],
               ]
             ]
           ],
@@ -1086,25 +1102,30 @@ is_deeply($sqlat->parse("SELECT * * FROM (SELECT *, FROM foobar baz buzz) foo ba
                     "-MISC",
                     [
                       [
-                        "-DESC",
+                        "-MISC",
                         [
                           [
-                            "-PAREN",
+                            "-DESC",
                             [
                               [
-                                "-LITERAL",
+                                "-PAREN",
                                 [
-                                  "y"
+                                  [
+                                    "-LITERAL",
+                                    [
+                                      "y"
+                                    ]
+                                  ]
                                 ]
                               ]
                             ]
-                          ]
-                        ]
-                      ],
-                      [
-                        "-LITERAL",
-                        [
-                          "x"
+                          ],
+                          [
+                            "-LITERAL",
+                            [
+                              "x"
+                            ]
+                          ],
                         ]
                       ],
                       [