This is an automated email from the ASF dual-hosted git repository.
github-bot pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
The following commit(s) were added to refs/heads/main by this push:
new a7d77634 Refactor: replace more `dialect_of!` checks with `Dialect`
trait methods (#2175)
a7d77634 is described below
commit a7d77634df6da1a5440a0a8cdc22aaa85439ee19
Author: Andy Grove <[email protected]>
AuthorDate: Fri Jan 23 12:29:08 2026 -0700
Refactor: replace more `dialect_of!` checks with `Dialect` trait methods
(#2175)
Co-authored-by: Claude Opus 4.5 <[email protected]>
---
src/dialect/bigquery.rs | 5 ++
src/dialect/clickhouse.rs | 40 ++++++++++++
src/dialect/duckdb.rs | 15 +++++
src/dialect/generic.rs | 48 +++++++++++++++
src/dialect/mod.rs | 153 ++++++++++++++++++++++++++++++++++++++++++++++
src/dialect/snowflake.rs | 15 +++++
src/parser/mod.rs | 50 +++++++--------
7 files changed, 297 insertions(+), 29 deletions(-)
diff --git a/src/dialect/bigquery.rs b/src/dialect/bigquery.rs
index 6ad8a508..5563d133 100644
--- a/src/dialect/bigquery.rs
+++ b/src/dialect/bigquery.rs
@@ -156,4 +156,9 @@ impl Dialect for BigQueryDialect {
fn supports_create_table_multi_schema_info_sources(&self) -> bool {
true
}
+
+ /// See
<https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select_replace>
+ fn supports_select_wildcard_replace(&self) -> bool {
+ true
+ }
}
diff --git a/src/dialect/clickhouse.rs b/src/dialect/clickhouse.rs
index 39e8a0b3..041b94ec 100644
--- a/src/dialect/clickhouse.rs
+++ b/src/dialect/clickhouse.rs
@@ -100,4 +100,44 @@ impl Dialect for ClickHouseDialect {
fn supports_nested_comments(&self) -> bool {
true
}
+
+ /// See <https://clickhouse.com/docs/en/sql-reference/statements/optimize>
+ fn supports_optimize_table(&self) -> bool {
+ true
+ }
+
+ /// See
<https://clickhouse.com/docs/en/sql-reference/statements/select/prewhere>
+ fn supports_prewhere(&self) -> bool {
+ true
+ }
+
+ /// See
<https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier>
+ fn supports_with_fill(&self) -> bool {
+ true
+ }
+
+ /// See
<https://clickhouse.com/docs/en/sql-reference/statements/select/limit-by>
+ fn supports_limit_by(&self) -> bool {
+ true
+ }
+
+ /// See
<https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier>
+ fn supports_interpolate(&self) -> bool {
+ true
+ }
+
+ /// See
<https://clickhouse.com/docs/en/sql-reference/statements/select#settings-in-select-query>
+ fn supports_settings(&self) -> bool {
+ true
+ }
+
+ /// See
<https://clickhouse.com/docs/en/sql-reference/statements/select/format>
+ fn supports_select_format(&self) -> bool {
+ true
+ }
+
+ /// See
<https://clickhouse.com/docs/sql-reference/statements/select#replace>
+ fn supports_select_wildcard_replace(&self) -> bool {
+ true
+ }
}
diff --git a/src/dialect/duckdb.rs b/src/dialect/duckdb.rs
index ea099013..b3803aee 100644
--- a/src/dialect/duckdb.rs
+++ b/src/dialect/duckdb.rs
@@ -113,4 +113,19 @@ impl Dialect for DuckDbDialect {
fn supports_notnull_operator(&self) -> bool {
true
}
+
+ /// See <https://duckdb.org/docs/extensions/overview>
+ fn supports_install(&self) -> bool {
+ true
+ }
+
+ /// See <https://duckdb.org/docs/sql/statements/attach#detach-syntax>
+ fn supports_detach(&self) -> bool {
+ true
+ }
+
+ /// See <https://duckdb.org/docs/sql/query_syntax/select#replace-clause>
+ fn supports_select_wildcard_replace(&self) -> bool {
+ true
+ }
}
diff --git a/src/dialect/generic.rs b/src/dialect/generic.rs
index 42510e2f..d460c523 100644
--- a/src/dialect/generic.rs
+++ b/src/dialect/generic.rs
@@ -223,4 +223,52 @@ impl Dialect for GenericDialect {
fn supports_lambda_functions(&self) -> bool {
true
}
+
+ fn supports_select_wildcard_replace(&self) -> bool {
+ true
+ }
+
+ fn supports_select_wildcard_ilike(&self) -> bool {
+ true
+ }
+
+ fn supports_select_wildcard_rename(&self) -> bool {
+ true
+ }
+
+ fn supports_optimize_table(&self) -> bool {
+ true
+ }
+
+ fn supports_install(&self) -> bool {
+ true
+ }
+
+ fn supports_detach(&self) -> bool {
+ true
+ }
+
+ fn supports_prewhere(&self) -> bool {
+ true
+ }
+
+ fn supports_with_fill(&self) -> bool {
+ true
+ }
+
+ fn supports_limit_by(&self) -> bool {
+ true
+ }
+
+ fn supports_interpolate(&self) -> bool {
+ true
+ }
+
+ fn supports_settings(&self) -> bool {
+ true
+ }
+
+ fn supports_select_format(&self) -> bool {
+ true
+ }
}
diff --git a/src/dialect/mod.rs b/src/dialect/mod.rs
index 284fc417..98ec93da 100644
--- a/src/dialect/mod.rs
+++ b/src/dialect/mod.rs
@@ -1332,6 +1332,159 @@ pub trait Dialect: Debug + Any {
fn supports_binary_kw_as_cast(&self) -> bool {
false
}
+
+ /// Returns true if this dialect supports the `REPLACE` option in a
+ /// `SELECT *` wildcard expression.
+ ///
+ /// Example:
+ /// ```sql
+ /// SELECT * REPLACE (col1 AS col1_alias) FROM table;
+ /// ```
+ ///
+ ///
[BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#select_replace)
+ ///
[ClickHouse](https://clickhouse.com/docs/sql-reference/statements/select#replace)
+ ///
[DuckDB](https://duckdb.org/docs/sql/query_syntax/select#replace-clause)
+ ///
[Snowflake](https://docs.snowflake.com/en/sql-reference/sql/select#parameters)
+ fn supports_select_wildcard_replace(&self) -> bool {
+ false
+ }
+
+ /// Returns true if this dialect supports the `ILIKE` option in a
+ /// `SELECT *` wildcard expression.
+ ///
+ /// Example:
+ /// ```sql
+ /// SELECT * ILIKE '%pattern%' FROM table;
+ /// ```
+ ///
+ ///
[Snowflake](https://docs.snowflake.com/en/sql-reference/sql/select#parameters)
+ fn supports_select_wildcard_ilike(&self) -> bool {
+ false
+ }
+
+ /// Returns true if this dialect supports the `RENAME` option in a
+ /// `SELECT *` wildcard expression.
+ ///
+ /// Example:
+ /// ```sql
+ /// SELECT * RENAME col1 AS col1_alias FROM table;
+ /// ```
+ ///
+ ///
[Snowflake](https://docs.snowflake.com/en/sql-reference/sql/select#parameters)
+ fn supports_select_wildcard_rename(&self) -> bool {
+ false
+ }
+
+ /// Returns true if this dialect supports the `OPTIMIZE TABLE` statement.
+ ///
+ /// Example:
+ /// ```sql
+ /// OPTIMIZE TABLE table_name;
+ /// ```
+ ///
+ ///
[ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
+ fn supports_optimize_table(&self) -> bool {
+ false
+ }
+
+ /// Returns true if this dialect supports the `INSTALL` statement.
+ ///
+ /// Example:
+ /// ```sql
+ /// INSTALL extension_name;
+ /// ```
+ ///
+ /// [DuckDB](https://duckdb.org/docs/extensions/overview)
+ fn supports_install(&self) -> bool {
+ false
+ }
+
+ /// Returns true if this dialect supports the `DETACH` statement.
+ ///
+ /// Example:
+ /// ```sql
+ /// DETACH DATABASE db_name;
+ /// ```
+ ///
+ /// [DuckDB](https://duckdb.org/docs/sql/statements/attach#detach-syntax)
+ fn supports_detach(&self) -> bool {
+ false
+ }
+
+ /// Returns true if this dialect supports the `PREWHERE` clause
+ /// in `SELECT` statements.
+ ///
+ /// Example:
+ /// ```sql
+ /// SELECT * FROM table PREWHERE col > 0 WHERE col < 100;
+ /// ```
+ ///
+ ///
[ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/prewhere)
+ fn supports_prewhere(&self) -> bool {
+ false
+ }
+
+ /// Returns true if this dialect supports the `WITH FILL` clause
+ /// in `ORDER BY` expressions.
+ ///
+ /// Example:
+ /// ```sql
+ /// SELECT * FROM table ORDER BY col WITH FILL FROM 1 TO 10 STEP 1;
+ /// ```
+ ///
+ ///
[ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier)
+ fn supports_with_fill(&self) -> bool {
+ false
+ }
+
+ /// Returns true if this dialect supports the `LIMIT BY` clause.
+ ///
+ /// Example:
+ /// ```sql
+ /// SELECT * FROM table LIMIT 10 BY col;
+ /// ```
+ ///
+ ///
[ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/limit-by)
+ fn supports_limit_by(&self) -> bool {
+ false
+ }
+
+ /// Returns true if this dialect supports the `INTERPOLATE` clause
+ /// in `ORDER BY` expressions.
+ ///
+ /// Example:
+ /// ```sql
+ /// SELECT * FROM table ORDER BY col WITH FILL INTERPOLATE (col2 AS col2 +
1);
+ /// ```
+ ///
+ ///
[ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/order-by#order-by-expr-with-fill-modifier)
+ fn supports_interpolate(&self) -> bool {
+ false
+ }
+
+ /// Returns true if this dialect supports the `SETTINGS` clause.
+ ///
+ /// Example:
+ /// ```sql
+ /// SELECT * FROM table SETTINGS max_threads = 4;
+ /// ```
+ ///
+ ///
[ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select#settings-in-select-query)
+ fn supports_settings(&self) -> bool {
+ false
+ }
+
+ /// Returns true if this dialect supports the `FORMAT` clause in `SELECT`
statements.
+ ///
+ /// Example:
+ /// ```sql
+ /// SELECT * FROM table FORMAT JSON;
+ /// ```
+ ///
+ ///
[ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/format)
+ fn supports_select_format(&self) -> bool {
+ false
+ }
}
/// Operators for which precedence must be defined.
diff --git a/src/dialect/snowflake.rs b/src/dialect/snowflake.rs
index d768f7a2..e2d8cb2e 100644
--- a/src/dialect/snowflake.rs
+++ b/src/dialect/snowflake.rs
@@ -616,6 +616,21 @@ impl Dialect for SnowflakeDialect {
fn supports_semantic_view_table_factor(&self) -> bool {
true
}
+
+ /// See <https://docs.snowflake.com/en/sql-reference/sql/select#parameters>
+ fn supports_select_wildcard_replace(&self) -> bool {
+ true
+ }
+
+ /// See <https://docs.snowflake.com/en/sql-reference/sql/select#parameters>
+ fn supports_select_wildcard_ilike(&self) -> bool {
+ true
+ }
+
+ /// See <https://docs.snowflake.com/en/sql-reference/sql/select#parameters>
+ fn supports_select_wildcard_rename(&self) -> bool {
+ true
+ }
}
// Peeks ahead to identify tokens that are expected after
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index d021d163..0276d058 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -633,7 +633,7 @@ impl<'a> Parser<'a> {
self.parse_attach_database()
}
}
- Keyword::DETACH if dialect_of!(self is DuckDbDialect |
GenericDialect) => {
+ Keyword::DETACH if self.dialect.supports_detach() => {
self.parse_detach_duckdb_database()
}
Keyword::MSCK => self.parse_msck().map(Into::into),
@@ -693,12 +693,10 @@ impl<'a> Parser<'a> {
}
Keyword::RENAME => self.parse_rename(),
// `INSTALL` is duckdb specific
https://duckdb.org/docs/extensions/overview
- Keyword::INSTALL if dialect_of!(self is DuckDbDialect |
GenericDialect) => {
- self.parse_install()
- }
+ Keyword::INSTALL if self.dialect.supports_install() =>
self.parse_install(),
Keyword::LOAD => self.parse_load(),
// `OPTIMIZE` is clickhouse specific
https://clickhouse.tech/docs/en/sql-reference/statements/optimize/
- Keyword::OPTIMIZE if dialect_of!(self is ClickHouseDialect |
GenericDialect) => {
+ Keyword::OPTIMIZE if self.dialect.supports_optimize_table() =>
{
self.parse_optimize_table()
}
// `COMMENT` is snowflake specific
https://docs.snowflake.com/en/sql-reference/sql/comment
@@ -12208,7 +12206,7 @@ impl<'a> Parser<'a> {
}
} else {
let exprs =
self.parse_comma_separated(Parser::parse_order_by_expr)?;
- let interpolate = if dialect_of!(self is ClickHouseDialect
| GenericDialect) {
+ let interpolate = if self.dialect.supports_interpolate() {
self.parse_interpolations()?
} else {
None
@@ -12250,9 +12248,7 @@ impl<'a> Parser<'a> {
}));
}
- let limit_by = if dialect_of!(self is ClickHouseDialect |
GenericDialect)
- && self.parse_keyword(Keyword::BY)
- {
+ let limit_by = if self.dialect.supports_limit_by() &&
self.parse_keyword(Keyword::BY) {
Some(self.parse_comma_separated(Parser::parse_expr)?)
} else {
None
@@ -13264,18 +13260,17 @@ impl<'a> Parser<'a> {
locks.push(self.parse_lock()?);
}
}
- let format_clause = if dialect_of!(self is ClickHouseDialect |
GenericDialect)
- && self.parse_keyword(Keyword::FORMAT)
- {
- if self.parse_keyword(Keyword::NULL) {
- Some(FormatClause::Null)
+ let format_clause =
+ if self.dialect.supports_select_format() &&
self.parse_keyword(Keyword::FORMAT) {
+ if self.parse_keyword(Keyword::NULL) {
+ Some(FormatClause::Null)
+ } else {
+ let ident = self.parse_identifier()?;
+ Some(FormatClause::Identifier(ident))
+ }
} else {
- let ident = self.parse_identifier()?;
- Some(FormatClause::Identifier(ident))
- }
- } else {
- None
- };
+ None
+ };
let pipe_operators = if self.dialect.supports_pipe_operator() {
self.parse_pipe_operators()?
@@ -13519,8 +13514,7 @@ impl<'a> Parser<'a> {
}
fn parse_settings(&mut self) -> Result<Option<Vec<Setting>>, ParserError> {
- let settings = if dialect_of!(self is ClickHouseDialect|GenericDialect)
- && self.parse_keyword(Keyword::SETTINGS)
+ let settings = if self.dialect.supports_settings() &&
self.parse_keyword(Keyword::SETTINGS)
{
let key_values = self.parse_comma_separated(|p| {
let key = p.parse_identifier()?;
@@ -13930,8 +13924,7 @@ impl<'a> Parser<'a> {
}
}
- let prewhere = if dialect_of!(self is ClickHouseDialect|GenericDialect)
- && self.parse_keyword(Keyword::PREWHERE)
+ let prewhere = if self.dialect.supports_prewhere() &&
self.parse_keyword(Keyword::PREWHERE)
{
Some(self.parse_expr()?)
} else {
@@ -17358,7 +17351,7 @@ impl<'a> Parser<'a> {
&mut self,
wildcard_token: TokenWithSpan,
) -> Result<WildcardAdditionalOptions, ParserError> {
- let opt_ilike = if dialect_of!(self is GenericDialect |
SnowflakeDialect) {
+ let opt_ilike = if self.dialect.supports_select_wildcard_ilike() {
self.parse_optional_select_item_ilike()?
} else {
None
@@ -17374,13 +17367,12 @@ impl<'a> Parser<'a> {
} else {
None
};
- let opt_replace = if dialect_of!(self is GenericDialect |
BigQueryDialect | ClickHouseDialect | DuckDbDialect | SnowflakeDialect)
- {
+ let opt_replace = if self.dialect.supports_select_wildcard_replace() {
self.parse_optional_select_item_replace()?
} else {
None
};
- let opt_rename = if dialect_of!(self is GenericDialect |
SnowflakeDialect) {
+ let opt_rename = if self.dialect.supports_select_wildcard_rename() {
self.parse_optional_select_item_rename()?
} else {
None
@@ -17577,7 +17569,7 @@ impl<'a> Parser<'a> {
let options = self.parse_order_by_options()?;
- let with_fill = if dialect_of!(self is ClickHouseDialect |
GenericDialect)
+ let with_fill = if self.dialect.supports_with_fill()
&& self.parse_keywords(&[Keyword::WITH, Keyword::FILL])
{
Some(self.parse_with_fill()?)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]