Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 63b1af9

Browse files
committed
Cleanup some aggregate code in the executor
Here we alter the code that calls build_pertrans_for_aggref() so that the function no longer needs to special-case whether it's dealing with an aggtransfn or an aggcombinefn. This allows us to reuse the build_aggregate_transfn_expr() function and just get rid of the build_aggregate_combinefn_expr() completely. All of the special case code that was in build_pertrans_for_aggref() has been moved up to the calling functions. This saves about a dozen lines of code in nodeAgg.c and a few dozen more in parse_agg.c Also, rename a few variables in nodeAgg.c to try to make it more clear that we're working with either a aggtransfn or an aggcombinefn. Some of the old names would have you believe that we were always working with an aggtransfn. Discussion: https://postgr.es/m/CAApHDvptMQ9FmF0D67zC_w88yVnoNVR2+kkOQGUrCmdxWxLULQ@mail.gmail.com
1 parent 7922595 commit 63b1af9

File tree

3 files changed

+118
-155
lines changed

3 files changed

+118
-155
lines changed

src/backend/executor/nodeAgg.c

Lines changed: 113 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -461,10 +461,11 @@ static void hashagg_tapeinfo_release(HashTapeInfo *tapeinfo, int tapenum);
461461
static Datum GetAggInitVal(Datum textInitVal, Oid transtype);
462462
static void build_pertrans_for_aggref(AggStatePerTrans pertrans,
463463
AggState *aggstate, EState *estate,
464-
Aggref *aggref, Oid aggtransfn, Oid aggtranstype,
465-
Oid aggserialfn, Oid aggdeserialfn,
466-
Datum initValue, bool initValueIsNull,
467-
Oid *inputTypes, int numArguments);
464+
Aggref *aggref, Oid transfn_oid,
465+
Oid aggtranstype, Oid aggserialfn,
466+
Oid aggdeserialfn, Datum initValue,
467+
bool initValueIsNull, Oid *inputTypes,
468+
int numArguments);
468469

469470

470471
/*
@@ -3724,8 +3725,8 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
37243725
Aggref *aggref = lfirst(l);
37253726
AggStatePerAgg peragg;
37263727
AggStatePerTrans pertrans;
3727-
Oid inputTypes[FUNC_MAX_ARGS];
3728-
int numArguments;
3728+
Oid aggTransFnInputTypes[FUNC_MAX_ARGS];
3729+
int numAggTransFnArgs;
37293730
int numDirectArgs;
37303731
HeapTuple aggTuple;
37313732
Form_pg_aggregate aggform;
@@ -3859,14 +3860,15 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
38593860
* could be different from the agg's declared input types, when the
38603861
* agg accepts ANY or a polymorphic type.
38613862
*/
3862-
numArguments = get_aggregate_argtypes(aggref, inputTypes);
3863+
numAggTransFnArgs = get_aggregate_argtypes(aggref,
3864+
aggTransFnInputTypes);
38633865

38643866
/* Count the "direct" arguments, if any */
38653867
numDirectArgs = list_length(aggref->aggdirectargs);
38663868

38673869
/* Detect how many arguments to pass to the finalfn */
38683870
if (aggform->aggfinalextra)
3869-
peragg->numFinalArgs = numArguments + 1;
3871+
peragg->numFinalArgs = numAggTransFnArgs + 1;
38703872
else
38713873
peragg->numFinalArgs = numDirectArgs + 1;
38723874

@@ -3880,7 +3882,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
38803882
*/
38813883
if (OidIsValid(finalfn_oid))
38823884
{
3883-
build_aggregate_finalfn_expr(inputTypes,
3885+
build_aggregate_finalfn_expr(aggTransFnInputTypes,
38843886
peragg->numFinalArgs,
38853887
aggtranstype,
38863888
aggref->aggtype,
@@ -3911,7 +3913,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
39113913
/*
39123914
* If this aggregation is performing state combines, then instead
39133915
* of using the transition function, we'll use the combine
3914-
* function
3916+
* function.
39153917
*/
39163918
if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
39173919
{
@@ -3924,8 +3926,7 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
39243926
else
39253927
transfn_oid = aggform->aggtransfn;
39263928

3927-
aclresult = pg_proc_aclcheck(transfn_oid, aggOwner,
3928-
ACL_EXECUTE);
3929+
aclresult = pg_proc_aclcheck(transfn_oid, aggOwner, ACL_EXECUTE);
39293930
if (aclresult != ACLCHECK_OK)
39303931
aclcheck_error(aclresult, OBJECT_FUNCTION,
39313932
get_func_name(transfn_oid));
@@ -3943,11 +3944,72 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
39433944
else
39443945
initValue = GetAggInitVal(textInitVal, aggtranstype);
39453946

3946-
build_pertrans_for_aggref(pertrans, aggstate, estate,
3947-
aggref, transfn_oid, aggtranstype,
3948-
serialfn_oid, deserialfn_oid,
3949-
initValue, initValueIsNull,
3950-
inputTypes, numArguments);
3947+
if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
3948+
{
3949+
Oid combineFnInputTypes[] = {aggtranstype,
3950+
aggtranstype};
3951+
3952+
/*
3953+
* When combining there's only one input, the to-be-combined
3954+
* transition value. The transition value is not counted
3955+
* here.
3956+
*/
3957+
pertrans->numTransInputs = 1;
3958+
3959+
/* aggcombinefn always has two arguments of aggtranstype */
3960+
build_pertrans_for_aggref(pertrans, aggstate, estate,
3961+
aggref, transfn_oid, aggtranstype,
3962+
serialfn_oid, deserialfn_oid,
3963+
initValue, initValueIsNull,
3964+
combineFnInputTypes, 2);
3965+
3966+
/*
3967+
* Ensure that a combine function to combine INTERNAL states
3968+
* is not strict. This should have been checked during CREATE
3969+
* AGGREGATE, but the strict property could have been changed
3970+
* since then.
3971+
*/
3972+
if (pertrans->transfn.fn_strict && aggtranstype == INTERNALOID)
3973+
ereport(ERROR,
3974+
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
3975+
errmsg("combine function with transition type %s must not be declared STRICT",
3976+
format_type_be(aggtranstype))));
3977+
}
3978+
else
3979+
{
3980+
/* Detect how many arguments to pass to the transfn */
3981+
if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
3982+
pertrans->numTransInputs = list_length(aggref->args);
3983+
else
3984+
pertrans->numTransInputs = numAggTransFnArgs;
3985+
3986+
build_pertrans_for_aggref(pertrans, aggstate, estate,
3987+
aggref, transfn_oid, aggtranstype,
3988+
serialfn_oid, deserialfn_oid,
3989+
initValue, initValueIsNull,
3990+
aggTransFnInputTypes,
3991+
numAggTransFnArgs);
3992+
3993+
/*
3994+
* If the transfn is strict and the initval is NULL, make sure
3995+
* input type and transtype are the same (or at least
3996+
* binary-compatible), so that it's OK to use the first
3997+
* aggregated input value as the initial transValue. This
3998+
* should have been checked at agg definition time, but we
3999+
* must check again in case the transfn's strictness property
4000+
* has been changed.
4001+
*/
4002+
if (pertrans->transfn.fn_strict && pertrans->initValueIsNull)
4003+
{
4004+
if (numAggTransFnArgs <= numDirectArgs ||
4005+
!IsBinaryCoercible(aggTransFnInputTypes[numDirectArgs],
4006+
aggtranstype))
4007+
ereport(ERROR,
4008+
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
4009+
errmsg("aggregate %u needs to have compatible input type and transition type",
4010+
aggref->aggfnoid)));
4011+
}
4012+
}
39514013
}
39524014
else
39534015
pertrans->aggshared = true;
@@ -4039,20 +4101,24 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
40394101
* Build the state needed to calculate a state value for an aggregate.
40404102
*
40414103
* This initializes all the fields in 'pertrans'. 'aggref' is the aggregate
4042-
* to initialize the state for. 'aggtransfn', 'aggtranstype', and the rest
4104+
* to initialize the state for. 'transfn_oid', 'aggtranstype', and the rest
40434105
* of the arguments could be calculated from 'aggref', but the caller has
40444106
* calculated them already, so might as well pass them.
4107+
*
4108+
* 'transfn_oid' may be either the Oid of the aggtransfn or the aggcombinefn.
40454109
*/
40464110
static void
40474111
build_pertrans_for_aggref(AggStatePerTrans pertrans,
40484112
AggState *aggstate, EState *estate,
40494113
Aggref *aggref,
4050-
Oid aggtransfn, Oid aggtranstype,
4114+
Oid transfn_oid, Oid aggtranstype,
40514115
Oid aggserialfn, Oid aggdeserialfn,
40524116
Datum initValue, bool initValueIsNull,
40534117
Oid *inputTypes, int numArguments)
40544118
{
40554119
int numGroupingSets = Max(aggstate->maxsets, 1);
4120+
Expr *transfnexpr;
4121+
int numTransArgs;
40564122
Expr *serialfnexpr = NULL;
40574123
Expr *deserialfnexpr = NULL;
40584124
ListCell *lc;
@@ -4067,7 +4133,7 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
40674133
pertrans->aggref = aggref;
40684134
pertrans->aggshared = false;
40694135
pertrans->aggCollation = aggref->inputcollid;
4070-
pertrans->transfn_oid = aggtransfn;
4136+
pertrans->transfn_oid = transfn_oid;
40714137
pertrans->serialfn_oid = aggserialfn;
40724138
pertrans->deserialfn_oid = aggdeserialfn;
40734139
pertrans->initValue = initValue;
@@ -4081,111 +4147,34 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
40814147

40824148
pertrans->aggtranstype = aggtranstype;
40834149

4150+
/* account for the current transition state */
4151+
numTransArgs = pertrans->numTransInputs + 1;
4152+
40844153
/*
4085-
* When combining states, we have no use at all for the aggregate
4086-
* function's transfn. Instead we use the combinefn. In this case, the
4087-
* transfn and transfn_oid fields of pertrans refer to the combine
4088-
* function rather than the transition function.
4154+
* Set up infrastructure for calling the transfn. Note that invtrans is
4155+
* not needed here.
40894156
*/
4090-
if (DO_AGGSPLIT_COMBINE(aggstate->aggsplit))
4091-
{
4092-
Expr *combinefnexpr;
4093-
size_t numTransArgs;
4094-
4095-
/*
4096-
* When combining there's only one input, the to-be-combined added
4097-
* transition value from below (this node's transition value is
4098-
* counted separately).
4099-
*/
4100-
pertrans->numTransInputs = 1;
4101-
4102-
/* account for the current transition state */
4103-
numTransArgs = pertrans->numTransInputs + 1;
4104-
4105-
build_aggregate_combinefn_expr(aggtranstype,
4106-
aggref->inputcollid,
4107-
aggtransfn,
4108-
&combinefnexpr);
4109-
fmgr_info(aggtransfn, &pertrans->transfn);
4110-
fmgr_info_set_expr((Node *) combinefnexpr, &pertrans->transfn);
4111-
4112-
pertrans->transfn_fcinfo =
4113-
(FunctionCallInfo) palloc(SizeForFunctionCallInfo(2));
4114-
InitFunctionCallInfoData(*pertrans->transfn_fcinfo,
4115-
&pertrans->transfn,
4116-
numTransArgs,
4117-
pertrans->aggCollation,
4118-
(void *) aggstate, NULL);
4119-
4120-
/*
4121-
* Ensure that a combine function to combine INTERNAL states is not
4122-
* strict. This should have been checked during CREATE AGGREGATE, but
4123-
* the strict property could have been changed since then.
4124-
*/
4125-
if (pertrans->transfn.fn_strict && aggtranstype == INTERNALOID)
4126-
ereport(ERROR,
4127-
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
4128-
errmsg("combine function with transition type %s must not be declared STRICT",
4129-
format_type_be(aggtranstype))));
4130-
}
4131-
else
4132-
{
4133-
Expr *transfnexpr;
4134-
size_t numTransArgs;
4135-
4136-
/* Detect how many arguments to pass to the transfn */
4137-
if (AGGKIND_IS_ORDERED_SET(aggref->aggkind))
4138-
pertrans->numTransInputs = numInputs;
4139-
else
4140-
pertrans->numTransInputs = numArguments;
4157+
build_aggregate_transfn_expr(inputTypes,
4158+
numArguments,
4159+
numDirectArgs,
4160+
aggref->aggvariadic,
4161+
aggtranstype,
4162+
aggref->inputcollid,
4163+
transfn_oid,
4164+
InvalidOid,
4165+
&transfnexpr,
4166+
NULL);
41414167

4142-
/* account for the current transition state */
4143-
numTransArgs = pertrans->numTransInputs + 1;
4168+
fmgr_info(transfn_oid, &pertrans->transfn);
4169+
fmgr_info_set_expr((Node *) transfnexpr, &pertrans->transfn);
41444170

4145-
/*
4146-
* Set up infrastructure for calling the transfn. Note that
4147-
* invtransfn is not needed here.
4148-
*/
4149-
build_aggregate_transfn_expr(inputTypes,
4150-
numArguments,
4151-
numDirectArgs,
4152-
aggref->aggvariadic,
4153-
aggtranstype,
4154-
aggref->inputcollid,
4155-
aggtransfn,
4156-
InvalidOid,
4157-
&transfnexpr,
4158-
NULL);
4159-
fmgr_info(aggtransfn, &pertrans->transfn);
4160-
fmgr_info_set_expr((Node *) transfnexpr, &pertrans->transfn);
4161-
4162-
pertrans->transfn_fcinfo =
4163-
(FunctionCallInfo) palloc(SizeForFunctionCallInfo(numTransArgs));
4164-
InitFunctionCallInfoData(*pertrans->transfn_fcinfo,
4165-
&pertrans->transfn,
4166-
numTransArgs,
4167-
pertrans->aggCollation,
4168-
(void *) aggstate, NULL);
4169-
4170-
/*
4171-
* If the transfn is strict and the initval is NULL, make sure input
4172-
* type and transtype are the same (or at least binary-compatible), so
4173-
* that it's OK to use the first aggregated input value as the initial
4174-
* transValue. This should have been checked at agg definition time,
4175-
* but we must check again in case the transfn's strictness property
4176-
* has been changed.
4177-
*/
4178-
if (pertrans->transfn.fn_strict && pertrans->initValueIsNull)
4179-
{
4180-
if (numArguments <= numDirectArgs ||
4181-
!IsBinaryCoercible(inputTypes[numDirectArgs],
4182-
aggtranstype))
4183-
ereport(ERROR,
4184-
(errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),
4185-
errmsg("aggregate %u needs to have compatible input type and transition type",
4186-
aggref->aggfnoid)));
4187-
}
4188-
}
4171+
pertrans->transfn_fcinfo =
4172+
(FunctionCallInfo) palloc(SizeForFunctionCallInfo(numTransArgs));
4173+
InitFunctionCallInfoData(*pertrans->transfn_fcinfo,
4174+
&pertrans->transfn,
4175+
numTransArgs,
4176+
pertrans->aggCollation,
4177+
(void *) aggstate, NULL);
41894178

41904179
/* get info about the state value's datatype */
41914180
get_typlenbyval(aggtranstype,
@@ -4276,6 +4265,9 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
42764265
*/
42774266
Assert(aggstate->aggstrategy != AGG_HASHED && aggstate->aggstrategy != AGG_MIXED);
42784267

4268+
/* ORDER BY aggregates are not supported with partial aggregation */
4269+
Assert(!DO_AGGSPLIT_COMBINE(aggstate->aggsplit));
4270+
42794271
/* If we have only one input, we need its len/byval info. */
42804272
if (numInputs == 1)
42814273
{

src/backend/parser/parse_agg.c

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1959,6 +1959,11 @@ resolve_aggregate_transtype(Oid aggfuncid,
19591959
* latter may be InvalidOid, however if invtransfn_oid is set then
19601960
* transfn_oid must also be set.
19611961
*
1962+
* transfn_oid may also be passed as the aggcombinefn when the *transfnexpr is
1963+
* to be used for a combine aggregate phase. We expect invtransfn_oid to be
1964+
* InvalidOid in this case since there is no such thing as an inverse
1965+
* combinefn.
1966+
*
19621967
* Pointers to the constructed trees are returned into *transfnexpr,
19631968
* *invtransfnexpr. If there is no invtransfn, the respective pointer is set
19641969
* to NULL. Since use of the invtransfn is optional, NULL may be passed for
@@ -2021,35 +2026,6 @@ build_aggregate_transfn_expr(Oid *agg_input_types,
20212026
}
20222027
}
20232028

2024-
/*
2025-
* Like build_aggregate_transfn_expr, but creates an expression tree for the
2026-
* combine function of an aggregate, rather than the transition function.
2027-
*/
2028-
void
2029-
build_aggregate_combinefn_expr(Oid agg_state_type,
2030-
Oid agg_input_collation,
2031-
Oid combinefn_oid,
2032-
Expr **combinefnexpr)
2033-
{
2034-
Node *argp;
2035-
List *args;
2036-
FuncExpr *fexpr;
2037-
2038-
/* combinefn takes two arguments of the aggregate state type */
2039-
argp = make_agg_arg(agg_state_type, agg_input_collation);
2040-
2041-
args = list_make2(argp, argp);
2042-
2043-
fexpr = makeFuncExpr(combinefn_oid,
2044-
agg_state_type,
2045-
args,
2046-
InvalidOid,
2047-
agg_input_collation,
2048-
COERCE_EXPLICIT_CALL);
2049-
/* combinefn is currently never treated as variadic */
2050-
*combinefnexpr = (Expr *) fexpr;
2051-
}
2052-
20532029
/*
20542030
* Like build_aggregate_transfn_expr, but creates an expression tree for the
20552031
* serialization function of an aggregate.

src/include/parser/parse_agg.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,6 @@ extern void build_aggregate_transfn_expr(Oid *agg_input_types,
4646
Expr **transfnexpr,
4747
Expr **invtransfnexpr);
4848

49-
extern void build_aggregate_combinefn_expr(Oid agg_state_type,
50-
Oid agg_input_collation,
51-
Oid combinefn_oid,
52-
Expr **combinefnexpr);
53-
5449
extern void build_aggregate_serialfn_expr(Oid serialfn_oid,
5550
Expr **serialfnexpr);
5651

0 commit comments

Comments
 (0)