mirror of
https://github.com/postgres/postgres.git
synced 2025-06-02 00:01:40 -04: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
|
* 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)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
ReleaseSysCache(aggTuple);
|
ReleaseSysCache(aggTuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update numaggs to match number of unique aggregates found */
|
||||||
|
aggstate->numaggs = aggno + 1;
|
||||||
|
|
||||||
return aggstate;
|
return aggstate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user