diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execExpr.c | 93 | ||||
-rw-r--r-- | src/backend/executor/execExprInterp.c | 104 |
2 files changed, 106 insertions, 91 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 */ |