Skip to content

Commit fe6eb36

Browse files
author
Nikita Glukhov
committed
Use nodes JsonFomat and JsonReturning in JsonCtorExpr transformation
1 parent a13e77d commit fe6eb36

File tree

8 files changed

+117
-55
lines changed

8 files changed

+117
-55
lines changed

src/backend/nodes/copyfuncs.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2304,11 +2304,7 @@ _copyJsonCtorExpr(const JsonCtorExpr *from)
23042304

23052305
COPY_NODE_FIELD(func);
23062306
COPY_SCALAR_FIELD(type);
2307-
COPY_SCALAR_FIELD(returning.format.type);
2308-
COPY_SCALAR_FIELD(returning.format.encoding);
2309-
COPY_LOCATION_FIELD(returning.format.location);
2310-
COPY_SCALAR_FIELD(returning.typid);
2311-
COPY_SCALAR_FIELD(returning.typmod);
2307+
COPY_NODE_FIELD(returning);
23122308
COPY_SCALAR_FIELD(absent_on_null);
23132309
COPY_SCALAR_FIELD(unique);
23142310

@@ -2355,7 +2351,7 @@ _copyJsonOutput(const JsonOutput *from)
23552351
JsonOutput *newnode = makeNode(JsonOutput);
23562352

23572353
COPY_NODE_FIELD(typeName);
2358-
COPY_SCALAR_FIELD(returning);
2354+
COPY_NODE_FIELD(returning);
23592355

23602356
return newnode;
23612357
}

src/backend/nodes/equalfuncs.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -853,11 +853,7 @@ _equalJsonCtorExpr(const JsonCtorExpr *a, const JsonCtorExpr *b)
853853
{
854854
COMPARE_NODE_FIELD(func);
855855
COMPARE_SCALAR_FIELD(type);
856-
COMPARE_SCALAR_FIELD(returning.format.type);
857-
COMPARE_SCALAR_FIELD(returning.format.encoding);
858-
COMPARE_LOCATION_FIELD(returning.format.location);
859-
COMPARE_SCALAR_FIELD(returning.typid);
860-
COMPARE_SCALAR_FIELD(returning.typmod);
856+
COMPARE_NODE_FIELD(returning);
861857
COMPARE_SCALAR_FIELD(absent_on_null);
862858
COMPARE_SCALAR_FIELD(unique);
863859

src/backend/nodes/nodeFuncs.c

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2291,7 +2291,13 @@ expression_tree_walker(Node *node,
22912291
}
22922292
break;
22932293
case T_JsonCtorExpr:
2294-
return walker(((JsonCtorExpr *) node)->func, context);
2294+
{
2295+
JsonCtorExpr *ctor = (JsonCtorExpr *) node;
2296+
2297+
if (walker(ctor->func, context))
2298+
return true;
2299+
}
2300+
break;
22952301
default:
22962302
elog(ERROR, "unrecognized node type: %d",
22972303
(int) nodeTag(node));
@@ -3245,6 +3251,7 @@ expression_tree_mutator(Node *node,
32453251

32463252
FLATCOPY(newnode, jve, JsonCtorExpr);
32473253
MUTATE(newnode->func, jve->func, FuncExpr *);
3254+
MUTATE(newnode->returning, jve->returning, JsonReturning *);
32483255

32493256
return (Node *) newnode;
32503257
}
@@ -3958,9 +3965,25 @@ raw_expression_tree_walker(Node *node,
39583965
}
39593966
break;
39603967
case T_JsonCtorExpr:
3961-
return walker(((JsonCtorExpr *) node)->func, context);
3968+
{
3969+
JsonCtorExpr *ctor = (JsonCtorExpr *) node;
3970+
3971+
if (walker(ctor->func, context))
3972+
return true;
3973+
if (walker(ctor->returning, context))
3974+
return true;
3975+
}
3976+
break;
39623977
case T_JsonOutput:
3963-
return walker(((JsonOutput *) node)->typeName, context);
3978+
{
3979+
JsonOutput *out = (JsonOutput *) node;
3980+
3981+
if (walker(out->typeName, context))
3982+
return true;
3983+
if (walker(out->returning, context))
3984+
return true;
3985+
}
3986+
break;
39643987
case T_JsonKeyValue:
39653988
{
39663989
JsonKeyValue *jkv = (JsonKeyValue *) node;

src/backend/nodes/outfuncs.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1746,11 +1746,7 @@ _outJsonCtorExpr(StringInfo str, const JsonCtorExpr *node)
17461746

17471747
WRITE_NODE_FIELD(func);
17481748
WRITE_INT_FIELD(type);
1749-
WRITE_ENUM_FIELD(returning.format.type, JsonFormatType);
1750-
WRITE_ENUM_FIELD(returning.format.encoding, JsonEncoding);
1751-
WRITE_LOCATION_FIELD(returning.format.location);
1752-
WRITE_OID_FIELD(returning.typid);
1753-
WRITE_INT_FIELD(returning.typmod);
1749+
WRITE_NODE_FIELD(returning);
17541750
WRITE_BOOL_FIELD(unique);
17551751
WRITE_BOOL_FIELD(absent_on_null);
17561752
}

src/backend/nodes/readfuncs.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1398,11 +1398,7 @@ _readJsonCtorExpr(void)
13981398

13991399
READ_NODE_FIELD(func);
14001400
READ_INT_FIELD(type);
1401-
READ_ENUM_FIELD(returning.format.type, JsonFormatType);
1402-
READ_ENUM_FIELD(returning.format.encoding, JsonEncoding);
1403-
READ_LOCATION_FIELD(returning.format.location);
1404-
READ_OID_FIELD(returning.typid);
1405-
READ_INT_FIELD(returning.typmod);
1401+
READ_NODE_FIELD(returning);
14061402
READ_BOOL_FIELD(unique);
14071403
READ_BOOL_FIELD(absent_on_null);
14081404

src/backend/parser/parse_expr.c

Lines changed: 76 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3762,7 +3762,7 @@ checkJsonOutputFormat(ParseState *pstate, const JsonFormat *format,
37623762
Oid targettype, bool allow_format_for_non_strings)
37633763
{
37643764
if (!allow_format_for_non_strings &&
3765-
format->type != JS_FORMAT_DEFAULT &&
3765+
format->format != JS_FORMAT_DEFAULT &&
37663766
(targettype != BYTEAOID &&
37673767
targettype != JSONOID &&
37683768
targettype != JSONBOID))
@@ -3779,7 +3779,7 @@ checkJsonOutputFormat(ParseState *pstate, const JsonFormat *format,
37793779
errmsg("cannot use JSON format with non-string output types")));
37803780
}
37813781

3782-
if (format->type == JS_FORMAT_JSON)
3782+
if (format->format == JS_FORMAT_JSON)
37833783
{
37843784
JsonEncoding enc = format->encoding != JS_ENC_DEFAULT ?
37853785
format->encoding : JS_ENC_UTF8;
@@ -3807,23 +3807,25 @@ checkJsonOutputFormat(ParseState *pstate, const JsonFormat *format,
38073807
* Assigns default format or checks specified format for its applicability to
38083808
* the target type.
38093809
*/
3810-
static void
3810+
static JsonReturning *
38113811
transformJsonOutput(ParseState *pstate, const JsonOutput *output,
3812-
bool allow_format, JsonReturning *ret)
3812+
bool allow_format)
38133813
{
3814+
JsonReturning *ret;
3815+
38143816
/* if output clause is not specified, make default clause value */
38153817
if (!output)
38163818
{
3817-
ret->format.type = JS_FORMAT_DEFAULT;
3818-
ret->format.encoding = JS_ENC_DEFAULT;
3819-
ret->format.location = -1;
3819+
ret = makeNode(JsonReturning);
3820+
3821+
ret->format = makeJsonFormat(JS_FORMAT_DEFAULT, JS_ENC_DEFAULT, -1);
38203822
ret->typid = InvalidOid;
38213823
ret->typmod = -1;
38223824

3823-
return;
3825+
return ret;
38243826
}
38253827

3826-
*ret = output->returning;
3828+
ret = copyObject(output->returning);
38273829

38283830
typenameTypeIdAndMod(pstate, output->typeName, &ret->typid, &ret->typmod);
38293831

@@ -3832,20 +3834,73 @@ transformJsonOutput(ParseState *pstate, const JsonOutput *output,
38323834
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
38333835
errmsg("returning SETOF types is not supported in SQL/JSON functions")));
38343836

3835-
if (ret->format.type == JS_FORMAT_DEFAULT)
3837+
if (ret->format->format == JS_FORMAT_DEFAULT)
38363838
/* assign JSONB format when returning jsonb, or JSON format otherwise */
3837-
ret->format.type =
3839+
ret->format->format =
38383840
ret->typid == JSONBOID ? JS_FORMAT_JSONB : JS_FORMAT_JSON;
38393841
else
3840-
checkJsonOutputFormat(pstate, &ret->format, ret->typid, allow_format);
3842+
checkJsonOutputFormat(pstate, ret->format, ret->typid, allow_format);
3843+
3844+
return ret;
3845+
}
3846+
3847+
/*
3848+
* Transform JSON output clause of JSON contructor functions.
3849+
*
3850+
* Derive RETURNING type, if not specified, from argument types.
3851+
*/
3852+
static JsonReturning *
3853+
transformJsonCtorOutput(ParseState *pstate, JsonOutput *output, List *args)
3854+
{
3855+
JsonReturning *returning = transformJsonOutput(pstate, output, true);
3856+
3857+
if (!OidIsValid(returning->typid))
3858+
{
3859+
ListCell *lc;
3860+
bool have_json = false;
3861+
bool have_jsonb = false;
3862+
3863+
foreach(lc, args)
3864+
{
3865+
Node *expr = lfirst(lc);
3866+
Oid typid = exprType(expr);
3867+
3868+
have_json |= typid == JSONOID;
3869+
have_jsonb |= typid == JSONBOID;
3870+
3871+
if (have_jsonb)
3872+
break;
3873+
}
3874+
3875+
if (have_jsonb)
3876+
{
3877+
returning->typid = JSONBOID;
3878+
returning->format->format = JS_FORMAT_JSONB;
3879+
}
3880+
else if (have_json)
3881+
{
3882+
returning->typid = JSONOID;
3883+
returning->format->format = JS_FORMAT_JSON;
3884+
}
3885+
else
3886+
{
3887+
/* XXX TEXTOID is default by standard */
3888+
returning->typid = JSONOID;
3889+
returning->format->format = JS_FORMAT_JSON;
3890+
}
3891+
3892+
returning->typmod = -1;
3893+
}
3894+
3895+
return returning;
38413896
}
38423897

38433898
/*
38443899
* Coerce json[b]-valued function expression to the output type.
38453900
*/
38463901
static Node *
3847-
coerceJsonFuncExpr(ParseState *pstate, Node *expr, JsonReturning *returning,
3848-
bool report_error)
3902+
coerceJsonFuncExpr(ParseState *pstate, Node *expr,
3903+
const JsonReturning *returning, bool report_error)
38493904
{
38503905
Node *res;
38513906
int location;
@@ -3858,16 +3913,16 @@ coerceJsonFuncExpr(ParseState *pstate, Node *expr, JsonReturning *returning,
38583913
location = exprLocation(expr);
38593914

38603915
if (location < 0)
3861-
location = returning ? returning->format.location : -1;
3916+
location = returning ? returning->format->location : -1;
38623917

38633918
/* special case for RETURNING bytea FORMAT json */
3864-
if (returning->format.type == JS_FORMAT_JSON &&
3919+
if (returning->format->format == JS_FORMAT_JSON &&
38653920
returning->typid == BYTEAOID)
38663921
{
38673922
/* encode json text into bytea using pg_convert_to() */
38683923
Node *texpr = coerce_to_specific_type(pstate, expr, TEXTOID,
38693924
"JSON_FUNCTION");
3870-
Const *enc = getJsonEncodingConst(&returning->format);
3925+
Const *enc = getJsonEncodingConst(returning->format);
38713926
FuncExpr *fexpr = makeFuncExpr(F_PG_CONVERT_TO, BYTEAOID,
38723927
list_make2(texpr, enc),
38733928
InvalidOid, InvalidOid,
@@ -3908,7 +3963,7 @@ coerceJsonFuncExpr(ParseState *pstate, Node *expr, JsonReturning *returning,
39083963
static Node *
39093964
transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor)
39103965
{
3911-
JsonReturning returning;
3966+
JsonReturning *returning;
39123967
JsonCtorExpr *jsctor;
39133968
FuncExpr *fexpr;
39143969
List *args = NIL;
@@ -3937,9 +3992,9 @@ transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor)
39373992
}
39383993
}
39393994

3940-
transformJsonOutput(pstate, ctor->output, true, &returning);
3995+
returning = transformJsonCtorOutput(pstate, ctor->output, args);
39413996

3942-
if (returning.format.type == JS_FORMAT_JSONB)
3997+
if (returning->format->format == JS_FORMAT_JSONB)
39433998
{
39443999
funcid = args ? F_JSONB_BUILD_OBJECT_EXT : F_JSONB_BUILD_OBJECT_NOARGS;
39454000
funcrettype = JSONBOID;
@@ -3961,5 +4016,5 @@ transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor)
39614016
jsctor->unique = ctor->unique;
39624017
jsctor->absent_on_null = ctor->absent_on_null;
39634018

3964-
return coerceJsonFuncExpr(pstate, (Node *) jsctor, &returning, true);
4019+
return coerceJsonFuncExpr(pstate, (Node *) jsctor, returning, true);
39654020
}

src/include/nodes/primnodes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1265,7 +1265,7 @@ typedef struct JsonCtorExpr
12651265
Expr xpr;
12661266
JsonCtorType type; /* constructor type */
12671267
FuncExpr *func; /* underlying json[b]_xxx() function call */
1268-
JsonReturning returning; /* RETURNING clause */
1268+
JsonReturning *returning; /* RETURNING clause */
12691269
bool absent_on_null; /* ABSENT ON NULL? */
12701270
bool unique; /* WITH UNIQUE KEYS? (JSON_OBJECT[AGG] only) */
12711271
} JsonCtorExpr;

src/test/regress/expected/sqljson.out

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,9 @@ SELECT JSON_OBJECT('foo': NULL::jsonb FORMAT JSON);
100100
WARNING: FORMAT JSON has no effect for json and jsonb types
101101
LINE 1: SELECT JSON_OBJECT('foo': NULL::jsonb FORMAT JSON);
102102
^
103-
json_object
104-
----------------
105-
{"foo" : null}
103+
json_object
104+
---------------
105+
{"foo": null}
106106
(1 row)
107107

108108
SELECT JSON_OBJECT('foo': NULL::jsonb FORMAT JSON ENCODING UTF8);
@@ -176,9 +176,9 @@ SELECT JSON_OBJECT(
176176
'c': json '[ 1,true,{ } ]',
177177
'd': jsonb '{ "x" : 123.45 }'
178178
);
179-
json_object
180-
------------------------------------------------------------------------
181-
{"a" : "123", "1.23" : 123, "c" : [ 1,true,{ } ], "d" : {"x": 123.45}}
179+
json_object
180+
-------------------------------------------------------------------
181+
{"a": "123", "c": [1, true, {}], "d": {"x": 123.45}, "1.23": 123}
182182
(1 row)
183183

184184
SELECT JSON_OBJECT(
@@ -207,9 +207,9 @@ SELECT JSON_OBJECT('a': '123', 'b': JSON_OBJECT('a': 111, 'b': 'aaa'));
207207
(1 row)
208208

209209
SELECT JSON_OBJECT('a': '123', 'b': JSON_OBJECT('a': 111, 'b': 'aaa' RETURNING jsonb));
210-
json_object
211-
---------------------------------------------
212-
{"a" : "123", "b" : {"a": 111, "b": "aaa"}}
210+
json_object
211+
-------------------------------------------
212+
{"a": "123", "b": {"a": 111, "b": "aaa"}}
213213
(1 row)
214214

215215
SELECT JSON_OBJECT('a': JSON_OBJECT('b': 1 RETURNING text));

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy