mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-21 08:29:39 +08:00
Remove precedence labeling of keywords TRUE, FALSE, UNKNOWN, and ZONE.
These were labeled with precedences just to avoid attaching explicit precedences to the productions in which they were the last terminal symbol. Since a terminal symbol precedence marking can affect many other things too, it seems like better practice to attach precedence labels to the productions, and not mark the terminal symbols. Ideally we'd also remove the precedence attached to NULL_P, but it turns out that we are actually depending on that having a precedence higher than POSTFIXOP, else we get a shift/reduce conflict for postfix operators in b_expr. (Which more or less proves my point about these markings having a high risk of unexpected consequences.) For the moment, move NULL_P into the set of keywords grouped with IDENT, so that at least it will act similarly to non-keywords; and document the interaction.
This commit is contained in:
parent
27525b1831
commit
12b7164578
@ -597,7 +597,8 @@ static void SplitColQualList(List *qualList,
|
|||||||
* have any bad effects since obviously the keywords will still behave the
|
* 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,
|
* 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
|
* 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.
|
* postfix-operator problems.
|
||||||
*
|
*
|
||||||
* The frame_bound productions UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING
|
* 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.
|
* blame any funny behavior of UNBOUNDED on the SQL standard, though.
|
||||||
*/
|
*/
|
||||||
%nonassoc UNBOUNDED /* ideally should have same precedence as IDENT */
|
%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 */
|
%left Op OPERATOR /* multi-character ops and user-defined operators */
|
||||||
%nonassoc NOTNULL
|
%nonassoc NOTNULL
|
||||||
%nonassoc ISNULL
|
%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 '*' '/' '%'
|
%left '*' '/' '%'
|
||||||
%left '^'
|
%left '^'
|
||||||
/* Unary Operators */
|
/* Unary Operators */
|
||||||
%left AT ZONE /* sets precedence for AT TIME ZONE */
|
%left AT /* sets precedence for AT TIME ZONE */
|
||||||
%left COLLATE
|
%left COLLATE
|
||||||
%right UMINUS
|
%right UMINUS
|
||||||
%left '[' ']'
|
%left '[' ']'
|
||||||
@ -9705,7 +9706,7 @@ a_expr: c_expr { $$ = $1; }
|
|||||||
n->location = @2;
|
n->location = @2;
|
||||||
$$ = (Node *) n;
|
$$ = (Node *) n;
|
||||||
}
|
}
|
||||||
| a_expr AT TIME ZONE a_expr
|
| a_expr AT TIME ZONE a_expr %prec AT
|
||||||
{
|
{
|
||||||
FuncCall *n = makeNode(FuncCall);
|
FuncCall *n = makeNode(FuncCall);
|
||||||
n->funcname = SystemFuncName("timezone");
|
n->funcname = SystemFuncName("timezone");
|
||||||
@ -9887,7 +9888,7 @@ a_expr: c_expr { $$ = $1; }
|
|||||||
* a ISNULL
|
* a ISNULL
|
||||||
* a NOTNULL
|
* a NOTNULL
|
||||||
*/
|
*/
|
||||||
| a_expr IS NULL_P
|
| a_expr IS NULL_P %prec IS
|
||||||
{
|
{
|
||||||
NullTest *n = makeNode(NullTest);
|
NullTest *n = makeNode(NullTest);
|
||||||
n->arg = (Expr *) $1;
|
n->arg = (Expr *) $1;
|
||||||
@ -9901,7 +9902,7 @@ a_expr: c_expr { $$ = $1; }
|
|||||||
n->nulltesttype = IS_NULL;
|
n->nulltesttype = IS_NULL;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
| a_expr IS NOT NULL_P
|
| a_expr IS NOT NULL_P %prec IS
|
||||||
{
|
{
|
||||||
NullTest *n = makeNode(NullTest);
|
NullTest *n = makeNode(NullTest);
|
||||||
n->arg = (Expr *) $1;
|
n->arg = (Expr *) $1;
|
||||||
@ -9919,42 +9920,42 @@ a_expr: c_expr { $$ = $1; }
|
|||||||
{
|
{
|
||||||
$$ = (Node *)makeOverlaps($1, $3, @2, yyscanner);
|
$$ = (Node *)makeOverlaps($1, $3, @2, yyscanner);
|
||||||
}
|
}
|
||||||
| a_expr IS TRUE_P
|
| a_expr IS TRUE_P %prec IS
|
||||||
{
|
{
|
||||||
BooleanTest *b = makeNode(BooleanTest);
|
BooleanTest *b = makeNode(BooleanTest);
|
||||||
b->arg = (Expr *) $1;
|
b->arg = (Expr *) $1;
|
||||||
b->booltesttype = IS_TRUE;
|
b->booltesttype = IS_TRUE;
|
||||||
$$ = (Node *)b;
|
$$ = (Node *)b;
|
||||||
}
|
}
|
||||||
| a_expr IS NOT TRUE_P
|
| a_expr IS NOT TRUE_P %prec IS
|
||||||
{
|
{
|
||||||
BooleanTest *b = makeNode(BooleanTest);
|
BooleanTest *b = makeNode(BooleanTest);
|
||||||
b->arg = (Expr *) $1;
|
b->arg = (Expr *) $1;
|
||||||
b->booltesttype = IS_NOT_TRUE;
|
b->booltesttype = IS_NOT_TRUE;
|
||||||
$$ = (Node *)b;
|
$$ = (Node *)b;
|
||||||
}
|
}
|
||||||
| a_expr IS FALSE_P
|
| a_expr IS FALSE_P %prec IS
|
||||||
{
|
{
|
||||||
BooleanTest *b = makeNode(BooleanTest);
|
BooleanTest *b = makeNode(BooleanTest);
|
||||||
b->arg = (Expr *) $1;
|
b->arg = (Expr *) $1;
|
||||||
b->booltesttype = IS_FALSE;
|
b->booltesttype = IS_FALSE;
|
||||||
$$ = (Node *)b;
|
$$ = (Node *)b;
|
||||||
}
|
}
|
||||||
| a_expr IS NOT FALSE_P
|
| a_expr IS NOT FALSE_P %prec IS
|
||||||
{
|
{
|
||||||
BooleanTest *b = makeNode(BooleanTest);
|
BooleanTest *b = makeNode(BooleanTest);
|
||||||
b->arg = (Expr *) $1;
|
b->arg = (Expr *) $1;
|
||||||
b->booltesttype = IS_NOT_FALSE;
|
b->booltesttype = IS_NOT_FALSE;
|
||||||
$$ = (Node *)b;
|
$$ = (Node *)b;
|
||||||
}
|
}
|
||||||
| a_expr IS UNKNOWN
|
| a_expr IS UNKNOWN %prec IS
|
||||||
{
|
{
|
||||||
BooleanTest *b = makeNode(BooleanTest);
|
BooleanTest *b = makeNode(BooleanTest);
|
||||||
b->arg = (Expr *) $1;
|
b->arg = (Expr *) $1;
|
||||||
b->booltesttype = IS_UNKNOWN;
|
b->booltesttype = IS_UNKNOWN;
|
||||||
$$ = (Node *)b;
|
$$ = (Node *)b;
|
||||||
}
|
}
|
||||||
| a_expr IS NOT UNKNOWN
|
| a_expr IS NOT UNKNOWN %prec IS
|
||||||
{
|
{
|
||||||
BooleanTest *b = makeNode(BooleanTest);
|
BooleanTest *b = makeNode(BooleanTest);
|
||||||
b->arg = (Expr *) $1;
|
b->arg = (Expr *) $1;
|
||||||
|
Loading…
Reference in New Issue
Block a user