Skip to content

Commit d667899

Browse files
committed
Support GROUP BY GROUPING SETS in PostgreSQL
1 parent 51a8556 commit d667899

File tree

4 files changed

+43
-1
lines changed

4 files changed

+43
-1
lines changed

src/cst/Select.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export type AllSelectNodes =
3737
| GroupByClause
3838
| GroupByRollup
3939
| GroupByCube
40+
| GroupByGroupingSets
4041
| HavingClause
4142
| WindowClause
4243
| QualifyClause
@@ -266,10 +267,12 @@ export interface GroupByClause extends BaseNode {
266267
type: "group_by_clause";
267268
groupByKw: [Keyword<"GROUP">, Keyword<"BY">];
268269
distinctKw?: Keyword<"ALL" | "DISTINCT">; // PostgreSQL
269-
columns: ListExpr<Expr | GroupByRollup | GroupByCube>;
270+
columns: ListExpr<GroupingElement>;
270271
withRollupKw?: [Keyword<"WITH">, Keyword<"ROLLUP">]; // MySQL, MariaDB
271272
}
272273

274+
type GroupingElement = Expr | GroupByRollup | GroupByCube | GroupByGroupingSets;
275+
273276
// BigQuery, PostgreSQL
274277
export interface GroupByRollup extends BaseNode {
275278
type: "group_by_rollup";
@@ -284,6 +287,13 @@ export interface GroupByCube extends BaseNode {
284287
columns: ParenExpr<ListExpr<Expr>>;
285288
}
286289

290+
// PostgreSQL
291+
export interface GroupByGroupingSets extends BaseNode {
292+
type: "group_by_grouping_sets";
293+
groupingSetsKw: Keyword<"GROUPING SETS">;
294+
columns: ParenExpr<ListExpr<GroupingElement>>;
295+
}
296+
287297
export interface HavingClause extends BaseNode {
288298
type: "having_clause";
289299
havingKw: Keyword<"HAVING">;

src/parser.pegjs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,6 +802,7 @@ group_by_distinct
802802
grouping_element
803803
= group_by_rollup
804804
/ group_by_cube
805+
/ group_by_grouping_sets
805806
/ paren$empty_list
806807
/ expr
807808

@@ -823,6 +824,15 @@ group_by_cube
823824
});
824825
}
825826

827+
group_by_grouping_sets
828+
= kw:(GROUPING __ SETS __) columns:paren$list$grouping_element &postgres {
829+
return loc({
830+
type: "group_by_grouping_sets",
831+
groupingSetsKw: read(kw),
832+
columns,
833+
});
834+
}
835+
826836
/**
827837
* SELECT .. HAVING
828838
* --------------------------------------------------------------------------------------
@@ -4951,6 +4961,7 @@ paren$list$equals_expr = .
49514961
paren$list$expr = .
49524962
paren$list$expr_or_default = .
49534963
paren$list$func_param = .
4964+
paren$list$grouping_element = .
49544965
paren$list$ident = .
49554966
paren$list$literal = .
49564967
paren$list$procedure_param = .
@@ -6035,6 +6046,7 @@ GRANT = kw:"GRANT"i !ident_part { return loc(createK
60356046
GRANTS = kw:"GRANTS"i !ident_part { return loc(createKeyword(kw)); }
60366047
GROUP = kw:"GROUP"i !ident_part { return loc(createKeyword(kw)); }
60376048
GROUP_CONCAT = kw:"GROUP_CONCAT"i !ident_part { return loc(createKeyword(kw)); }
6049+
GROUPING = kw:"GROUPING"i !ident_part { return loc(createKeyword(kw)); }
60386050
GROUPS = kw:"GROUPS"i !ident_part { return loc(createKeyword(kw)); }
60396051
HASH = kw:"HASH"i !ident_part { return loc(createKeyword(kw)); }
60406052
HAVING = kw:"HAVING"i !ident_part { return loc(createKeyword(kw)); }
@@ -6240,6 +6252,7 @@ SELECT = kw:"SELECT"i !ident_part { return loc(createK
62406252
SESSION = kw:"SESSION"i !ident_part { return loc(createKeyword(kw)); }
62416253
SESSION_USER = kw:"SESSION_USER"i !ident_part { return loc(createKeyword(kw)); }
62426254
SET = kw:"SET"i !ident_part { return loc(createKeyword(kw)); }
6255+
SETS = kw:"SETS"i !ident_part { return loc(createKeyword(kw)); }
62436256
SHARE = kw:"SHARE"i !ident_part { return loc(createKeyword(kw)); }
62446257
SHARED = kw:"SHARED"i !ident_part { return loc(createKeyword(kw)); }
62456258
SHOW = kw:"SHOW"i !ident_part { return loc(createKeyword(kw)); }

src/showNode/select.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ export const selectMap: FullTransformMap<string, AllSelectNodes> = {
103103
show([node.groupByKw, node.distinctKw, node.columns, node.withRollupKw]),
104104
group_by_rollup: (node) => show([node.rollupKw, node.columns]),
105105
group_by_cube: (node) => show([node.cubeKw, node.columns]),
106+
group_by_grouping_sets: (node) => show([node.groupingSetsKw, node.columns]),
106107
having_clause: (node) => show([node.havingKw, node.expr]),
107108
qualify_clause: (node) => show([node.qualifyKw, node.expr]),
108109
order_by_clause: (node) =>

test/select/group_by.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,24 @@ describe("select GROUP BY", () => {
4747
});
4848
});
4949

50+
dialect("postgresql", () => {
51+
it("supports GROUPING SETS", () => {
52+
testClauseWc("GROUP BY GROUPING SETS ( (id, name), age )");
53+
});
54+
55+
it("supports multiple GROUPING SETS", () => {
56+
testClauseWc("GROUP BY GROUPING SETS (id), GROUPING SETS (name)");
57+
});
58+
59+
it("supports ROLLUP & CUBE inside GROUPING SETS", () => {
60+
testClauseWc("GROUP BY GROUPING SETS ( ROLLUP(id), CUBE(age) )");
61+
});
62+
63+
it("supports GROUPING SETS inside GROUPING SETS", () => {
64+
testClauseWc("GROUP BY GROUPING SETS ( GROUPING SETS (foo, bar), GROUPING SETS (age) )");
65+
});
66+
});
67+
5068
dialect(["mysql", "mariadb"], () => {
5169
it("supports GROUP BY .. WITH ROLLUP", () => {
5270
testClauseWc("GROUP BY id, name WITH ROLLUP");

0 commit comments

Comments
 (0)