Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 85caf17

Browse files
committed
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.
1 parent ef5842b commit 85caf17

File tree

1 file changed

+28
-3
lines changed

1 file changed

+28
-3
lines changed

src/backend/executor/nodeAgg.c

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
* Portions Copyright (c) 1994, Regents of the University of California
4646
*
4747
* IDENTIFICATION
48-
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.102 2003/01/10 23:54:24 tgl Exp $
48+
* $Header: /cvsroot/pgsql/src/backend/executor/nodeAgg.c,v 1.103 2003/02/04 00:48:23 tgl Exp $
4949
*
5050
*-------------------------------------------------------------------------
5151
*/
@@ -1159,20 +1159,42 @@ ExecInitAgg(Agg *node, EState *estate)
11591159

11601160
/*
11611161
* Perform lookups of aggregate function info, and initialize the
1162-
* unchanging fields of the per-agg data
1162+
* unchanging fields of the per-agg data. We also detect duplicate
1163+
* aggregates (for example, "SELECT sum(x) ... HAVING sum(x) > 0").
1164+
* When duplicates are detected, we only make an AggStatePerAgg struct
1165+
* for the first one. The clones are simply pointed at the same result
1166+
* entry by giving them duplicate aggno values.
11631167
*/
11641168
aggno = -1;
11651169
foreach(alist, aggstate->aggs)
11661170
{
11671171
AggrefExprState *aggrefstate = (AggrefExprState *) lfirst(alist);
11681172
Aggref *aggref = (Aggref *) aggrefstate->xprstate.expr;
1169-
AggStatePerAgg peraggstate = &peragg[++aggno];
1173+
AggStatePerAgg peraggstate;
11701174
HeapTuple aggTuple;
11711175
Form_pg_aggregate aggform;
11721176
AclResult aclresult;
11731177
Oid transfn_oid,
11741178
finalfn_oid;
11751179
Datum textInitVal;
1180+
int i;
1181+
1182+
/* Look for a previous duplicate aggregate */
1183+
for (i = 0; i <= aggno; i++)
1184+
{
1185+
if (equal(aggref, peragg[i].aggref) &&
1186+
!contain_volatile_functions((Node *) aggref))
1187+
break;
1188+
}
1189+
if (i <= aggno)
1190+
{
1191+
/* Found a match to an existing entry, so just mark it */
1192+
aggrefstate->aggno = i;
1193+
continue;
1194+
}
1195+
1196+
/* Nope, so assign a new PerAgg record */
1197+
peraggstate = &peragg[++aggno];
11761198

11771199
/* Mark Aggref state node with assigned index in the result array */
11781200
aggrefstate->aggno = aggno;
@@ -1271,6 +1293,9 @@ ExecInitAgg(Agg *node, EState *estate)
12711293
ReleaseSysCache(aggTuple);
12721294
}
12731295

1296+
/* Update numaggs to match number of unique aggregates found */
1297+
aggstate->numaggs = aggno + 1;
1298+
12741299
return aggstate;
12751300
}
12761301

0 commit comments

Comments
 (0)