Skip to content

Commit 37b4e0f

Browse files
committed
Make setrefs.c match by ressortgroupref even for plain Vars.
Previously, we skipped using search_indexed_tlist_for_sortgroupref() if the tlist expression being sought in the child plan node was merely a Var. This is purely an optimization, based on the theory that search_indexed_tlist_for_var() is faster, and one copy of a Var should be as good as another. However, the GROUPING SETS patch broke the latter assumption: grouping columns containing the "same" Var can sometimes have different outputs, as shown in the test case added here. So do it the hard way whenever a ressortgroupref marking exists. (If this seems like a bottleneck, we could imagine building a tlist index data structure for ressortgroupref values, as we do for Vars. But I'll let that idea go until there's some evidence it's worthwhile.) Back-patch to 9.6. The problem also exists in 9.5 where GROUPING SETS came in, but this patch is insufficient to resolve the problem in 9.5: there is some obscure dependency on the upper-planner-pathification work that happened in 9.6. Given that this is such a weird corner case, and no end users have complained about it, it doesn't seem worth the work to develop a fix for 9.5. Patch by me, per a report from Heikki Linnakangas. (This does not fix Heikki's original complaint, just the follow-on one.) Discussion: https://postgr.es/m/aefc657e-edb2-64d5-6df1-a0828f6e9104@iki.fi
1 parent ea8480a commit 37b4e0f

File tree

3 files changed

+42
-3
lines changed

3 files changed

+42
-3
lines changed

src/backend/optimizer/plan/setrefs.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1687,8 +1687,8 @@ set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
16871687
TargetEntry *tle = (TargetEntry *) lfirst(l);
16881688
Node *newexpr;
16891689

1690-
/* If it's a non-Var sort/group item, first try to match by sortref */
1691-
if (tle->ressortgroupref != 0 && !IsA(tle->expr, Var))
1690+
/* If it's a sort/group item, first try to match by sortref */
1691+
if (tle->ressortgroupref != 0)
16921692
{
16931693
newexpr = (Node *)
16941694
search_indexed_tlist_for_sortgroupref((Node *) tle->expr,
@@ -2049,7 +2049,6 @@ search_indexed_tlist_for_non_var(Node *node,
20492049

20502050
/*
20512051
* search_indexed_tlist_for_sortgroupref --- find a sort/group expression
2052-
* (which is assumed not to be just a Var)
20532052
*
20542053
* If a match is found, return a Var constructed to reference the tlist item.
20552054
* If no match, return NULL.

src/test/regress/expected/groupingsets.out

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,35 @@ select a, d, grouping(a,b,c)
352352
2 | 2 | 2
353353
(4 rows)
354354

355+
-- check that distinct grouping columns are kept separate
356+
-- even if they are equal()
357+
explain (costs off)
358+
select g as alias1, g as alias2
359+
from generate_series(1,3) g
360+
group by alias1, rollup(alias2);
361+
QUERY PLAN
362+
------------------------------------------------
363+
GroupAggregate
364+
Group Key: g, g
365+
Group Key: g
366+
-> Sort
367+
Sort Key: g
368+
-> Function Scan on generate_series g
369+
(6 rows)
370+
371+
select g as alias1, g as alias2
372+
from generate_series(1,3) g
373+
group by alias1, rollup(alias2);
374+
alias1 | alias2
375+
--------+--------
376+
1 | 1
377+
1 |
378+
2 | 2
379+
2 |
380+
3 | 3
381+
3 |
382+
(6 rows)
383+
355384
-- simple rescan tests
356385
select a, b, sum(v.x)
357386
from (values (1),(2)) v(x), gstest_data(v.x)

src/test/regress/sql/groupingsets.sql

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,17 @@ select a, d, grouping(a,b,c)
130130
from gstest3
131131
group by grouping sets ((a,b), (a,c));
132132

133+
-- check that distinct grouping columns are kept separate
134+
-- even if they are equal()
135+
explain (costs off)
136+
select g as alias1, g as alias2
137+
from generate_series(1,3) g
138+
group by alias1, rollup(alias2);
139+
140+
select g as alias1, g as alias2
141+
from generate_series(1,3) g
142+
group by alias1, rollup(alias2);
143+
133144
-- simple rescan tests
134145

135146
select a, b, sum(v.x)

0 commit comments

Comments
 (0)