diff options
Diffstat (limited to 'src/backend/executor/nodeWindowAgg.c')
-rw-r--r-- | src/backend/executor/nodeWindowAgg.c | 33 |
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); |