Skip to content

Commit a54676a

Browse files
committed
Marginal cleanup of GROUPING SETS code in grouping_planner().
Improve comments and make it a shade less messy. I think we might want to move all of this somewhere else later, but it needs to be more readable first. In passing, re-pgindent the file, affecting some recently-added comments concerning parallel query planning.
1 parent c44d013 commit a54676a

File tree

1 file changed

+57
-36
lines changed

1 file changed

+57
-36
lines changed

src/backend/optimizer/plan/planner.c

Lines changed: 57 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)