aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_expr.c
diff options
context:
space:
mode:
authorAndrew Dunstan <andrew@dunslane.net>2022-03-05 08:07:15 -0500
committerAndrew Dunstan <andrew@dunslane.net>2022-03-31 15:45:24 -0400
commit49082c2cc3d8167cca70cfe697afb064710828ca (patch)
tree004b744b04f1014bf82634f08ea62f98e6e619f7 /src/backend/parser/parse_expr.c
parentad43a413c4f7f5d024a5b2f51e00d280a22f1874 (diff)
downloadpostgresql-49082c2cc3d8167cca70cfe697afb064710828ca.tar.gz
postgresql-49082c2cc3d8167cca70cfe697afb064710828ca.zip
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
Diffstat (limited to 'src/backend/parser/parse_expr.c')
-rw-r--r--src/backend/parser/parse_expr.c46
1 files changed, 36 insertions, 10 deletions
diff --git a/src/backend/parser/parse_expr.c b/src/backend/parser/parse_expr.c
index e1400072501..31f0c9f693d 100644
--- a/src/backend/parser/parse_expr.c
+++ b/src/backend/parser/parse_expr.c
@@ -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");