This is an automated email from the ASF dual-hosted git repository.

iffyio 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 e406422b Add support for cluster by expressions (#1883)
e406422b is described below

commit e406422bacb6a8d1a09f053faaa1f9a063dc0f40
Author: Artem Osipov <59066880+osipovar...@users.noreply.github.com>
AuthorDate: Mon Jun 16 13:33:16 2025 +0300

    Add support for cluster by expressions (#1883)
    
    Co-authored-by: osipovartem <artem@PC.localdomain>
---
 src/ast/dml.rs                       |  4 +++-
 src/ast/helpers/stmt_create_table.rs |  6 +++---
 src/dialect/snowflake.rs             |  2 +-
 src/parser/mod.rs                    |  2 +-
 tests/sqlparser_bigquery.rs          |  4 ++--
 tests/sqlparser_snowflake.rs         | 26 +++++++++++++++++++++-----
 6 files changed, 31 insertions(+), 13 deletions(-)

diff --git a/src/ast/dml.rs b/src/ast/dml.rs
index da82a4ed..292650c8 100644
--- a/src/ast/dml.rs
+++ b/src/ast/dml.rs
@@ -175,7 +175,9 @@ pub struct CreateTable {
     pub partition_by: Option<Box<Expr>>,
     /// BigQuery: Table clustering column list.
     /// 
<https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#table_option_list>
-    pub cluster_by: Option<WrappedCollection<Vec<Ident>>>,
+    /// Snowflake: Table clustering list which contains base column, 
expressions on base columns.
+    /// 
<https://docs.snowflake.com/en/user-guide/tables-clustering-keys#defining-a-clustering-key-for-a-table>
+    pub cluster_by: Option<WrappedCollection<Vec<Expr>>>,
     /// Hive: Table clustering column list.
     /// 
<https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateTable>
     pub clustered_by: Option<ClusteredBy>,
diff --git a/src/ast/helpers/stmt_create_table.rs 
b/src/ast/helpers/stmt_create_table.rs
index 542d30ea..d66a869b 100644
--- a/src/ast/helpers/stmt_create_table.rs
+++ b/src/ast/helpers/stmt_create_table.rs
@@ -90,7 +90,7 @@ pub struct CreateTableBuilder {
     pub primary_key: Option<Box<Expr>>,
     pub order_by: Option<OneOrManyWithParens<Expr>>,
     pub partition_by: Option<Box<Expr>>,
-    pub cluster_by: Option<WrappedCollection<Vec<Ident>>>,
+    pub cluster_by: Option<WrappedCollection<Vec<Expr>>>,
     pub clustered_by: Option<ClusteredBy>,
     pub inherits: Option<Vec<ObjectName>>,
     pub strict: bool,
@@ -279,7 +279,7 @@ impl CreateTableBuilder {
         self
     }
 
-    pub fn cluster_by(mut self, cluster_by: 
Option<WrappedCollection<Vec<Ident>>>) -> Self {
+    pub fn cluster_by(mut self, cluster_by: 
Option<WrappedCollection<Vec<Expr>>>) -> Self {
         self.cluster_by = cluster_by;
         self
     }
@@ -542,7 +542,7 @@ impl TryFrom<Statement> for CreateTableBuilder {
 #[derive(Default)]
 pub(crate) struct CreateTableConfiguration {
     pub partition_by: Option<Box<Expr>>,
-    pub cluster_by: Option<WrappedCollection<Vec<Ident>>>,
+    pub cluster_by: Option<WrappedCollection<Vec<Expr>>>,
     pub inherits: Option<Vec<ObjectName>>,
     pub table_options: CreateTableOptions,
 }
diff --git a/src/dialect/snowflake.rs b/src/dialect/snowflake.rs
index 990e2ea2..ea0b94a6 100644
--- a/src/dialect/snowflake.rs
+++ b/src/dialect/snowflake.rs
@@ -453,7 +453,7 @@ pub fn parse_create_table(
                     parser.expect_keyword_is(Keyword::BY)?;
                     parser.expect_token(&Token::LParen)?;
                     let cluster_by = Some(WrappedCollection::Parentheses(
-                        parser.parse_comma_separated(|p| 
p.parse_identifier())?,
+                        parser.parse_comma_separated(|p| p.parse_expr())?,
                     ));
                     parser.expect_token(&Token::RParen)?;
 
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 2c208e2e..73cc3e0e 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -7316,7 +7316,7 @@ impl<'a> Parser<'a> {
         if dialect_of!(self is BigQueryDialect | GenericDialect) {
             if self.parse_keywords(&[Keyword::CLUSTER, Keyword::BY]) {
                 cluster_by = Some(WrappedCollection::NoWrapping(
-                    self.parse_comma_separated(|p| p.parse_identifier())?,
+                    self.parse_comma_separated(|p| p.parse_expr())?,
                 ));
             };
 
diff --git a/tests/sqlparser_bigquery.rs b/tests/sqlparser_bigquery.rs
index b64f190f..6a303577 100644
--- a/tests/sqlparser_bigquery.rs
+++ b/tests/sqlparser_bigquery.rs
@@ -536,8 +536,8 @@ fn parse_create_table_with_options() {
                 (
                     
Some(Box::new(Expr::Identifier(Ident::new("_PARTITIONDATE")))),
                     Some(WrappedCollection::NoWrapping(vec![
-                        Ident::new("userid"),
-                        Ident::new("age"),
+                        Expr::Identifier(Ident::new("userid")),
+                        Expr::Identifier(Ident::new("age")),
                     ])),
                     CreateTableOptions::Options(vec![
                         SqlOption::KeyValue {
diff --git a/tests/sqlparser_snowflake.rs b/tests/sqlparser_snowflake.rs
index 7a164c24..7d734ca2 100644
--- a/tests/sqlparser_snowflake.rs
+++ b/tests/sqlparser_snowflake.rs
@@ -471,15 +471,31 @@ fn test_snowflake_create_table_if_not_exists() {
 
 #[test]
 fn test_snowflake_create_table_cluster_by() {
-    match snowflake().verified_stmt("CREATE TABLE my_table (a INT) CLUSTER BY 
(a, b)") {
+    match snowflake().verified_stmt("CREATE TABLE my_table (a INT) CLUSTER BY 
(a, b, my_func(c))") {
         Statement::CreateTable(CreateTable {
             name, cluster_by, ..
         }) => {
             assert_eq!("my_table", name.to_string());
             assert_eq!(
                 Some(WrappedCollection::Parentheses(vec![
-                    Ident::new("a"),
-                    Ident::new("b"),
+                    Expr::Identifier(Ident::new("a")),
+                    Expr::Identifier(Ident::new("b")),
+                    Expr::Function(Function {
+                        name: ObjectName::from(vec![Ident::new("my_func")]),
+                        uses_odbc_syntax: false,
+                        parameters: FunctionArguments::None,
+                        args: FunctionArguments::List(FunctionArgumentList {
+                            args: 
vec![FunctionArg::Unnamed(FunctionArgExpr::Expr(
+                                Expr::Identifier(Ident::new("c"))
+                            ))],
+                            duplicate_treatment: None,
+                            clauses: vec![],
+                        }),
+                        filter: None,
+                        null_treatment: None,
+                        over: None,
+                        within_group: vec![],
+                    }),
                 ])),
                 cluster_by
             )
@@ -903,8 +919,8 @@ fn test_snowflake_create_iceberg_table_all_options() {
             assert_eq!("my_table", name.to_string());
             assert_eq!(
                 Some(WrappedCollection::Parentheses(vec![
-                    Ident::new("a"),
-                    Ident::new("b"),
+                    Expr::Identifier(Ident::new("a")),
+                    Expr::Identifier(Ident::new("b")),
                 ])),
                 cluster_by
             );


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@datafusion.apache.org
For additional commands, e-mail: commits-h...@datafusion.apache.org

Reply via email to