From c15d34220b7e4ae8185f80e8cb7e2ef13ad979ef Mon Sep 17 00:00:00 2001 From: teooooozhang Date: Sat, 18 Feb 2023 09:43:19 +0800 Subject: [PATCH] =?UTF-8?q?=E6=93=8D=E4=BD=9C=E7=AC=A6=E4=BC=98=E5=85=88?= =?UTF-8?q?=E7=BA=A7=E4=BF=AE=E5=A4=8D=EF=BC=9ANOT=20BETWEEN/LIKE/ILIKE/SI?= =?UTF-8?q?MILAR?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/common/backend/parser/gram.y | 50 +++++++++++++-------------- src/common/backend/parser/parser.cpp | 12 +++++++ src/test/regress/expected/boolean.out | 24 +++++++++++++ src/test/regress/sql/boolean.sql | 4 +++ 4 files changed, 65 insertions(+), 25 deletions(-) diff --git a/src/common/backend/parser/gram.y b/src/common/backend/parser/gram.y index e509cfe24..859b08d87 100644 --- a/src/common/backend/parser/gram.y +++ b/src/common/backend/parser/gram.y @@ -940,7 +940,7 @@ static void setDelimiterName(core_yyscan_t yyscanner, char*input, VariableSetStm END_OF_INPUT END_OF_INPUT_COLON END_OF_PROC - NOT_IN + NOT_IN NOT_BETWEEN NOT_LIKE NOT_ILIKE NOT_SIMILAR /* Precedence: lowest to highest */ %nonassoc COMMENT @@ -957,10 +957,10 @@ static void setDelimiterName(core_yyscan_t yyscanner, char*input, VariableSetStm %right NOT %right '=' CmpNullOp COLON_EQUALS %nonassoc '<' '>' CmpOp -%nonassoc LIKE ILIKE SIMILAR +%nonassoc LIKE ILIKE SIMILAR NOT_LIKE NOT_ILIKE NOT_SIMILAR %nonassoc ESCAPE %nonassoc OVERLAPS -%nonassoc BETWEEN +%nonassoc BETWEEN NOT_BETWEEN %nonassoc IN_P NOT_IN %left POSTFIXOP /* dummy for postfix Op rules */ %nonassoc lower_than_index @@ -23594,13 +23594,13 @@ a_expr: c_expr { $$ = $1; } n->call_func = false; $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~", $1, (Node *) n, @2); } - | a_expr NOT LIKE a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~", $1, $4, @2); } - | a_expr NOT LIKE a_expr ESCAPE a_expr + | a_expr NOT_LIKE a_expr %prec NOT_LIKE + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~", $1, $3, @2); } + | a_expr NOT_LIKE a_expr ESCAPE a_expr %prec NOT_LIKE { FuncCall *n = makeNode(FuncCall); n->funcname = SystemFuncName("like_escape"); - n->args = list_make2($4, $6); + n->args = list_make2($3, $5); n->agg_order = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; @@ -23626,13 +23626,13 @@ a_expr: c_expr { $$ = $1; } n->call_func = false; $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~~*", $1, (Node *) n, @2); } - | a_expr NOT ILIKE a_expr - { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~*", $1, $4, @2); } - | a_expr NOT ILIKE a_expr ESCAPE a_expr + | a_expr NOT_ILIKE a_expr %prec NOT_ILIKE + { $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~~*", $1, $3, @2); } + | a_expr NOT_ILIKE a_expr ESCAPE a_expr %prec NOT_ILIKE { FuncCall *n = makeNode(FuncCall); n->funcname = SystemFuncName("like_escape"); - n->args = list_make2($4, $6); + n->args = list_make2($3, $5); n->agg_order = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; @@ -23671,11 +23671,11 @@ a_expr: c_expr { $$ = $1; } n->call_func = false; $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "~", $1, (Node *) n, @2); } - | a_expr NOT SIMILAR TO a_expr %prec SIMILAR + | a_expr NOT_SIMILAR TO a_expr %prec NOT_SIMILAR { FuncCall *n = makeNode(FuncCall); n->funcname = SystemFuncName("similar_escape"); - n->args = list_make2($5, makeNullAConst(-1)); + n->args = list_make2($4, makeNullAConst(-1)); n->agg_order = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; @@ -23685,11 +23685,11 @@ a_expr: c_expr { $$ = $1; } n->call_func = false; $$ = (Node *) makeSimpleA_Expr(AEXPR_OP, "!~", $1, (Node *) n, @2); } - | a_expr NOT SIMILAR TO a_expr ESCAPE a_expr + | a_expr NOT_SIMILAR TO a_expr ESCAPE a_expr %prec NOT_SIMILAR { FuncCall *n = makeNode(FuncCall); n->funcname = SystemFuncName("similar_escape"); - n->args = list_make2($5, $7); + n->args = list_make2($4, $6); n->agg_order = NIL; n->agg_star = FALSE; n->agg_distinct = FALSE; @@ -23843,11 +23843,11 @@ a_expr: c_expr { $$ = $1; } (Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6, @2), @2); } - | a_expr NOT BETWEEN opt_asymmetric b_expr AND b_expr %prec BETWEEN + | a_expr NOT_BETWEEN opt_asymmetric b_expr AND b_expr %prec NOT_BETWEEN { $$ = (Node *) makeA_Expr(AEXPR_OR, NIL, - (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5, @2), - (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $4, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $6, @2), @2); } | a_expr BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN @@ -23863,16 +23863,16 @@ a_expr: c_expr { $$ = $1; } @2), @2); } - | a_expr NOT BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN + | a_expr NOT_BETWEEN SYMMETRIC b_expr AND b_expr %prec NOT_BETWEEN { $$ = (Node *) makeA_Expr(AEXPR_AND, NIL, (Node *) makeA_Expr(AEXPR_OR, NIL, - (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $5, @2), - (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $4, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $6, @2), @2), (Node *) makeA_Expr(AEXPR_OR, NIL, - (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $7, @2), - (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $5, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $6, @2), + (Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $4, @2), @2), @2); } @@ -25673,11 +25673,11 @@ subquery_Op: { $$ = $3; } | LIKE { $$ = list_make1(makeString("~~")); } - | NOT LIKE + | NOT_LIKE %prec NOT_LIKE { $$ = list_make1(makeString("!~~")); } | ILIKE { $$ = list_make1(makeString("~~*")); } - | NOT ILIKE + | NOT_ILIKE %prec NOT_ILIKE { $$ = list_make1(makeString("!~~*")); } /* cannot put SIMILAR TO here, because SIMILAR TO is a hack. * the regular expression is preprocessed by a function (similar_escape), diff --git a/src/common/backend/parser/parser.cpp b/src/common/backend/parser/parser.cpp index 61432d6d0..6a00f8b5e 100644 --- a/src/common/backend/parser/parser.cpp +++ b/src/common/backend/parser/parser.cpp @@ -234,6 +234,18 @@ int base_yylex(YYSTYPE* lvalp, YYLTYPE* llocp, core_yyscan_t yyscanner) case IN_P: cur_token = NOT_IN; break; + case BETWEEN: + cur_token = NOT_BETWEEN; + break; + case LIKE: + cur_token = NOT_LIKE; + break; + case ILIKE: + cur_token = NOT_ILIKE; + break; + case SIMILAR: + cur_token = NOT_SIMILAR; + 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 856a6b5fb..d3d4d8c64 100644 --- a/src/test/regress/expected/boolean.out +++ b/src/test/regress/expected/boolean.out @@ -476,6 +476,30 @@ select true >= 'ss' not in (md5('ss')); t (1 row) +select false >= 'ss' not between 'ss' and 'ss'; + ?column? +---------- + t +(1 row) + +select false >= 'ss' not like 'ss'; + ?column? +---------- + t +(1 row) + +select false >= 'ss' not ilike 'ss'; + ?column? +---------- + t +(1 row) + +select false >= 'ss' not similar to '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 106bb3b19..605c15704 100644 --- a/src/test/regress/sql/boolean.sql +++ b/src/test/regress/sql/boolean.sql @@ -207,6 +207,10 @@ SELECT -2::bool; SELECT 1-2::bool; select true >= 'ss' not in (md5('ss')); +select false >= 'ss' not between 'ss' and 'ss'; +select false >= 'ss' not like 'ss'; +select false >= 'ss' not ilike 'ss'; +select false >= 'ss' not similar to 'ss'; -- -- Clean up