# 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()
);
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 ),
);
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;
}
$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] ] ]
$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
]
},
{
+ 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 => [