8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.126 2002/11/06 00:00:44 tgl Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.127 2002/11/06 22:31:24 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -931,6 +931,7 @@ grouping_planner(Query *parse, double tuple_fraction)
931
931
AttrNumber * groupColIdx = NULL ;
932
932
Path * cheapest_path ;
933
933
Path * sorted_path ;
934
+ bool use_hashed_grouping = false;
934
935
935
936
/* Preprocess targetlist in case we are inside an INSERT/UPDATE. */
936
937
tlist = preprocess_targetlist (tlist ,
@@ -1209,6 +1210,29 @@ grouping_planner(Query *parse, double tuple_fraction)
1209
1210
group_pathkeys = canonicalize_pathkeys (parse , group_pathkeys );
1210
1211
sort_pathkeys = canonicalize_pathkeys (parse , sort_pathkeys );
1211
1212
1213
+ /*
1214
+ * Consider whether we might want to use hashed grouping.
1215
+ */
1216
+ if (parse -> groupClause )
1217
+ {
1218
+ /*
1219
+ * Executor doesn't support hashed aggregation with DISTINCT
1220
+ * aggregates. (Doing so would imply storing *all* the input
1221
+ * values in the hash table, which seems like a certain loser.)
1222
+ */
1223
+ if (parse -> hasAggs &&
1224
+ (contain_distinct_agg_clause ((Node * ) tlist ) ||
1225
+ contain_distinct_agg_clause (parse -> havingQual )))
1226
+ use_hashed_grouping = false;
1227
+ else
1228
+ {
1229
+ #if 0 /* much more to do here */
1230
+ /* TEMPORARY HOTWIRE FOR TESTING */
1231
+ use_hashed_grouping = true;
1232
+ #endif
1233
+ }
1234
+ }
1235
+
1212
1236
/*
1213
1237
* Select the best path and create a plan to execute it.
1214
1238
*
@@ -1279,22 +1303,30 @@ grouping_planner(Query *parse, double tuple_fraction)
1279
1303
}
1280
1304
1281
1305
/*
1282
- * If any aggregate is present, insert the Agg node , plus an explicit
1283
- * sort if necessary.
1306
+ * Insert AGG or GROUP node if needed , plus an explicit sort step
1307
+ * if necessary.
1284
1308
*
1285
1309
* HAVING clause, if any, becomes qual of the Agg node
1286
1310
*/
1287
- if (parse -> hasAggs )
1311
+ if (use_hashed_grouping )
1288
1312
{
1313
+ /* Hashed aggregate plan --- no sort needed */
1314
+ result_plan = (Plan * ) make_agg (tlist ,
1315
+ (List * ) parse -> havingQual ,
1316
+ AGG_HASHED ,
1317
+ length (parse -> groupClause ),
1318
+ groupColIdx ,
1319
+ result_plan );
1320
+ /* Hashed aggregation produces randomly-ordered results */
1321
+ current_pathkeys = NIL ;
1322
+ }
1323
+ else if (parse -> hasAggs )
1324
+ {
1325
+ /* Plain aggregate plan --- sort if needed */
1289
1326
AggStrategy aggstrategy ;
1290
1327
1291
1328
if (parse -> groupClause )
1292
1329
{
1293
- aggstrategy = AGG_SORTED ;
1294
- /*
1295
- * Add an explicit sort if we couldn't make the path come out
1296
- * the way the AGG node needs it.
1297
- */
1298
1330
if (!pathkeys_contained_in (group_pathkeys , current_pathkeys ))
1299
1331
{
1300
1332
result_plan = make_groupsortplan (parse ,
@@ -1303,20 +1335,25 @@ grouping_planner(Query *parse, double tuple_fraction)
1303
1335
result_plan );
1304
1336
current_pathkeys = group_pathkeys ;
1305
1337
}
1338
+ aggstrategy = AGG_SORTED ;
1339
+ /*
1340
+ * The AGG node will not change the sort ordering of its
1341
+ * groups, so current_pathkeys describes the result too.
1342
+ */
1306
1343
}
1307
1344
else
1345
+ {
1308
1346
aggstrategy = AGG_PLAIN ;
1347
+ /* Result will be only one row anyway; no sort order */
1348
+ current_pathkeys = NIL ;
1349
+ }
1309
1350
1310
1351
result_plan = (Plan * ) make_agg (tlist ,
1311
1352
(List * ) parse -> havingQual ,
1312
1353
aggstrategy ,
1313
1354
length (parse -> groupClause ),
1314
1355
groupColIdx ,
1315
1356
result_plan );
1316
- /*
1317
- * Note: plain or grouped Agg does not affect any existing
1318
- * sort order of the tuples
1319
- */
1320
1357
}
1321
1358
else
1322
1359
{
0 commit comments