}
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++;
}
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)
{
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;
}
}
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);
/* 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)
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)
{
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++)
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);
}
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)
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) ||
/* 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;
{
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;
{
case JSON_QUERY_OP:
res = JsonPathQuery(item, path, jexpr->wrapper, &empty, error,
- op->d.jsonexpr.args);
+ jsestate->args);
if (error && *error)
{
*resnull = true;
{
struct JsonCoercionState *jcstate;
JsonbValue *jbv = JsonPathValue(item, path, &empty, error,
- op->d.jsonexpr.args);
+ jsestate->args);
if (error && *error)
return (Datum) 0;
/* 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 &&
/* 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;
}
* 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);
}
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;
*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,
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);
var->evaluated = false;
}
- needSubtrans = ExecEvalJsonNeedsSubTransaction(jexpr, &op->d.jsonexpr.coercions);
+ needSubtrans = ExecEvalJsonNeedsSubTransaction(jexpr, &jsestate->coercions);
cxt.path = path;
cxt.error = throwErrors ? NULL : &error;
{
/* 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 */
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 */
/* 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 */
/* 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;
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);
JsonCoercion
JsonCommon
JsonConstructorExpr
+JsonConstructorExprState
JsonConstructorType
JsonEncoding
JsonExpr
JsonExprOp
+JsonExprState
JsonFormat
JsonFormatType
JsonFunc