Code review for commit b6e1157e7d

b6e1157e7d made some changes to enforce that
JsonValueExpr.formatted_expr is always set and is the expression that
gives a JsonValueExpr its runtime value, but that's not really
apparent from the comments about and the code manipulating
formatted_expr.  This commit fixes that.

Per suggestion from Álvaro Herrera.

Discussion: https://postgr.es/m/20230718155313.3wqg6encgt32adqb%40alvherre.pgsql
This commit is contained in:
Amit Langote 2023-07-21 19:15:34 +09:00
parent 97ff8dd02c
commit 7c7412cae3
6 changed files with 24 additions and 20 deletions

View File

@ -848,16 +848,13 @@ makeJsonFormat(JsonFormatType type, JsonEncoding encoding, int location)
* creates a JsonValueExpr node * creates a JsonValueExpr node
*/ */
JsonValueExpr * JsonValueExpr *
makeJsonValueExpr(Expr *expr, JsonFormat *format) makeJsonValueExpr(Expr *raw_expr, Expr *formatted_expr,
JsonFormat *format)
{ {
JsonValueExpr *jve = makeNode(JsonValueExpr); JsonValueExpr *jve = makeNode(JsonValueExpr);
jve->raw_expr = expr; jve->raw_expr = raw_expr;
jve->formatted_expr = formatted_expr;
/*
* Set after checking the format, if needed, in transformJsonValueExpr().
*/
jve->formatted_expr = NULL;
jve->format = format; jve->format = format;
return jve; return jve;

View File

@ -225,9 +225,7 @@ exprType(const Node *expr)
{ {
const JsonValueExpr *jve = (const JsonValueExpr *) expr; const JsonValueExpr *jve = (const JsonValueExpr *) expr;
type = exprType((Node *) type = exprType((Node *) jve->formatted_expr);
(jve->formatted_expr ? jve->formatted_expr :
jve->raw_expr));
} }
break; break;
case T_JsonConstructorExpr: case T_JsonConstructorExpr:

View File

@ -16362,7 +16362,9 @@ opt_asymmetric: ASYMMETRIC
json_value_expr: json_value_expr:
a_expr json_format_clause_opt a_expr json_format_clause_opt
{ {
$$ = (Node *) makeJsonValueExpr((Expr *) $1, castNode(JsonFormat, $2)); /* formatted_expr will be set during parse-analysis. */
$$ = (Node *) makeJsonValueExpr((Expr *) $1, NULL,
castNode(JsonFormat, $2));
} }
; ;

View File

@ -3205,6 +3205,10 @@ makeJsonByteaToTextConversion(Node *expr, JsonFormat *format, int location)
/* /*
* Transform JSON value expression using specified input JSON format or * Transform JSON value expression using specified input JSON format or
* default format otherwise. * default format otherwise.
*
* Returned expression is either ve->raw_expr coerced to text (if needed) or
* a JsonValueExpr with formatted_expr set to the coerced copy of raw_expr
* if the specified format requires it.
*/ */
static Node * static Node *
transformJsonValueExpr(ParseState *pstate, const char *constructName, transformJsonValueExpr(ParseState *pstate, const char *constructName,
@ -3304,6 +3308,10 @@ transformJsonValueExpr(ParseState *pstate, const char *constructName,
} }
} }
/* If returning a JsonValueExpr, formatted_expr must have been set. */
Assert(!IsA(expr, JsonValueExpr) ||
((JsonValueExpr *) expr)->formatted_expr != NULL);
return expr; return expr;
} }
@ -3631,13 +3639,12 @@ transformJsonArrayQueryConstructor(ParseState *pstate,
makeString(pstrdup("a"))); makeString(pstrdup("a")));
colref->location = ctor->location; colref->location = ctor->location;
agg->arg = makeJsonValueExpr((Expr *) colref, ctor->format);
/* /*
* No formatting necessary, so set formatted_expr to be the same as * No formatting necessary, so set formatted_expr to be the same as
* raw_expr. * raw_expr.
*/ */
agg->arg->formatted_expr = agg->arg->raw_expr; agg->arg = makeJsonValueExpr((Expr *) colref, (Expr *) colref,
ctor->format);
agg->absent_on_null = ctor->absent_on_null; agg->absent_on_null = ctor->absent_on_null;
agg->constructor = makeNode(JsonAggConstructor); agg->constructor = makeNode(JsonAggConstructor);
agg->constructor->agg_order = NIL; agg->constructor->agg_order = NIL;
@ -3906,9 +3913,7 @@ transformJsonParseArg(ParseState *pstate, Node *jsexpr, JsonFormat *format,
expr = makeJsonByteaToTextConversion(expr, format, exprLocation(expr)); expr = makeJsonByteaToTextConversion(expr, format, exprLocation(expr));
*exprtype = TEXTOID; *exprtype = TEXTOID;
jve = makeJsonValueExpr((Expr *) raw_expr, format); jve = makeJsonValueExpr((Expr *) raw_expr, (Expr *) expr, format);
jve->formatted_expr = (Expr *) expr;
expr = (Node *) jve; expr = (Node *) jve;
} }
else else

View File

@ -110,7 +110,8 @@ extern VacuumRelation *makeVacuumRelation(RangeVar *relation, Oid oid, List *va_
extern JsonFormat *makeJsonFormat(JsonFormatType type, JsonEncoding encoding, extern JsonFormat *makeJsonFormat(JsonFormatType type, JsonEncoding encoding,
int location); int location);
extern JsonValueExpr *makeJsonValueExpr(Expr *expr, JsonFormat *format); extern JsonValueExpr *makeJsonValueExpr(Expr *raw_expr, Expr *formatted_expr,
JsonFormat *format);
extern Node *makeJsonKeyValue(Node *key, Node *value); extern Node *makeJsonKeyValue(Node *key, Node *value);
extern Node *makeJsonIsPredicate(Node *expr, JsonFormat *format, extern Node *makeJsonIsPredicate(Node *expr, JsonFormat *format,
JsonValueType item_type, bool unique_keys, JsonValueType item_type, bool unique_keys,

View File

@ -1596,8 +1596,9 @@ typedef struct JsonReturning
* JsonValueExpr - * JsonValueExpr -
* representation of JSON value expression (expr [FORMAT JsonFormat]) * representation of JSON value expression (expr [FORMAT JsonFormat])
* *
* Note that raw_expr is only there for displaying and is not evaluated by * The actual value is obtained by evaluating formatted_expr. raw_expr is
* ExecInterpExpr() and eval_const_exprs_mutator(). * only there for displaying the original user-written expression and is not
* evaluated by ExecInterpExpr() and eval_const_exprs_mutator().
*/ */
typedef struct JsonValueExpr typedef struct JsonValueExpr
{ {