From: Peter Rabbitson Date: Fri, 4 Sep 2009 15:13:57 +0000 (+0000) Subject: Fix Tester to deal properly with NOT and single parenthesized expressions X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=9e8dab3fcb42dd5eeaab3b630bd71018ebc141d3;p=scpubgit%2FQ-Branch.git Fix Tester to deal properly with NOT and single parenthesized expressions --- diff --git a/lib/SQL/Abstract/Test.pm b/lib/SQL/Abstract/Test.pm index 98277b9..cfedf16 100644 --- a/lib/SQL/Abstract/Test.pm +++ b/lib/SQL/Abstract/Test.pm @@ -53,6 +53,7 @@ my @expression_terminator_sql_keywords = ( # These are binary operator keywords always a single LHS and RHS # * AND/OR are handled separately as they are N-ary +# * so is NOT as being unary # * BETWEEN without paranthesis around the ANDed arguments (which # makes it a non-binary op) is detected and accomodated in # _recurse_parse() @@ -63,7 +64,7 @@ my @binary_op_keywords = ( ); my $tokenizer_re_str = join("\n\t|\n", - ( map { '\b' . $_ . '\b' } @expression_terminator_sql_keywords, 'AND', 'OR' ), + ( map { '\b' . $_ . '\b' } @expression_terminator_sql_keywords, 'AND', 'OR', 'NOT'), ( map { q! (?<= [\w\s\`\'\)] ) ! . $_ . q! (?= [\w\s\`\'\(] ) ! } @binary_op_keywords ), ); @@ -261,7 +262,7 @@ sub _recurse_parse { or ($state == PARSE_IN_EXPR && grep { $lookahead =~ /^ $_ $/xi } ('\)', @expression_terminator_sql_keywords ) ) or - ($state == PARSE_RHS && grep { $lookahead =~ /^ $_ $/xi } ('\)', @expression_terminator_sql_keywords, @binary_op_keywords, 'AND', 'OR' ) ) + ($state == PARSE_RHS && grep { $lookahead =~ /^ $_ $/xi } ('\)', @expression_terminator_sql_keywords, @binary_op_keywords, 'AND', 'OR', 'NOT' ) ) ) { return $left; } @@ -310,6 +311,14 @@ sub _recurse_parse { $left = $left ? [@$left, [$op => [$right] ]] : [[ $op => [$right] ]]; } + # NOT (last as to allow all other NOT X pieces first) + elsif ( $token =~ /^ not $/ix ) { + my $op = uc $token; + my $right = _recurse_parse ($tokens, PARSE_RHS); + $left = $left ? [ @$left, [$op => [$right] ]] + : [[ $op => [$right] ]]; + + } # leaf expression else { $left = $left ? [@$left, [EXPR => [$token] ] ] @@ -357,6 +366,14 @@ sub _parenthesis_unroll { $changes++; } + # only one EXPR element in the parenthesis + elsif ( + @{$child->[1]} == 1 && $child->[1][0][0] eq 'EXPR' + ) { + push @children, $child->[1][0]; + $changes++; + } + # only one element in the parenthesis which is a binary op with two EXPR sub-children elsif ( @{$child->[1]} == 1 diff --git a/t/10test.t b/t/10test.t index 11c3705..91c9fee 100644 --- a/t/10test.t +++ b/t/10test.t @@ -136,6 +136,22 @@ my @sql_tests = ( ] }, { + equal => 1, + statements => [ + q/SELECT foo FROM bar WHERE (a) AND (b = 2)/, + q/SELECT foo FROM bar WHERE (a AND b = 2)/, + q/SELECT foo FROM bar WHERE (a AND (b = 2))/, + q/SELECT foo FROM bar WHERE a AND (b = 2)/, + ] + }, + { + equal => 0, + statements => [ + q/SELECT foo FROM bar WHERE NOT a AND (b = 2)/, + q/SELECT foo FROM bar WHERE (NOT a) AND (b = 2)/, + ] + }, + { equal => 0, parenthesis_significant => 1, statements => [