Skip to content

Commit 38867ab

Browse files
committed
Fix comment reviews
1 parent e3b641c commit 38867ab

File tree

4 files changed

+90
-56
lines changed

4 files changed

+90
-56
lines changed

src/ast/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,14 @@ pub use self::operator::{BinaryOperator, UnaryOperator};
4343
pub use self::query::{
4444
AfterMatchSkip, ConnectBy, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
4545
ExceptSelectItem, ExcludeSelectItem, ExprWithAlias, Fetch, ForClause, ForJson, ForXml,
46-
GroupByExpr, IdentWithAlias, IlikeSelectItem, Join, JoinConstraint, JoinOperator,
47-
JsonTableColumn, JsonTableColumnErrorHandling, LateralView, LockClause, LockType,
46+
GroupByExpr, GroupByWithModifier, IdentWithAlias, IlikeSelectItem, Join, JoinConstraint,
47+
JoinOperator, JsonTableColumn, JsonTableColumnErrorHandling, LateralView, LockClause, LockType,
4848
MatchRecognizePattern, MatchRecognizeSymbol, Measure, NamedWindowDefinition, NamedWindowExpr,
4949
NonBlock, Offset, OffsetRows, OrderByExpr, PivotValueSource, Query, RenameSelectItem,
5050
RepetitionQuantifier, ReplaceSelectElement, ReplaceSelectItem, RowsPerMatch, Select,
5151
SelectInto, SelectItem, SetExpr, SetOperator, SetQuantifier, SymbolDefinition, Table,
5252
TableAlias, TableFactor, TableVersion, TableWithJoins, Top, TopQuantity, ValueTableMode,
53-
Values, WildcardAdditionalOptions, With, WithModifier,
53+
Values, WildcardAdditionalOptions, With,
5454
};
5555
pub use self::value::{
5656
escape_double_quote_string, escape_quoted_string, DateTimeField, DollarQuotedString,

src/ast/query.rs

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -298,22 +298,7 @@ impl fmt::Display for Select {
298298
if let Some(ref selection) = self.selection {
299299
write!(f, " WHERE {selection}")?;
300300
}
301-
match &self.group_by {
302-
GroupByExpr::All(modifiers) => {
303-
write!(f, " GROUP BY ALL")?;
304-
if !modifiers.is_empty() {
305-
write!(f, " {}", display_separated(modifiers, " "))?;
306-
}
307-
}
308-
GroupByExpr::Expressions(exprs, modifiers) => {
309-
if !exprs.is_empty() {
310-
write!(f, " GROUP BY {}", display_comma_separated(exprs))?;
311-
}
312-
if !modifiers.is_empty() {
313-
write!(f, " {}", display_separated(modifiers, " "))?;
314-
}
315-
}
316-
}
301+
write!(f, "{}", self.group_by)?;
317302
if !self.cluster_by.is_empty() {
318303
write!(
319304
f,
@@ -1876,18 +1861,22 @@ impl fmt::Display for SelectInto {
18761861
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
18771862
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
18781863
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1879-
pub enum WithModifier {
1864+
pub enum GroupByWithModifier {
1865+
/// ClickHouse supports GROUP BY WITH modifiers(includes ROLLUP|CUBE|TOTALS).
1866+
/// e.g. GROUP BY year WITH ROLLUP WITH TOTALS
1867+
///
1868+
/// [ClickHouse]: <https://clickhouse.com/docs/en/sql-reference/statements/select/group-by#rollup-modifier>
18801869
Rollup,
18811870
Cube,
18821871
Totals,
18831872
}
18841873

1885-
impl fmt::Display for WithModifier {
1874+
impl fmt::Display for GroupByWithModifier {
18861875
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
18871876
match self {
1888-
WithModifier::Rollup => write!(f, "WITH ROLLUP"),
1889-
WithModifier::Cube => write!(f, "WITH CUBE"),
1890-
WithModifier::Totals => write!(f, "WITH TOTALS"),
1877+
GroupByWithModifier::Rollup => write!(f, "WITH ROLLUP"),
1878+
GroupByWithModifier::Cube => write!(f, "WITH CUBE"),
1879+
GroupByWithModifier::Totals => write!(f, "WITH TOTALS"),
18911880
}
18921881
}
18931882
}
@@ -1905,24 +1894,31 @@ pub enum GroupByExpr {
19051894
/// ClickHouse also supports WITH modifiers after GROUP BY ALL and expressions.
19061895
///
19071896
/// [ClickHouse]: <https://clickhouse.com/docs/en/sql-reference/statements/select/group-by#rollup-modifier>
1908-
All(Vec<WithModifier>),
1897+
All(Vec<GroupByWithModifier>),
19091898

19101899
/// Expressions
1911-
Expressions(Vec<Expr>, Vec<WithModifier>),
1900+
Expressions(Vec<Expr>, Vec<GroupByWithModifier>),
19121901
}
19131902

19141903
impl fmt::Display for GroupByExpr {
19151904
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
19161905
match self {
19171906
GroupByExpr::All(modifiers) => {
1918-
write!(f, "GROUP BY ALL")?;
1919-
write!(f, " {}", display_separated(modifiers, " "))?;
1907+
write!(f, " GROUP BY ALL")?;
1908+
if !modifiers.is_empty() {
1909+
write!(f, " {}", display_separated(modifiers, " "))?;
1910+
}
19201911
Ok(())
19211912
}
19221913
GroupByExpr::Expressions(col_names, modifiers) => {
1914+
if col_names.is_empty() {
1915+
return Ok(());
1916+
}
19231917
let col_names = display_comma_separated(col_names);
1924-
write!(f, "GROUP BY ({col_names})")?;
1925-
write!(f, " {}", display_separated(modifiers, " "))?;
1918+
write!(f, " GROUP BY {col_names}")?;
1919+
if !modifiers.is_empty() {
1920+
write!(f, " {}", display_separated(modifiers, " "))?;
1921+
}
19261922
Ok(())
19271923
}
19281924
}

src/parser/mod.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8294,21 +8294,22 @@ impl<'a> Parser<'a> {
82948294
};
82958295

82968296
let mut modifiers = vec![];
8297-
loop {
8298-
if dialect_of!(self is ClickHouseDialect | GenericDialect)
8299-
&& self.parse_keyword(Keyword::WITH)
8300-
{
8301-
if self.parse_keyword(Keyword::ROLLUP) {
8302-
modifiers.push(WithModifier::Rollup);
8303-
} else if self.parse_keyword(Keyword::CUBE) {
8304-
modifiers.push(WithModifier::Cube);
8305-
} else if self.parse_keyword(Keyword::TOTALS) {
8306-
modifiers.push(WithModifier::Totals);
8307-
} else {
8308-
self.expected("ROLLUP, CUBE, or TOTALS", self.peek_token())?;
8297+
if dialect_of!(self is ClickHouseDialect | GenericDialect) {
8298+
loop {
8299+
if !self.parse_keyword(Keyword::WITH) {
8300+
break;
83098301
}
8310-
} else {
8311-
break;
8302+
let keyword = self.expect_one_of_keywords(&[
8303+
Keyword::ROLLUP,
8304+
Keyword::CUBE,
8305+
Keyword::TOTALS,
8306+
])?;
8307+
modifiers.push(match keyword {
8308+
Keyword::ROLLUP => GroupByWithModifier::Rollup,
8309+
Keyword::CUBE => GroupByWithModifier::Cube,
8310+
Keyword::TOTALS => GroupByWithModifier::Totals,
8311+
_ => unreachable!(),
8312+
});
83128313
}
83138314
}
83148315
match expressions {

tests/sqlparser_clickhouse.rs

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -628,19 +628,56 @@ fn parse_create_materialized_view() {
628628

629629
#[test]
630630
fn parse_group_by_with_modifier() {
631-
match clickhouse_and_generic().verified_stmt("SELECT * FROM t GROUP BY x WITH ROLLUP WITH CUBE")
632-
{
633-
Statement::Query(query) => {
634-
let group_by = &query.body.as_select().unwrap().group_by;
635-
assert_eq!(
636-
group_by,
637-
&GroupByExpr::Expressions(
638-
vec![Identifier(Ident::new("x"))],
639-
vec![WithModifier::Rollup, WithModifier::Cube]
640-
)
641-
);
631+
let clauses = ["x", "a, b", "ALL"];
632+
let modifiers = [
633+
"WITH ROLLUP",
634+
"WITH CUBE",
635+
"WITH TOTALS",
636+
"WITH ROLLUP WITH CUBE",
637+
];
638+
let expected_modifiers = [
639+
vec![GroupByWithModifier::Rollup],
640+
vec![GroupByWithModifier::Cube],
641+
vec![GroupByWithModifier::Totals],
642+
vec![GroupByWithModifier::Rollup, GroupByWithModifier::Cube],
643+
];
644+
for clause in &clauses {
645+
for (modifier, expected_modifier) in modifiers.iter().zip(expected_modifiers.iter()) {
646+
let sql = format!("SELECT * FROM t GROUP BY {clause} {modifier}");
647+
match clickhouse_and_generic().verified_stmt(&sql) {
648+
Statement::Query(query) => {
649+
let group_by = &query.body.as_select().unwrap().group_by;
650+
if clause == &"ALL" {
651+
assert_eq!(group_by, &GroupByExpr::All(expected_modifier.to_vec()));
652+
} else {
653+
assert_eq!(
654+
group_by,
655+
&GroupByExpr::Expressions(
656+
clause
657+
.split(", ")
658+
.map(|c| Identifier(Ident::new(c)))
659+
.collect(),
660+
expected_modifier.to_vec()
661+
)
662+
);
663+
}
664+
}
665+
_ => unreachable!(),
666+
}
642667
}
643-
_ => unreachable!(),
668+
}
669+
670+
// invalid cases
671+
let invalid_cases = [
672+
"SELECT * FROM t GROUP BY x WITH",
673+
"SELECT * FROM t GROUP BY x WITH ROLLUP CUBE",
674+
"SELECT * FROM t GROUP BY x WITH WITH ROLLUP",
675+
"SELECT * FROM t GROUP BY WITH ROLLUP",
676+
];
677+
for sql in invalid_cases {
678+
clickhouse_and_generic()
679+
.parse_sql_statements(sql)
680+
.expect_err("Expected: one of ROLLUP or CUBE or TOTALS, found: WITH");
644681
}
645682
}
646683

0 commit comments

Comments
 (0)