aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeWindowAgg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/nodeWindowAgg.c')
-rw-r--r--src/backend/executor/nodeWindowAgg.c33
1 files changed, 30 insertions, 3 deletions
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 2fcc630a925..40a925331c9 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -116,6 +116,8 @@ typedef struct WindowStatePerAggData
FmgrInfo invtransfn;
FmgrInfo finalfn;
+ int numFinalArgs; /* number of arguments to pass to finalfn */
+
/*
* initial value from pg_aggregate entry
*/
@@ -557,14 +559,28 @@ finalize_windowaggregate(WindowAggState *winstate,
*/
if (OidIsValid(peraggstate->finalfn_oid))
{
+ int numFinalArgs = peraggstate->numFinalArgs;
FunctionCallInfoData fcinfo;
+ bool anynull;
+ int i;
- InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn), 1,
+ InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn),
+ numFinalArgs,
perfuncstate->winCollation,
(void *) winstate, NULL);
fcinfo.arg[0] = peraggstate->transValue;
fcinfo.argnull[0] = peraggstate->transValueIsNull;
- if (fcinfo.flinfo->fn_strict && peraggstate->transValueIsNull)
+ anynull = peraggstate->transValueIsNull;
+
+ /* Fill any remaining argument positions with nulls */
+ for (i = 1; i < numFinalArgs; i++)
+ {
+ fcinfo.arg[i] = (Datum) 0;
+ fcinfo.argnull[i] = true;
+ anynull = true;
+ }
+
+ if (fcinfo.flinfo->fn_strict && anynull)
{
/* don't call a strict function with NULL inputs */
*result = (Datum) 0;
@@ -2089,6 +2105,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
Oid transfn_oid,
invtransfn_oid,
finalfn_oid;
+ bool finalextra;
Expr *transfnexpr,
*invtransfnexpr,
*finalfnexpr;
@@ -2127,6 +2144,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
peraggstate->transfn_oid = transfn_oid = aggform->aggmtransfn;
peraggstate->invtransfn_oid = invtransfn_oid = aggform->aggminvtransfn;
peraggstate->finalfn_oid = finalfn_oid = aggform->aggmfinalfn;
+ finalextra = aggform->aggmfinalextra;
aggtranstype = aggform->aggmtranstype;
initvalAttNo = Anum_pg_aggregate_aggminitval;
}
@@ -2135,6 +2153,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
peraggstate->transfn_oid = transfn_oid = aggform->aggtransfn;
peraggstate->invtransfn_oid = invtransfn_oid = InvalidOid;
peraggstate->finalfn_oid = finalfn_oid = aggform->aggfinalfn;
+ finalextra = aggform->aggfinalextra;
aggtranstype = aggform->aggtranstype;
initvalAttNo = Anum_pg_aggregate_agginitval;
}
@@ -2185,6 +2204,12 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
}
}
+ /* Detect how many arguments to pass to the finalfn */
+ if (finalextra)
+ peraggstate->numFinalArgs = numArguments + 1;
+ else
+ peraggstate->numFinalArgs = 1;
+
/* resolve actual type of transition state, if polymorphic */
aggtranstype = resolve_aggregate_transtype(wfunc->winfnoid,
aggtranstype,
@@ -2195,7 +2220,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
build_aggregate_fnexprs(inputTypes,
numArguments,
0, /* no ordered-set window functions yet */
- false,
+ peraggstate->numFinalArgs,
false, /* no variadic window functions yet */
aggtranstype,
wfunc->wintype,
@@ -2207,6 +2232,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
&invtransfnexpr,
&finalfnexpr);
+ /* set up infrastructure for calling the transfn(s) and finalfn */
fmgr_info(transfn_oid, &peraggstate->transfn);
fmgr_info_set_expr((Node *) transfnexpr, &peraggstate->transfn);
@@ -2222,6 +2248,7 @@ initialize_peragg(WindowAggState *winstate, WindowFunc *wfunc,
fmgr_info_set_expr((Node *) finalfnexpr, &peraggstate->finalfn);
}
+ /* get info about relevant datatypes */
get_typlenbyval(wfunc->wintype,
&peraggstate->resulttypeLen,
&peraggstate->resulttypeByVal);