Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit d0c1cce

Browse files
author
Nikita Glukhov
committed
Add JSON_ARRAY() transformation
1 parent 02e07a5 commit d0c1cce

File tree

8 files changed

+349
-16
lines changed

8 files changed

+349
-16
lines changed

src/backend/nodes/copyfuncs.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2152,6 +2152,22 @@ _copyJsonObjectCtor(const JsonObjectCtor *from)
21522152
return newnode;
21532153
}
21542154

2155+
/*
2156+
* _copyJsonArrayCtor
2157+
*/
2158+
static JsonArrayCtor *
2159+
_copyJsonArrayCtor(const JsonArrayCtor *from)
2160+
{
2161+
JsonArrayCtor *newnode = makeNode(JsonArrayCtor);
2162+
2163+
COPY_NODE_FIELD(exprs);
2164+
COPY_NODE_FIELD(output);
2165+
COPY_SCALAR_FIELD(absent_on_null);
2166+
COPY_LOCATION_FIELD(location);
2167+
2168+
return newnode;
2169+
}
2170+
21552171
/* ****************************************************************
21562172
* relation.h copy functions
21572173
*
@@ -5010,6 +5026,9 @@ copyObjectImpl(const void *from)
50105026
case T_JsonObjectCtor:
50115027
retval = _copyJsonObjectCtor(from);
50125028
break;
5029+
case T_JsonArrayCtor:
5030+
retval = _copyJsonArrayCtor(from);
5031+
break;
50135032

50145033
/*
50155034
* RELATION NODES

src/backend/parser/parse_expr.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ static Node *transformIndirection(ParseState *pstate, A_Indirection *ind);
123123
static Node *transformTypeCast(ParseState *pstate, TypeCast *tc);
124124
static Node *transformCollateClause(ParseState *pstate, CollateClause *c);
125125
static Node *transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor);
126+
static Node *transformJsonArrayCtor(ParseState *pstate, JsonArrayCtor *ctor);
126127
static Node *make_row_comparison_op(ParseState *pstate, List *opname,
127128
List *largs, List *rargs, int location);
128129
static Node *make_row_distinct_op(ParseState *pstate, List *opname,
@@ -375,6 +376,10 @@ transformExprRecurse(ParseState *pstate, Node *expr)
375376
result = transformJsonObjectCtor(pstate, (JsonObjectCtor *) expr);
376377
break;
377378

379+
case T_JsonArrayCtor:
380+
result = transformJsonArrayCtor(pstate, (JsonArrayCtor *) expr);
381+
break;
382+
378383
default:
379384
/* should not reach here */
380385
elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
@@ -3722,3 +3727,47 @@ transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor)
37223727

37233728
return coerceJsonFuncExpr(pstate, (Node *) fexpr, ctor->output);
37243729
}
3730+
3731+
static Node *
3732+
transformJsonArrayCtor(ParseState *pstate, JsonArrayCtor *ctor)
3733+
{
3734+
FuncExpr *fexpr;
3735+
List *args = NIL;
3736+
Oid funcid;
3737+
Oid funcrettype;
3738+
3739+
if (ctor->exprs)
3740+
{
3741+
ListCell *lc;
3742+
3743+
args = lappend(args, makeBoolConst(ctor->absent_on_null, false));
3744+
3745+
foreach(lc, ctor->exprs)
3746+
{
3747+
JsonValueExpr *jsval = castNode(JsonValueExpr, lfirst(lc));
3748+
Node *val = transformJsonValueExpr(pstate, jsval,
3749+
JS_FORMAT_DEFAULT);
3750+
3751+
args = lappend(args, val);
3752+
}
3753+
}
3754+
3755+
transformJsonOutput(pstate, &ctor->output);
3756+
3757+
if (ctor->output->format.type == JS_FORMAT_JSONB)
3758+
{
3759+
funcid = args ? F_JSONB_BUILD_ARRAY_EXT : F_JSONB_BUILD_ARRAY_NOARGS;
3760+
funcrettype = JSONBOID;
3761+
}
3762+
else
3763+
{
3764+
funcid = args ? F_JSON_BUILD_ARRAY_EXT : F_JSON_BUILD_ARRAY_NOARGS;
3765+
funcrettype = JSONOID;
3766+
}
3767+
3768+
fexpr = makeFuncExpr(funcid, funcrettype, args,
3769+
InvalidOid, InvalidOid, COERCE_EXPLICIT_CALL);
3770+
fexpr->location = ctor->location;
3771+
3772+
return coerceJsonFuncExpr(pstate, (Node *) fexpr, ctor->output);
3773+
}

src/backend/utils/adt/json.c

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,6 @@ static void datum_to_json(Datum val, bool is_null, StringInfo result,
118118
static void add_json(Datum val, bool is_null, StringInfo result,
119119
Oid val_type, bool key_scalar);
120120
static text *catenate_stringinfo_string(StringInfo buffer, const char *addon);
121-
static Datum json_build_array_worker(FunctionCallInfo fcinfo, int first_vararg,
122-
bool absent_on_null);
123121

124122
static JsonIterator *JsonIteratorInitFromLex(JsonContainer *jc,
125123
JsonLexContext *lex, JsonIterator *parent);
@@ -2351,11 +2349,9 @@ json_build_object_noargs(PG_FUNCTION_ARGS)
23512349
PG_RETURN_TEXT_P(cstring_to_text_with_len("{}", 2));
23522350
}
23532351

2354-
/*
2355-
* SQL function json_build_array(variadic "any")
2356-
*/
2357-
Datum
2358-
json_build_array(PG_FUNCTION_ARGS)
2352+
static Datum
2353+
json_build_array_worker(FunctionCallInfo fcinfo, int first_vararg,
2354+
bool absent_on_null)
23592355
{
23602356
int nargs = PG_NARGS();
23612357
int i;
@@ -2368,8 +2364,11 @@ json_build_array(PG_FUNCTION_ARGS)
23682364

23692365
appendStringInfoChar(result, '[');
23702366

2371-
for (i = 0; i < nargs; i++)
2367+
for (i = first_vararg; i < nargs; i++)
23722368
{
2369+
if (absent_on_null && PG_ARGISNULL(i))
2370+
continue;
2371+
23732372
/*
23742373
* Note: since json_build_array() is declared as taking type "any",
23752374
* the parser will not do any type conversion on unknown-type literals
@@ -2401,6 +2400,24 @@ json_build_array(PG_FUNCTION_ARGS)
24012400
PG_RETURN_TEXT_P(cstring_to_text_with_len(result->data, result->len));
24022401
}
24032402

2403+
/*
2404+
* SQL function json_build_array(variadic "any")
2405+
*/
2406+
Datum
2407+
json_build_array(PG_FUNCTION_ARGS)
2408+
{
2409+
return json_build_array_worker(fcinfo, 0, false);
2410+
}
2411+
2412+
/*
2413+
* SQL function json_build_array_ext(absent_on_null bool, variadic "any")
2414+
*/
2415+
Datum
2416+
json_build_array_ext(PG_FUNCTION_ARGS)
2417+
{
2418+
return json_build_array_worker(fcinfo, 1, PG_GETARG_BOOL(0));
2419+
}
2420+
24042421
/*
24052422
* degenerate case of json_build_array where it gets 0 arguments.
24062423
*/

src/backend/utils/adt/jsonb.c

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,6 @@ static void add_jsonb(Datum val, bool is_null, JsonbInState *result,
9797
static JsonbParseState *clone_parse_state(JsonbParseState *state);
9898
static char *JsonbToCStringWorker(StringInfo out, JsonbContainer *in, int estimated_len, bool indent);
9999
static void add_indent(StringInfo out, bool indent, int level);
100-
static Datum jsonb_build_array_worker(FunctionCallInfo fcinfo, int first_vararg,
101-
bool absent_on_null);
102100

103101
/*
104102
* jsonb type input function
@@ -1428,11 +1426,9 @@ jsonb_build_object_noargs(PG_FUNCTION_ARGS)
14281426
PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
14291427
}
14301428

1431-
/*
1432-
* SQL function jsonb_build_array(variadic "any")
1433-
*/
1434-
Datum
1435-
jsonb_build_array(PG_FUNCTION_ARGS)
1429+
static Datum
1430+
jsonb_build_array_worker(FunctionCallInfo fcinfo, int first_vararg,
1431+
bool absent_on_null)
14361432
{
14371433
int nargs = PG_NARGS();
14381434
int i;
@@ -1444,7 +1440,7 @@ jsonb_build_array(PG_FUNCTION_ARGS)
14441440

14451441
result.res = pushJsonbValue(&result.parseState, WJB_BEGIN_ARRAY, NULL);
14461442

1447-
for (i = 0; i < nargs; i++)
1443+
for (i = first_vararg; i < nargs; i++)
14481444
{
14491445
val_type = get_fn_expr_argtype(fcinfo->flinfo, i);
14501446
/* see comments in jsonb_build_object above */
@@ -1464,6 +1460,10 @@ jsonb_build_array(PG_FUNCTION_ARGS)
14641460
ereport(ERROR,
14651461
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
14661462
errmsg("could not determine data type for argument %d", i + 1)));
1463+
1464+
if (absent_on_null && PG_ARGISNULL(i))
1465+
continue;
1466+
14671467
add_jsonb(arg, PG_ARGISNULL(i), &result, val_type, false);
14681468
}
14691469

@@ -1472,6 +1472,24 @@ jsonb_build_array(PG_FUNCTION_ARGS)
14721472
PG_RETURN_POINTER(JsonbValueToJsonb(result.res));
14731473
}
14741474

1475+
/*
1476+
* SQL function jsonb_build_array(variadic "any")
1477+
*/
1478+
Datum
1479+
jsonb_build_array(PG_FUNCTION_ARGS)
1480+
{
1481+
return jsonb_build_array_worker(fcinfo, 0, false);
1482+
}
1483+
1484+
/*
1485+
* SQL function jsonb_build_array_ext(absent_on_null bool, variadic "any")
1486+
*/
1487+
Datum
1488+
jsonb_build_array_ext(PG_FUNCTION_ARGS)
1489+
{
1490+
return jsonb_build_array_worker(fcinfo, 1, PG_GETARG_BOOL(0));
1491+
}
1492+
14751493
/*
14761494
* degenerate case of jsonb_build_array where it gets 0 arguments.
14771495
*/

src/include/catalog/pg_proc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4478,6 +4478,8 @@ DATA(insert OID = 3198 ( json_build_array PGNSP PGUID 12 1 0 2276 0 f f f f
44784478
DESCR("build a json array from any inputs");
44794479
DATA(insert OID = 3199 ( json_build_array PGNSP PGUID 12 1 0 0 0 f f f f f f s s 0 0 114 "" _null_ _null_ _null_ _null_ _null_ json_build_array_noargs _null_ _null_ _null_ ));
44804480
DESCR("build an empty json array");
4481+
DATA(insert OID = 3998 ( json_build_array_ext PGNSP PGUID 12 1 0 2276 0 f f f f f f s s 2 0 114 "16 2276" "{16,2276}" "{i,v}" _null_ _null_ _null_ json_build_array_ext _null_ _null_ _null_ ));
4482+
DESCR("build a json array from any inputs");
44814483
DATA(insert OID = 3200 ( json_build_object PGNSP PGUID 12 1 0 2276 0 f f f f f f s s 1 0 114 "2276" "{2276}" "{v}" _null_ _null_ _null_ json_build_object _null_ _null_ _null_ ));
44824484
DESCR("build a json object from pairwise key/value inputs");
44834485
DATA(insert OID = 3201 ( json_build_object PGNSP PGUID 12 1 0 0 0 f f f f f f s s 0 0 114 "" _null_ _null_ _null_ _null_ _null_ json_build_object_noargs _null_ _null_ _null_ ));
@@ -4938,6 +4940,8 @@ DATA(insert OID = 3271 ( jsonb_build_array PGNSP PGUID 12 1 0 2276 0 f f f f
49384940
DESCR("build a jsonb array from any inputs");
49394941
DATA(insert OID = 3272 ( jsonb_build_array PGNSP PGUID 12 1 0 0 0 f f f f f f s s 0 0 3802 "" _null_ _null_ _null_ _null_ _null_ jsonb_build_array_noargs _null_ _null_ _null_ ));
49404942
DESCR("build an empty jsonb array");
4943+
DATA(insert OID = 6068 ( jsonb_build_array_ext PGNSP PGUID 12 1 0 2276 0 f f f f f f s s 2 0 3802 "16 2276" "{16,2276}" "{i,v}" _null_ _null_ _null_ jsonb_build_array_ext _null_ _null_ _null_ ));
4944+
DESCR("build a jsonb array from any inputs");
49414945
DATA(insert OID = 3273 ( jsonb_build_object PGNSP PGUID 12 1 0 2276 0 f f f f f f s s 1 0 3802 "2276" "{2276}" "{v}" _null_ _null_ _null_ jsonb_build_object _null_ _null_ _null_ ));
49424946
DESCR("build a jsonb object from pairwise key/value inputs");
49434947
DATA(insert OID = 3274 ( jsonb_build_object PGNSP PGUID 12 1 0 0 0 f f f f f f s s 0 0 3802 "" _null_ _null_ _null_ _null_ _null_ jsonb_build_object_noargs _null_ _null_ _null_ ));

0 commit comments

Comments
 (0)