1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-27 23:21:58 +03:00

RETURNING clause for JSON() and JSON_SCALAR()

This patch is extracted from a larger patch that allowed setting the
default returned value from these functions to json or jsonb. That had
problems, but this piece of it is fine. For these functions only json or
jsonb can be specified in the RETURNING clause.

Extracted from an original patch from 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
This commit is contained in:
Andrew Dunstan
2022-03-05 08:07:15 -05:00
parent ad43a413c4
commit 49082c2cc3
9 changed files with 135 additions and 16 deletions

View File

@ -4450,19 +4450,48 @@ transformJsonFuncExpr(ParseState *pstate, JsonFuncExpr *func)
return (Node *) jsexpr;
}
static JsonReturning *
transformJsonConstructorRet(ParseState *pstate, JsonOutput *output, const char *fname)
{
JsonReturning *returning;
if (output)
{
returning = transformJsonOutput(pstate, output, false);
Assert(OidIsValid(returning->typid));
if (returning->typid != JSONOID && returning->typid != JSONBOID)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
errmsg("cannot use RETURNING type %s in %s",
format_type_be(returning->typid), fname),
parser_errposition(pstate, output->typeName->location)));
}
else
{
Oid targettype = JSONOID;
JsonFormatType format = JS_FORMAT_JSON;
returning = makeNode(JsonReturning);
returning->format = makeJsonFormat(format, JS_ENC_DEFAULT, -1);
returning->typid = targettype;
returning->typmod = -1;
}
return returning;
}
/*
* Transform a JSON() expression.
*/
static Node *
transformJsonParseExpr(ParseState *pstate, JsonParseExpr *jsexpr)
{
JsonReturning *returning = makeNode(JsonReturning);
JsonReturning *returning = transformJsonConstructorRet(pstate, jsexpr->output,
"JSON()");
Node *arg;
returning->format = makeJsonFormat(JS_FORMAT_JSON, JS_ENC_DEFAULT, -1);
returning->typid = JSONOID;
returning->typmod = -1;
if (jsexpr->unique_keys)
{
/*
@ -4502,12 +4531,9 @@ transformJsonParseExpr(ParseState *pstate, JsonParseExpr *jsexpr)
static Node *
transformJsonScalarExpr(ParseState *pstate, JsonScalarExpr *jsexpr)
{
JsonReturning *returning = makeNode(JsonReturning);
Node *arg = transformExprRecurse(pstate, (Node *) jsexpr->expr);
returning->format = makeJsonFormat(JS_FORMAT_JSON, JS_ENC_DEFAULT, -1);
returning->typid = JSONOID;
returning->typmod = -1;
JsonReturning *returning = transformJsonConstructorRet(pstate, jsexpr->output,
"JSON_SCALAR()");
if (exprType(arg) == UNKNOWNOID)
arg = coerce_to_specific_type(pstate, arg, TEXTOID, "JSON_SCALAR");