From f4fb45d15c59d7add2e1b81a9d477d0119a9691a Mon Sep 17 00:00:00 2001 From: Andrew Dunstan Date: Thu, 3 Mar 2022 13:02:10 -0500 Subject: SQL/JSON constructors This patch introduces the SQL/JSON standard constructors for JSON: JSON() JSON_ARRAY() JSON_ARRAYAGG() JSON_OBJECT() JSON_OBJECTAGG() For the most part these functions provide facilities that mimic existing json/jsonb functions. However, they also offer some useful additional functionality. In addition to text input, the JSON() function accepts bytea input, which it will decode and constuct a json value from. The other functions provide useful options for handling duplicate keys and null values. This series of patches will be followed by a consolidated documentation patch. Nikita Glukhov Reviewers have included (in no particular order) Andres Freund, Alexander Korotkov, Pavel Stehule, Andrew Alsup, Erik Rijkers, Zihong Yu, Himanshu Upadhyaya, Daniel Gustafsson, Justin Pryzby. Discussion: https://postgr.es/m/cd0bb935-0158-78a7-08b5-904886deac4b@postgrespro.ru --- src/backend/executor/execExprInterp.c | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) (limited to 'src/backend/executor/execExprInterp.c') 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; +} -- cgit v1.2.3