Skip to content

Commit 38674f6

Browse files
committed
Desugar CUBE and ROLLUP into GROUPING SETS.
1 parent b38bb1a commit 38674f6

File tree

4 files changed

+112
-1
lines changed

4 files changed

+112
-1
lines changed

src/query/ast/src/parser/token.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,7 @@ impl TokenKind {
985985
| TokenKind::FLOAT
986986
// | TokenKind::FOREIGN
987987
// | TokenKind::GREATEST
988-
| TokenKind::GROUPING
988+
// | TokenKind::GROUPING
989989
| TokenKind::CUBE
990990
| TokenKind::ROLLUP
991991
// | TokenKind::IFNULL

src/query/sql/src/planner/binder/aggregate.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,24 @@ impl Binder {
338338
self.resolve_grouping_sets(bind_context, select_list, sets, &available_aliases)
339339
.await
340340
}
341+
// TODO: avoid too many clones.
342+
GroupBy::Rollup(exprs) => {
343+
// ROLLUP (a,b,c) => GROUPING SETS ((a,b,c), (a,b), (a), ())
344+
let mut sets = Vec::with_capacity(exprs.len() + 1);
345+
for i in (0..=exprs.len()).rev() {
346+
sets.push(exprs[0..i].to_vec());
347+
}
348+
self.resolve_grouping_sets(bind_context, select_list, &sets, &available_aliases)
349+
.await
350+
}
351+
GroupBy::Cube(exprs) => {
352+
// CUBE (a,b) => GROUPING SETS ((a,b),(a),(b),()) // All subsets
353+
let sets = (0..=exprs.len())
354+
.flat_map(|count| exprs.clone().into_iter().combinations(count))
355+
.collect::<Vec<_>>();
356+
self.resolve_grouping_sets(bind_context, select_list, &sets, &available_aliases)
357+
.await
358+
}
341359
}
342360
}
343361

tests/sqllogictests/suites/duckdb/sql/aggregate/group/group_by_grouping_sets.test

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,41 @@ NULL B 10 0 1 2 1
5555
b NULL 11 1 0 1 2
5656
NULL NULL 18 1 1 3 3
5757

58+
query TTIIIII
59+
select a, b, sum(c) as sc, grouping(b), grouping(a), grouping(a,b), grouping(b,a) from t group by grouping sets ((a,b),(a),()) order by sc;
60+
----
61+
a A 3 0 0 0 0
62+
a B 4 0 0 0 0
63+
b A 5 0 0 0 0
64+
b B 6 0 0 0 0
65+
a NULL 7 1 0 1 2
66+
b NULL 11 1 0 1 2
67+
NULL NULL 18 1 1 3 3
68+
69+
70+
query TTIIIII
71+
select a, b, sum(c) as sc, grouping(b), grouping(a), grouping(a,b), grouping(b,a) from t group by cube (a,b) order by sc;
72+
----
73+
a A 3 0 0 0 0
74+
a B 4 0 0 0 0
75+
b A 5 0 0 0 0
76+
b B 6 0 0 0 0
77+
a NULL 7 1 0 1 2
78+
NULL A 8 0 1 2 1
79+
NULL B 10 0 1 2 1
80+
b NULL 11 1 0 1 2
81+
NULL NULL 18 1 1 3 3
82+
83+
query TTIIIII
84+
select a, b, sum(c) as sc, grouping(b), grouping(a), grouping(a,b), grouping(b,a) from t group by rollup (a,b) order by sc;
85+
----
86+
a A 3 0 0 0 0
87+
a B 4 0 0 0 0
88+
b A 5 0 0 0 0
89+
b B 6 0 0 0 0
90+
a NULL 7 1 0 1 2
91+
b NULL 11 1 0 1 2
92+
NULL NULL 18 1 1 3 3
93+
5894
statement ok
5995
drop table t all;
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
query T
2+
explain select number % 2 as a, number % 3 as b, number % 5 as c from numbers(1) group by rollup(a, b, c);
3+
----
4+
EvalScalar
5+
├── expressions: [group_item (#1), group_item (#2), group_item (#3)]
6+
├── estimated rows: 1.00
7+
└── AggregateFinal
8+
├── group by: [a, b, c, _grouping_id]
9+
├── aggregate functions: []
10+
├── estimated rows: 1.00
11+
└── AggregatePartial
12+
├── group by: [a, b, c, _grouping_id]
13+
├── aggregate functions: []
14+
├── estimated rows: 1.00
15+
└── AggregateExpand
16+
├── grouping sets: [(a, b, c), (a, b), (a), ()]
17+
├── estimated rows: 1.00
18+
└── EvalScalar
19+
├── expressions: [numbers.number (#0) % 2, numbers.number (#0) % 3, numbers.number (#0) % 5]
20+
├── estimated rows: 1.00
21+
└── TableScan
22+
├── table: default.system.numbers
23+
├── read rows: 1
24+
├── read bytes: 8
25+
├── partitions total: 1
26+
├── partitions scanned: 1
27+
├── push downs: [filters: [], limit: NONE]
28+
└── estimated rows: 1.00
29+
30+
query T
31+
explain select number % 2 as a, number % 3 as b, number % 5 as c from numbers(1) group by cube(a, b, c);
32+
----
33+
EvalScalar
34+
├── expressions: [group_item (#1), group_item (#2), group_item (#3)]
35+
├── estimated rows: 1.00
36+
└── AggregateFinal
37+
├── group by: [a, b, c, _grouping_id]
38+
├── aggregate functions: []
39+
├── estimated rows: 1.00
40+
└── AggregatePartial
41+
├── group by: [a, b, c, _grouping_id]
42+
├── aggregate functions: []
43+
├── estimated rows: 1.00
44+
└── AggregateExpand
45+
├── grouping sets: [(), (a), (b), (c), (a, b), (a, c), (b, c), (a, b, c)]
46+
├── estimated rows: 1.00
47+
└── EvalScalar
48+
├── expressions: [numbers.number (#0) % 2, numbers.number (#0) % 3, numbers.number (#0) % 5]
49+
├── estimated rows: 1.00
50+
└── TableScan
51+
├── table: default.system.numbers
52+
├── read rows: 1
53+
├── read bytes: 8
54+
├── partitions total: 1
55+
├── partitions scanned: 1
56+
├── push downs: [filters: [], limit: NONE]
57+
└── estimated rows: 1.00

0 commit comments

Comments
 (0)