From 740b70d61f6f48929567dff84fc7ddcebef1551e Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Thu, 16 Jun 2022 18:33:42 -0700
Subject: [PATCH v2 4/4] WIP: expression eval: Fix EEOP_JSON_CONSTRUCTOR and
 EEOP_JSONEXPR size.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/include/executor/execExpr.h       | 111 ++++++++++++++------------
 src/backend/executor/execExpr.c       |  93 +++++++++++----------
 src/backend/executor/execExprInterp.c | 104 ++++++++++++------------
 3 files changed, 168 insertions(+), 140 deletions(-)

diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h
index 2fba1450c65..95f05ddaa59 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 */
@@ -671,16 +673,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 */
@@ -692,45 +685,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;
@@ -777,6 +732,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/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 4128248be40..ca0b4cefb0f 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -2460,32 +2460,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++;
 					}
@@ -2496,14 +2502,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)
 							{
@@ -2522,8 +2528,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;
 						}
 					}
 
@@ -2562,41 +2568,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;
 
-				scratch.d.jsonexpr.formatted_expr =
-					palloc(sizeof(*scratch.d.jsonexpr.formatted_expr));
+				jsestate->jsexpr = jexpr;
+
+				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);
 
@@ -2607,11 +2616,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)
@@ -2630,11 +2639,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)
 				{
@@ -2643,13 +2652,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 77e1cb1b7b4..9913907cec8 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -4520,39 +4520,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);
@@ -4562,14 +4563,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)
@@ -4637,14 +4638,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) ||
@@ -4654,25 +4658,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;
@@ -4905,7 +4909,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;
@@ -4914,7 +4919,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;
@@ -4927,7 +4932,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;
@@ -4950,8 +4955,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 &&
@@ -4983,27 +4988,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;
 			}
 
@@ -5039,11 +5044,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);
 	}
 
@@ -5076,7 +5081,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;
@@ -5088,7 +5094,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,
@@ -5098,11 +5104,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);
 
@@ -5110,7 +5116,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;
@@ -5125,7 +5131,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 */
-- 
2.35.1.677.gabf474a5dd

