aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndres Freund <andres@anarazel.de>2022-06-16 18:33:42 -0700
committerAndres Freund <andres@anarazel.de>2022-07-05 11:25:08 -0700
commit67b26703b4152a30a91208e28a4b72b3abda5832 (patch)
treefe8068d2e9ed3dc909ca097c167dd2356149af33 /src
parent3f8148c256e067dc2e8929ed174671ba7dc3339c (diff)
downloadpostgresql-67b26703b4152a30a91208e28a4b72b3abda5832.tar.gz
postgresql-67b26703b4152a30a91208e28a4b72b3abda5832.zip
expression eval: Fix EEOP_JSON_CONSTRUCTOR and EEOP_JSONEXPR size.
The new expression step types increased the size of ExprEvalStep by ~4 for all types of expression steps, slowing down expression evaluation noticeably. Move them out of line. There's other issues with these expression steps, but addressing them is largely independent of this aspect. Author: Andres Freund <andres@anarazel.de> Reviewed-By: Andrew Dunstan <andrew@dunslane.net> Discussion: https://postgr.es/m/20220616233130.rparivafipt6doj3@alap3.anarazel.de Backpatch: 15-
Diffstat (limited to 'src')
-rw-r--r--src/backend/executor/execExpr.c93
-rw-r--r--src/backend/executor/execExprInterp.c104
-rw-r--r--src/include/executor/execExpr.h111
-rw-r--r--src/tools/pgindent/typedefs.list2
4 files changed, 170 insertions, 140 deletions
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 2831e7978b5..1f65daf2035 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -2470,32 +2470,38 @@ ExecInitExprRec(Expr *node, ExprState *state,
}
else
{
+ JsonConstructorExprState *jcstate;
+
+ jcstate = palloc0(sizeof(JsonConstructorExprState));
+
scratch.opcode = EEOP_JSON_CONSTRUCTOR;
- scratch.d.json_constructor.constructor = ctor;
- scratch.d.json_constructor.arg_values = palloc(sizeof(Datum) * nargs);
- scratch.d.json_constructor.arg_nulls = palloc(sizeof(bool) * nargs);
- scratch.d.json_constructor.arg_types = palloc(sizeof(Oid) * nargs);
- scratch.d.json_constructor.nargs = nargs;
+ scratch.d.json_constructor.jcstate = jcstate;
+
+ jcstate->constructor = ctor;
+ jcstate->arg_values = palloc(sizeof(Datum) * nargs);
+ jcstate->arg_nulls = palloc(sizeof(bool) * nargs);
+ jcstate->arg_types = palloc(sizeof(Oid) * nargs);
+ jcstate->nargs = nargs;
foreach(lc, args)
{
Expr *arg = (Expr *) lfirst(lc);
- scratch.d.json_constructor.arg_types[argno] = exprType((Node *) arg);
+ jcstate->arg_types[argno] = exprType((Node *) arg);
if (IsA(arg, Const))
{
/* Don't evaluate const arguments every round */
Const *con = (Const *) arg;
- scratch.d.json_constructor.arg_values[argno] = con->constvalue;
- scratch.d.json_constructor.arg_nulls[argno] = con->constisnull;
+ jcstate->arg_values[argno] = con->constvalue;
+ jcstate->arg_nulls[argno] = con->constisnull;
}
else
{
ExecInitExprRec(arg, state,
- &scratch.d.json_constructor.arg_values[argno],
- &scratch.d.json_constructor.arg_nulls[argno]);
+ &jcstate->arg_values[argno],
+ &jcstate->arg_nulls[argno]);
}
argno++;
}
@@ -2506,14 +2512,14 @@ ExecInitExprRec(Expr *node, ExprState *state,
bool is_jsonb =
ctor->returning->format->format_type == JS_FORMAT_JSONB;
- scratch.d.json_constructor.arg_type_cache =
- palloc(sizeof(*scratch.d.json_constructor.arg_type_cache) * nargs);
+ jcstate->arg_type_cache =
+ palloc(sizeof(*jcstate->arg_type_cache) * nargs);
for (int i = 0; i < nargs; i++)
{
int category;
Oid outfuncid;
- Oid typid = scratch.d.json_constructor.arg_types[i];
+ Oid typid = jcstate->arg_types[i];
if (is_jsonb)
{
@@ -2532,8 +2538,8 @@ ExecInitExprRec(Expr *node, ExprState *state,
category = (int) jscat;
}
- scratch.d.json_constructor.arg_type_cache[i].outfuncid = outfuncid;
- scratch.d.json_constructor.arg_type_cache[i].category = category;
+ jcstate->arg_type_cache[i].outfuncid = outfuncid;
+ jcstate->arg_type_cache[i].category = category;
}
}
@@ -2572,41 +2578,44 @@ ExecInitExprRec(Expr *node, ExprState *state,
case T_JsonExpr:
{
JsonExpr *jexpr = castNode(JsonExpr, node);
+ JsonExprState *jsestate = palloc0(sizeof(JsonExprState));
ListCell *argexprlc;
ListCell *argnamelc;
scratch.opcode = EEOP_JSONEXPR;
- scratch.d.jsonexpr.jsexpr = jexpr;
+ scratch.d.jsonexpr.jsestate = jsestate;
+
+ jsestate->jsexpr = jexpr;
- scratch.d.jsonexpr.formatted_expr =
- palloc(sizeof(*scratch.d.jsonexpr.formatted_expr));
+ jsestate->formatted_expr =
+ palloc(sizeof(*jsestate->formatted_expr));
ExecInitExprRec((Expr *) jexpr->formatted_expr, state,
- &scratch.d.jsonexpr.formatted_expr->value,
- &scratch.d.jsonexpr.formatted_expr->isnull);
+ &jsestate->formatted_expr->value,
+ &jsestate->formatted_expr->isnull);
- scratch.d.jsonexpr.pathspec =
- palloc(sizeof(*scratch.d.jsonexpr.pathspec));
+ jsestate->pathspec =
+ palloc(sizeof(*jsestate->pathspec));
ExecInitExprRec((Expr *) jexpr->path_spec, state,
- &scratch.d.jsonexpr.pathspec->value,
- &scratch.d.jsonexpr.pathspec->isnull);
+ &jsestate->pathspec->value,
+ &jsestate->pathspec->isnull);
- scratch.d.jsonexpr.res_expr =
- palloc(sizeof(*scratch.d.jsonexpr.res_expr));
+ jsestate->res_expr =
+ palloc(sizeof(*jsestate->res_expr));
- scratch.d.jsonexpr.result_expr = jexpr->result_coercion
+ jsestate->result_expr = jexpr->result_coercion
? ExecInitExprWithCaseValue((Expr *) jexpr->result_coercion->expr,
state->parent,
- &scratch.d.jsonexpr.res_expr->value,
- &scratch.d.jsonexpr.res_expr->isnull)
+ &jsestate->res_expr->value,
+ &jsestate->res_expr->isnull)
: NULL;
- scratch.d.jsonexpr.default_on_empty = !jexpr->on_empty ? NULL :
+ jsestate->default_on_empty = !jexpr->on_empty ? NULL :
ExecInitExpr((Expr *) jexpr->on_empty->default_expr,
state->parent);
- scratch.d.jsonexpr.default_on_error =
+ jsestate->default_on_error =
ExecInitExpr((Expr *) jexpr->on_error->default_expr,
state->parent);
@@ -2617,11 +2626,11 @@ ExecInitExprRec(Expr *node, ExprState *state,
/* lookup the result type's input function */
getTypeInputInfo(jexpr->returning->typid, &typinput,
- &scratch.d.jsonexpr.input.typioparam);
- fmgr_info(typinput, &scratch.d.jsonexpr.input.func);
+ &jsestate->input.typioparam);
+ fmgr_info(typinput, &jsestate->input.func);
}
- scratch.d.jsonexpr.args = NIL;
+ jsestate->args = NIL;
forboth(argexprlc, jexpr->passing_values,
argnamelc, jexpr->passing_names)
@@ -2640,11 +2649,11 @@ ExecInitExprRec(Expr *node, ExprState *state,
var->value = (Datum) 0;
var->isnull = true;
- scratch.d.jsonexpr.args =
- lappend(scratch.d.jsonexpr.args, var);
+ jsestate->args =
+ lappend(jsestate->args, var);
}
- scratch.d.jsonexpr.cache = NULL;
+ jsestate->cache = NULL;
if (jexpr->coercions)
{
@@ -2653,13 +2662,13 @@ ExecInitExprRec(Expr *node, ExprState *state,
Datum *caseval;
bool *casenull;
- scratch.d.jsonexpr.coercion_expr =
- palloc(sizeof(*scratch.d.jsonexpr.coercion_expr));
+ jsestate->coercion_expr =
+ palloc(sizeof(*jsestate->coercion_expr));
- caseval = &scratch.d.jsonexpr.coercion_expr->value;
- casenull = &scratch.d.jsonexpr.coercion_expr->isnull;
+ caseval = &jsestate->coercion_expr->value;
+ casenull = &jsestate->coercion_expr->isnull;
- for (cstate = &scratch.d.jsonexpr.coercions.null,
+ for (cstate = &jsestate->coercions.null,
coercion = &jexpr->coercions->null;
coercion <= &jexpr->coercions->composite;
coercion++, cstate++)
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index eaec697bb38..80c5e04dd5f 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -4510,39 +4510,40 @@ ExecEvalJsonConstructor(ExprState *state, ExprEvalStep *op,
ExprContext *econtext)
{
Datum res;
- JsonConstructorExpr *ctor = op->d.json_constructor.constructor;
+ JsonConstructorExprState *jcstate = op->d.json_constructor.jcstate;
+ JsonConstructorExpr *ctor = jcstate->constructor;
bool is_jsonb = ctor->returning->format->format_type == JS_FORMAT_JSONB;
bool isnull = false;
if (ctor->type == JSCTOR_JSON_ARRAY)
res = (is_jsonb ?
jsonb_build_array_worker :
- json_build_array_worker) (op->d.json_constructor.nargs,
- op->d.json_constructor.arg_values,
- op->d.json_constructor.arg_nulls,
- op->d.json_constructor.arg_types,
- op->d.json_constructor.constructor->absent_on_null);
+ json_build_array_worker) (jcstate->nargs,
+ jcstate->arg_values,
+ jcstate->arg_nulls,
+ jcstate->arg_types,
+ ctor->absent_on_null);
else if (ctor->type == JSCTOR_JSON_OBJECT)
res = (is_jsonb ?
jsonb_build_object_worker :
- json_build_object_worker) (op->d.json_constructor.nargs,
- op->d.json_constructor.arg_values,
- op->d.json_constructor.arg_nulls,
- op->d.json_constructor.arg_types,
- op->d.json_constructor.constructor->absent_on_null,
- op->d.json_constructor.constructor->unique);
+ json_build_object_worker) (jcstate->nargs,
+ jcstate->arg_values,
+ jcstate->arg_nulls,
+ jcstate->arg_types,
+ ctor->absent_on_null,
+ ctor->unique);
else if (ctor->type == JSCTOR_JSON_SCALAR)
{
- if (op->d.json_constructor.arg_nulls[0])
+ if (jcstate->arg_nulls[0])
{
res = (Datum) 0;
isnull = true;
}
else
{
- Datum value = op->d.json_constructor.arg_values[0];
- int category = op->d.json_constructor.arg_type_cache[0].category;
- Oid outfuncid = op->d.json_constructor.arg_type_cache[0].outfuncid;
+ Datum value = jcstate->arg_values[0];
+ int category = jcstate->arg_type_cache[0].category;
+ Oid outfuncid = jcstate->arg_type_cache[0].outfuncid;
if (is_jsonb)
res = to_jsonb_worker(value, category, outfuncid);
@@ -4552,14 +4553,14 @@ ExecEvalJsonConstructor(ExprState *state, ExprEvalStep *op,
}
else if (ctor->type == JSCTOR_JSON_PARSE)
{
- if (op->d.json_constructor.arg_nulls[0])
+ if (jcstate->arg_nulls[0])
{
res = (Datum) 0;
isnull = true;
}
else
{
- Datum value = op->d.json_constructor.arg_values[0];
+ Datum value = jcstate->arg_values[0];
text *js = DatumGetTextP(value);
if (is_jsonb)
@@ -4627,14 +4628,17 @@ ExecEvalJsonExprCoercion(ExprEvalStep *op, ExprContext *econtext,
Datum res, bool *isNull, void *p, bool *error)
{
ExprState *estate = p;
+ JsonExprState *jsestate;
if (estate) /* coerce using specified expression */
return ExecEvalExpr(estate, econtext, isNull);
- if (op->d.jsonexpr.jsexpr->op != JSON_EXISTS_OP)
+ jsestate = op->d.jsonexpr.jsestate;
+
+ if (jsestate->jsexpr->op != JSON_EXISTS_OP)
{
- JsonCoercion *coercion = op->d.jsonexpr.jsexpr->result_coercion;
- JsonExpr *jexpr = op->d.jsonexpr.jsexpr;
+ JsonCoercion *coercion = jsestate->jsexpr->result_coercion;
+ JsonExpr *jexpr = jsestate->jsexpr;
Jsonb *jb = *isNull ? NULL : DatumGetJsonbP(res);
if ((coercion && coercion->via_io) ||
@@ -4644,25 +4648,25 @@ ExecEvalJsonExprCoercion(ExprEvalStep *op, ExprContext *econtext,
/* strip quotes and call typinput function */
char *str = *isNull ? NULL : JsonbUnquote(jb);
- return InputFunctionCall(&op->d.jsonexpr.input.func, str,
- op->d.jsonexpr.input.typioparam,
+ return InputFunctionCall(&jsestate->input.func, str,
+ jsestate->input.typioparam,
jexpr->returning->typmod);
}
else if (coercion && coercion->via_populate)
return json_populate_type(res, JSONBOID,
jexpr->returning->typid,
jexpr->returning->typmod,
- &op->d.jsonexpr.cache,
+ &jsestate->cache,
econtext->ecxt_per_query_memory,
isNull);
}
- if (op->d.jsonexpr.result_expr)
+ if (jsestate->result_expr)
{
- op->d.jsonexpr.res_expr->value = res;
- op->d.jsonexpr.res_expr->isnull = *isNull;
+ jsestate->res_expr->value = res;
+ jsestate->res_expr->isnull = *isNull;
- res = ExecEvalExpr(op->d.jsonexpr.result_expr, econtext, isNull);
+ res = ExecEvalExpr(jsestate->result_expr, econtext, isNull);
}
return res;
@@ -4895,7 +4899,8 @@ ExecEvalJsonExpr(ExprEvalStep *op, ExprContext *econtext,
{
ExecEvalJsonExprContext *cxt = pcxt;
JsonPath *path = cxt->path;
- JsonExpr *jexpr = op->d.jsonexpr.jsexpr;
+ JsonExprState *jsestate = op->d.jsonexpr.jsestate;
+ JsonExpr *jexpr = jsestate->jsexpr;
ExprState *estate = NULL;
bool empty = false;
Datum res = (Datum) 0;
@@ -4904,7 +4909,7 @@ ExecEvalJsonExpr(ExprEvalStep *op, ExprContext *econtext,
{
case JSON_QUERY_OP:
res = JsonPathQuery(item, path, jexpr->wrapper, &empty, error,
- op->d.jsonexpr.args);
+ jsestate->args);
if (error && *error)
{
*resnull = true;
@@ -4917,7 +4922,7 @@ ExecEvalJsonExpr(ExprEvalStep *op, ExprContext *econtext,
{
struct JsonCoercionState *jcstate;
JsonbValue *jbv = JsonPathValue(item, path, &empty, error,
- op->d.jsonexpr.args);
+ jsestate->args);
if (error && *error)
return (Datum) 0;
@@ -4940,8 +4945,8 @@ ExecEvalJsonExpr(ExprEvalStep *op, ExprContext *econtext,
/* Use coercion from SQL/JSON item type to the output type */
res = ExecPrepareJsonItemCoercion(jbv,
- op->d.jsonexpr.jsexpr->returning,
- &op->d.jsonexpr.coercions,
+ jsestate->jsexpr->returning,
+ &jsestate->coercions,
&jcstate);
if (jcstate->coercion &&
@@ -4973,27 +4978,27 @@ ExecEvalJsonExpr(ExprEvalStep *op, ExprContext *econtext,
/* coerce using specific expression */
estate = jcstate->estate;
- op->d.jsonexpr.coercion_expr->value = res;
- op->d.jsonexpr.coercion_expr->isnull = *resnull;
+ jsestate->coercion_expr->value = res;
+ jsestate->coercion_expr->isnull = *resnull;
break;
}
case JSON_EXISTS_OP:
{
bool exists = JsonPathExists(item, path,
- op->d.jsonexpr.args,
+ jsestate->args,
error);
*resnull = error && *error;
res = BoolGetDatum(exists);
- if (!op->d.jsonexpr.result_expr)
+ if (!jsestate->result_expr)
return res;
/* coerce using result expression */
- estate = op->d.jsonexpr.result_expr;
- op->d.jsonexpr.res_expr->value = res;
- op->d.jsonexpr.res_expr->isnull = *resnull;
+ estate = jsestate->result_expr;
+ jsestate->res_expr->value = res;
+ jsestate->res_expr->isnull = *resnull;
break;
}
@@ -5029,11 +5034,11 @@ ExecEvalJsonExpr(ExprEvalStep *op, ExprContext *econtext,
* Execute DEFAULT expression as a coercion expression, because
* its result is already coerced to the target type.
*/
- estate = op->d.jsonexpr.default_on_empty;
+ estate = jsestate->default_on_empty;
else
/* Execute ON EMPTY behavior */
res = ExecEvalJsonBehavior(econtext, jexpr->on_empty,
- op->d.jsonexpr.default_on_empty,
+ jsestate->default_on_empty,
resnull);
}
@@ -5066,7 +5071,8 @@ void
ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
{
ExecEvalJsonExprContext cxt;
- JsonExpr *jexpr = op->d.jsonexpr.jsexpr;
+ JsonExprState *jsestate = op->d.jsonexpr.jsestate;
+ JsonExpr *jexpr = jsestate->jsexpr;
Datum item;
Datum res = (Datum) 0;
JsonPath *path;
@@ -5078,7 +5084,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
*op->resnull = true; /* until we get a result */
*op->resvalue = (Datum) 0;
- if (op->d.jsonexpr.formatted_expr->isnull || op->d.jsonexpr.pathspec->isnull)
+ if (jsestate->formatted_expr->isnull || jsestate->pathspec->isnull)
{
/* execute domain checks for NULLs */
(void) ExecEvalJsonExprCoercion(op, econtext, res, op->resnull,
@@ -5088,11 +5094,11 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
return;
}
- item = op->d.jsonexpr.formatted_expr->value;
- path = DatumGetJsonPathP(op->d.jsonexpr.pathspec->value);
+ item = jsestate->formatted_expr->value;
+ path = DatumGetJsonPathP(jsestate->pathspec->value);
/* reset JSON path variable contexts */
- foreach(lc, op->d.jsonexpr.args)
+ foreach(lc, jsestate->args)
{
JsonPathVariableEvalContext *var = lfirst(lc);
@@ -5100,7 +5106,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
var->evaluated = false;
}
- needSubtrans = ExecEvalJsonNeedsSubTransaction(jexpr, &op->d.jsonexpr.coercions);
+ needSubtrans = ExecEvalJsonNeedsSubTransaction(jexpr, &jsestate->coercions);
cxt.path = path;
cxt.error = throwErrors ? NULL : &error;
@@ -5115,7 +5121,7 @@ ExecEvalJson(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
{
/* Execute ON ERROR behavior */
res = ExecEvalJsonBehavior(econtext, jexpr->on_error,
- op->d.jsonexpr.default_on_error,
+ jsestate->default_on_error,
op->resnull);
/* result is already coerced in DEFAULT behavior case */
diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h
index e34db8c93cb..fa2d9be4c99 100644
--- a/src/include/executor/execExpr.h
+++ b/src/include/executor/execExpr.h
@@ -22,6 +22,8 @@ struct ExprEvalStep;
struct SubscriptingRefState;
struct ScalarArrayOpExprHashTable;
struct JsonbValue;
+struct JsonExprState;
+struct JsonConstructorExprState;
/* Bits in ExprState->flags (see also execnodes.h for public flag bits): */
/* expression's interpreter has been initialized */
@@ -676,16 +678,7 @@ typedef struct ExprEvalStep
/* for EEOP_JSON_CONSTRUCTOR */
struct
{
- JsonConstructorExpr *constructor;
- Datum *arg_values;
- bool *arg_nulls;
- Oid *arg_types;
- struct
- {
- int category;
- Oid outfuncid;
- } *arg_type_cache; /* cache for datum_to_json[b]() */
- int nargs;
+ struct JsonConstructorExprState *jcstate;
} json_constructor;
/* for EEOP_IS_JSON */
@@ -697,45 +690,7 @@ typedef struct ExprEvalStep
/* for EEOP_JSONEXPR */
struct
{
- JsonExpr *jsexpr; /* original expression node */
-
- struct
- {
- FmgrInfo func; /* typinput function for output type */
- Oid typioparam;
- } input; /* I/O info for output type */
-
- NullableDatum
- *formatted_expr, /* formatted context item value */
- *res_expr, /* result item */
- *coercion_expr, /* input for JSON item coercion */
- *pathspec; /* path specification value */
-
- ExprState *result_expr; /* coerced to output type */
- ExprState *default_on_empty; /* ON EMPTY DEFAULT expression */
- ExprState *default_on_error; /* ON ERROR DEFAULT expression */
- List *args; /* passing arguments */
-
- void *cache; /* cache for json_populate_type() */
-
- struct JsonCoercionsState
- {
- struct JsonCoercionState
- {
- JsonCoercion *coercion; /* coercion expression */
- ExprState *estate; /* coercion expression state */
- } null,
- string,
- numeric ,
- boolean,
- date,
- time,
- timetz,
- timestamp,
- timestamptz,
- composite;
- } coercions; /* states for coercion from SQL/JSON item
- * types directly to the output type */
+ struct JsonExprState *jsestate;
} jsonexpr;
} d;
@@ -782,6 +737,64 @@ typedef struct SubscriptExecSteps
ExecEvalSubroutine sbs_fetch_old; /* fetch old value for assignment */
} SubscriptExecSteps;
+/* EEOP_JSON_CONSTRUCTOR state, too big to inline */
+typedef struct JsonConstructorExprState
+{
+ JsonConstructorExpr *constructor;
+ Datum *arg_values;
+ bool *arg_nulls;
+ Oid *arg_types;
+ struct
+ {
+ int category;
+ Oid outfuncid;
+ } *arg_type_cache; /* cache for datum_to_json[b]() */
+ int nargs;
+} JsonConstructorExprState;
+
+/* EEOP_JSONEXPR state, too big to inline */
+typedef struct JsonExprState
+{
+ JsonExpr *jsexpr; /* original expression node */
+
+ struct
+ {
+ FmgrInfo func; /* typinput function for output type */
+ Oid typioparam;
+ } input; /* I/O info for output type */
+
+ NullableDatum
+ *formatted_expr, /* formatted context item value */
+ *res_expr, /* result item */
+ *coercion_expr, /* input for JSON item coercion */
+ *pathspec; /* path specification value */
+
+ ExprState *result_expr; /* coerced to output type */
+ ExprState *default_on_empty; /* ON EMPTY DEFAULT expression */
+ ExprState *default_on_error; /* ON ERROR DEFAULT expression */
+ List *args; /* passing arguments */
+
+ void *cache; /* cache for json_populate_type() */
+
+ struct JsonCoercionsState
+ {
+ struct JsonCoercionState
+ {
+ JsonCoercion *coercion; /* coercion expression */
+ ExprState *estate; /* coercion expression state */
+ } null,
+ string,
+ numeric ,
+ boolean,
+ date,
+ time,
+ timetz,
+ timestamp,
+ timestamptz,
+ composite;
+ } coercions; /* states for coercion from SQL/JSON item
+ * types directly to the output type */
+} JsonExprState;
/* functions in execExpr.c */
extern void ExprEvalPushStep(ExprState *es, const ExprEvalStep *s);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 4fb746930aa..c7f550e822d 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -1237,10 +1237,12 @@ JsonBehaviorType
JsonCoercion
JsonCommon
JsonConstructorExpr
+JsonConstructorExprState
JsonConstructorType
JsonEncoding
JsonExpr
JsonExprOp
+JsonExprState
JsonFormat
JsonFormatType
JsonFunc