Skip to content
Snippets Groups Projects
Commit 85caf178 authored by Tom Lane's avatar Tom Lane
Browse files

Detect duplicate aggregate calls and evaluate only one copy. This

speeds up some useful real-world cases like
SELECT x, COUNT(*) FROM t GROUP BY x HAVING COUNT(*) > 100.
parent ef5842b5
No related branches found
No related tags found
No related merge requests found
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.102 2003/01/10 23:54:24 tgl Exp $ * $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.103 2003/02/04 00:48:23 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1159,20 +1159,42 @@ ExecInitAgg(Agg *node, EState *estate) ...@@ -1159,20 +1159,42 @@ ExecInitAgg(Agg *node, EState *estate)
/* /*
* Perform lookups of aggregate function info, and initialize the * Perform lookups of aggregate function info, and initialize the
* unchanging fields of the per-agg data * unchanging fields of the per-agg data. We also detect duplicate
* aggregates (for example, "SELECT sum(x) ... HAVING sum(x) > 0").
* When duplicates are detected, we only make an AggStatePerAgg struct
* for the first one. The clones are simply pointed at the same result
* entry by giving them duplicate aggno values.
*/ */
aggno = -1; aggno = -1;
foreach(alist, aggstate->aggs) foreach(alist, aggstate->aggs)
{ {
AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(alist); AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(alist);
Aggref *aggref = (Aggref *) aggrefstate->xprstate.expr; Aggref *aggref = (Aggref *) aggrefstate->xprstate.expr;
AggStatePerAgg peraggstate = &peragg[++aggno]; AggStatePerAgg peraggstate;
HeapTuple aggTuple; HeapTuple aggTuple;
Form_pg_aggregate aggform; Form_pg_aggregate aggform;
AclResult aclresult; AclResult aclresult;
Oid transfn_oid, Oid transfn_oid,
finalfn_oid; finalfn_oid;
Datum textInitVal; Datum textInitVal;
int i;
/* Look for a previous duplicate aggregate */
for (i = 0; i <= aggno; i++)
{
if (equal(aggref, peragg[i].aggref) &&
!contain_volatile_functions((Node *) aggref))
break;
}
if (i <= aggno)
{
/* Found a match to an existing entry, so just mark it */
aggrefstate->aggno = i;
continue;
}
/* Nope, so assign a new PerAgg record */
peraggstate = &peragg[++aggno];
/* Mark Aggref state node with assigned index in the result array */ /* Mark Aggref state node with assigned index in the result array */
aggrefstate->aggno = aggno; aggrefstate->aggno = aggno;
...@@ -1271,6 +1293,9 @@ ExecInitAgg(Agg *node, EState *estate) ...@@ -1271,6 +1293,9 @@ ExecInitAgg(Agg *node, EState *estate)
ReleaseSysCache(aggTuple); ReleaseSysCache(aggTuple);
} }
/* Update numaggs to match number of unique aggregates found */
aggstate->numaggs = aggno + 1;
return aggstate; return aggstate;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment