Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit40b736f

Browse files
author
Nikita Glukhov
committed
Add JSON_ARRAY(subquery) transformation
1 parent397c243 commit40b736f

File tree

6 files changed

+153
-0
lines changed

6 files changed

+153
-0
lines changed

‎src/backend/nodes/copyfuncs.c‎

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2413,6 +2413,23 @@ _copyJsonArrayAgg(const JsonArrayAgg *from)
24132413
returnnewnode;
24142414
}
24152415

2416+
/*
2417+
* _copyJsonArrayQueryCtor
2418+
*/
2419+
staticJsonArrayQueryCtor*
2420+
_copyJsonArrayQueryCtor(constJsonArrayQueryCtor*from)
2421+
{
2422+
JsonArrayQueryCtor*newnode=makeNode(JsonArrayQueryCtor);
2423+
2424+
COPY_NODE_FIELD(query);
2425+
COPY_NODE_FIELD(output);
2426+
COPY_SCALAR_FIELD(format);
2427+
COPY_SCALAR_FIELD(absent_on_null);
2428+
COPY_LOCATION_FIELD(location);
2429+
2430+
returnnewnode;
2431+
}
2432+
24162433
/* ****************************************************************
24172434
*pathnodes.h copy functions
24182435
*
@@ -5337,6 +5354,9 @@ copyObjectImpl(const void *from)
53375354
caseT_JsonArrayCtor:
53385355
retval=_copyJsonArrayCtor(from);
53395356
break;
5357+
caseT_JsonArrayQueryCtor:
5358+
retval=_copyJsonArrayQueryCtor(from);
5359+
break;
53405360
caseT_JsonArrayAgg:
53415361
retval=_copyJsonArrayAgg(from);
53425362
break;

‎src/backend/nodes/nodeFuncs.c‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4052,6 +4052,16 @@ raw_expression_tree_walker(Node *node,
40524052
return true;
40534053
}
40544054
break;
4055+
caseT_JsonArrayQueryCtor:
4056+
{
4057+
JsonArrayQueryCtor*jaqc= (JsonArrayQueryCtor*)node;
4058+
4059+
if (walker(jaqc->output,context))
4060+
return true;
4061+
if (walker(jaqc->query,context))
4062+
return true;
4063+
}
4064+
break;
40554065
default:
40564066
elog(ERROR,"unrecognized node type: %d",
40574067
(int)nodeTag(node));

‎src/backend/parser/parse_expr.c‎

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ static Node *transformTypeCast(ParseState *pstate, TypeCast *tc);
125125
staticNode*transformCollateClause(ParseState*pstate,CollateClause*c);
126126
staticNode*transformJsonObjectCtor(ParseState*pstate,JsonObjectCtor*ctor);
127127
staticNode*transformJsonArrayCtor(ParseState*pstate,JsonArrayCtor*ctor);
128+
staticNode*transformJsonArrayQueryCtor(ParseState*pstate,
129+
JsonArrayQueryCtor*ctor);
128130
staticNode*transformJsonObjectAgg(ParseState*pstate,JsonObjectAgg*agg);
129131
staticNode*transformJsonArrayAgg(ParseState*pstate,JsonArrayAgg*agg);
130132
staticNode*make_row_comparison_op(ParseState*pstate,List*opname,
@@ -383,6 +385,10 @@ transformExprRecurse(ParseState *pstate, Node *expr)
383385
result=transformJsonArrayCtor(pstate, (JsonArrayCtor*)expr);
384386
break;
385387

388+
caseT_JsonArrayQueryCtor:
389+
result=transformJsonArrayQueryCtor(pstate, (JsonArrayQueryCtor*)expr);
390+
break;
391+
386392
caseT_JsonObjectAgg:
387393
result=transformJsonObjectAgg(pstate, (JsonObjectAgg*)expr);
388394
break;
@@ -4012,6 +4018,71 @@ transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor)
40124018
returncoerceJsonFuncExpr(pstate, (Node*)jsctor,jsctor->returning, true);
40134019
}
40144020

4021+
/*
4022+
* Transform JSON_ARRAY(query [FORMAT] [RETURNING] [ON NULL]) into
4023+
* (SELECT JSON_ARRAYAGG(a [FORMAT] [RETURNING] [ON NULL]) FROM (query) q(a))
4024+
*/
4025+
staticNode*
4026+
transformJsonArrayQueryCtor(ParseState*pstate,JsonArrayQueryCtor*ctor)
4027+
{
4028+
SubLink*sublink=makeNode(SubLink);
4029+
SelectStmt*select=makeNode(SelectStmt);
4030+
RangeSubselect*range=makeNode(RangeSubselect);
4031+
Alias*alias=makeNode(Alias);
4032+
ResTarget*target=makeNode(ResTarget);
4033+
JsonArrayAgg*agg=makeNode(JsonArrayAgg);
4034+
ColumnRef*colref=makeNode(ColumnRef);
4035+
Query*query;
4036+
ParseState*qpstate;
4037+
4038+
/* Transform query only for counting target list entries. */
4039+
qpstate=make_parsestate(pstate);
4040+
4041+
query=transformStmt(qpstate,ctor->query);
4042+
4043+
if (count_nonjunk_tlist_entries(query->targetList)!=1)
4044+
ereport(ERROR,
4045+
(errcode(ERRCODE_SYNTAX_ERROR),
4046+
errmsg("subquery must return only one column"),
4047+
parser_errposition(pstate,ctor->location)));
4048+
4049+
free_parsestate(qpstate);
4050+
4051+
colref->fields=list_make2(makeString(pstrdup("q")),
4052+
makeString(pstrdup("a")));
4053+
colref->location=ctor->location;
4054+
4055+
agg->arg=makeJsonValueExpr((Expr*)colref,ctor->format);
4056+
agg->ctor.agg_order=NIL;
4057+
agg->ctor.output=ctor->output;
4058+
agg->absent_on_null=ctor->absent_on_null;
4059+
agg->ctor.location=ctor->location;
4060+
4061+
target->name=NULL;
4062+
target->indirection=NIL;
4063+
target->val= (Node*)agg;
4064+
target->location=ctor->location;
4065+
4066+
alias->aliasname=pstrdup("q");
4067+
alias->colnames=list_make1(makeString(pstrdup("a")));
4068+
4069+
range->lateral= false;
4070+
range->subquery=ctor->query;
4071+
range->alias=alias;
4072+
4073+
select->targetList=list_make1(target);
4074+
select->fromClause=list_make1(range);
4075+
4076+
sublink->subLinkType=EXPR_SUBLINK;
4077+
sublink->subLinkId=0;
4078+
sublink->testexpr=NULL;
4079+
sublink->operName=NIL;
4080+
sublink->subselect= (Node*)select;
4081+
sublink->location=ctor->location;
4082+
4083+
returntransformExprRecurse(pstate, (Node*)sublink);
4084+
}
4085+
40154086
/*
40164087
* Common code for JSON_OBJECTAGG and JSON_ARRAYAGG transformation.
40174088
*/

‎src/backend/parser/parse_target.c‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1935,6 +1935,7 @@ FigureColnameInternal(Node *node, char **name)
19351935
*name="json_object";
19361936
return2;
19371937
caseT_JsonArrayCtor:
1938+
caseT_JsonArrayQueryCtor:
19381939
*name="json_array";
19391940
return2;
19401941
caseT_JsonObjectAgg:

‎src/test/regress/expected/sqljson.out‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,46 @@ SELECT JSON_ARRAY(JSON_ARRAY('{ "a" : 123 }' FORMAT JSON RETURNING text) FORMAT
423423
[[{ "a" : 123 }]]
424424
(1 row)
425425

426+
SELECT JSON_ARRAY(SELECT i FROM (VALUES (1), (2), (NULL), (4)) foo(i));
427+
json_array
428+
------------
429+
[1, 2, 4]
430+
(1 row)
431+
432+
SELECT JSON_ARRAY(SELECT i FROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i));
433+
json_array
434+
------------
435+
[[1,2], +
436+
[3,4]]
437+
(1 row)
438+
439+
SELECT JSON_ARRAY(SELECT i FROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i) RETURNING jsonb);
440+
json_array
441+
------------------
442+
[[1, 2], [3, 4]]
443+
(1 row)
444+
445+
--SELECT JSON_ARRAY(SELECT i FROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i) NULL ON NULL);
446+
--SELECT JSON_ARRAY(SELECT i FROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i) NULL ON NULL RETURNING jsonb);
447+
SELECT JSON_ARRAY(SELECT i FROM (VALUES (3), (1), (NULL), (2)) foo(i) ORDER BY i);
448+
json_array
449+
------------
450+
[1, 2, 3]
451+
(1 row)
452+
453+
-- Should fail
454+
SELECT JSON_ARRAY(SELECT FROM (VALUES (1)) foo(i));
455+
ERROR: subquery must return only one column
456+
LINE 1: SELECT JSON_ARRAY(SELECT FROM (VALUES (1)) foo(i));
457+
^
458+
SELECT JSON_ARRAY(SELECT i, i FROM (VALUES (1)) foo(i));
459+
ERROR: subquery must return only one column
460+
LINE 1: SELECT JSON_ARRAY(SELECT i, i FROM (VALUES (1)) foo(i));
461+
^
462+
SELECT JSON_ARRAY(SELECT * FROM (VALUES (1, 2)) foo(i, j));
463+
ERROR: subquery must return only one column
464+
LINE 1: SELECT JSON_ARRAY(SELECT * FROM (VALUES (1, 2)) foo(i, j));
465+
^
426466
-- JSON_ARRAYAGG()
427467
SELECTJSON_ARRAYAGG(i) IS NULL,
428468
JSON_ARRAYAGG(i RETURNING jsonb) IS NULL

‎src/test/regress/sql/sqljson.sql‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,17 @@ SELECT JSON_ARRAY(JSON_ARRAY('{ "a" : 123 }' RETURNING text));
116116
SELECT JSON_ARRAY(JSON_ARRAY('{ "a" : 123 }' FORMAT JSON RETURNINGtext));
117117
SELECT JSON_ARRAY(JSON_ARRAY('{ "a" : 123 }' FORMAT JSON RETURNINGtext) FORMAT JSON);
118118

119+
SELECT JSON_ARRAY(SELECT iFROM (VALUES (1), (2), (NULL), (4)) foo(i));
120+
SELECT JSON_ARRAY(SELECT iFROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i));
121+
SELECT JSON_ARRAY(SELECT iFROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i) RETURNING jsonb);
122+
--SELECT JSON_ARRAY(SELECT i FROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i) NULL ON NULL);
123+
--SELECT JSON_ARRAY(SELECT i FROM (VALUES (NULL::int[]), ('{1,2}'), (NULL), (NULL), ('{3,4}'), (NULL)) foo(i) NULL ON NULL RETURNING jsonb);
124+
SELECT JSON_ARRAY(SELECT iFROM (VALUES (3), (1), (NULL), (2)) foo(i)ORDER BY i);
125+
-- Should fail
126+
SELECT JSON_ARRAY(SELECTFROM (VALUES (1)) foo(i));
127+
SELECT JSON_ARRAY(SELECT i, iFROM (VALUES (1)) foo(i));
128+
SELECT JSON_ARRAY(SELECT*FROM (VALUES (1,2)) foo(i, j));
129+
119130
-- JSON_ARRAYAGG()
120131
SELECTJSON_ARRAYAGG(i) ISNULL,
121132
JSON_ARRAYAGG(i RETURNING jsonb) ISNULL

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp