mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-27 08:39:28 +08:00
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.
This commit is contained in:
parent
ef5842b5f7
commit
85caf1784a
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user