diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/execExpr.c | 45 | ||||
-rw-r--r-- | src/backend/executor/execExprInterp.c | 42 |
2 files changed, 86 insertions, 1 deletions
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c index 1c364a7f4c5..d4d3850ec7c 100644 --- a/src/backend/executor/execExpr.c +++ b/src/backend/executor/execExpr.c @@ -47,6 +47,8 @@ #include "utils/array.h" #include "utils/builtins.h" #include "utils/datum.h" +#include "utils/json.h" +#include "utils/jsonb.h" #include "utils/jsonpath.h" #include "utils/lsyscache.h" #include "utils/typcache.h" @@ -2460,6 +2462,12 @@ ExecInitExprRec(Expr *node, ExprState *state, { ExecInitExprRec(ctor->func, state, resv, resnull); } + else if ((ctor->type == JSCTOR_JSON_PARSE && !ctor->unique) || + ctor->type == JSCTOR_JSON_SERIALIZE) + { + /* Use the value of the first argument as a result */ + ExecInitExprRec(linitial(args), state, resv, resnull); + } else { scratch.opcode = EEOP_JSON_CONSTRUCTOR; @@ -2492,6 +2500,43 @@ ExecInitExprRec(Expr *node, ExprState *state, argno++; } + /* prepare type cache for datum_to_json[b]() */ + if (ctor->type == JSCTOR_JSON_SCALAR) + { + 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); + + for (int i = 0; i < nargs; i++) + { + int category; + Oid outfuncid; + Oid typid = scratch.d.json_constructor.arg_types[i]; + + if (is_jsonb) + { + JsonbTypeCategory jbcat; + + jsonb_categorize_type(typid, &jbcat, &outfuncid); + + category = (int) jbcat; + } + else + { + JsonTypeCategory jscat; + + json_categorize_type(typid, &jscat, &outfuncid); + + category = (int) jscat; + } + + scratch.d.json_constructor.arg_type_cache[i].outfuncid = outfuncid; + scratch.d.json_constructor.arg_type_cache[i].category = category; + } + } + ExprEvalPushStep(state, &scratch); } diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 1215f707e28..7d4253d970d 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -3982,7 +3982,7 @@ ExecEvalJsonIsPredicate(ExprState *state, ExprEvalStep *op) * JSON text validation. */ if (res && (pred->unique_keys || exprtype == TEXTOID)) - res = json_validate(json, pred->unique_keys); + res = json_validate(json, pred->unique_keys, false); } else if (exprtype == JSONBOID) { @@ -4527,6 +4527,46 @@ ExecEvalJsonConstructor(ExprState *state, ExprEvalStep *op, op->d.json_constructor.arg_types, op->d.json_constructor.constructor->absent_on_null, op->d.json_constructor.constructor->unique); + else if (ctor->type == JSCTOR_JSON_SCALAR) + { + if (op->d.json_constructor.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; + + if (is_jsonb) + res = to_jsonb_worker(value, category, outfuncid); + else + res = to_json_worker(value, category, outfuncid); + } + } + else if (ctor->type == JSCTOR_JSON_PARSE) + { + if (op->d.json_constructor.arg_nulls[0]) + { + res = (Datum) 0; + isnull = true; + } + else + { + Datum value = op->d.json_constructor.arg_values[0]; + text *js = DatumGetTextP(value); + + if (is_jsonb) + res = jsonb_from_text(js, true); + else + { + (void) json_validate(js, true, true); + res = value; + } + } + } else { res = (Datum) 0; |