Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
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)