|
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"
|
@@ -124,6 +126,8 @@ static Node *transformTypeCast(ParseState *pstate, TypeCast *tc);
|
124 | 126 | static Node *transformCollateClause(ParseState *pstate, CollateClause *c);
|
125 | 127 | static Node *transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor);
|
126 | 128 | static Node *transformJsonArrayCtor(ParseState *pstate, JsonArrayCtor *ctor);
|
| 129 | +static Node *transformJsonObjectAgg(ParseState *pstate, JsonObjectAgg *agg); |
| 130 | +static Node *transformJsonArrayAgg(ParseState *pstate, JsonArrayAgg *agg); |
127 | 131 | static Node *make_row_comparison_op(ParseState *pstate, List *opname,
|
128 | 132 | List *largs, List *rargs, int location);
|
129 | 133 | static Node *make_row_distinct_op(ParseState *pstate, List *opname,
|
@@ -380,6 +384,14 @@ transformExprRecurse(ParseState *pstate, Node *expr)
|
380 | 384 | result = transformJsonArrayCtor(pstate, (JsonArrayCtor *) expr);
|
381 | 385 | break;
|
382 | 386 |
|
| 387 | + case T_JsonObjectAgg: |
| 388 | + result = transformJsonObjectAgg(pstate, (JsonObjectAgg *) expr); |
| 389 | + break; |
| 390 | + |
| 391 | + case T_JsonArrayAgg: |
| 392 | + result = transformJsonArrayAgg(pstate, (JsonArrayAgg *) expr); |
| 393 | + break; |
| 394 | + |
383 | 395 | default:
|
384 | 396 | /* should not reach here */
|
385 | 397 | elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr));
|
@@ -3728,6 +3740,130 @@ transformJsonObjectCtor(ParseState *pstate, JsonObjectCtor *ctor)
|
3728 | 3740 | return coerceJsonFuncExpr(pstate, (Node *) fexpr, ctor->output);
|
3729 | 3741 | }
|
3730 | 3742 |
|
| 3743 | +static Node * |
| 3744 | +transformJsonAggCtor(ParseState *pstate, JsonAggCtor *agg_ctor, List *args, |
| 3745 | + Oid aggfnoid, Oid aggtype) |
| 3746 | +{ |
| 3747 | + Node *node; |
| 3748 | + Expr *aggfilter = agg_ctor->agg_filter ? (Expr *) |
| 3749 | + transformWhereClause(pstate, agg_ctor->agg_filter, |
| 3750 | + EXPR_KIND_FILTER, "FILTER") : NULL; |
| 3751 | + |
| 3752 | + if (agg_ctor->over) |
| 3753 | + { |
| 3754 | + /* window function */ |
| 3755 | + WindowFunc *wfunc = makeNode(WindowFunc); |
| 3756 | + |
| 3757 | + wfunc->winfnoid = aggfnoid; |
| 3758 | + wfunc->wintype = aggtype; |
| 3759 | + /* wincollid and inputcollid will be set by parse_collate.c */ |
| 3760 | + wfunc->args = args; |
| 3761 | + /* winref will be set by transformWindowFuncCall */ |
| 3762 | + wfunc->winstar = false; |
| 3763 | + wfunc->winagg = true; |
| 3764 | + wfunc->aggfilter = aggfilter; |
| 3765 | + wfunc->location = agg_ctor->location; |
| 3766 | + |
| 3767 | + /* |
| 3768 | + * ordered aggs not allowed in windows yet |
| 3769 | + */ |
| 3770 | + if (agg_ctor->agg_order != NIL) |
| 3771 | + ereport(ERROR, |
| 3772 | + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), |
| 3773 | + errmsg("aggregate ORDER BY is not implemented for window functions"), |
| 3774 | + parser_errposition(pstate, agg_ctor->location))); |
| 3775 | + |
| 3776 | + /* parse_agg.c does additional window-func-specific processing */ |
| 3777 | + transformWindowFuncCall(pstate, wfunc, agg_ctor->over); |
| 3778 | + |
| 3779 | + node = (Node *) wfunc; |
| 3780 | + } |
| 3781 | + else |
| 3782 | + { |
| 3783 | + Aggref *aggref = makeNode(Aggref); |
| 3784 | + |
| 3785 | + aggref->aggfnoid = aggfnoid; |
| 3786 | + aggref->aggtype = aggtype; |
| 3787 | + |
| 3788 | + /* aggcollid and inputcollid will be set by parse_collate.c */ |
| 3789 | + aggref->aggtranstype = InvalidOid; /* will be set by planner */ |
| 3790 | + /* aggargtypes will be set by transformAggregateCall */ |
| 3791 | + /* aggdirectargs and args will be set by transformAggregateCall */ |
| 3792 | + /* aggorder and aggdistinct will be set by transformAggregateCall */ |
| 3793 | + aggref->aggfilter = aggfilter; |
| 3794 | + aggref->aggstar = false; |
| 3795 | + aggref->aggvariadic = false; |
| 3796 | + aggref->aggkind = AGGKIND_NORMAL; |
| 3797 | + /* agglevelsup will be set by transformAggregateCall */ |
| 3798 | + aggref->aggsplit = AGGSPLIT_SIMPLE; /* planner might change this */ |
| 3799 | + aggref->location = agg_ctor->location; |
| 3800 | + |
| 3801 | + transformAggregateCall(pstate, aggref, args, agg_ctor->agg_order, false); |
| 3802 | + |
| 3803 | + node = (Node *) aggref; |
| 3804 | + } |
| 3805 | + |
| 3806 | + return coerceJsonFuncExpr(pstate, node, agg_ctor->output); |
| 3807 | +} |
| 3808 | + |
| 3809 | +static Node * |
| 3810 | +transformJsonObjectAgg(ParseState *pstate, JsonObjectAgg *agg) |
| 3811 | +{ |
| 3812 | + Node *key; |
| 3813 | + Node *val; |
| 3814 | + List *args; |
| 3815 | + Oid aggfnoid; |
| 3816 | + Oid aggtype; |
| 3817 | + |
| 3818 | + transformJsonOutput(pstate, &agg->ctor.output); |
| 3819 | + |
| 3820 | + key = transformExprRecurse(pstate, (Node *) agg->arg->key); |
| 3821 | + val = transformJsonValueExpr(pstate, agg->arg->value, JS_FORMAT_DEFAULT); |
| 3822 | + args = list_make4(key, |
| 3823 | + val, |
| 3824 | + makeBoolConst(agg->absent_on_null, false), |
| 3825 | + makeBoolConst(agg->unique, false)); |
| 3826 | + |
| 3827 | + if (agg->ctor.output->format.type == JS_FORMAT_JSONB) |
| 3828 | + { |
| 3829 | + aggfnoid = F_JSONB_OBJECTAGG; |
| 3830 | + aggtype = JSONBOID; |
| 3831 | + } |
| 3832 | + else |
| 3833 | + { |
| 3834 | + aggfnoid = F_JSON_OBJECTAGG; |
| 3835 | + aggtype = JSONOID; |
| 3836 | + } |
| 3837 | + |
| 3838 | + return transformJsonAggCtor(pstate, &agg->ctor, args, aggfnoid, aggtype); |
| 3839 | +} |
| 3840 | + |
| 3841 | +static Node * |
| 3842 | +transformJsonArrayAgg(ParseState *pstate, JsonArrayAgg *agg) |
| 3843 | +{ |
| 3844 | + Node *arg; |
| 3845 | + Oid aggfnoid; |
| 3846 | + Oid aggtype; |
| 3847 | + |
| 3848 | + transformJsonOutput(pstate, &agg->ctor.output); |
| 3849 | + |
| 3850 | + arg = transformJsonValueExpr(pstate, agg->arg, JS_FORMAT_DEFAULT); |
| 3851 | + |
| 3852 | + if (agg->ctor.output->format.type == JS_FORMAT_JSONB) |
| 3853 | + { |
| 3854 | + aggfnoid = agg->absent_on_null ? F_JSONB_AGG_STRICT : F_JSONB_AGG; |
| 3855 | + aggtype = JSONBOID; |
| 3856 | + } |
| 3857 | + else |
| 3858 | + { |
| 3859 | + aggfnoid = agg->absent_on_null ? F_JSON_AGG_STRICT : F_JSON_AGG; |
| 3860 | + aggtype = JSONOID; |
| 3861 | + } |
| 3862 | + |
| 3863 | + return transformJsonAggCtor(pstate, &agg->ctor, list_make1(arg), |
| 3864 | + aggfnoid, aggtype); |
| 3865 | +} |
| 3866 | + |
3731 | 3867 | static Node *
|
3732 | 3868 | transformJsonArrayCtor(ParseState *pstate, JsonArrayCtor *ctor)
|
3733 | 3869 | {
|
|
0 commit comments