diff options
Diffstat (limited to 'src/backend/executor/nodeAgg.c')
-rw-r--r-- | src/backend/executor/nodeAgg.c | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c index 2fc606cf29d..96d200e4461 100644 --- a/src/backend/executor/nodeAgg.c +++ b/src/backend/executor/nodeAgg.c @@ -583,7 +583,7 @@ initialize_aggregate(AggState *aggstate, AggStatePerTrans pertrans, /* * Start a fresh sort operation for each DISTINCT/ORDER BY aggregate. */ - if (pertrans->numSortCols > 0) + if (pertrans->aggsortrequired) { /* * In case of rescan, maybe there could be an uncompleted sort @@ -1309,7 +1309,7 @@ finalize_aggregates(AggState *aggstate, pergroupstate = &pergroup[transno]; - if (pertrans->numSortCols > 0) + if (pertrans->aggsortrequired) { Assert(aggstate->aggstrategy != AGG_HASHED && aggstate->aggstrategy != AGG_MIXED); @@ -1323,6 +1323,21 @@ finalize_aggregates(AggState *aggstate, pertrans, pergroupstate); } + else if (pertrans->numDistinctCols > 0 && pertrans->haslast) + { + pertrans->haslast = false; + + if (pertrans->numDistinctCols == 1) + { + if (!pertrans->inputtypeByVal && !pertrans->lastisnull) + pfree(DatumGetPointer(pertrans->lastdatum)); + + pertrans->lastisnull = false; + pertrans->lastdatum = (Datum) 0; + } + else + ExecClearTuple(pertrans->uniqslot); + } } /* @@ -4127,6 +4142,12 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, * stick them into arrays. We ignore ORDER BY for an ordered-set agg, * however; the agg's transfn and finalfn are responsible for that. * + * When the planner has set the aggpresorted flag, the input to the + * aggregate is already correctly sorted. For ORDER BY aggregates we can + * simply treat these as normal aggregates. For presorted DISTINCT + * aggregates an extra step must be added to remove duplicate consecutive + * inputs. + * * Note that by construction, if there is a DISTINCT clause then the ORDER * BY clause is a prefix of it (see transformDistinctClause). */ @@ -4134,18 +4155,27 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans, { sortlist = NIL; numSortCols = numDistinctCols = 0; + pertrans->aggsortrequired = false; + } + else if (aggref->aggpresorted && aggref->aggdistinct == NIL) + { + sortlist = NIL; + numSortCols = numDistinctCols = 0; + pertrans->aggsortrequired = false; } else if (aggref->aggdistinct) { sortlist = aggref->aggdistinct; numSortCols = numDistinctCols = list_length(sortlist); Assert(numSortCols >= list_length(aggref->aggorder)); + pertrans->aggsortrequired = !aggref->aggpresorted; } else { sortlist = aggref->aggorder; numSortCols = list_length(sortlist); numDistinctCols = 0; + pertrans->aggsortrequired = (numSortCols > 0); } pertrans->numSortCols = numSortCols; |