@@ -202,14 +202,14 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
202
202
glob -> hasRowSecurity = false;
203
203
204
204
/*
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.
210
210
*
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
213
213
* restriction, but for now it seems best not to have parallel workers
214
214
* trying to create their own parallel workers.
215
215
*
@@ -218,8 +218,8 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
218
218
* tries to run a parallel plan in serializable mode; it just won't get
219
219
* any workers and will run serially. But it seems like a good heuristic
220
220
* 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.
223
223
*/
224
224
glob -> parallelModeOK = (cursorOptions & CURSOR_OPT_PARALLEL_OK ) != 0 &&
225
225
IsUnderPostmaster && dynamic_shared_memory_type != DSM_IMPL_NONE &&
@@ -239,9 +239,9 @@ standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
239
239
*
240
240
* (It's been suggested that we should always impose these restrictions
241
241
* 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.)
245
245
*
246
246
* FIXME: It's assumed that code further down will set parallelModeNeeded
247
247
* to true if a parallel path is actually chosen. Since the core
@@ -1425,7 +1425,6 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
1425
1425
List * activeWindows = NIL ;
1426
1426
OnConflictExpr * onconfl ;
1427
1427
int maxref = 0 ;
1428
- int * tleref_to_colnum_map ;
1429
1428
List * rollup_lists = NIL ;
1430
1429
List * rollup_groupclauses = NIL ;
1431
1430
standard_qp_extra qp_extra ;
@@ -1439,40 +1438,58 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
1439
1438
/* A recursive query should always have setOperations */
1440
1439
Assert (!root -> hasRecursion );
1441
1440
1442
- /* Preprocess Grouping set , if any */
1441
+ /* Preprocess grouping sets , if any */
1443
1442
if (parse -> groupingSets )
1444
- parse -> groupingSets = expand_grouping_sets (parse -> groupingSets , -1 );
1445
-
1446
- if (parse -> groupClause )
1447
1443
{
1444
+ int * tleref_to_colnum_map ;
1445
+ List * sets ;
1448
1446
ListCell * lc ;
1447
+ ListCell * lc2 ;
1448
+ ListCell * lc_set ;
1449
1449
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) */
1450
1454
foreach (lc , parse -> groupClause )
1451
1455
{
1452
1456
SortGroupClause * gc = lfirst (lc );
1453
1457
1454
1458
if (gc -> tleSortGroupRef > maxref )
1455
1459
maxref = gc -> tleSortGroupRef ;
1456
1460
}
1457
- }
1458
1461
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 ));
1460
1464
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 );
1467
1467
1468
1468
foreach (lc_set , sets )
1469
1469
{
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 ));
1476
1493
1477
1494
/*
1478
1495
* Now that we've pinned down an order for the groupClause for
@@ -1481,7 +1498,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
1481
1498
* (0-based) into the groupClause for this collection of
1482
1499
* grouping sets.
1483
1500
*/
1484
-
1501
+ ref = 0 ;
1485
1502
foreach (lc , groupclause )
1486
1503
{
1487
1504
SortGroupClause * gc = lfirst (lc );
@@ -1497,6 +1514,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
1497
1514
}
1498
1515
}
1499
1516
1517
+ /* Save the reordered sets and corresponding groupclauses */
1500
1518
rollup_lists = lcons (current_sets , rollup_lists );
1501
1519
rollup_groupclauses = lcons (groupclause , rollup_groupclauses );
1502
1520
}
@@ -1953,10 +1971,9 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
1953
1971
1954
1972
/*
1955
1973
* 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
1957
1975
* finalize GROUPING() operations.
1958
1976
*/
1959
-
1960
1977
if (parse -> groupingSets )
1961
1978
{
1962
1979
AttrNumber * grouping_map = palloc0 (sizeof (AttrNumber ) * (maxref + 1 ));
@@ -1996,9 +2013,12 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
1996
2013
/* Hashed aggregation produces randomly-ordered results */
1997
2014
current_pathkeys = NIL ;
1998
2015
}
1999
- else if (parse -> hasAggs || (parse -> groupingSets && parse -> groupClause ))
2016
+ else if (parse -> hasAggs ||
2017
+ (parse -> groupingSets && parse -> groupClause ))
2000
2018
{
2001
2019
/*
2020
+ * Aggregation and/or non-degenerate grouping sets.
2021
+ *
2002
2022
* Output is in sorted order by group_pathkeys if, and only
2003
2023
* if, there is a single rollup operation on a non-empty list
2004
2024
* of grouping expressions.
@@ -3473,7 +3493,8 @@ extract_rollup_sets(List *groupingSets)
3473
3493
* prefix relationships.
3474
3494
*
3475
3495
* 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.
3477
3498
*
3478
3499
* If we're passed in a sortclause, we follow its order of columns to the
3479
3500
* extent possible, to minimize the chance that we add unnecessary sorts.
0 commit comments