15
15
16
16
#include "postgres.h"
17
17
18
+ #include "catalog/pg_aggregate.h"
19
+ #include "catalog/pg_proc.h"
18
20
#include "catalog/pg_type.h"
19
21
#include "commands/dbcommands.h"
20
22
#include "miscadmin.h"
@@ -123,6 +125,8 @@ static Node *transformTypeCast(ParseState *pstate, TypeCast *tc);
123
125
static Node * transformCollateClause (ParseState * pstate , CollateClause * c );
124
126
static Node * transformJsonObjectCtor (ParseState * pstate , JsonObjectCtor * ctor );
125
127
static Node * transformJsonArrayCtor (ParseState * pstate , JsonArrayCtor * ctor );
128
+ static Node * transformJsonObjectAgg (ParseState * pstate , JsonObjectAgg * agg );
129
+ static Node * transformJsonArrayAgg (ParseState * pstate , JsonArrayAgg * agg );
126
130
static Node * make_row_comparison_op (ParseState * pstate , List * opname ,
127
131
List * largs , List * rargs , int location );
128
132
static Node * make_row_distinct_op (ParseState * pstate , List * opname ,
@@ -379,6 +383,14 @@ transformExprRecurse(ParseState *pstate, Node *expr)
379
383
result = transformJsonArrayCtor (pstate , (JsonArrayCtor * ) expr );
380
384
break ;
381
385
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
+
382
394
default :
383
395
/* should not reach here */
384
396
elog (ERROR , "unrecognized node type: %d" , (int ) nodeTag (expr ));
@@ -3991,7 +4003,6 @@ transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor)
3991
4003
3992
4004
jsctor = makeNode (JsonCtorExpr );
3993
4005
jsctor -> args = args ;
3994
- jsctor -> func = NULL ;
3995
4006
jsctor -> type = JSCTOR_JSON_OBJECT ;
3996
4007
jsctor -> returning = transformJsonCtorOutput (pstate , ctor -> output , args );
3997
4008
jsctor -> unique = ctor -> unique ;
@@ -4001,6 +4012,171 @@ transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor)
4001
4012
return coerceJsonFuncExpr (pstate , (Node * ) jsctor , jsctor -> returning , true);
4002
4013
}
4003
4014
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
+
4004
4180
/*
4005
4181
* Transform JSON_ARRAY() constructor.
4006
4182
*
0 commit comments