diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 933a1a2ff9f3739529154e6e07aca4f1a06b95ab..dd959618419032acd3df1fa14644c9b2052dd462 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -597,7 +597,8 @@ static void SplitColQualList(List *qualList, * have any bad effects since obviously the keywords will still behave the * same as if they weren't keywords). We need to do this for PARTITION, * RANGE, ROWS to support opt_existing_window_name; and for RANGE, ROWS - * so that they can follow a_expr without creating + * so that they can follow a_expr without creating postfix-operator problems; + * and for NULL so that it can follow b_expr in ColQualList without creating * postfix-operator problems. * * The frame_bound productions UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING @@ -610,16 +611,16 @@ static void SplitColQualList(List *qualList, * blame any funny behavior of UNBOUNDED on the SQL standard, though. */ %nonassoc UNBOUNDED /* ideally should have same precedence as IDENT */ -%nonassoc IDENT PARTITION RANGE ROWS PRECEDING FOLLOWING +%nonassoc IDENT NULL_P PARTITION RANGE ROWS PRECEDING FOLLOWING %left Op OPERATOR /* multi-character ops and user-defined operators */ %nonassoc NOTNULL %nonassoc ISNULL -%nonassoc IS NULL_P TRUE_P FALSE_P UNKNOWN /* sets precedence for IS NULL, etc */ +%nonassoc IS /* sets precedence for IS NULL, etc */ %left '+' '-' %left '*' '/' '%' %left '^' /* Unary Operators */ -%left AT ZONE /* sets precedence for AT TIME ZONE */ +%left AT /* sets precedence for AT TIME ZONE */ %left COLLATE %right UMINUS %left '[' ']' @@ -9705,7 +9706,7 @@ a_expr: c_expr { $$ = $1; } n->location = @2; $$ = (Node *) n; } - | a_expr AT TIME ZONE a_expr + | a_expr AT TIME ZONE a_expr %prec AT { FuncCall *n = makeNode(FuncCall); n->funcname = SystemFuncName("timezone"); @@ -9887,7 +9888,7 @@ a_expr: c_expr { $$ = $1; } * a ISNULL * a NOTNULL */ - | a_expr IS NULL_P + | a_expr IS NULL_P %prec IS { NullTest *n = makeNode(NullTest); n->arg = (Expr *) $1; @@ -9901,7 +9902,7 @@ a_expr: c_expr { $$ = $1; } n->nulltesttype = IS_NULL; $$ = (Node *)n; } - | a_expr IS NOT NULL_P + | a_expr IS NOT NULL_P %prec IS { NullTest *n = makeNode(NullTest); n->arg = (Expr *) $1; @@ -9919,42 +9920,42 @@ a_expr: c_expr { $$ = $1; } { $$ = (Node *)makeOverlaps($1, $3, @2, yyscanner); } - | a_expr IS TRUE_P + | a_expr IS TRUE_P %prec IS { BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1; b->booltesttype = IS_TRUE; $$ = (Node *)b; } - | a_expr IS NOT TRUE_P + | a_expr IS NOT TRUE_P %prec IS { BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1; b->booltesttype = IS_NOT_TRUE; $$ = (Node *)b; } - | a_expr IS FALSE_P + | a_expr IS FALSE_P %prec IS { BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1; b->booltesttype = IS_FALSE; $$ = (Node *)b; } - | a_expr IS NOT FALSE_P + | a_expr IS NOT FALSE_P %prec IS { BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1; b->booltesttype = IS_NOT_FALSE; $$ = (Node *)b; } - | a_expr IS UNKNOWN + | a_expr IS UNKNOWN %prec IS { BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1; b->booltesttype = IS_UNKNOWN; $$ = (Node *)b; } - | a_expr IS NOT UNKNOWN + | a_expr IS NOT UNKNOWN %prec IS { BooleanTest *b = makeNode(BooleanTest); b->arg = (Expr *) $1;