X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FSQL%2FAbstract%2FTree.pm;h=97b90a6b455530251348e059976c574482db683d;hb=0ec2e26564ab5809a4b1c76ca7b3084c7a06fccd;hp=c6faef97f21f76f7b80942756063f32ee37e4d78;hpb=7d27345242d34aa0ad38e3a5f54d0bd09b558d32;p=dbsrgits%2FSQL-Abstract.git diff --git a/lib/SQL/Abstract/Tree.pm b/lib/SQL/Abstract/Tree.pm index c6faef9..97b90a6 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", ; @@ -419,12 +420,16 @@ sub _recurse_parse { @right = $self->_recurse_parse($tokens, PARSE_IN_EXPR); } - @left = [$op => [ @left, @right ]]; + push @left, [$op => [ (@left ? pop @left : ''), @right ]]; } # 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 ]; @@ -664,8 +669,9 @@ sub _parenthesis_unroll { $changes++; } - # if the parent operator explicitly allows it nuke the parenthesis - if ( $ast->[0] =~ $unrollable_ops_re ) { + # if the parent operator explicitly allows it AND the child isn't a subselect + # nuke the parenthesis + if ($ast->[0] =~ $unrollable_ops_re and $child->[1][0][0] ne 'SELECT') { push @children, @{$child->[1]}; $changes++; } @@ -753,7 +759,10 @@ sub _parenthesis_unroll { # a construct of ... ( somefunc ( ... ) ) ... can safely lose the outer parens # except for the case of ( NOT ( ... ) ) which has already been handled earlier + # and except for the case of RNO, where the double are explicit syntax elsif ( + $ast->[0] ne 'ROW_NUMBER() OVER' + and @{$child->[1]} == 1 and @{$child->[1][0][1]} == 1