Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit abb1646

Browse filesBrowse files
committed
Fix unexpected side-effects of operator_precedence_warning.
The implementation of that feature involves injecting nodes into the raw parsetree where explicit parentheses appear. Various places in parse_expr.c that test to see "is this child node of type Foo" need to look through such nodes, else we'll get different behavior when operator_precedence_warning is on than when it is off. Note that we only need to handle this when testing untransformed child nodes, since the AEXPR_PAREN nodes will be gone anyway after transformExprRecurse. Per report from Scott Ribe and additional code-reading. Back-patch to 9.5 where this feature was added. Report: <ED37E303-1B0A-4CD8-8E1E-B9C4C2DD9A17@elevated-dev.com>
1 parent 80f66a9 commit abb1646
Copy full SHA for abb1646

File tree

Expand file treeCollapse file tree

1 file changed

+29
-5
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+29
-5
lines changed

‎src/backend/parser/parse_expr.c

Copy file name to clipboardExpand all lines: src/backend/parser/parse_expr.c
+29-5Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,14 @@ transformAExprOp(ParseState *pstate, A_Expr *a)
857857
emit_precedence_warnings(pstate, opgroup, opname,
858858
lexpr, rexpr,
859859
a->location);
860+
861+
/* Look through AEXPR_PAREN nodes so they don't affect tests below */
862+
while (lexpr && IsA(lexpr, A_Expr) &&
863+
((A_Expr *) lexpr)->kind == AEXPR_PAREN)
864+
lexpr = ((A_Expr *) lexpr)->lexpr;
865+
while (rexpr && IsA(rexpr, A_Expr) &&
866+
((A_Expr *) rexpr)->kind == AEXPR_PAREN)
867+
rexpr = ((A_Expr *) rexpr)->lexpr;
860868
}
861869

862870
/*
@@ -1903,6 +1911,11 @@ transformArrayExpr(ParseState *pstate, A_ArrayExpr *a,
19031911
Node *e = (Node *) lfirst(element);
19041912
Node *newe;
19051913

1914+
/* Look through AEXPR_PAREN nodes so they don't affect test below */
1915+
while (e && IsA(e, A_Expr) &&
1916+
((A_Expr *) e)->kind == AEXPR_PAREN)
1917+
e = ((A_Expr *) e)->lexpr;
1918+
19061919
/*
19071920
* If an element is itself an A_ArrayExpr, recurse directly so that we
19081921
* can pass down any target type we were given.
@@ -2453,29 +2466,40 @@ transformWholeRowRef(ParseState *pstate, RangeTblEntry *rte, int location)
24532466
/*
24542467
* Handle an explicit CAST construct.
24552468
*
2456-
* Transform the argument, then look up the type name and apply any necessary
2469+
* Transform the argument, look up the type name, and apply any necessary
24572470
* coercion function(s).
24582471
*/
24592472
static Node *
24602473
transformTypeCast(ParseState *pstate, TypeCast *tc)
24612474
{
24622475
Node *result;
2476+
Node *arg = tc->arg;
24632477
Node *expr;
24642478
Oid inputType;
24652479
Oid targetType;
24662480
int32 targetTypmod;
24672481
int location;
24682482

2483+
/* Look up the type name first */
24692484
typenameTypeIdAndMod(pstate, tc->typeName, &targetType, &targetTypmod);
24702485

2486+
/*
2487+
* Look through any AEXPR_PAREN nodes that may have been inserted thanks
2488+
* to operator_precedence_warning. Otherwise, ARRAY[]::foo[] behaves
2489+
* differently from (ARRAY[])::foo[].
2490+
*/
2491+
while (arg && IsA(arg, A_Expr) &&
2492+
((A_Expr *) arg)->kind == AEXPR_PAREN)
2493+
arg = ((A_Expr *) arg)->lexpr;
2494+
24712495
/*
24722496
* If the subject of the typecast is an ARRAY[] construct and the target
24732497
* type is an array type, we invoke transformArrayExpr() directly so that
24742498
* we can pass down the type information. This avoids some cases where
24752499
* transformArrayExpr() might not infer the correct type. Otherwise, just
24762500
* transform the argument normally.
24772501
*/
2478-
if (IsA(tc->arg, A_ArrayExpr))
2502+
if (IsA(arg, A_ArrayExpr))
24792503
{
24802504
Oid targetBaseType;
24812505
int32 targetBaseTypmod;
@@ -2493,16 +2517,16 @@ transformTypeCast(ParseState *pstate, TypeCast *tc)
24932517
if (OidIsValid(elementType))
24942518
{
24952519
expr = transformArrayExpr(pstate,
2496-
(A_ArrayExpr *) tc->arg,
2520+
(A_ArrayExpr *) arg,
24972521
targetBaseType,
24982522
elementType,
24992523
targetBaseTypmod);
25002524
}
25012525
else
2502-
expr = transformExprRecurse(pstate, tc->arg);
2526+
expr = transformExprRecurse(pstate, arg);
25032527
}
25042528
else
2505-
expr = transformExprRecurse(pstate, tc->arg);
2529+
expr = transformExprRecurse(pstate, arg);
25062530

25072531
inputType = exprType(expr);
25082532
if (inputType == InvalidOid)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.