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);
123125static Node * transformCollateClause (ParseState * pstate , CollateClause * c );
124126static Node * transformJsonObjectCtor (ParseState * pstate , JsonObjectCtor * ctor );
125127static Node * transformJsonArrayCtor (ParseState * pstate , JsonArrayCtor * ctor );
128+ static Node * transformJsonObjectAgg (ParseState * pstate , JsonObjectAgg * agg );
129+ static Node * transformJsonArrayAgg (ParseState * pstate , JsonArrayAgg * agg );
126130static Node * make_row_comparison_op (ParseState * pstate , List * opname ,
127131 List * largs , List * rargs , int location );
128132static Node * 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+ case T_JsonObjectAgg :
387+ result = transformJsonObjectAgg (pstate , (JsonObjectAgg * ) expr );
388+ break ;
389+
390+ case T_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 return coerceJsonFuncExpr (pstate , (Node * ) jsctor , jsctor -> returning , true);
40024013}
40034014
4015+ /*
4016+ * Common code for JSON_OBJECTAGG and JSON_ARRAYAGG transformation.
4017+ */
4018+ static Node *
4019+ transformJsonAggCtor (ParseState * pstate , JsonAggCtor * agg_ctor ,
4020+ JsonReturning * returning , List * args , const char * aggfn ,
4021+ Oid aggtype , JsonCtorType ctor_type ,
4022+ bool unique , bool absent_on_null )
4023+ {
4024+ Oid aggfnoid ;
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+ return coerceJsonFuncExpr (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+ static Node *
4108+ transformJsonObjectAgg (ParseState * pstate , JsonObjectAgg * agg )
4109+ {
4110+ JsonReturning returning ;
4111+ Node * key ;
4112+ Node * val ;
4113+ List * args ;
4114+ const char * aggfnname ;
4115+ Oid aggtype ;
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+ return transformJsonAggCtor (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+ static Node *
4151+ transformJsonArrayAgg (ParseState * pstate , JsonArrayAgg * agg )
4152+ {
4153+ JsonReturning returning ;
4154+ Node * arg ;
4155+ const char * aggfnname ;
4156+ Oid aggtype ;
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+ return transformJsonAggCtor (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 *
0 commit comments