aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeAgg.c
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2016-12-20 09:20:17 +0200
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2016-12-20 09:20:17 +0200
commitdb80acfc9d50ac56811d22802ab3d822ab313055 (patch)
treed4ef4a9e278ea7a841668342b2e0c9dc5a900c04 /src/backend/executor/nodeAgg.c
parent7cd0fd655d681e0ed5f7269fa421d977f1df0889 (diff)
downloadpostgresql-db80acfc9d50ac56811d22802ab3d822ab313055.tar.gz
postgresql-db80acfc9d50ac56811d22802ab3d822ab313055.zip
Fix sharing Agg transition state of DISTINCT or ordered aggs.
If a query contained two aggregates that could share the transition value, we would correctly collect the input into a tuplesort only once, but incorrectly run the transition function over the accumulated input twice, in finalize_aggregates(). That caused a crash, when we tried to call tuplesort_performsort() on an already-freed NULL tuplestore. Backport to 9.6, where sharing of transition state and this bug were introduced. Analysis by Tom Lane. Discussion: https://www.postgresql.org/message-id/ac5b0b69-744c-9114-6218-8300ac920e61@iki.fi
Diffstat (limited to 'src/backend/executor/nodeAgg.c')
-rw-r--r--src/backend/executor/nodeAgg.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index a093862f34b..781938e2bb4 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -1575,16 +1575,19 @@ finalize_aggregates(AggState *aggstate,
Datum *aggvalues = econtext->ecxt_aggvalues;
bool *aggnulls = econtext->ecxt_aggnulls;
int aggno;
+ int transno;
Assert(currentSet == 0 ||
((Agg *) aggstate->ss.ps.plan)->aggstrategy != AGG_HASHED);
aggstate->current_set = currentSet;
- for (aggno = 0; aggno < aggstate->numaggs; aggno++)
+ /*
+ * If there were any DISTINCT and/or ORDER BY aggregates, sort their
+ * inputs and run the transition functions.
+ */
+ for (transno = 0; transno < aggstate->numtrans; transno++)
{
- AggStatePerAgg peragg = &peraggs[aggno];
- int transno = peragg->transno;
AggStatePerTrans pertrans = &aggstate->pertrans[transno];
AggStatePerGroup pergroupstate;
@@ -1603,6 +1606,18 @@ finalize_aggregates(AggState *aggstate,
pertrans,
pergroupstate);
}
+ }
+
+ /*
+ * Run the final functions.
+ */
+ for (aggno = 0; aggno < aggstate->numaggs; aggno++)
+ {
+ AggStatePerAgg peragg = &peraggs[aggno];
+ int transno = peragg->transno;
+ AggStatePerGroup pergroupstate;
+
+ pergroupstate = &pergroup[transno + (currentSet * (aggstate->numtrans))];
if (DO_AGGSPLIT_SKIPFINAL(aggstate->aggsplit))
finalize_partialaggregate(aggstate, peragg, pergroupstate,