Skip to content

Commit a923af3

Browse files
committed
Fix build_grouping_chain() to not clobber its input lists.
There's no good reason for stomping on the input data; it makes the logic in this function no simpler, in fact probably the reverse. And it makes it impossible to separate path generation from plan generation, as I'm working towards doing; that will require more than one traversal of these lists.
1 parent 6a61d1f commit a923af3

File tree

1 file changed

+54
-62
lines changed

1 file changed

+54
-62
lines changed

src/backend/optimizer/plan/planner.c

Lines changed: 54 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,13 +2035,6 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
20352035
&agg_costs,
20362036
numGroups,
20372037
result_plan);
2038-
2039-
/*
2040-
* these are destroyed by build_grouping_chain, so make sure
2041-
* we don't try and touch them again
2042-
*/
2043-
rollup_groupclauses = NIL;
2044-
rollup_lists = NIL;
20452038
}
20462039
else if (parse->groupClause)
20472040
{
@@ -2461,10 +2454,10 @@ remap_groupColIdx(PlannerInfo *root, List *groupClause)
24612454

24622455
/*
24632456
* Build Agg and Sort nodes to implement sorted grouping with one or more
2464-
* grouping sets. (A plain GROUP BY or just the presence of aggregates counts
2457+
* grouping sets. A plain GROUP BY or just the presence of aggregates counts
24652458
* for this purpose as a single grouping set; the calling code is responsible
2466-
* for providing a non-empty rollup_groupclauses list for such cases, though
2467-
* rollup_lists may be null.)
2459+
* for providing a single-element rollup_groupclauses list for such cases,
2460+
* though rollup_lists may be nil.
24682461
*
24692462
* The last entry in rollup_groupclauses (which is the one the input is sorted
24702463
* on, if at all) is the one used for the returned Agg node. Any additional
@@ -2473,8 +2466,6 @@ remap_groupColIdx(PlannerInfo *root, List *groupClause)
24732466
* participate in the plan directly, but they are both a convenient way to
24742467
* represent the required data and a convenient way to account for the costs
24752468
* of execution.
2476-
*
2477-
* rollup_groupclauses and rollup_lists are destroyed by this function.
24782469
*/
24792470
static Plan *
24802471
build_grouping_chain(PlannerInfo *root,
@@ -2514,62 +2505,71 @@ build_grouping_chain(PlannerInfo *root,
25142505
* Generate the side nodes that describe the other sort and group
25152506
* operations besides the top one.
25162507
*/
2517-
while (list_length(rollup_groupclauses) > 1)
2508+
if (list_length(rollup_groupclauses) > 1)
25182509
{
2519-
List *groupClause = linitial(rollup_groupclauses);
2520-
List *gsets = linitial(rollup_lists);
2521-
AttrNumber *new_grpColIdx;
2522-
Plan *sort_plan;
2523-
Plan *agg_plan;
2524-
2525-
Assert(groupClause);
2526-
Assert(gsets);
2527-
2528-
new_grpColIdx = remap_groupColIdx(root, groupClause);
2510+
ListCell *lc,
2511+
*lc2;
25292512

2530-
sort_plan = (Plan *)
2531-
make_sort_from_groupcols(root,
2532-
groupClause,
2533-
new_grpColIdx,
2534-
result_plan);
2535-
2536-
/*
2537-
* sort_plan includes the cost of result_plan over again, which is not
2538-
* what we want (since it's not actually running that plan). So
2539-
* correct the cost figures.
2540-
*/
2513+
Assert(list_length(rollup_groupclauses) == list_length(rollup_lists));
2514+
forboth(lc, rollup_groupclauses, lc2, rollup_lists)
2515+
{
2516+
List *groupClause = (List *) lfirst(lc);
2517+
List *gsets = (List *) lfirst(lc2);
2518+
AttrNumber *new_grpColIdx;
2519+
Plan *sort_plan;
2520+
Plan *agg_plan;
2521+
2522+
/* We want to iterate over all but the last rollup list elements */
2523+
if (lnext(lc) == NULL)
2524+
break;
25412525

2542-
sort_plan->startup_cost -= result_plan->total_cost;
2543-
sort_plan->total_cost -= result_plan->total_cost;
2526+
new_grpColIdx = remap_groupColIdx(root, groupClause);
25442527

2545-
agg_plan = (Plan *) make_agg(root,
2546-
tlist,
2547-
(List *) parse->havingQual,
2548-
AGG_SORTED,
2549-
agg_costs,
2550-
list_length(linitial(gsets)),
2551-
new_grpColIdx,
2552-
extract_grouping_ops(groupClause),
2553-
gsets,
2554-
numGroups,
2555-
sort_plan);
2528+
sort_plan = (Plan *)
2529+
make_sort_from_groupcols(root,
2530+
groupClause,
2531+
new_grpColIdx,
2532+
result_plan);
25562533

2557-
sort_plan->lefttree = NULL;
2534+
/*
2535+
* sort_plan includes the cost of result_plan, which is not what
2536+
* we want (since we'll not actually run that plan again). So
2537+
* correct the cost figures.
2538+
*/
2539+
sort_plan->startup_cost -= result_plan->total_cost;
2540+
sort_plan->total_cost -= result_plan->total_cost;
2541+
2542+
agg_plan = (Plan *) make_agg(root,
2543+
tlist,
2544+
(List *) parse->havingQual,
2545+
AGG_SORTED,
2546+
agg_costs,
2547+
list_length(linitial(gsets)),
2548+
new_grpColIdx,
2549+
extract_grouping_ops(groupClause),
2550+
gsets,
2551+
numGroups,
2552+
sort_plan);
25582553

2559-
chain = lappend(chain, agg_plan);
2554+
/*
2555+
* Nuke stuff we don't need to avoid bloating debug output.
2556+
*/
2557+
sort_plan->targetlist = NIL;
2558+
sort_plan->lefttree = NULL;
25602559

2561-
if (rollup_lists)
2562-
rollup_lists = list_delete_first(rollup_lists);
2560+
agg_plan->targetlist = NIL;
2561+
agg_plan->qual = NIL;
25632562

2564-
rollup_groupclauses = list_delete_first(rollup_groupclauses);
2563+
chain = lappend(chain, agg_plan);
2564+
}
25652565
}
25662566

25672567
/*
25682568
* Now make the final Agg node
25692569
*/
25702570
{
2571-
List *groupClause = linitial(rollup_groupclauses);
2572-
List *gsets = rollup_lists ? linitial(rollup_lists) : NIL;
2571+
List *groupClause = (List *) llast(rollup_groupclauses);
2572+
List *gsets = rollup_lists ? (List *) llast(rollup_lists) : NIL;
25732573
int numGroupCols;
25742574
ListCell *lc;
25752575

@@ -2601,14 +2601,6 @@ build_grouping_chain(PlannerInfo *root,
26012601
Plan *subplan = lfirst(lc);
26022602

26032603
result_plan->total_cost += subplan->total_cost;
2604-
2605-
/*
2606-
* Nuke stuff we don't need to avoid bloating debug output.
2607-
*/
2608-
2609-
subplan->targetlist = NIL;
2610-
subplan->qual = NIL;
2611-
subplan->lefttree->targetlist = NIL;
26122604
}
26132605
}
26142606

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy