aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execExpr.c63
-rw-r--r--src/backend/executor/execExprInterp.c48
2 files changed, 111 insertions, 0 deletions
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index d0b91e881db..a9547aaef15 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -2450,6 +2450,69 @@ ExecInitExprRec(Expr *node, ExprState *state,
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
+ {
+ 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;
+
+ foreach(lc, args)
+ {
+ Expr *arg = (Expr *) lfirst(lc);
+
+ scratch.d.json_constructor.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;
+ }
+ else
+ {
+ ExecInitExprRec(arg, state,
+ &scratch.d.json_constructor.arg_values[argno],
+ &scratch.d.json_constructor.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;
+
default:
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(node));
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 64bd17b62e3..f2a0821a7ab 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"
@@ -477,6 +479,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
&&CASE_EEOP_GROUPING_FUNC,
&&CASE_EEOP_WINDOW_FUNC,
&&CASE_EEOP_SUBPLAN,
+ &&CASE_EEOP_JSON_CONSTRUCTOR,
&&CASE_EEOP_AGG_STRICT_DESERIALIZE,
&&CASE_EEOP_AGG_DESERIALIZE,
&&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
@@ -1786,7 +1789,13 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
{
/* too complex for an inline implementation */
ExecEvalAggOrderedTransTuple(state, op, econtext);
+ EEO_NEXT();
+ }
+ EEO_CASE(EEOP_JSON_CONSTRUCTOR)
+ {
+ /* too complex for an inline implementation */
+ ExecEvalJsonConstructor(state, op, econtext);
EEO_NEXT();
}
@@ -4380,3 +4389,42 @@ ExecAggPlainTransByRef(AggState *aggstate, AggStatePerTrans pertrans,
MemoryContextSwitchTo(oldContext);
}
+
+/*
+ * Evaluate a JSON constructor expression.
+ */
+void
+ExecEvalJsonConstructor(ExprState *state, ExprEvalStep *op,
+ ExprContext *econtext)
+{
+ Datum res;
+ JsonConstructorExpr *ctor = op->d.json_constructor.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);
+ 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);
+ else
+ {
+ res = (Datum) 0;
+ elog(ERROR, "invalid JsonConstructorExpr type %d", ctor->type);
+ }
+
+ *op->resvalue = res;
+ *op->resnull = isnull;
+}