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

Commitcd4b585

Browse files
author
Nikita Glukhov
committed
Add JSON_OBJECTAGG() and JSON_ARRAYAGG() transformation
1 parent1233b33 commitcd4b585

File tree

15 files changed

+853
-76
lines changed

15 files changed

+853
-76
lines changed

‎src/backend/executor/execExpr.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2138,6 +2138,12 @@ ExecInitExprRec(Expr *node, ExprState *state,
21382138
intnargs=list_length(args);
21392139
intargno=0;
21402140

2141+
if (ctor->func)
2142+
{
2143+
ExecInitExprRec(ctor->func,state,resv,resnull);
2144+
break;
2145+
}
2146+
21412147
scratch.opcode=EEOP_JSON_CTOR;
21422148
scratch.d.json_ctor.ctor=ctor;
21432149
scratch.d.json_ctor.arg_values=palloc(sizeof(Datum)*nargs);

‎src/backend/nodes/copyfuncs.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2344,6 +2344,26 @@ _copyJsonObjectCtor(const JsonObjectCtor *from)
23442344
returnnewnode;
23452345
}
23462346

2347+
/*
2348+
* _copyJsonObjectAgg
2349+
*/
2350+
staticJsonObjectAgg*
2351+
_copyJsonObjectAgg(constJsonObjectAgg*from)
2352+
{
2353+
JsonObjectAgg*newnode=makeNode(JsonObjectAgg);
2354+
2355+
COPY_NODE_FIELD(ctor.output);
2356+
COPY_NODE_FIELD(ctor.agg_filter);
2357+
COPY_NODE_FIELD(ctor.agg_order);
2358+
COPY_NODE_FIELD(ctor.over);
2359+
COPY_LOCATION_FIELD(ctor.location);
2360+
COPY_NODE_FIELD(arg);
2361+
COPY_SCALAR_FIELD(absent_on_null);
2362+
COPY_SCALAR_FIELD(unique);
2363+
2364+
returnnewnode;
2365+
}
2366+
23472367
/*
23482368
* _copyJsonOutput
23492369
*/
@@ -2374,6 +2394,25 @@ _copyJsonArrayCtor(const JsonArrayCtor *from)
23742394
returnnewnode;
23752395
}
23762396

2397+
/*
2398+
* _copyJsonArrayAgg
2399+
*/
2400+
staticJsonArrayAgg*
2401+
_copyJsonArrayAgg(constJsonArrayAgg*from)
2402+
{
2403+
JsonArrayAgg*newnode=makeNode(JsonArrayAgg);
2404+
2405+
COPY_NODE_FIELD(ctor.output);
2406+
COPY_NODE_FIELD(ctor.agg_filter);
2407+
COPY_NODE_FIELD(ctor.agg_order);
2408+
COPY_NODE_FIELD(ctor.over);
2409+
COPY_LOCATION_FIELD(ctor.location);
2410+
COPY_NODE_FIELD(arg);
2411+
COPY_SCALAR_FIELD(absent_on_null);
2412+
2413+
returnnewnode;
2414+
}
2415+
23772416
/* ****************************************************************
23782417
*pathnodes.h copy functions
23792418
*
@@ -5289,12 +5328,18 @@ copyObjectImpl(const void *from)
52895328
caseT_JsonObjectCtor:
52905329
retval=_copyJsonObjectCtor(from);
52915330
break;
5331+
caseT_JsonObjectAgg:
5332+
retval=_copyJsonObjectAgg(from);
5333+
break;
52925334
caseT_JsonOutput:
52935335
retval=_copyJsonOutput(from);
52945336
break;
52955337
caseT_JsonArrayCtor:
52965338
retval=_copyJsonArrayCtor(from);
52975339
break;
5340+
caseT_JsonArrayAgg:
5341+
retval=_copyJsonArrayAgg(from);
5342+
break;
52985343

52995344
/*
53005345
* RELATION NODES

‎src/backend/nodes/nodeFuncs.c

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3254,7 +3254,7 @@ expression_tree_mutator(Node *node,
32543254

32553255
FLATCOPY(newnode,jve,JsonCtorExpr);
32563256
MUTATE(newnode->args,jve->args,List*);
3257-
MUTATE(newnode->func,jve->func,FuncExpr*);
3257+
MUTATE(newnode->func,jve->func,Expr*);
32583258
MUTATE(newnode->returning,jve->returning,JsonReturning*);
32593259

32603260
return (Node*)newnode;
@@ -4020,6 +4020,38 @@ raw_expression_tree_walker(Node *node,
40204020
return true;
40214021
}
40224022
break;
4023+
caseT_JsonObjectAgg:
4024+
{
4025+
JsonObjectAgg*joa= (JsonObjectAgg*)node;
4026+
4027+
if (walker(joa->ctor.output,context))
4028+
return true;
4029+
if (walker(joa->ctor.agg_order,context))
4030+
return true;
4031+
if (walker(joa->ctor.agg_filter,context))
4032+
return true;
4033+
if (walker(joa->ctor.over,context))
4034+
return true;
4035+
if (walker(joa->arg,context))
4036+
return true;
4037+
}
4038+
break;
4039+
caseT_JsonArrayAgg:
4040+
{
4041+
JsonArrayAgg*jaa= (JsonArrayAgg*)node;
4042+
4043+
if (walker(jaa->ctor.output,context))
4044+
return true;
4045+
if (walker(jaa->ctor.agg_order,context))
4046+
return true;
4047+
if (walker(jaa->ctor.agg_filter,context))
4048+
return true;
4049+
if (walker(jaa->ctor.over,context))
4050+
return true;
4051+
if (walker(jaa->arg,context))
4052+
return true;
4053+
}
4054+
break;
40234055
default:
40244056
elog(ERROR,"unrecognized node type: %d",
40254057
(int)nodeTag(node));

‎src/backend/parser/parse_expr.c

Lines changed: 177 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515

1616
#include"postgres.h"
1717

18+
#include"catalog/pg_aggregate.h"
19+
#include"catalog/pg_proc.h"
1820
#include"catalog/pg_type.h"
1921
#include"commands/dbcommands.h"
2022
#include"miscadmin.h"
@@ -123,6 +125,8 @@ static Node *transformTypeCast(ParseState *pstate, TypeCast *tc);
123125
staticNode*transformCollateClause(ParseState*pstate,CollateClause*c);
124126
staticNode*transformJsonObjectCtor(ParseState*pstate,JsonObjectCtor*ctor);
125127
staticNode*transformJsonArrayCtor(ParseState*pstate,JsonArrayCtor*ctor);
128+
staticNode*transformJsonObjectAgg(ParseState*pstate,JsonObjectAgg*agg);
129+
staticNode*transformJsonArrayAgg(ParseState*pstate,JsonArrayAgg*agg);
126130
staticNode*make_row_comparison_op(ParseState*pstate,List*opname,
127131
List*largs,List*rargs,intlocation);
128132
staticNode*make_row_distinct_op(ParseState*pstate,List*opname,
@@ -379,6 +383,14 @@ transformExprRecurse(ParseState *pstate, Node *expr)
379383
result=transformJsonArrayCtor(pstate, (JsonArrayCtor*)expr);
380384
break;
381385

386+
caseT_JsonObjectAgg:
387+
result=transformJsonObjectAgg(pstate, (JsonObjectAgg*)expr);
388+
break;
389+
390+
caseT_JsonArrayAgg:
391+
result=transformJsonArrayAgg(pstate, (JsonArrayAgg*)expr);
392+
break;
393+
382394
default:
383395
/* should not reach here */
384396
elog(ERROR,"unrecognized node type: %d", (int)nodeTag(expr));
@@ -3991,7 +4003,6 @@ transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor)
39914003

39924004
jsctor=makeNode(JsonCtorExpr);
39934005
jsctor->args=args;
3994-
jsctor->func=NULL;
39954006
jsctor->type=JSCTOR_JSON_OBJECT;
39964007
jsctor->returning=transformJsonCtorOutput(pstate,ctor->output,args);
39974008
jsctor->unique=ctor->unique;
@@ -4001,6 +4012,171 @@ transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor)
40014012
returncoerceJsonFuncExpr(pstate, (Node*)jsctor,jsctor->returning, true);
40024013
}
40034014

4015+
/*
4016+
* Common code for JSON_OBJECTAGG and JSON_ARRAYAGG transformation.
4017+
*/
4018+
staticNode*
4019+
transformJsonAggCtor(ParseState*pstate,JsonAggCtor*agg_ctor,
4020+
JsonReturning*returning,List*args,constchar*aggfn,
4021+
Oidaggtype,JsonCtorTypector_type,
4022+
boolunique,boolabsent_on_null)
4023+
{
4024+
Oidaggfnoid;
4025+
JsonCtorExpr*jsctor;
4026+
Node*node;
4027+
Expr*aggfilter=agg_ctor->agg_filter ? (Expr*)
4028+
transformWhereClause(pstate,agg_ctor->agg_filter,
4029+
EXPR_KIND_FILTER,"FILTER") :NULL;
4030+
4031+
aggfnoid=DatumGetInt32(DirectFunctionCall1(regprocin,
4032+
CStringGetDatum(aggfn)));
4033+
4034+
if (agg_ctor->over)
4035+
{
4036+
/* window function */
4037+
WindowFunc*wfunc=makeNode(WindowFunc);
4038+
4039+
wfunc->winfnoid=aggfnoid;
4040+
wfunc->wintype=aggtype;
4041+
/* wincollid and inputcollid will be set by parse_collate.c */
4042+
wfunc->args=args;
4043+
/* winref will be set by transformWindowFuncCall */
4044+
wfunc->winstar= false;
4045+
wfunc->winagg= true;
4046+
wfunc->aggfilter=aggfilter;
4047+
wfunc->location=agg_ctor->location;
4048+
4049+
/*
4050+
* ordered aggs not allowed in windows yet
4051+
*/
4052+
if (agg_ctor->agg_order!=NIL)
4053+
ereport(ERROR,
4054+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
4055+
errmsg("aggregate ORDER BY is not implemented for window functions"),
4056+
parser_errposition(pstate,agg_ctor->location)));
4057+
4058+
/* parse_agg.c does additional window-func-specific processing */
4059+
transformWindowFuncCall(pstate,wfunc,agg_ctor->over);
4060+
4061+
node= (Node*)wfunc;
4062+
}
4063+
else
4064+
{
4065+
Aggref*aggref=makeNode(Aggref);
4066+
4067+
aggref->aggfnoid=aggfnoid;
4068+
aggref->aggtype=aggtype;
4069+
4070+
/* aggcollid and inputcollid will be set by parse_collate.c */
4071+
aggref->aggtranstype=InvalidOid;/* will be set by planner */
4072+
/* aggargtypes will be set by transformAggregateCall */
4073+
/* aggdirectargs and args will be set by transformAggregateCall */
4074+
/* aggorder and aggdistinct will be set by transformAggregateCall */
4075+
aggref->aggfilter=aggfilter;
4076+
aggref->aggstar= false;
4077+
aggref->aggvariadic= false;
4078+
aggref->aggkind=AGGKIND_NORMAL;
4079+
/* agglevelsup will be set by transformAggregateCall */
4080+
aggref->aggsplit=AGGSPLIT_SIMPLE;/* planner might change this */
4081+
aggref->location=agg_ctor->location;
4082+
4083+
transformAggregateCall(pstate,aggref,args,agg_ctor->agg_order, false);
4084+
4085+
node= (Node*)aggref;
4086+
}
4087+
4088+
jsctor=makeNode(JsonCtorExpr);
4089+
jsctor->func= (Expr*)node;
4090+
jsctor->type=ctor_type;
4091+
jsctor->returning=*returning;
4092+
jsctor->unique=unique;
4093+
jsctor->absent_on_null=absent_on_null;
4094+
jsctor->location=agg_ctor->location;
4095+
4096+
returncoerceJsonFuncExpr(pstate, (Node*)jsctor,returning, true);
4097+
}
4098+
4099+
/*
4100+
* Transform JSON_OBJECTAGG() aggregate function.
4101+
*
4102+
* JSON_OBJECTAGG() is transformed into
4103+
* json[b]_objectagg(key, value, absent_on_null, check_unique) call depending on
4104+
* the output JSON format. Then the function call result is coerced to the
4105+
* target output type.
4106+
*/
4107+
staticNode*
4108+
transformJsonObjectAgg(ParseState*pstate,JsonObjectAgg*agg)
4109+
{
4110+
JsonReturningreturning;
4111+
Node*key;
4112+
Node*val;
4113+
List*args;
4114+
constchar*aggfnname;
4115+
Oidaggtype;
4116+
4117+
transformJsonOutput(pstate,agg->ctor.output, true,&returning);
4118+
4119+
key=transformExprRecurse(pstate, (Node*)agg->arg->key);
4120+
val=transformJsonValueExpr(pstate,agg->arg->value,JS_FORMAT_DEFAULT);
4121+
4122+
args=list_make4(key,
4123+
val,
4124+
makeBoolConst(agg->absent_on_null, false),
4125+
makeBoolConst(agg->unique, false));
4126+
4127+
if (returning.format.type==JS_FORMAT_JSONB)
4128+
{
4129+
aggfnname="pg_catalog.jsonb_objectagg";/* F_JSONB_OBJECTAGG */
4130+
aggtype=JSONBOID;
4131+
}
4132+
else
4133+
{
4134+
aggfnname="pg_catalog.json_objectagg";/* F_JSON_OBJECTAGG; */
4135+
aggtype=JSONOID;
4136+
}
4137+
4138+
returntransformJsonAggCtor(pstate,&agg->ctor,&returning,args,aggfnname,
4139+
aggtype,JSCTOR_JSON_OBJECTAGG,
4140+
agg->unique,agg->absent_on_null);
4141+
}
4142+
4143+
/*
4144+
* Transform JSON_ARRAYAGG() aggregate function.
4145+
*
4146+
* JSON_ARRAYAGG() is transformed into json[b]_agg[_strict]() call depending
4147+
* on the output JSON format and absent_on_null. Then the function call result
4148+
* is coerced to the target output type.
4149+
*/
4150+
staticNode*
4151+
transformJsonArrayAgg(ParseState*pstate,JsonArrayAgg*agg)
4152+
{
4153+
JsonReturningreturning;
4154+
Node*arg;
4155+
constchar*aggfnname;
4156+
Oidaggtype;
4157+
4158+
transformJsonOutput(pstate,agg->ctor.output, true,&returning);
4159+
4160+
arg=transformJsonValueExpr(pstate,agg->arg,JS_FORMAT_DEFAULT);
4161+
4162+
if (returning.format.type==JS_FORMAT_JSONB)
4163+
{
4164+
aggfnname=agg->absent_on_null ?
4165+
"pg_catalog.jsonb_agg_strict" :"pg_catalog.jsonb_agg";
4166+
aggtype=JSONBOID;
4167+
}
4168+
else
4169+
{
4170+
aggfnname=agg->absent_on_null ?
4171+
"pg_catalog.json_agg_strict" :"pg_catalog.json_agg";
4172+
aggtype=JSONOID;
4173+
}
4174+
4175+
returntransformJsonAggCtor(pstate,&agg->ctor,&returning,list_make1(arg),
4176+
aggfnname,aggtype,JSCTOR_JSON_ARRAYAGG,
4177+
false,agg->absent_on_null);
4178+
}
4179+
40044180
/*
40054181
* Transform JSON_ARRAY() constructor.
40064182
*

‎src/backend/parser/parse_target.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,6 +1937,12 @@ FigureColnameInternal(Node *node, char **name)
19371937
caseT_JsonArrayCtor:
19381938
*name="json_array";
19391939
return2;
1940+
caseT_JsonObjectAgg:
1941+
*name="json_objectagg";
1942+
return2;
1943+
caseT_JsonArrayAgg:
1944+
*name="json_arrayagg";
1945+
return2;
19401946
default:
19411947
break;
19421948
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp