Skip to content

Commit 66a9003

Browse files
committed
Don't include CaseTestExpr in JsonValueExpr.formatted_expr
A CaseTestExpr is currently being put into JsonValueExpr.formatted_expr as placeholder for the result of evaluating JsonValueExpr.raw_expr, which in turn is evaluated separately. Though, there's no need for this indirection if raw_expr itself can be embedded into formatted_expr and evaluated as part of evaluating the latter, especially as there is no special reason to evaluate it separately. So this commit makes it so. As a result, JsonValueExpr.raw_expr no longer needs to be evaluated in ExecInterpExpr(), eval_const_exprs_mutator() etc. and is now only used for displaying the original "unformatted" expression in ruleutils.c. Comments about and the code manipulating formatted_expr is updated to mention that it is now always set and is the expression that gives a JsonValueExpr its runtime value. While at it, this also removes the function makeCaseTestExpr(), because the code in makeJsonConstructorExpr() looks more readable without it IMO and isn't used by anyone else either. Finally, a note is added in the comment above CaseTestExpr's definition that JsonConstructorExpr is also using it. Backpatched to 16 from the development branch to keep the code in sync across branches. Reviewed-by: Álvaro Herrera <alvherre@alvh.no-ip.org> Discussion: https://postgr.es/m/CA+HiwqE4XTdfb1nW=Ojoy_tQSRhYt-q_kb6i5d4xcKyrLC1Nbg@mail.gmail.com
1 parent c0f5313 commit 66a9003

File tree

8 files changed

+56
-67
lines changed

8 files changed

+56
-67
lines changed

src/backend/executor/execExpr.c

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2294,21 +2294,8 @@ ExecInitExprRec(Expr *node, ExprState *state,
22942294
{
22952295
JsonValueExpr *jve = (JsonValueExpr *) node;
22962296

2297-
ExecInitExprRec(jve->raw_expr, state, resv, resnull);
2298-
2299-
if (jve->formatted_expr)
2300-
{
2301-
Datum *innermost_caseval = state->innermost_caseval;
2302-
bool *innermost_isnull = state->innermost_casenull;
2303-
2304-
state->innermost_caseval = resv;
2305-
state->innermost_casenull = resnull;
2306-
2307-
ExecInitExprRec(jve->formatted_expr, state, resv, resnull);
2308-
2309-
state->innermost_caseval = innermost_caseval;
2310-
state->innermost_casenull = innermost_isnull;
2311-
}
2297+
Assert(jve->formatted_expr != NULL);
2298+
ExecInitExprRec(jve->formatted_expr, state, resv, resnull);
23122299
break;
23132300
}
23142301

src/backend/nodes/makefuncs.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -848,12 +848,13 @@ makeJsonFormat(JsonFormatType type, JsonEncoding encoding, int location)
848848
* creates a JsonValueExpr node
849849
*/
850850
JsonValueExpr *
851-
makeJsonValueExpr(Expr *expr, JsonFormat *format)
851+
makeJsonValueExpr(Expr *raw_expr, Expr *formatted_expr,
852+
JsonFormat *format)
852853
{
853854
JsonValueExpr *jve = makeNode(JsonValueExpr);
854855

855-
jve->raw_expr = expr;
856-
jve->formatted_expr = NULL;
856+
jve->raw_expr = raw_expr;
857+
jve->formatted_expr = formatted_expr;
857858
jve->format = format;
858859

859860
return jve;

src/backend/nodes/nodeFuncs.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -225,9 +225,7 @@ exprType(const Node *expr)
225225
{
226226
const JsonValueExpr *jve = (const JsonValueExpr *) expr;
227227

228-
type = exprType((Node *)
229-
(jve->formatted_expr ? jve->formatted_expr :
230-
jve->raw_expr));
228+
type = exprType((Node *) jve->formatted_expr);
231229
}
232230
break;
233231
case T_JsonConstructorExpr:

src/backend/optimizer/util/clauses.c

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2827,25 +2827,12 @@ eval_const_expressions_mutator(Node *node,
28272827
case T_JsonValueExpr:
28282828
{
28292829
JsonValueExpr *jve = (JsonValueExpr *) node;
2830-
Node *raw;
2830+
Node *formatted;
28312831

2832-
raw = eval_const_expressions_mutator((Node *) jve->raw_expr,
2833-
context);
2834-
if (raw && IsA(raw, Const))
2835-
{
2836-
Node *formatted;
2837-
Node *save_case_val = context->case_val;
2838-
2839-
context->case_val = raw;
2840-
2841-
formatted = eval_const_expressions_mutator((Node *) jve->formatted_expr,
2842-
context);
2843-
2844-
context->case_val = save_case_val;
2845-
2846-
if (formatted && IsA(formatted, Const))
2847-
return formatted;
2848-
}
2832+
formatted = eval_const_expressions_mutator((Node *) jve->formatted_expr,
2833+
context);
2834+
if (formatted && IsA(formatted, Const))
2835+
return formatted;
28492836
break;
28502837
}
28512838

src/backend/parser/gram.y

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16353,7 +16353,9 @@ opt_asymmetric: ASYMMETRIC
1635316353
json_value_expr:
1635416354
a_expr json_format_clause_opt
1635516355
{
16356-
$$ = (Node *) makeJsonValueExpr((Expr *) $1, castNode(JsonFormat, $2));
16356+
/* formatted_expr will be set during parse-analysis. */
16357+
$$ = (Node *) makeJsonValueExpr((Expr *) $1, NULL,
16358+
castNode(JsonFormat, $2));
1635716359
}
1635816360
;
1635916361

src/backend/parser/parse_expr.c

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3202,24 +3202,13 @@ makeJsonByteaToTextConversion(Node *expr, JsonFormat *format, int location)
32023202
return (Node *) fexpr;
32033203
}
32043204

3205-
/*
3206-
* Make a CaseTestExpr node.
3207-
*/
3208-
static Node *
3209-
makeCaseTestExpr(Node *expr)
3210-
{
3211-
CaseTestExpr *placeholder = makeNode(CaseTestExpr);
3212-
3213-
placeholder->typeId = exprType(expr);
3214-
placeholder->typeMod = exprTypmod(expr);
3215-
placeholder->collation = exprCollation(expr);
3216-
3217-
return (Node *) placeholder;
3218-
}
3219-
32203205
/*
32213206
* Transform JSON value expression using specified input JSON format or
32223207
* default format otherwise.
3208+
*
3209+
* Returned expression is either ve->raw_expr coerced to text (if needed) or
3210+
* a JsonValueExpr with formatted_expr set to the coerced copy of raw_expr
3211+
* if the specified format requires it.
32233212
*/
32243213
static Node *
32253214
transformJsonValueExpr(ParseState *pstate, const char *constructName,
@@ -3268,11 +3257,8 @@ transformJsonValueExpr(ParseState *pstate, const char *constructName,
32683257
if (format != JS_FORMAT_DEFAULT)
32693258
{
32703259
Oid targettype = format == JS_FORMAT_JSONB ? JSONBOID : JSONOID;
3271-
Node *orig = makeCaseTestExpr(expr);
32723260
Node *coerced;
32733261

3274-
expr = orig;
3275-
32763262
if (exprtype != BYTEAOID && typcategory != TYPCATEGORY_STRING)
32773263
ereport(ERROR,
32783264
errcode(ERRCODE_DATATYPE_MISMATCH),
@@ -3310,7 +3296,7 @@ transformJsonValueExpr(ParseState *pstate, const char *constructName,
33103296
coerced = (Node *) fexpr;
33113297
}
33123298

3313-
if (coerced == orig)
3299+
if (coerced == expr)
33143300
expr = rawexpr;
33153301
else
33163302
{
@@ -3322,6 +3308,10 @@ transformJsonValueExpr(ParseState *pstate, const char *constructName,
33223308
}
33233309
}
33243310

3311+
/* If returning a JsonValueExpr, formatted_expr must have been set. */
3312+
Assert(!IsA(expr, JsonValueExpr) ||
3313+
((JsonValueExpr *) expr)->formatted_expr != NULL);
3314+
33253315
return expr;
33263316
}
33273317

@@ -3537,8 +3527,22 @@ makeJsonConstructorExpr(ParseState *pstate, JsonConstructorType type,
35373527
jsctor->absent_on_null = absent_on_null;
35383528
jsctor->location = location;
35393529

3530+
/*
3531+
* Coerce to the RETURNING type and format, if needed. We abuse
3532+
* CaseTestExpr here as placeholder to pass the result of either
3533+
* evaluating 'fexpr' or whatever is produced by ExecEvalJsonConstructor()
3534+
* that is of type JSON or JSONB to the coercion function.
3535+
*/
35403536
if (fexpr)
3541-
placeholder = makeCaseTestExpr((Node *) fexpr);
3537+
{
3538+
CaseTestExpr *cte = makeNode(CaseTestExpr);
3539+
3540+
cte->typeId = exprType((Node *) fexpr);
3541+
cte->typeMod = exprTypmod((Node *) fexpr);
3542+
cte->collation = exprCollation((Node *) fexpr);
3543+
3544+
placeholder = (Node *) cte;
3545+
}
35423546
else
35433547
{
35443548
CaseTestExpr *cte = makeNode(CaseTestExpr);
@@ -3635,7 +3639,12 @@ transformJsonArrayQueryConstructor(ParseState *pstate,
36353639
makeString(pstrdup("a")));
36363640
colref->location = ctor->location;
36373641

3638-
agg->arg = makeJsonValueExpr((Expr *) colref, ctor->format);
3642+
/*
3643+
* No formatting necessary, so set formatted_expr to be the same as
3644+
* raw_expr.
3645+
*/
3646+
agg->arg = makeJsonValueExpr((Expr *) colref, (Expr *) colref,
3647+
ctor->format);
36393648
agg->absent_on_null = ctor->absent_on_null;
36403649
agg->constructor = makeNode(JsonAggConstructor);
36413650
agg->constructor->agg_order = NIL;
@@ -3900,13 +3909,11 @@ transformJsonParseArg(ParseState *pstate, Node *jsexpr, JsonFormat *format,
39003909
{
39013910
JsonValueExpr *jve;
39023911

3903-
expr = makeCaseTestExpr(raw_expr);
3912+
expr = raw_expr;
39043913
expr = makeJsonByteaToTextConversion(expr, format, exprLocation(expr));
39053914
*exprtype = TEXTOID;
39063915

3907-
jve = makeJsonValueExpr((Expr *) raw_expr, format);
3908-
3909-
jve->formatted_expr = (Expr *) expr;
3916+
jve = makeJsonValueExpr((Expr *) raw_expr, (Expr *) expr, format);
39103917
expr = (Node *) jve;
39113918
}
39123919
else

src/include/nodes/makefuncs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ extern VacuumRelation *makeVacuumRelation(RangeVar *relation, Oid oid, List *va_
110110

111111
extern JsonFormat *makeJsonFormat(JsonFormatType type, JsonEncoding encoding,
112112
int location);
113-
extern JsonValueExpr *makeJsonValueExpr(Expr *expr, JsonFormat *format);
113+
extern JsonValueExpr *makeJsonValueExpr(Expr *raw_expr, Expr *formatted_expr,
114+
JsonFormat *format);
114115
extern Node *makeJsonKeyValue(Node *key, Node *value);
115116
extern Node *makeJsonIsPredicate(Node *expr, JsonFormat *format,
116117
JsonValueType item_type, bool unique_keys,

src/include/nodes/primnodes.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1264,6 +1264,8 @@ typedef struct CaseWhen
12641264
* see build_coercion_expression().
12651265
* * Nested FieldStore/SubscriptingRef assignment expressions in INSERT/UPDATE;
12661266
* see transformAssignmentIndirection().
1267+
* * Placeholder for intermediate results in some SQL/JSON expression nodes,
1268+
* such as JsonConstructorExpr.
12671269
*
12681270
* The uses in CaseExpr and ArrayCoerceExpr are safe only to the extent that
12691271
* there is not any other CaseExpr or ArrayCoerceExpr between the value source
@@ -1593,12 +1595,16 @@ typedef struct JsonReturning
15931595
/*
15941596
* JsonValueExpr -
15951597
* representation of JSON value expression (expr [FORMAT JsonFormat])
1598+
*
1599+
* The actual value is obtained by evaluating formatted_expr. raw_expr is
1600+
* only there for displaying the original user-written expression and is not
1601+
* evaluated by ExecInterpExpr() and eval_const_exprs_mutator().
15961602
*/
15971603
typedef struct JsonValueExpr
15981604
{
15991605
NodeTag type;
16001606
Expr *raw_expr; /* raw expression */
1601-
Expr *formatted_expr; /* formatted expression or NULL */
1607+
Expr *formatted_expr; /* formatted expression */
16021608
JsonFormat *format; /* FORMAT clause, if specified */
16031609
} JsonValueExpr;
16041610

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy