Support SELECT * EXCEPT/REPLACE syntax from ClickHouse (#1013)

This commit is contained in:
Lukasz Stefaniak 2023-10-23 23:55:11 +02:00 committed by GitHub
parent 56f24ce236
commit e857a45201
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 13 deletions

View file

@ -434,11 +434,13 @@ pub struct WildcardAdditionalOptions {
/// `[EXCLUDE...]`. /// `[EXCLUDE...]`.
pub opt_exclude: Option<ExcludeSelectItem>, pub opt_exclude: Option<ExcludeSelectItem>,
/// `[EXCEPT...]`. /// `[EXCEPT...]`.
/// Clickhouse syntax: <https://clickhouse.com/docs/en/sql-reference/statements/select#except>
pub opt_except: Option<ExceptSelectItem>, pub opt_except: Option<ExceptSelectItem>,
/// `[RENAME ...]`. /// `[RENAME ...]`.
pub opt_rename: Option<RenameSelectItem>, pub opt_rename: Option<RenameSelectItem>,
/// `[REPLACE]` /// `[REPLACE]`
/// BigQuery syntax: <https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select_replace> /// BigQuery syntax: <https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select_replace>
/// Clickhouse syntax: <https://clickhouse.com/docs/en/sql-reference/statements/select#replace>
pub opt_replace: Option<ReplaceSelectItem>, pub opt_replace: Option<ReplaceSelectItem>,
} }

View file

@ -6993,7 +6993,8 @@ impl<'a> Parser<'a> {
} else { } else {
None None
}; };
let opt_except = if dialect_of!(self is GenericDialect | BigQueryDialect) { let opt_except = if dialect_of!(self is GenericDialect | BigQueryDialect | ClickHouseDialect)
{
self.parse_optional_select_item_except()? self.parse_optional_select_item_except()?
} else { } else {
None None
@ -7004,7 +7005,8 @@ impl<'a> Parser<'a> {
None None
}; };
let opt_replace = if dialect_of!(self is GenericDialect | BigQueryDialect) { let opt_replace = if dialect_of!(self is GenericDialect | BigQueryDialect | ClickHouseDialect)
{
self.parse_optional_select_item_replace()? self.parse_optional_select_item_replace()?
} else { } else {
None None
@ -7047,6 +7049,7 @@ impl<'a> Parser<'a> {
&mut self, &mut self,
) -> Result<Option<ExceptSelectItem>, ParserError> { ) -> Result<Option<ExceptSelectItem>, ParserError> {
let opt_except = if self.parse_keyword(Keyword::EXCEPT) { let opt_except = if self.parse_keyword(Keyword::EXCEPT) {
if self.peek_token().token == Token::LParen {
let idents = self.parse_parenthesized_column_list(Mandatory, false)?; let idents = self.parse_parenthesized_column_list(Mandatory, false)?;
match &idents[..] { match &idents[..] {
[] => { [] => {
@ -7060,6 +7063,14 @@ impl<'a> Parser<'a> {
additional_elements: idents.to_vec(), additional_elements: idents.to_vec(),
}), }),
} }
} else {
// Clickhouse allows EXCEPT column_name
let ident = self.parse_identifier()?;
Some(ExceptSelectItem {
first_element: ident,
additional_elements: vec![],
})
}
} else { } else {
None None
}; };

View file

@ -355,6 +355,24 @@ fn parse_limit_by() {
); );
} }
#[test]
fn parse_select_star_except() {
clickhouse().verified_stmt("SELECT * EXCEPT (prev_status) FROM anomalies");
}
#[test]
fn parse_select_star_except_no_parens() {
clickhouse().one_statement_parses_to(
"SELECT * EXCEPT prev_status FROM anomalies",
"SELECT * EXCEPT (prev_status) FROM anomalies",
);
}
#[test]
fn parse_select_star_replace() {
clickhouse().verified_stmt("SELECT * REPLACE (i + 1 AS i) FROM columns_transformers");
}
fn clickhouse() -> TestedDialects { fn clickhouse() -> TestedDialects {
TestedDialects { TestedDialects {
dialects: vec![Box::new(ClickHouseDialect {})], dialects: vec![Box::new(ClickHouseDialect {})],