Skip to content

Commit 49ced4f

Browse files
author
Nikita Glukhov
committed
Remove COERCE_INTERNAL_CAST in JsonValueExpr
1 parent edcf87d commit 49ced4f

File tree

12 files changed

+123
-34
lines changed

12 files changed

+123
-34
lines changed

contrib/pg_stat_statements/pg_stat_statements.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3090,7 +3090,8 @@ JumbleExpr(pgssJumbleState *jstate, Node *node)
30903090
{
30913091
JsonValueExpr *expr = (JsonValueExpr *) node;
30923092

3093-
JumbleExpr(jstate, (Node *) expr->expr);
3093+
JumbleExpr(jstate, (Node *) expr->raw_expr);
3094+
JumbleExpr(jstate, (Node *) expr->formatted_expr);
30943095
APP_JUMB(expr->format.type);
30953096
APP_JUMB(expr->format.encoding);
30963097
}

src/backend/executor/execExpr.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2109,9 +2109,26 @@ ExecInitExprRec(Expr *node, ExprState *state,
21092109
}
21102110

21112111
case T_JsonValueExpr:
2112-
ExecInitExprRec(((JsonValueExpr *) node)->expr, state, resv,
2113-
resnull);
2114-
break;
2112+
{
2113+
JsonValueExpr *jve = (JsonValueExpr *) node;
2114+
2115+
ExecInitExprRec(jve->raw_expr, state, resv, resnull);
2116+
2117+
if (jve->formatted_expr)
2118+
{
2119+
Datum *innermost_caseval = state->innermost_caseval;
2120+
bool *innermost_isnull = state->innermost_casenull;
2121+
2122+
state->innermost_caseval = resv;
2123+
state->innermost_casenull = resnull;
2124+
2125+
ExecInitExprRec(jve->formatted_expr, state, resv, resnull);
2126+
2127+
state->innermost_caseval = innermost_caseval;
2128+
state->innermost_casenull = innermost_isnull;
2129+
}
2130+
break;
2131+
}
21152132

21162133
default:
21172134
elog(ERROR, "unrecognized node type: %d",

src/backend/nodes/copyfuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2256,7 +2256,8 @@ _copyJsonValueExpr(const JsonValueExpr *from)
22562256
{
22572257
JsonValueExpr *newnode = makeNode(JsonValueExpr);
22582258

2259-
COPY_NODE_FIELD(expr);
2259+
COPY_NODE_FIELD(raw_expr);
2260+
COPY_NODE_FIELD(formatted_expr);
22602261
COPY_SCALAR_FIELD(format);
22612262

22622263
return newnode;

src/backend/nodes/equalfuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,8 @@ _equalOnConflictExpr(const OnConflictExpr *a, const OnConflictExpr *b)
821821
static bool
822822
_equalJsonValueExpr(const JsonValueExpr *a, const JsonValueExpr *b)
823823
{
824-
COMPARE_NODE_FIELD(expr);
824+
COMPARE_NODE_FIELD(raw_expr);
825+
COMPARE_NODE_FIELD(formatted_expr);
825826
COMPARE_SCALAR_FIELD(format.type);
826827
COMPARE_SCALAR_FIELD(format.encoding);
827828
COMPARE_LOCATION_FIELD(format.location);

src/backend/nodes/makefuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,8 @@ makeJsonValueExpr(Expr *expr, JsonFormat *format)
841841
{
842842
JsonValueExpr *jve = makeNode(JsonValueExpr);
843843

844-
jve->expr = expr;
844+
jve->raw_expr = expr;
845+
jve->formatted_expr = NULL;
845846
jve->format = format;
846847

847848
return jve;

src/backend/nodes/nodeFuncs.c

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,11 @@ exprType(const Node *expr)
259259
type = exprType((Node *) ((const PlaceHolderVar *) expr)->phexpr);
260260
break;
261261
case T_JsonValueExpr:
262-
type = exprType((Node *) ((const JsonValueExpr *) expr)->expr);
262+
{
263+
const JsonValueExpr *jve = (const JsonValueExpr *) expr;
264+
265+
type = exprType((Node *) (jve->formatted_expr ? jve->formatted_expr : jve->raw_expr));
266+
}
263267
break;
264268
default:
265269
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
@@ -495,7 +499,7 @@ exprTypmod(const Node *expr)
495499
case T_PlaceHolderVar:
496500
return exprTypmod((Node *) ((const PlaceHolderVar *) expr)->phexpr);
497501
case T_JsonValueExpr:
498-
return exprTypmod((Node *) ((const JsonValueExpr *) expr)->expr);
502+
return exprTypmod((Node *) ((const JsonValueExpr *) expr)->formatted_expr);
499503
default:
500504
break;
501505
}
@@ -912,7 +916,7 @@ exprCollation(const Node *expr)
912916
coll = exprCollation((Node *) ((const PlaceHolderVar *) expr)->phexpr);
913917
break;
914918
case T_JsonValueExpr:
915-
coll = exprCollation((Node *) ((const JsonValueExpr *) expr)->expr);
919+
coll = exprCollation((Node *) ((const JsonValueExpr *) expr)->formatted_expr);
916920
break;
917921
default:
918922
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
@@ -1118,7 +1122,7 @@ exprSetCollation(Node *expr, Oid collation)
11181122
* type */
11191123
break;
11201124
case T_JsonValueExpr:
1121-
exprSetCollation((Node *) ((const JsonValueExpr *) expr)->expr,
1125+
exprSetCollation((Node *) ((JsonValueExpr *) expr)->formatted_expr,
11221126
collation);
11231127
break;
11241128
default:
@@ -1562,7 +1566,7 @@ exprLocation(const Node *expr)
15621566
loc = ((const PartitionRangeDatum *) expr)->location;
15631567
break;
15641568
case T_JsonValueExpr:
1565-
loc = exprLocation((Node *) ((const JsonValueExpr *) expr)->expr);
1569+
loc = exprLocation((Node *) ((const JsonValueExpr *) expr)->raw_expr);
15661570
break;
15671571
default:
15681572
/* for any other node type it's just unknown... */
@@ -2262,7 +2266,15 @@ expression_tree_walker(Node *node,
22622266
}
22632267
break;
22642268
case T_JsonValueExpr:
2265-
return walker(((JsonValueExpr *) node)->expr, context);
2269+
{
2270+
JsonValueExpr *jve = (JsonValueExpr *) node;
2271+
2272+
if (walker(jve->raw_expr, context))
2273+
return true;
2274+
if (walker(jve->formatted_expr, context))
2275+
return true;
2276+
}
2277+
break;
22662278
default:
22672279
elog(ERROR, "unrecognized node type: %d",
22682280
(int) nodeTag(node));
@@ -3192,7 +3204,8 @@ expression_tree_mutator(Node *node,
31923204
JsonValueExpr *newnode;
31933205

31943206
FLATCOPY(newnode, jve, JsonValueExpr);
3195-
MUTATE(newnode->expr, jve->expr, Expr *);
3207+
MUTATE(newnode->raw_expr, jve->raw_expr, Expr *);
3208+
MUTATE(newnode->formatted_expr, jve->formatted_expr, Expr *);
31963209

31973210
return (Node *) newnode;
31983211
}
@@ -3892,7 +3905,15 @@ raw_expression_tree_walker(Node *node,
38923905
case T_CommonTableExpr:
38933906
return walker(((CommonTableExpr *) node)->ctequery, context);
38943907
case T_JsonValueExpr:
3895-
return walker(((JsonValueExpr *) node)->expr, context);
3908+
{
3909+
JsonValueExpr *jve = (JsonValueExpr *) node;
3910+
3911+
if (walker(jve->raw_expr, context))
3912+
return true;
3913+
if (walker(jve->formatted_expr, context))
3914+
return true;
3915+
}
3916+
break;
38963917
default:
38973918
elog(ERROR, "unrecognized node type: %d",
38983919
(int) nodeTag(node));

src/backend/nodes/outfuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1714,7 +1714,8 @@ _outJsonValueExpr(StringInfo str, const JsonValueExpr *node)
17141714
{
17151715
WRITE_NODE_TYPE("JSONVALUEEXPR");
17161716

1717-
WRITE_NODE_FIELD(expr);
1717+
WRITE_NODE_FIELD(raw_expr);
1718+
WRITE_NODE_FIELD(formatted_expr);
17181719
WRITE_ENUM_FIELD(format.type, JsonFormatType);
17191720
WRITE_ENUM_FIELD(format.encoding, JsonEncoding);
17201721
WRITE_LOCATION_FIELD(format.location);

src/backend/nodes/readfuncs.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1351,7 +1351,8 @@ _readJsonValueExpr(void)
13511351
{
13521352
READ_LOCALS(JsonValueExpr);
13531353

1354-
READ_NODE_FIELD(expr);
1354+
READ_NODE_FIELD(raw_expr);
1355+
READ_NODE_FIELD(formatted_expr);
13551356
READ_ENUM_FIELD(format.type, JsonFormatType);
13561357
READ_ENUM_FIELD(format.encoding, JsonEncoding);
13571358
READ_LOCATION_FIELD(format.location);

src/backend/optimizer/util/clauses.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3523,6 +3523,29 @@ eval_const_expressions_mutator(Node *node,
35233523
return ece_evaluate_expr((Node *) newcre);
35243524
return (Node *) newcre;
35253525
}
3526+
case T_JsonValueExpr:
3527+
{
3528+
JsonValueExpr *jve = (JsonValueExpr *) node;
3529+
Node *raw = eval_const_expressions_mutator((Node *) jve->raw_expr,
3530+
context);
3531+
3532+
if (raw && IsA(raw, Const))
3533+
{
3534+
Node *formatted;
3535+
Node *save_case_val = context->case_val;
3536+
3537+
context->case_val = raw;
3538+
3539+
formatted = eval_const_expressions_mutator((Node *) jve->formatted_expr,
3540+
context);
3541+
3542+
context->case_val = save_case_val;
3543+
3544+
if (formatted && IsA(formatted, Const))
3545+
return formatted;
3546+
}
3547+
break;
3548+
}
35263549
default:
35273550
break;
35283551
}

src/backend/parser/parse_expr.c

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3627,6 +3627,21 @@ makeJsonByteaToTextConversion(Node *expr, JsonFormat *format, int location)
36273627
return (Node *) fexpr;
36283628
}
36293629

3630+
/*
3631+
* Make CaseTestExpr node.
3632+
*/
3633+
static Node *
3634+
makeCaseTestExpr(Node *expr)
3635+
{
3636+
CaseTestExpr *placeholder = makeNode(CaseTestExpr);
3637+
3638+
placeholder->typeId = exprType(expr);
3639+
placeholder->typeMod = exprTypmod(expr);
3640+
placeholder->collation = exprCollation(expr);
3641+
3642+
return (Node *) placeholder;
3643+
}
3644+
36303645
/*
36313646
* Transform JSON value expression using specified input JSON format or
36323647
* default format otherwise.
@@ -3635,7 +3650,8 @@ static Node *
36353650
transformJsonValueExpr(ParseState *pstate, JsonValueExpr *ve,
36363651
JsonFormatType default_format)
36373652
{
3638-
Node *expr = transformExprRecurse(pstate, (Node *) ve->expr);
3653+
Node *expr = transformExprRecurse(pstate, (Node *) ve->raw_expr);
3654+
Node *rawexpr;
36393655
JsonFormatType format;
36403656
Oid exprtype;
36413657
int location;
@@ -3645,6 +3661,7 @@ transformJsonValueExpr(ParseState *pstate, JsonValueExpr *ve,
36453661
if (exprType(expr) == UNKNOWNOID)
36463662
expr = coerce_to_specific_type(pstate, expr, TEXTOID, "JSON_VALUE_EXPR");
36473663

3664+
rawexpr = expr;
36483665
exprtype = exprType(expr);
36493666
location = exprLocation(expr);
36503667

@@ -3676,8 +3693,10 @@ transformJsonValueExpr(ParseState *pstate, JsonValueExpr *ve,
36763693
if (format != JS_FORMAT_DEFAULT)
36773694
{
36783695
Oid targettype = format == JS_FORMAT_JSONB ? JSONBOID : JSONOID;
3696+
Node *orig = makeCaseTestExpr(expr);
36793697
Node *coerced;
3680-
FuncExpr *fexpr;
3698+
3699+
expr = orig;
36813700

36823701
if (exprtype != BYTEAOID && typcategory != TYPCATEGORY_STRING)
36833702
ereport(ERROR,
@@ -3699,28 +3718,32 @@ transformJsonValueExpr(ParseState *pstate, JsonValueExpr *ve,
36993718
coerced = coerce_to_target_type(pstate, expr, exprtype,
37003719
targettype, -1,
37013720
COERCION_EXPLICIT,
3702-
COERCE_INTERNAL_CAST,
3721+
COERCE_EXPLICIT_CAST,
37033722
location);
37043723

3705-
if (coerced)
3706-
expr = coerced;
3707-
else
3724+
if (!coerced)
37083725
{
37093726
/* If coercion failed, use to_json()/to_jsonb() functions. */
37103727
Oid fnoid = targettype == JSONOID ? F_TO_JSON : F_TO_JSONB;
3711-
3712-
fexpr = makeFuncExpr(fnoid, targettype, list_make1(expr),
3713-
InvalidOid, InvalidOid,
3714-
COERCE_INTERNAL_CAST);
3728+
FuncExpr *fexpr = makeFuncExpr(fnoid, targettype,
3729+
list_make1(expr),
3730+
InvalidOid, InvalidOid,
3731+
COERCE_EXPLICIT_CALL);
37153732
fexpr->location = location;
37163733

3717-
expr = (Node *) fexpr;
3734+
coerced = (Node *) fexpr;
37183735
}
37193736

3720-
ve = copyObject(ve);
3721-
ve->expr = (Expr *) expr;
3737+
if (coerced == orig)
3738+
expr = rawexpr;
3739+
else
3740+
{
3741+
ve = copyObject(ve);
3742+
ve->raw_expr = (Expr *) rawexpr;
3743+
ve->formatted_expr = (Expr *) coerced;
37223744

3723-
expr = (Node *) ve;
3745+
expr = (Node *) ve;
3746+
}
37243747
}
37253748

37263749
return expr;

src/backend/utils/adt/ruleutils.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7790,7 +7790,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
77907790

77917791
case T_JsonValueExpr:
77927792
/* maybe simple, check args */
7793-
return isSimpleNode((Node *) ((JsonValueExpr *) node)->expr,
7793+
return isSimpleNode((Node *) ((JsonValueExpr *) node)->raw_expr,
77947794
node, prettyFlags);
77957795

77967796
default:
@@ -9117,7 +9117,7 @@ get_rule_expr(Node *node, deparse_context *context,
91179117
{
91189118
JsonValueExpr *jve = (JsonValueExpr *) node;
91199119

9120-
get_rule_expr((Node *) jve->expr, context, false);
9120+
get_rule_expr((Node *) jve->raw_expr, context, false);
91219121
get_json_format(&jve->format, context);
91229122
}
91239123
break;

src/include/nodes/parsenodes.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1499,7 +1499,6 @@ typedef struct JsonOutput
14991499
JsonReturning returning; /* RETURNING FORMAT clause and type Oids */
15001500
} JsonOutput;
15011501

1502-
15031502
/*****************************************************************************
15041503
* Raw Grammar Output Statements
15051504
*****************************************************************************/

0 commit comments

Comments
 (0)