From: Peter Rabbitson Date: Wed, 21 May 2014 09:22:24 +0000 (+0200) Subject: Treat RNO as a unary op, and properly normalize it X-Git-Tag: v1.78~7 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=4247c384fc4291dab9ad93625b267e862b2c9906;p=dbsrgits%2FSQL-Abstract.git Treat RNO as a unary op, and properly normalize it --- diff --git a/lib/SQL/Abstract/Tree.pm b/lib/SQL/Abstract/Tree.pm index d60e236..ae93c95 100644 --- a/lib/SQL/Abstract/Tree.pm +++ b/lib/SQL/Abstract/Tree.pm @@ -83,7 +83,6 @@ my @expression_start_keywords = ( 'SAVEPOINT', 'RELEASE \s+ SAVEPOINT', 'RETURNING', - 'ROW_NUMBER \s* \( \s* \) \s+ OVER', ); my $expr_start_re = join ("\n\t|\n", @expression_start_keywords ); @@ -115,7 +114,9 @@ $binary_op_re = join "\n\t|\n", ; $binary_op_re = qr/$binary_op_re/x; -my $unary_op_re = '(?: NOT \s+ EXISTS | NOT )'; +my $rno_re = qr/ROW_NUMBER \s* \( \s* \) \s+ OVER/ix; + +my $unary_op_re = 'NOT \s+ EXISTS | NOT | ' . $rno_re; $unary_op_re = join "\n\t|\n", "$op_look_behind (?i: $unary_op_re ) $op_look_ahead", ; @@ -425,6 +426,10 @@ sub _recurse_parse { # unary op keywords elsif ( $token =~ $unary_op_re ) { my $op = uc $token; + + # normalize RNO explicitly + $op = 'ROW_NUMBER() OVER' if $op =~ /^$rno_re$/; + my @right = $self->_recurse_parse ($tokens, PARSE_RHS); push @left, [ $op => \@right ]; diff --git a/t/11parser.t b/t/11parser.t index 5ce1a80..f02a868 100644 --- a/t/11parser.t +++ b/t/11parser.t @@ -576,6 +576,78 @@ is_deeply($sqlat->parse("CASE WHEN FOO() > BAR()"), [ ] ]); +is_deeply($sqlat->parse("SELECT [me].[id], ROW_NUMBER ( ) OVER (ORDER BY (SELECT 1)) AS [rno__row__index] FROM bar"), [ + [ + "SELECT", + [ + [ + "-LIST", + [ + [ + "-LITERAL", + [ + "[me].[id]" + ] + ], + [ + "AS", + [ + [ + "ROW_NUMBER() OVER", + [ + [ + "-PAREN", + [ + [ + "ORDER BY", + [ + [ + "-PAREN", + [ + [ + "SELECT", + [ + [ + "-LITERAL", + [ + 1 + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ] + ], + [ + "-LITERAL", + [ + "[rno__row__index]" + ] + ] + ] + ] + ] + ] + ] + ], + [ + "FROM", + [ + [ + "-LITERAL", + [ + "bar" + ] + ] + ] + ] +]); + is_deeply($sqlat->parse("SELECT x, y FROM foo WHERE x IN (?, ?, ?, ?)"), [ [