aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2003-02-04 00:48:23 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2003-02-04 00:48:23 +0000
commit85caf1784a318afdd3c4ba66ffd23c0d0af99cd6 (patch)
tree9b435b860726eb02ec116f723e3dc7f1da3872de /src
parentef5842b5f718437b504e801258025b188f764380 (diff)
downloadpostgresql-85caf1784a318afdd3c4ba66ffd23c0d0af99cd6.tar.gz
postgresql-85caf1784a318afdd3c4ba66ffd23c0d0af99cd6.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/backend/executor/nodeAgg.c31
1 files changed, 28 insertions, 3 deletions
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index d8eeae15ad7..0cb2f3e2b6f 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -45,7 +45,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* 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)
/*
* 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;
foreach(alist, aggstate->aggs)
{
AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(alist);
Aggref *aggref = (Aggref *) aggrefstate->xprstate.expr;
- AggStatePerAgg peraggstate = &peragg[++aggno];
+ AggStatePerAgg peraggstate;
HeapTuple aggTuple;
Form_pg_aggregate aggform;
AclResult aclresult;
Oid transfn_oid,
finalfn_oid;
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 */
aggrefstate->aggno = aggno;
@@ -1271,6 +1293,9 @@ ExecInitAgg(Agg *node, EState *estate)
ReleaseSysCache(aggTuple);
}
+ /* Update numaggs to match number of unique aggregates found */
+ aggstate->numaggs = aggno + 1;
+
return aggstate;
}