|
45 | 45 | * Portions Copyright (c) 1994, Regents of the University of California
|
46 | 46 | *
|
47 | 47 | * 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 $ |
49 | 49 | *
|
50 | 50 | *-------------------------------------------------------------------------
|
51 | 51 | */
|
@@ -1159,20 +1159,42 @@ ExecInitAgg(Agg *node, EState *estate)
|
1159 | 1159 |
|
1160 | 1160 | /*
|
1161 | 1161 | * 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. |
1163 | 1167 | */
|
1164 | 1168 | aggno=-1;
|
1165 | 1169 | foreach(alist,aggstate->aggs)
|
1166 | 1170 | {
|
1167 | 1171 | AggrefExprState*aggrefstate= (AggrefExprState*)lfirst(alist);
|
1168 | 1172 | Aggref*aggref= (Aggref*)aggrefstate->xprstate.expr;
|
1169 |
| -AggStatePerAggperaggstate=&peragg[++aggno]; |
| 1173 | +AggStatePerAggperaggstate; |
1170 | 1174 | HeapTupleaggTuple;
|
1171 | 1175 | Form_pg_aggregateaggform;
|
1172 | 1176 | AclResultaclresult;
|
1173 | 1177 | Oidtransfn_oid,
|
1174 | 1178 | finalfn_oid;
|
1175 | 1179 | DatumtextInitVal;
|
| 1180 | +inti; |
| 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]; |
1176 | 1198 |
|
1177 | 1199 | /* Mark Aggref state node with assigned index in the result array */
|
1178 | 1200 | aggrefstate->aggno=aggno;
|
@@ -1271,6 +1293,9 @@ ExecInitAgg(Agg *node, EState *estate)
|
1271 | 1293 | ReleaseSysCache(aggTuple);
|
1272 | 1294 | }
|
1273 | 1295 |
|
| 1296 | +/* Update numaggs to match number of unique aggregates found */ |
| 1297 | +aggstate->numaggs=aggno+1; |
| 1298 | + |
1274 | 1299 | returnaggstate;
|
1275 | 1300 | }
|
1276 | 1301 |
|
|