Skip to content

Commit 5ce16ed

Browse files
committed
Merge remote-tracking branch 'origin/main' into support-drop-procederue
2 parents 7b78eb9 + 17e5c0c commit 5ce16ed

13 files changed

+726
-166
lines changed

derive/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ impl Visit for TableFactor {
9797
match self {
9898
Self::Table { name, alias } => {
9999
visitor.pre_visit_relation(name)?;
100-
alias.visit(name)?;
100+
name.visit(visitor)?;
101101
visitor.post_visit_relation(name)?;
102102
alias.visit(visitor)?;
103103
}

src/ast/data_type.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use serde::{Deserialize, Serialize};
2020
#[cfg(feature = "visitor")]
2121
use sqlparser_derive::{Visit, VisitMut};
2222

23-
use crate::ast::{display_comma_separated, ObjectName, StructField};
23+
use crate::ast::{display_comma_separated, ObjectName, StructField, UnionField};
2424

2525
use super::{value::escape_single_quote_string, ColumnDef};
2626

@@ -303,6 +303,10 @@ pub enum DataType {
303303
/// [hive]: https://docs.cloudera.com/cdw-runtime/cloud/impala-sql-reference/topics/impala-struct.html
304304
/// [bigquery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type
305305
Struct(Vec<StructField>),
306+
/// Union
307+
///
308+
/// [duckdb]: https://duckdb.org/docs/sql/data_types/union.html
309+
Union(Vec<UnionField>),
306310
/// Nullable - special marker NULL represents in ClickHouse as a data type.
307311
///
308312
/// [clickhouse]: https://clickhouse.com/docs/en/sql-reference/data-types/nullable
@@ -516,6 +520,9 @@ impl fmt::Display for DataType {
516520
write!(f, "STRUCT")
517521
}
518522
}
523+
DataType::Union(fields) => {
524+
write!(f, "UNION({})", display_comma_separated(fields))
525+
}
519526
// ClickHouse
520527
DataType::Nullable(data_type) => {
521528
write!(f, "Nullable({})", data_type)

src/ast/mod.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,12 @@ 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,
51-
SelectInto, SelectItem, SetExpr, SetOperator, SetQuantifier, SymbolDefinition, Table,
51+
SelectInto, SelectItem, SetExpr, SetOperator, SetQuantifier, Setting, SymbolDefinition, Table,
5252
TableAlias, TableFactor, TableVersion, TableWithJoins, Top, TopQuantity, ValueTableMode,
5353
Values, WildcardAdditionalOptions, With,
5454
};
@@ -294,6 +294,23 @@ impl fmt::Display for StructField {
294294
}
295295
}
296296

297+
/// A field definition within a union
298+
///
299+
/// [duckdb]: https://duckdb.org/docs/sql/data_types/union.html
300+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
301+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
302+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
303+
pub struct UnionField {
304+
pub field_name: Ident,
305+
pub field_type: DataType,
306+
}
307+
308+
impl fmt::Display for UnionField {
309+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
310+
write!(f, "{} {}", self.field_name, self.field_type)
311+
}
312+
}
313+
297314
/// A dictionary field within a dictionary.
298315
///
299316
/// [duckdb]: https://duckdb.org/docs/sql/data_types/struct#creating-structs

src/ast/query.rs

Lines changed: 83 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ pub struct Query {
5050
/// `FOR JSON { AUTO | PATH } [ , INCLUDE_NULL_VALUES ]`
5151
/// (MSSQL-specific)
5252
pub for_clause: Option<ForClause>,
53+
/// ClickHouse syntax: `SELECT * FROM t SETTINGS key1 = value1, key2 = value2`
54+
///
55+
/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select#settings-in-select-query)
56+
pub settings: Option<Vec<Setting>>,
5357
}
5458

5559
impl fmt::Display for Query {
@@ -70,6 +74,9 @@ impl fmt::Display for Query {
7074
if !self.limit_by.is_empty() {
7175
write!(f, " BY {}", display_separated(&self.limit_by, ", "))?;
7276
}
77+
if let Some(ref settings) = self.settings {
78+
write!(f, " SETTINGS {}", display_comma_separated(settings))?;
79+
}
7380
if let Some(ref fetch) = self.fetch {
7481
write!(f, " {fetch}")?;
7582
}
@@ -240,6 +247,11 @@ pub struct Select {
240247
pub from: Vec<TableWithJoins>,
241248
/// LATERAL VIEWs
242249
pub lateral_views: Vec<LateralView>,
250+
/// ClickHouse syntax: `PREWHERE a = 1 WHERE b = 2`,
251+
/// and it can be used together with WHERE selection.
252+
///
253+
/// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/prewhere)
254+
pub prewhere: Option<Expr>,
243255
/// WHERE
244256
pub selection: Option<Expr>,
245257
/// GROUP BY
@@ -295,14 +307,17 @@ impl fmt::Display for Select {
295307
write!(f, "{lv}")?;
296308
}
297309
}
310+
if let Some(ref prewhere) = self.prewhere {
311+
write!(f, " PREWHERE {prewhere}")?;
312+
}
298313
if let Some(ref selection) = self.selection {
299314
write!(f, " WHERE {selection}")?;
300315
}
301316
match &self.group_by {
302-
GroupByExpr::All => write!(f, " GROUP BY ALL")?,
303-
GroupByExpr::Expressions(exprs) => {
317+
GroupByExpr::All(_) => write!(f, " {}", self.group_by)?,
318+
GroupByExpr::Expressions(exprs, _) => {
304319
if !exprs.is_empty() {
305-
write!(f, " GROUP BY {}", display_comma_separated(exprs))?;
320+
write!(f, " {}", self.group_by)?
306321
}
307322
}
308323
}
@@ -547,19 +562,20 @@ impl fmt::Display for IdentWithAlias {
547562
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
548563
pub struct WildcardAdditionalOptions {
549564
/// `[ILIKE...]`.
550-
/// Snowflake syntax: <https://docs.snowflake.com/en/sql-reference/sql/select>
565+
/// Snowflake syntax: <https://docs.snowflake.com/en/sql-reference/sql/select#parameters>
551566
pub opt_ilike: Option<IlikeSelectItem>,
552567
/// `[EXCLUDE...]`.
553568
pub opt_exclude: Option<ExcludeSelectItem>,
554569
/// `[EXCEPT...]`.
555570
/// Clickhouse syntax: <https://clickhouse.com/docs/en/sql-reference/statements/select#except>
556571
pub opt_except: Option<ExceptSelectItem>,
557-
/// `[RENAME ...]`.
558-
pub opt_rename: Option<RenameSelectItem>,
559572
/// `[REPLACE]`
560573
/// BigQuery syntax: <https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select_replace>
561574
/// Clickhouse syntax: <https://clickhouse.com/docs/en/sql-reference/statements/select#replace>
575+
/// Snowflake syntax: <https://docs.snowflake.com/en/sql-reference/sql/select#parameters>
562576
pub opt_replace: Option<ReplaceSelectItem>,
577+
/// `[RENAME ...]`.
578+
pub opt_rename: Option<RenameSelectItem>,
563579
}
564580

565581
impl fmt::Display for WildcardAdditionalOptions {
@@ -573,12 +589,12 @@ impl fmt::Display for WildcardAdditionalOptions {
573589
if let Some(except) = &self.opt_except {
574590
write!(f, " {except}")?;
575591
}
576-
if let Some(rename) = &self.opt_rename {
577-
write!(f, " {rename}")?;
578-
}
579592
if let Some(replace) = &self.opt_replace {
580593
write!(f, " {replace}")?;
581594
}
595+
if let Some(rename) = &self.opt_rename {
596+
write!(f, " {rename}")?;
597+
}
582598
Ok(())
583599
}
584600
}
@@ -827,6 +843,20 @@ impl fmt::Display for ConnectBy {
827843
}
828844
}
829845

846+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
847+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
848+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
849+
pub struct Setting {
850+
pub key: Ident,
851+
pub value: Value,
852+
}
853+
854+
impl fmt::Display for Setting {
855+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
856+
write!(f, "{} = {}", self.key, self.value)
857+
}
858+
}
859+
830860
/// An expression optionally followed by an alias.
831861
///
832862
/// Example:
@@ -1865,27 +1895,65 @@ impl fmt::Display for SelectInto {
18651895
}
18661896
}
18671897

1898+
/// ClickHouse supports GROUP BY WITH modifiers(includes ROLLUP|CUBE|TOTALS).
1899+
/// e.g. GROUP BY year WITH ROLLUP WITH TOTALS
1900+
///
1901+
/// [ClickHouse]: <https://clickhouse.com/docs/en/sql-reference/statements/select/group-by#rollup-modifier>
1902+
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1903+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1904+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1905+
pub enum GroupByWithModifier {
1906+
Rollup,
1907+
Cube,
1908+
Totals,
1909+
}
1910+
1911+
impl fmt::Display for GroupByWithModifier {
1912+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1913+
match self {
1914+
GroupByWithModifier::Rollup => write!(f, "WITH ROLLUP"),
1915+
GroupByWithModifier::Cube => write!(f, "WITH CUBE"),
1916+
GroupByWithModifier::Totals => write!(f, "WITH TOTALS"),
1917+
}
1918+
}
1919+
}
1920+
18681921
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
18691922
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
18701923
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
18711924
pub enum GroupByExpr {
1872-
/// ALL syntax of [Snowflake], and [DuckDB]
1925+
/// ALL syntax of [Snowflake], [DuckDB] and [ClickHouse].
18731926
///
18741927
/// [Snowflake]: <https://docs.snowflake.com/en/sql-reference/constructs/group-by#label-group-by-all-columns>
18751928
/// [DuckDB]: <https://duckdb.org/docs/sql/query_syntax/groupby.html>
1876-
All,
1929+
/// [ClickHouse]: <https://clickhouse.com/docs/en/sql-reference/statements/select/group-by#group-by-all>
1930+
///
1931+
/// ClickHouse also supports WITH modifiers after GROUP BY ALL and expressions.
1932+
///
1933+
/// [ClickHouse]: <https://clickhouse.com/docs/en/sql-reference/statements/select/group-by#rollup-modifier>
1934+
All(Vec<GroupByWithModifier>),
18771935

18781936
/// Expressions
1879-
Expressions(Vec<Expr>),
1937+
Expressions(Vec<Expr>, Vec<GroupByWithModifier>),
18801938
}
18811939

18821940
impl fmt::Display for GroupByExpr {
18831941
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
18841942
match self {
1885-
GroupByExpr::All => write!(f, "GROUP BY ALL"),
1886-
GroupByExpr::Expressions(col_names) => {
1943+
GroupByExpr::All(modifiers) => {
1944+
write!(f, "GROUP BY ALL")?;
1945+
if !modifiers.is_empty() {
1946+
write!(f, " {}", display_separated(modifiers, " "))?;
1947+
}
1948+
Ok(())
1949+
}
1950+
GroupByExpr::Expressions(col_names, modifiers) => {
18871951
let col_names = display_comma_separated(col_names);
1888-
write!(f, "GROUP BY ({col_names})")
1952+
write!(f, "GROUP BY {col_names}")?;
1953+
if !modifiers.is_empty() {
1954+
write!(f, " {}", display_separated(modifiers, " "))?;
1955+
}
1956+
Ok(())
18891957
}
18901958
}
18911959
}

src/keywords.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,7 @@ define_keywords!(
558558
PRECISION,
559559
PREPARE,
560560
PRESERVE,
561+
PREWHERE,
561562
PRIMARY,
562563
PRIOR,
563564
PRIVILEGES,
@@ -650,6 +651,7 @@ define_keywords!(
650651
SESSION_USER,
651652
SET,
652653
SETS,
654+
SETTINGS,
653655
SHARE,
654656
SHOW,
655657
SIMILAR,
@@ -721,6 +723,7 @@ define_keywords!(
721723
TINYINT,
722724
TO,
723725
TOP,
726+
TOTALS,
724727
TRAILING,
725728
TRANSACTION,
726729
TRANSIENT,
@@ -849,6 +852,10 @@ pub const RESERVED_FOR_TABLE_ALIAS: &[Keyword] = &[
849852
Keyword::FOR,
850853
// for MYSQL PARTITION SELECTION
851854
Keyword::PARTITION,
855+
// for Clickhouse PREWHERE
856+
Keyword::PREWHERE,
857+
// for ClickHouse SELECT * FROM t SETTINGS ...
858+
Keyword::SETTINGS,
852859
// for Snowflake START WITH .. CONNECT BY
853860
Keyword::START,
854861
Keyword::CONNECT,

0 commit comments

Comments
 (0)