88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.126 2002/11/0600:00:44 tgl Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.127 2002/11/0622:31:24 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -931,6 +931,7 @@ grouping_planner(Query *parse, double tuple_fraction)
931931AttrNumber * groupColIdx = NULL ;
932932Path * cheapest_path ;
933933Path * sorted_path ;
934+ bool use_hashed_grouping = false;
934935
935936/* Preprocess targetlist in case we are inside an INSERT/UPDATE. */
936937tlist = preprocess_targetlist (tlist ,
@@ -1209,6 +1210,29 @@ grouping_planner(Query *parse, double tuple_fraction)
12091210group_pathkeys = canonicalize_pathkeys (parse ,group_pathkeys );
12101211sort_pathkeys = canonicalize_pathkeys (parse ,sort_pathkeys );
12111212
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+
12121236/*
12131237 * Select the best path and create a plan to execute it.
12141238 *
@@ -1279,22 +1303,30 @@ grouping_planner(Query *parse, double tuple_fraction)
12791303}
12801304
12811305/*
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.
12841308 *
12851309 * HAVING clause, if any, becomes qual of the Agg node
12861310 */
1287- if (parse -> hasAggs )
1311+ if (use_hashed_grouping )
12881312{
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 */
12891326AggStrategy aggstrategy ;
12901327
12911328if (parse -> groupClause )
12921329{
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- */
12981330if (!pathkeys_contained_in (group_pathkeys ,current_pathkeys ))
12991331{
13001332result_plan = make_groupsortplan (parse ,
@@ -1303,20 +1335,25 @@ grouping_planner(Query *parse, double tuple_fraction)
13031335result_plan );
13041336current_pathkeys = group_pathkeys ;
13051337}
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+ */
13061343}
13071344else
1345+ {
13081346aggstrategy = AGG_PLAIN ;
1347+ /* Result will be only one row anyway; no sort order */
1348+ current_pathkeys = NIL ;
1349+ }
13091350
13101351result_plan = (Plan * )make_agg (tlist ,
13111352(List * )parse -> havingQual ,
13121353aggstrategy ,
13131354length (parse -> groupClause ),
13141355groupColIdx ,
13151356result_plan );
1316- /*
1317- * Note: plain or grouped Agg does not affect any existing
1318- * sort order of the tuples
1319- */
13201357}
13211358else
13221359{