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]

Reply via email to