diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index ffa7c3cef..e509cfe24 100644 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -940,6 +940,7 @@ static void setDelimiterName(core_yyscan_t yyscanner, char*input, VariableSetStm END_OF_INPUT END_OF_INPUT_COLON END_OF_PROC + NOT_IN /* Precedence: lowest to highest */ %nonassoc COMMENT @@ -960,7 +961,7 @@ static void setDelimiterName(core_yyscan_t yyscanner, char*input, VariableSetStm %nonassoc ESCAPE %nonassoc OVERLAPS %nonassoc BETWEEN -%nonassoc IN_P +%nonassoc IN_P NOT_IN %left POSTFIXOP /* dummy for postfix Op rules */ %nonassoc lower_than_index %nonassoc INDEX @@ -23894,25 +23895,25 @@ a_expr: c_expr { $$ = $1; } $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "=", $1, $3, @2); } } - | a_expr NOT IN_P in_expr + | a_expr NOT_IN in_expr %prec NOT_IN { /* in_expr returns a SubLink or a list of a_exprs */ - if (IsA($4, SubLink)) + if (IsA($3, SubLink)) { /* generate NOT (foo = ANY (subquery)) */ /* Make an = ANY node */ - SubLink *n = (SubLink *) $4; + SubLink *n = (SubLink *) $3; n->subLinkType = ANY_SUBLINK; n->testexpr = $1; n->operName = list_make1(makeString("=")); - n->location = @3; + n->location = @2; /* Stick a NOT on top */ $$ = (Node *) makeA_Expr(AEXPR_NOT, NIL, NULL, (Node *) n, @2); } else { /* generate scalar NOT IN expression */ - $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "<>", $1, $4, @2); + $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "<>", $1, $3, @2); } } | a_expr subquery_Op sub_type select_with_parens %prec Op diff --git a/src/common/backend/parser/parser.cpp b/src/common/backend/parser/parser.cpp index 2ddbfa28c..61432d6d0 100644 --- a/src/common/backend/parser/parser.cpp +++ b/src/common/backend/parser/parser.cpp @@ -231,6 +231,9 @@ int base_yylex(YYSTYPE* lvalp, YYLTYPE* llocp, core_yyscan_t yyscanner) case ENFORCED: cur_token = NOT_ENFORCED; break; + case IN_P: + cur_token = NOT_IN; + break; default: /* save the lookahead token for next time */ SET_LOOKAHEAD_TOKEN(); diff --git a/src/test/regress/expected/boolean.out b/src/test/regress/expected/boolean.out index da7bc2f33..856a6b5fb 100644 --- a/src/test/regress/expected/boolean.out +++ b/src/test/regress/expected/boolean.out @@ -470,6 +470,12 @@ SELECT 1-2::bool; 0 (1 row) +select true >= 'ss' not in (md5('ss')); + ?column? +---------- + t +(1 row) + -- -- Clean up -- Many tables are retained by the regression test, but these do not seem diff --git a/src/test/regress/sql/boolean.sql b/src/test/regress/sql/boolean.sql index 4be3f3f24..106bb3b19 100644 --- a/src/test/regress/sql/boolean.sql +++ b/src/test/regress/sql/boolean.sql @@ -206,6 +206,8 @@ SELECT -2::bool; SELECT 1-2::bool; +select true >= 'ss' not in (md5('ss')); + -- -- Clean up -- Many tables are retained by the regression test, but these do not seem