Skip to content

Commit 51a8556

Browse files
committed
Support PostgreSQL GROUP BY CUBE()
1 parent e931678 commit 51a8556

File tree

4 files changed

+31
-6
lines changed

4 files changed

+31
-6
lines changed

src/cst/Select.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export type AllSelectNodes =
3636
| WhereClause
3737
| GroupByClause
3838
| GroupByRollup
39+
| GroupByCube
3940
| HavingClause
4041
| WindowClause
4142
| QualifyClause
@@ -265,7 +266,7 @@ export interface GroupByClause extends BaseNode {
265266
type: "group_by_clause";
266267
groupByKw: [Keyword<"GROUP">, Keyword<"BY">];
267268
distinctKw?: Keyword<"ALL" | "DISTINCT">; // PostgreSQL
268-
columns: ListExpr<Expr | GroupByRollup>;
269+
columns: ListExpr<Expr | GroupByRollup | GroupByCube>;
269270
withRollupKw?: [Keyword<"WITH">, Keyword<"ROLLUP">]; // MySQL, MariaDB
270271
}
271272

@@ -276,6 +277,13 @@ export interface GroupByRollup extends BaseNode {
276277
columns: ParenExpr<ListExpr<Expr>>;
277278
}
278279

280+
// PostgreSQL
281+
export interface GroupByCube extends BaseNode {
282+
type: "group_by_cube";
283+
cubeKw: Keyword<"CUBE">;
284+
columns: ParenExpr<ListExpr<Expr>>;
285+
}
286+
279287
export interface HavingClause extends BaseNode {
280288
type: "having_clause";
281289
havingKw: Keyword<"HAVING">;

src/parser.pegjs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,7 @@ group_by_distinct
801801

802802
grouping_element
803803
= group_by_rollup
804+
/ group_by_cube
804805
/ paren$empty_list
805806
/ expr
806807

@@ -813,6 +814,15 @@ group_by_rollup
813814
});
814815
}
815816

817+
group_by_cube
818+
= kw:(CUBE __) cols:paren$list$expr &postgres {
819+
return loc({
820+
type: "group_by_cube",
821+
cubeKw: read(kw),
822+
columns: cols,
823+
});
824+
}
825+
816826
/**
817827
* SELECT .. HAVING
818828
* --------------------------------------------------------------------------------------
@@ -5915,6 +5925,7 @@ COPY = kw:"COPY"i !ident_part { return loc(createK
59155925
COUNT = kw:"COUNT"i !ident_part { return loc(createKeyword(kw)); }
59165926
CREATE = kw:"CREATE"i !ident_part { return loc(createKeyword(kw)); }
59175927
CROSS = kw:"CROSS"i !ident_part { return loc(createKeyword(kw)); }
5928+
CUBE = kw:"CUBE"i !ident_part { return loc(createKeyword(kw)); }
59185929
CUME_DIST = kw:"CUME_DIST"i !ident_part { return loc(createKeyword(kw)); }
59195930
CURRENT = kw:"CURRENT"i !ident_part { return loc(createKeyword(kw)); }
59205931
CURRENT_CATALOG = kw:"CURRENT_CATALOG"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
@@ -102,6 +102,7 @@ export const selectMap: FullTransformMap<string, AllSelectNodes> = {
102102
group_by_clause: (node) =>
103103
show([node.groupByKw, node.distinctKw, node.columns, node.withRollupKw]),
104104
group_by_rollup: (node) => show([node.rollupKw, node.columns]),
105+
group_by_cube: (node) => show([node.cubeKw, node.columns]),
105106
having_clause: (node) => show([node.havingKw, node.expr]),
106107
qualify_clause: (node) => show([node.qualifyKw, node.expr]),
107108
order_by_clause: (node) =>

test/select/group_by.test.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,22 @@ describe("select GROUP BY", () => {
2727
});
2828

2929
dialect("postgresql", () => {
30-
it("supports multiple ROLLUPs in one GROUP BY", () => {
31-
testClauseWc("GROUP BY ROLLUP(id), ROLLUP(name)");
30+
it("supports GROUP BY CUBE()", () => {
31+
testClauseWc("GROUP BY CUBE (id, name + age)");
32+
testClauseWc("GROUP BY CUBE (id, (name, age))");
3233
});
3334

34-
it("parses multiple ROLLUPs as group_by_rollup nodes", () => {
35-
const clause = parseClause("GROUP BY ROLLUP(id), ROLLUP(name)");
35+
it("supports multiple ROLLUPs and CUBEs in one GROUP BY", () => {
36+
testClauseWc("GROUP BY ROLLUP(id), CUBE(name)");
37+
});
38+
39+
it("parses multiple ROLLUPs & CUBEs as group_by_rollup/cube nodes", () => {
40+
const clause = parseClause("GROUP BY ROLLUP(id), CUBE(name)");
3641
if (clause.type !== "group_by_clause") {
3742
throw new Error("Expected group_by_clause");
3843
}
3944
expect(clause.columns.items[0].type).toBe("group_by_rollup");
40-
expect(clause.columns.items[1].type).toBe("group_by_rollup");
45+
expect(clause.columns.items[1].type).toBe("group_by_cube");
4146
});
4247
});
4348
});

0 commit comments

Comments
 (0)