@@ -50,6 +50,10 @@ pub struct Query {
50
50
/// `FOR JSON { AUTO | PATH } [ , INCLUDE_NULL_VALUES ]`
51
51
/// (MSSQL-specific)
52
52
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 > > ,
53
57
}
54
58
55
59
impl fmt:: Display for Query {
@@ -70,6 +74,9 @@ impl fmt::Display for Query {
70
74
if !self . limit_by . is_empty ( ) {
71
75
write ! ( f, " BY {}" , display_separated( & self . limit_by, ", " ) ) ?;
72
76
}
77
+ if let Some ( ref settings) = self . settings {
78
+ write ! ( f, " SETTINGS {}" , display_comma_separated( settings) ) ?;
79
+ }
73
80
if let Some ( ref fetch) = self . fetch {
74
81
write ! ( f, " {fetch}" ) ?;
75
82
}
@@ -240,6 +247,11 @@ pub struct Select {
240
247
pub from : Vec < TableWithJoins > ,
241
248
/// LATERAL VIEWs
242
249
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 > ,
243
255
/// WHERE
244
256
pub selection : Option < Expr > ,
245
257
/// GROUP BY
@@ -295,14 +307,17 @@ impl fmt::Display for Select {
295
307
write ! ( f, "{lv}" ) ?;
296
308
}
297
309
}
310
+ if let Some ( ref prewhere) = self . prewhere {
311
+ write ! ( f, " PREWHERE {prewhere}" ) ?;
312
+ }
298
313
if let Some ( ref selection) = self . selection {
299
314
write ! ( f, " WHERE {selection}" ) ?;
300
315
}
301
316
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, _ ) => {
304
319
if !exprs. is_empty ( ) {
305
- write ! ( f, " GROUP BY {}" , display_comma_separated ( exprs ) ) ? ;
320
+ write ! ( f, " {}" , self . group_by ) ?
306
321
}
307
322
}
308
323
}
@@ -547,19 +562,20 @@ impl fmt::Display for IdentWithAlias {
547
562
#[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
548
563
pub struct WildcardAdditionalOptions {
549
564
/// `[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 >
551
566
pub opt_ilike : Option < IlikeSelectItem > ,
552
567
/// `[EXCLUDE...]`.
553
568
pub opt_exclude : Option < ExcludeSelectItem > ,
554
569
/// `[EXCEPT...]`.
555
570
/// Clickhouse syntax: <https://clickhouse.com/docs/en/sql-reference/statements/select#except>
556
571
pub opt_except : Option < ExceptSelectItem > ,
557
- /// `[RENAME ...]`.
558
- pub opt_rename : Option < RenameSelectItem > ,
559
572
/// `[REPLACE]`
560
573
/// BigQuery syntax: <https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select_replace>
561
574
/// 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>
562
576
pub opt_replace : Option < ReplaceSelectItem > ,
577
+ /// `[RENAME ...]`.
578
+ pub opt_rename : Option < RenameSelectItem > ,
563
579
}
564
580
565
581
impl fmt:: Display for WildcardAdditionalOptions {
@@ -573,12 +589,12 @@ impl fmt::Display for WildcardAdditionalOptions {
573
589
if let Some ( except) = & self . opt_except {
574
590
write ! ( f, " {except}" ) ?;
575
591
}
576
- if let Some ( rename) = & self . opt_rename {
577
- write ! ( f, " {rename}" ) ?;
578
- }
579
592
if let Some ( replace) = & self . opt_replace {
580
593
write ! ( f, " {replace}" ) ?;
581
594
}
595
+ if let Some ( rename) = & self . opt_rename {
596
+ write ! ( f, " {rename}" ) ?;
597
+ }
582
598
Ok ( ( ) )
583
599
}
584
600
}
@@ -827,6 +843,20 @@ impl fmt::Display for ConnectBy {
827
843
}
828
844
}
829
845
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
+
830
860
/// An expression optionally followed by an alias.
831
861
///
832
862
/// Example:
@@ -1865,27 +1895,65 @@ impl fmt::Display for SelectInto {
1865
1895
}
1866
1896
}
1867
1897
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
+
1868
1921
#[ derive( Debug , Clone , PartialEq , PartialOrd , Eq , Ord , Hash ) ]
1869
1922
#[ cfg_attr( feature = "serde" , derive( Serialize , Deserialize ) ) ]
1870
1923
#[ cfg_attr( feature = "visitor" , derive( Visit , VisitMut ) ) ]
1871
1924
pub enum GroupByExpr {
1872
- /// ALL syntax of [Snowflake], and [DuckDB]
1925
+ /// ALL syntax of [Snowflake], [DuckDB] and [ClickHouse].
1873
1926
///
1874
1927
/// [Snowflake]: <https://docs.snowflake.com/en/sql-reference/constructs/group-by#label-group-by-all-columns>
1875
1928
/// [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 > ) ,
1877
1935
1878
1936
/// Expressions
1879
- Expressions ( Vec < Expr > ) ,
1937
+ Expressions ( Vec < Expr > , Vec < GroupByWithModifier > ) ,
1880
1938
}
1881
1939
1882
1940
impl fmt:: Display for GroupByExpr {
1883
1941
fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
1884
1942
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) => {
1887
1951
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 ( ( ) )
1889
1957
}
1890
1958
}
1891
1959
}
0 commit comments