Skip to content

Commit 0837ac6

Browse files
committed
Merge commit '68c41a9d5a99eea1f98b254d7c26fdbe0a1a4cf7'
2 parents e5b608c + 68c41a9 commit 0837ac6

File tree

12 files changed

+313
-92
lines changed

12 files changed

+313
-92
lines changed

src/ast/data_type.rs

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ pub enum DataType {
8585
///
8686
/// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#binary-string-type
8787
/// [MS SQL Server]: https://learn.microsoft.com/pt-br/sql/t-sql/data-types/binary-and-varbinary-transact-sql?view=sql-server-ver16
88-
Varbinary(Option<u64>),
88+
Varbinary(Option<BinaryLength>),
8989
/// Large binary object with optional length e.g. BLOB, BLOB(1000), [standard], [Oracle]
9090
///
9191
/// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#binary-large-object-string-type
@@ -408,9 +408,7 @@ impl fmt::Display for DataType {
408408
}
409409
DataType::Clob(size) => format_type_with_optional_length(f, "CLOB", size, false),
410410
DataType::Binary(size) => format_type_with_optional_length(f, "BINARY", size, false),
411-
DataType::Varbinary(size) => {
412-
format_type_with_optional_length(f, "VARBINARY", size, false)
413-
}
411+
DataType::Varbinary(size) => format_varbinary_type(f, "VARBINARY", size),
414412
DataType::Blob(size) => format_type_with_optional_length(f, "BLOB", size, false),
415413
DataType::TinyBlob => write!(f, "TINYBLOB"),
416414
DataType::MediumBlob => write!(f, "MEDIUMBLOB"),
@@ -673,6 +671,18 @@ fn format_character_string_type(
673671
Ok(())
674672
}
675673

674+
fn format_varbinary_type(
675+
f: &mut fmt::Formatter,
676+
sql_type: &str,
677+
size: &Option<BinaryLength>,
678+
) -> fmt::Result {
679+
write!(f, "{sql_type}")?;
680+
if let Some(size) = size {
681+
write!(f, "({size})")?;
682+
}
683+
Ok(())
684+
}
685+
676686
fn format_datetime_precision_and_tz(
677687
f: &mut fmt::Formatter,
678688
sql_type: &'static str,
@@ -862,6 +872,32 @@ impl fmt::Display for CharLengthUnits {
862872
}
863873
}
864874

875+
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
876+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
877+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
878+
pub enum BinaryLength {
879+
IntegerLength {
880+
/// Default (if VARYING)
881+
length: u64,
882+
},
883+
/// VARBINARY(MAX) used in T-SQL (Microsoft SQL Server)
884+
Max,
885+
}
886+
887+
impl fmt::Display for BinaryLength {
888+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
889+
match self {
890+
BinaryLength::IntegerLength { length } => {
891+
write!(f, "{}", length)?;
892+
}
893+
BinaryLength::Max => {
894+
write!(f, "MAX")?;
895+
}
896+
}
897+
Ok(())
898+
}
899+
}
900+
865901
/// Represents the data type of the elements in an array (if any) as well as
866902
/// the syntax used to declare the array.
867903
///

src/ast/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ use sqlparser_derive::{Visit, VisitMut};
4040
use crate::tokenizer::Span;
4141

4242
pub use self::data_type::{
43-
ArrayElemTypeDef, CharLengthUnits, CharacterLength, DataType, EnumMember, ExactNumberInfo,
44-
StructBracketKind, TimezoneInfo,
43+
ArrayElemTypeDef, BinaryLength, CharLengthUnits, CharacterLength, DataType, EnumMember,
44+
ExactNumberInfo, StructBracketKind, TimezoneInfo,
4545
};
4646
pub use self::dcl::{
4747
AlterRoleOperation, ResetConfig, RoleOption, SecondaryRoles, SetConfigValue, Use,

src/ast/query.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2077,20 +2077,34 @@ impl fmt::Display for Join {
20772077
self.relation,
20782078
suffix(constraint)
20792079
),
2080-
JoinOperator::LeftOuter(constraint) => write!(
2080+
JoinOperator::Left(constraint) => write!(
20812081
f,
20822082
" {}LEFT JOIN {}{}",
20832083
prefix(constraint),
20842084
self.relation,
20852085
suffix(constraint)
20862086
),
2087-
JoinOperator::RightOuter(constraint) => write!(
2087+
JoinOperator::LeftOuter(constraint) => write!(
2088+
f,
2089+
" {}LEFT OUTER JOIN {}{}",
2090+
prefix(constraint),
2091+
self.relation,
2092+
suffix(constraint)
2093+
),
2094+
JoinOperator::Right(constraint) => write!(
20882095
f,
20892096
" {}RIGHT JOIN {}{}",
20902097
prefix(constraint),
20912098
self.relation,
20922099
suffix(constraint)
20932100
),
2101+
JoinOperator::RightOuter(constraint) => write!(
2102+
f,
2103+
" {}RIGHT OUTER JOIN {}{}",
2104+
prefix(constraint),
2105+
self.relation,
2106+
suffix(constraint)
2107+
),
20942108
JoinOperator::FullOuter(constraint) => write!(
20952109
f,
20962110
" {}FULL JOIN {}{}",
@@ -2162,7 +2176,9 @@ impl fmt::Display for Join {
21622176
pub enum JoinOperator {
21632177
Join(JoinConstraint),
21642178
Inner(JoinConstraint),
2179+
Left(JoinConstraint),
21652180
LeftOuter(JoinConstraint),
2181+
Right(JoinConstraint),
21662182
RightOuter(JoinConstraint),
21672183
FullOuter(JoinConstraint),
21682184
CrossJoin,
@@ -2599,13 +2615,18 @@ impl fmt::Display for SelectInto {
25992615
/// e.g. GROUP BY year WITH ROLLUP WITH TOTALS
26002616
///
26012617
/// [ClickHouse]: <https://clickhouse.com/docs/en/sql-reference/statements/select/group-by#rollup-modifier>
2602-
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
2618+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
26032619
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
26042620
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
26052621
pub enum GroupByWithModifier {
26062622
Rollup,
26072623
Cube,
26082624
Totals,
2625+
/// Hive supports GROUP BY GROUPING SETS syntax.
2626+
/// e.g. GROUP BY year , month GROUPING SETS((year,month),(year),(month))
2627+
///
2628+
/// [Hive]: <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=30151323#EnhancedAggregation,Cube,GroupingandRollup-GROUPINGSETSclause>
2629+
GroupingSets(Expr),
26092630
}
26102631

26112632
impl fmt::Display for GroupByWithModifier {
@@ -2614,6 +2635,9 @@ impl fmt::Display for GroupByWithModifier {
26142635
GroupByWithModifier::Rollup => write!(f, "WITH ROLLUP"),
26152636
GroupByWithModifier::Cube => write!(f, "WITH CUBE"),
26162637
GroupByWithModifier::Totals => write!(f, "WITH TOTALS"),
2638+
GroupByWithModifier::GroupingSets(expr) => {
2639+
write!(f, "{expr}")
2640+
}
26172641
}
26182642
}
26192643
}

src/ast/spans.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,7 +2015,9 @@ impl Spanned for JoinOperator {
20152015
match self {
20162016
JoinOperator::Join(join_constraint) => join_constraint.span(),
20172017
JoinOperator::Inner(join_constraint) => join_constraint.span(),
2018+
JoinOperator::Left(join_constraint) => join_constraint.span(),
20182019
JoinOperator::LeftOuter(join_constraint) => join_constraint.span(),
2020+
JoinOperator::Right(join_constraint) => join_constraint.span(),
20192021
JoinOperator::RightOuter(join_constraint) => join_constraint.span(),
20202022
JoinOperator::FullOuter(join_constraint) => join_constraint.span(),
20212023
JoinOperator::CrossJoin => Span::empty(),

src/dialect/clickhouse.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,4 +84,14 @@ impl Dialect for ClickHouseDialect {
8484
fn supports_order_by_all(&self) -> bool {
8585
true
8686
}
87+
88+
// See <https://clickhouse.com/docs/en/sql-reference/aggregate-functions/grouping_function#grouping-sets>
89+
fn supports_group_by_expr(&self) -> bool {
90+
true
91+
}
92+
93+
/// See <https://clickhouse.com/docs/en/sql-reference/statements/select/group-by#rollup-modifier>
94+
fn supports_group_by_with_modifier(&self) -> bool {
95+
true
96+
}
8797
}

src/dialect/generic.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ impl Dialect for GenericDialect {
4848
true
4949
}
5050

51+
fn supports_group_by_with_modifier(&self) -> bool {
52+
true
53+
}
54+
5155
fn supports_connect_by(&self) -> bool {
5256
true
5357
}

src/dialect/hive.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,23 @@ impl Dialect for HiveDialect {
5252
true
5353
}
5454

55-
/// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362061#Tutorial-BuiltInOperators>
55+
/// See <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362061#Tutorial-BuiltInOperators>
5656
fn supports_bang_not_operator(&self) -> bool {
5757
true
5858
}
5959

60-
/// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
60+
/// See <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
6161
fn supports_load_data(&self) -> bool {
6262
true
6363
}
6464

65-
/// See Hive <https://cwiki.apache.org/confluence/display/hive/languagemanual+sampling>
65+
/// See <https://cwiki.apache.org/confluence/display/hive/languagemanual+sampling>
6666
fn supports_table_sample_before_alias(&self) -> bool {
6767
true
6868
}
69+
70+
/// See <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=30151323#EnhancedAggregation,Cube,GroupingandRollup-CubesandRollupsr>
71+
fn supports_group_by_with_modifier(&self) -> bool {
72+
true
73+
}
6974
}

src/dialect/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,12 @@ pub trait Dialect: Debug + Any {
245245
false
246246
}
247247

248+
/// Returns true if the dialects supports `GROUP BY` modifiers prefixed by a `WITH` keyword.
249+
/// Example: `GROUP BY value WITH ROLLUP`.
250+
fn supports_group_by_with_modifier(&self) -> bool {
251+
false
252+
}
253+
248254
/// Returns true if the dialect supports CONNECT BY.
249255
fn supports_connect_by(&self) -> bool {
250256
false

src/parser/mod.rs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5740,7 +5740,7 @@ impl<'a> Parser<'a> {
57405740
drop_behavior,
57415741
})
57425742
}
5743-
/// ```sql
5743+
/// ```sql
57445744
/// DROP CONNECTOR [IF EXISTS] name
57455745
/// ```
57465746
///
@@ -8766,7 +8766,7 @@ impl<'a> Parser<'a> {
87668766
}
87678767
Keyword::CLOB => Ok(DataType::Clob(self.parse_optional_precision()?)),
87688768
Keyword::BINARY => Ok(DataType::Binary(self.parse_optional_precision()?)),
8769-
Keyword::VARBINARY => Ok(DataType::Varbinary(self.parse_optional_precision()?)),
8769+
Keyword::VARBINARY => Ok(DataType::Varbinary(self.parse_optional_binary_length()?)),
87708770
Keyword::BLOB => Ok(DataType::Blob(self.parse_optional_precision()?)),
87718771
Keyword::TINYBLOB => Ok(DataType::TinyBlob),
87728772
Keyword::MEDIUMBLOB => Ok(DataType::MediumBlob),
@@ -9148,7 +9148,7 @@ impl<'a> Parser<'a> {
91489148
};
91499149

91509150
let mut modifiers = vec![];
9151-
if dialect_of!(self is ClickHouseDialect | GenericDialect) {
9151+
if self.dialect.supports_group_by_with_modifier() {
91529152
loop {
91539153
if !self.parse_keyword(Keyword::WITH) {
91549154
break;
@@ -9171,6 +9171,14 @@ impl<'a> Parser<'a> {
91719171
});
91729172
}
91739173
}
9174+
if self.parse_keywords(&[Keyword::GROUPING, Keyword::SETS]) {
9175+
self.expect_token(&Token::LParen)?;
9176+
let result = self.parse_comma_separated(|p| p.parse_tuple(true, true))?;
9177+
self.expect_token(&Token::RParen)?;
9178+
modifiers.push(GroupByWithModifier::GroupingSets(Expr::GroupingSets(
9179+
result,
9180+
)));
9181+
};
91749182
let group_by = match expressions {
91759183
None => GroupByExpr::All(modifiers),
91769184
Some(exprs) => GroupByExpr::Expressions(exprs, modifiers),
@@ -9664,6 +9672,16 @@ impl<'a> Parser<'a> {
96649672
}
96659673
}
96669674

9675+
pub fn parse_optional_binary_length(&mut self) -> Result<Option<BinaryLength>, ParserError> {
9676+
if self.consume_token(&Token::LParen) {
9677+
let binary_length = self.parse_binary_length()?;
9678+
self.expect_token(&Token::RParen)?;
9679+
Ok(Some(binary_length))
9680+
} else {
9681+
Ok(None)
9682+
}
9683+
}
9684+
96679685
pub fn parse_character_length(&mut self) -> Result<CharacterLength, ParserError> {
96689686
if self.parse_keyword(Keyword::MAX) {
96699687
return Ok(CharacterLength::Max);
@@ -9679,6 +9697,14 @@ impl<'a> Parser<'a> {
96799697
Ok(CharacterLength::IntegerLength { length, unit })
96809698
}
96819699

9700+
pub fn parse_binary_length(&mut self) -> Result<BinaryLength, ParserError> {
9701+
if self.parse_keyword(Keyword::MAX) {
9702+
return Ok(BinaryLength::Max);
9703+
}
9704+
let length = self.parse_literal_uint()?;
9705+
Ok(BinaryLength::IntegerLength { length })
9706+
}
9707+
96829708
pub fn parse_optional_precision_scale(
96839709
&mut self,
96849710
) -> Result<(Option<u64>, Option<u64>), ParserError> {
@@ -11178,9 +11204,9 @@ impl<'a> Parser<'a> {
1117811204
}
1117911205
Some(Keyword::JOIN) => {
1118011206
if is_left {
11181-
JoinOperator::LeftOuter
11207+
JoinOperator::Left
1118211208
} else {
11183-
JoinOperator::RightOuter
11209+
JoinOperator::Right
1118411210
}
1118511211
}
1118611212
_ => {

tests/sqlparser_clickhouse.rs

Lines changed: 0 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,61 +1069,6 @@ fn parse_create_materialized_view() {
10691069
clickhouse_and_generic().verified_stmt(sql);
10701070
}
10711071

1072-
#[test]
1073-
fn parse_group_by_with_modifier() {
1074-
let clauses = ["x", "a, b", "ALL"];
1075-
let modifiers = [
1076-
"WITH ROLLUP",
1077-
"WITH CUBE",
1078-
"WITH TOTALS",
1079-
"WITH ROLLUP WITH CUBE",
1080-
];
1081-
let expected_modifiers = [
1082-
vec![GroupByWithModifier::Rollup],
1083-
vec![GroupByWithModifier::Cube],
1084-
vec![GroupByWithModifier::Totals],
1085-
vec![GroupByWithModifier::Rollup, GroupByWithModifier::Cube],
1086-
];
1087-
for clause in &clauses {
1088-
for (modifier, expected_modifier) in modifiers.iter().zip(expected_modifiers.iter()) {
1089-
let sql = format!("SELECT * FROM t GROUP BY {clause} {modifier}");
1090-
match clickhouse_and_generic().verified_stmt(&sql) {
1091-
Statement::Query(query) => {
1092-
let group_by = &query.body.as_select().unwrap().group_by;
1093-
if clause == &"ALL" {
1094-
assert_eq!(group_by, &GroupByExpr::All(expected_modifier.to_vec()));
1095-
} else {
1096-
assert_eq!(
1097-
group_by,
1098-
&GroupByExpr::Expressions(
1099-
clause
1100-
.split(", ")
1101-
.map(|c| Identifier(Ident::new(c)))
1102-
.collect(),
1103-
expected_modifier.to_vec()
1104-
)
1105-
);
1106-
}
1107-
}
1108-
_ => unreachable!(),
1109-
}
1110-
}
1111-
}
1112-
1113-
// invalid cases
1114-
let invalid_cases = [
1115-
"SELECT * FROM t GROUP BY x WITH",
1116-
"SELECT * FROM t GROUP BY x WITH ROLLUP CUBE",
1117-
"SELECT * FROM t GROUP BY x WITH WITH ROLLUP",
1118-
"SELECT * FROM t GROUP BY WITH ROLLUP",
1119-
];
1120-
for sql in invalid_cases {
1121-
clickhouse_and_generic()
1122-
.parse_sql_statements(sql)
1123-
.expect_err("Expected: one of ROLLUP or CUBE or TOTALS, found: WITH");
1124-
}
1125-
}
1126-
11271072
#[test]
11281073
fn parse_select_order_by_with_fill_interpolate() {
11291074
let sql = "SELECT id, fname, lname FROM customer WHERE id < 5 \

0 commit comments

Comments
 (0)