@@ -202,14 +202,14 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
202202 glob -> hasRowSecurity = false;
203203
204204 /*
205- * Assess whether it's feasible to use parallel mode for this query.
206- * We can't do this in a standalone backend, or if the command will
207- * try to modify any data, or if this is a cursor operation, or if
208- * GUCs are set to values that don't permit parallelism, or if
209- * parallel-unsafe functions are present in the query tree.
205+ * Assess whether it's feasible to use parallel mode for this query. We
206+ * can't do this in a standalone backend, or if the command will try to
207+ * modify any data, or if this is a cursor operation, or if GUCs are set
208+ * to values that don't permit parallelism, or if parallel-unsafe
209+ * functions are present in the query tree.
210210 *
211- * For now, we don't try to use parallel mode if we're running inside
212- * a parallel worker. We might eventually be able to relax this
211+ * For now, we don't try to use parallel mode if we're running inside a
212+ * parallel worker. We might eventually be able to relax this
213213 * restriction, but for now it seems best not to have parallel workers
214214 * trying to create their own parallel workers.
215215 *
@@ -218,8 +218,8 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
218218 * tries to run a parallel plan in serializable mode; it just won't get
219219 * any workers and will run serially. But it seems like a good heuristic
220220 * to assume that the same serialization level will be in effect at plan
221- * time and execution time, so don't generate a parallel plan if we're
222- * in serializable mode.
221+ * time and execution time, so don't generate a parallel plan if we're in
222+ * serializable mode.
223223 */
224224 glob -> parallelModeOK = (cursorOptions & CURSOR_OPT_PARALLEL_OK ) != 0 &&
225225 IsUnderPostmaster && dynamic_shared_memory_type != DSM_IMPL_NONE &&
@@ -239,9 +239,9 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
239239 *
240240 * (It's been suggested that we should always impose these restrictions
241241 * whenever glob->parallelModeOK is true, so that it's easier to notice
242- * incorrectly-labeled functions sooner. That might be the right thing
243- * to do, but for now I've taken this approach. We could also control
244- * this with a GUC.)
242+ * incorrectly-labeled functions sooner. That might be the right thing to
243+ * do, but for now I've taken this approach. We could also control this
244+ * with a GUC.)
245245 *
246246 * FIXME: It's assumed that code further down will set parallelModeNeeded
247247 * to true if a parallel path is actually chosen. Since the core
@@ -1425,7 +1425,6 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
14251425 List * activeWindows = NIL ;
14261426 OnConflictExpr * onconfl ;
14271427 int maxref = 0 ;
1428- int * tleref_to_colnum_map ;
14291428 List * rollup_lists = NIL ;
14301429 List * rollup_groupclauses = NIL ;
14311430 standard_qp_extra qp_extra ;
@@ -1439,40 +1438,58 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
14391438 /* A recursive query should always have setOperations */
14401439 Assert (!root -> hasRecursion );
14411440
1442- /* Preprocess Grouping set , if any */
1441+ /* Preprocess grouping sets , if any */
14431442 if (parse -> groupingSets )
1444- parse -> groupingSets = expand_grouping_sets (parse -> groupingSets , -1 );
1445-
1446- if (parse -> groupClause )
14471443 {
1444+ int * tleref_to_colnum_map ;
1445+ List * sets ;
14481446 ListCell * lc ;
1447+ ListCell * lc2 ;
1448+ ListCell * lc_set ;
14491449
1450+ parse -> groupingSets = expand_grouping_sets (parse -> groupingSets , -1 );
1451+
1452+ /* Identify max SortGroupRef in groupClause, for array sizing */
1453+ /* (note this value will be used again later) */
14501454 foreach (lc , parse -> groupClause )
14511455 {
14521456 SortGroupClause * gc = lfirst (lc );
14531457
14541458 if (gc -> tleSortGroupRef > maxref )
14551459 maxref = gc -> tleSortGroupRef ;
14561460 }
1457- }
14581461
1459- tleref_to_colnum_map = palloc ((maxref + 1 ) * sizeof (int ));
1462+ /* Allocate workspace array for remapping */
1463+ tleref_to_colnum_map = (int * ) palloc ((maxref + 1 ) * sizeof (int ));
14601464
1461- if (parse -> groupingSets )
1462- {
1463- ListCell * lc ;
1464- ListCell * lc2 ;
1465- ListCell * lc_set ;
1466- List * sets = extract_rollup_sets (parse -> groupingSets );
1465+ /* Examine the rollup sets */
1466+ sets = extract_rollup_sets (parse -> groupingSets );
14671467
14681468 foreach (lc_set , sets )
14691469 {
1470- List * current_sets = reorder_grouping_sets (lfirst (lc_set ),
1471- (list_length (sets ) == 1
1472- ? parse -> sortClause
1473- : NIL ));
1474- List * groupclause = preprocess_groupclause (root , linitial (current_sets ));
1475- int ref = 0 ;
1470+ List * current_sets = (List * ) lfirst (lc_set );
1471+ List * groupclause ;
1472+ int ref ;
1473+
1474+ /*
1475+ * Reorder the current list of grouping sets into correct
1476+ * prefix order. If only one aggregation pass is needed, try
1477+ * to make the list match the ORDER BY clause; if more than
1478+ * one pass is needed, we don't bother with that.
1479+ */
1480+ current_sets = reorder_grouping_sets (current_sets ,
1481+ (list_length (sets ) == 1
1482+ ? parse -> sortClause
1483+ : NIL ));
1484+
1485+ /*
1486+ * Order the groupClause appropriately. If the first grouping
1487+ * set is empty, this can match regular GROUP BY
1488+ * preprocessing, otherwise we have to force the groupClause
1489+ * to match that grouping set's order.
1490+ */
1491+ groupclause = preprocess_groupclause (root ,
1492+ linitial (current_sets ));
14761493
14771494 /*
14781495 * Now that we've pinned down an order for the groupClause for
@@ -1481,7 +1498,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
14811498 * (0-based) into the groupClause for this collection of
14821499 * grouping sets.
14831500 */
1484-
1501+ ref = 0 ;
14851502 foreach (lc , groupclause )
14861503 {
14871504 SortGroupClause * gc = lfirst (lc );
@@ -1497,6 +1514,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
14971514 }
14981515 }
14991516
1517+ /* Save the reordered sets and corresponding groupclauses */
15001518 rollup_lists = lcons (current_sets , rollup_lists );
15011519 rollup_groupclauses = lcons (groupclause , rollup_groupclauses );
15021520 }
@@ -1953,10 +1971,9 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
19531971
19541972 /*
19551973 * groupColIdx is now cast in stone, so record a mapping from
1956- * tleSortGroupRef to column index. setrefs.c needs this to
1974+ * tleSortGroupRef to column index. setrefs.c will need this to
19571975 * finalize GROUPING() operations.
19581976 */
1959-
19601977 if (parse -> groupingSets )
19611978 {
19621979 AttrNumber * grouping_map = palloc0 (sizeof (AttrNumber ) * (maxref + 1 ));
@@ -1996,9 +2013,12 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
19962013 /* Hashed aggregation produces randomly-ordered results */
19972014 current_pathkeys = NIL ;
19982015 }
1999- else if (parse -> hasAggs || (parse -> groupingSets && parse -> groupClause ))
2016+ else if (parse -> hasAggs ||
2017+ (parse -> groupingSets && parse -> groupClause ))
20002018 {
20012019 /*
2020+ * Aggregation and/or non-degenerate grouping sets.
2021+ *
20022022 * Output is in sorted order by group_pathkeys if, and only
20032023 * if, there is a single rollup operation on a non-empty list
20042024 * of grouping expressions.
@@ -3473,7 +3493,8 @@ extract_rollup_sets(List *groupingSets)
34733493 * prefix relationships.
34743494 *
34753495 * The input must be ordered with smallest sets first; the result is returned
3476- * with largest sets first.
3496+ * with largest sets first. Note that the result shares no list substructure
3497+ * with the input, so it's safe for the caller to modify it later.
34773498 *
34783499 * If we're passed in a sortclause, we follow its order of columns to the
34793500 * extent possible, to minimize the chance that we add unnecessary sorts.
0 commit comments