diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execExpr.c | 91 | ||||
-rw-r--r-- | src/backend/executor/execExprInterp.c | 50 |
2 files changed, 141 insertions, 0 deletions
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index c61f23c6c18..6c5a3780292 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -2279,6 +2279,97 @@ ExecInitExprRec(Expr *node, ExprState *state, break; } + case T_JsonValueExpr: + { + JsonValueExpr *jve = (JsonValueExpr *) node; + + ExecInitExprRec(jve->raw_expr, state, resv, resnull); + + if (jve->formatted_expr) + { + Datum *innermost_caseval = state->innermost_caseval; + bool *innermost_isnull = state->innermost_casenull; + + state->innermost_caseval = resv; + state->innermost_casenull = resnull; + + ExecInitExprRec(jve->formatted_expr, state, resv, resnull); + + state->innermost_caseval = innermost_caseval; + state->innermost_casenull = innermost_isnull; + } + break; + } + + case T_JsonConstructorExpr: + { + JsonConstructorExpr *ctor = (JsonConstructorExpr *) node; + List *args = ctor->args; + ListCell *lc; + int nargs = list_length(args); + int argno = 0; + + if (ctor->func) + { + ExecInitExprRec(ctor->func, state, resv, resnull); + } + else + { + JsonConstructorExprState *jcstate; + + jcstate = palloc0(sizeof(JsonConstructorExprState)); + + scratch.opcode = EEOP_JSON_CONSTRUCTOR; + scratch.d.json_constructor.jcstate = jcstate; + + jcstate->constructor = ctor; + jcstate->arg_values = (Datum *) palloc(sizeof(Datum) * nargs); + jcstate->arg_nulls = (bool *) palloc(sizeof(bool) * nargs); + jcstate->arg_types = (Oid *) palloc(sizeof(Oid) * nargs); + jcstate->nargs = nargs; + + foreach(lc, args) + { + Expr *arg = (Expr *) lfirst(lc); + + jcstate->arg_types[argno] = exprType((Node *) arg); + + if (IsA(arg, Const)) + { + /* Don't evaluate const arguments every round */ + Const *con = (Const *) arg; + + jcstate->arg_values[argno] = con->constvalue; + jcstate->arg_nulls[argno] = con->constisnull; + } + else + { + ExecInitExprRec(arg, state, + &jcstate->arg_values[argno], + &jcstate->arg_nulls[argno]); + } + argno++; + } + + ExprEvalPushStep(state, &scratch); + } + + if (ctor->coercion) + { + Datum *innermost_caseval = state->innermost_caseval; + bool *innermost_isnull = state->innermost_casenull; + + state->innermost_caseval = resv; + state->innermost_casenull = resnull; + + ExecInitExprRec(ctor->coercion, state, resv, resnull); + + state->innermost_caseval = innermost_caseval; + state->innermost_casenull = innermost_isnull; + } + } + break; + case T_NullTest: { NullTest *ntest = (NullTest *) node; diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index dd7d1af220a..a37ba4dd55b 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -71,6 +71,8 @@ #include "utils/date.h" #include "utils/datum.h" #include "utils/expandedrecord.h" +#include "utils/json.h" +#include "utils/jsonb.h" #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/timestamp.h" @@ -474,6 +476,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) &&CASE_EEOP_SCALARARRAYOP, &&CASE_EEOP_HASHED_SCALARARRAYOP, &&CASE_EEOP_XMLEXPR, + &&CASE_EEOP_JSON_CONSTRUCTOR, &&CASE_EEOP_AGGREF, &&CASE_EEOP_GROUPING_FUNC, &&CASE_EEOP_WINDOW_FUNC, @@ -1511,6 +1514,13 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_NEXT(); } + EEO_CASE(EEOP_JSON_CONSTRUCTOR) + { + /* too complex for an inline implementation */ + ExecEvalJsonConstructor(state, op, econtext); + EEO_NEXT(); + } + EEO_CASE(EEOP_AGGREF) { /* @@ -4437,3 +4447,43 @@ ExecAggPlainTransByRef(AggState *aggstate, AggStatePerTrans pertrans, MemoryContextSwitchTo(oldContext); } + +/* + * Evaluate a JSON constructor expression. + */ +void +ExecEvalJsonConstructor(ExprState *state, ExprEvalStep *op, + ExprContext *econtext) +{ + Datum res; + 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) (jcstate->nargs, + jcstate->arg_values, + jcstate->arg_nulls, + jcstate->arg_types, + jcstate->constructor->absent_on_null); + else if (ctor->type == JSCTOR_JSON_OBJECT) + res = (is_jsonb ? + jsonb_build_object_worker : + json_build_object_worker) (jcstate->nargs, + jcstate->arg_values, + jcstate->arg_nulls, + jcstate->arg_types, + jcstate->constructor->absent_on_null, + jcstate->constructor->unique); + else + { + res = (Datum) 0; + elog(ERROR, "invalid JsonConstructorExpr type %d", ctor->type); + } + + *op->resvalue = res; + *op->resnull = isnull; +} |