Skip to content

Commit a1637ca

Browse files
committed
Repair logic for reordering grouping sets optimization.
The logic in reorder_grouping_sets to order grouping set elements to match a pre-specified sort ordering was defective, resulting in unnecessary sort nodes (though the query output would still be correct). Repair, simplifying the code a little, and add a test. Per report from Richard Guo, though I didn't use their patch. Original bug seems to have been my fault. Backpatch back to 9.5 where grouping sets were introduced. Discussion: https://postgr.es/m/CAN_9JTzyjGcUjiBHxLsgqfk7PkdLGXiM=pwM+=ph2LsWw0WO1A@mail.gmail.com
1 parent 69da8c1 commit a1637ca

File tree

3 files changed

+34
-21
lines changed

3 files changed

+34
-21
lines changed

src/backend/optimizer/plan/planner.c

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3255,7 +3255,6 @@ static List *
32553255
reorder_grouping_sets(List *groupingsets, List *sortclause)
32563256
{
32573257
ListCell *lc;
3258-
ListCell *lc2;
32593258
List *previous = NIL;
32603259
List *result = NIL;
32613260

@@ -3265,35 +3264,33 @@ reorder_grouping_sets(List *groupingsets, List *sortclause)
32653264
List *new_elems = list_difference_int(candidate, previous);
32663265
GroupingSetData *gs = makeNode(GroupingSetData);
32673266

3268-
if (list_length(new_elems) > 0)
3267+
while (list_length(sortclause) > list_length(previous) &&
3268+
list_length(new_elems) > 0)
32693269
{
3270-
while (list_length(sortclause) > list_length(previous))
3271-
{
3272-
SortGroupClause *sc = list_nth(sortclause, list_length(previous));
3273-
int ref = sc->tleSortGroupRef;
3270+
SortGroupClause *sc = list_nth(sortclause, list_length(previous));
3271+
int ref = sc->tleSortGroupRef;
32743272

3275-
if (list_member_int(new_elems, ref))
3276-
{
3277-
previous = lappend_int(previous, ref);
3278-
new_elems = list_delete_int(new_elems, ref);
3279-
}
3280-
else
3281-
{
3282-
/* diverged from the sortclause; give up on it */
3283-
sortclause = NIL;
3284-
break;
3285-
}
3273+
if (list_member_int(new_elems, ref))
3274+
{
3275+
previous = lappend_int(previous, ref);
3276+
new_elems = list_delete_int(new_elems, ref);
32863277
}
3287-
3288-
foreach(lc2, new_elems)
3278+
else
32893279
{
3290-
previous = lappend_int(previous, lfirst_int(lc2));
3280+
/* diverged from the sortclause; give up on it */
3281+
sortclause = NIL;
3282+
break;
32913283
}
32923284
}
32933285

3286+
/*
3287+
* Safe to use list_concat (which shares cells of the second arg)
3288+
* because we know that new_elems does not share cells with anything.
3289+
*/
3290+
previous = list_concat(previous, new_elems);
3291+
32943292
gs->set = list_copy(previous);
32953293
result = lcons(gs, result);
3296-
list_free(new_elems);
32973294
}
32983295

32993296
list_free(previous);

src/test/regress/expected/groupingsets.out

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -637,6 +637,19 @@ select a, b, sum(v.x)
637637
| | 9
638638
(12 rows)
639639

640+
-- Test reordering of grouping sets
641+
explain (costs off)
642+
select * from gstest1 group by grouping sets((a,b,v),(v)) order by v,b,a;
643+
QUERY PLAN
644+
------------------------------------------------------------------------------
645+
GroupAggregate
646+
Group Key: "*VALUES*".column3, "*VALUES*".column2, "*VALUES*".column1
647+
Group Key: "*VALUES*".column3
648+
-> Sort
649+
Sort Key: "*VALUES*".column3, "*VALUES*".column2, "*VALUES*".column1
650+
-> Values Scan on "*VALUES*"
651+
(6 rows)
652+
640653
-- Agg level check. This query should error out.
641654
select (select grouping(a,b) from gstest2) from gstest2 group by a,b;
642655
ERROR: arguments to GROUPING must be grouping expressions of the associated query level

src/test/regress/sql/groupingsets.sql

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ select a, b, sum(v.x)
213213
from (values (1),(2)) v(x), gstest_data(v.x)
214214
group by cube (a,b) order by a,b;
215215

216+
-- Test reordering of grouping sets
217+
explain (costs off)
218+
select * from gstest1 group by grouping sets((a,b,v),(v)) order by v,b,a;
216219

217220
-- Agg level check. This query should error out.
218221
select (select grouping(a,b) from gstest2) from gstest2 group by a,b;

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