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 e380494e Only set `hive_formats` on `CreateTable` if formats are 
present (#2105)
e380494e is described below

commit e380494eb0440a31d83542a99d9e9df8de3923ca
Author: Michael Victor Zink <[email protected]>
AuthorDate: Wed Nov 26 01:52:23 2025 -0800

    Only set `hive_formats` on `CreateTable` if formats are present (#2105)
---
 src/dialect/snowflake.rs    | 10 +++++-----
 src/parser/mod.rs           | 45 ++++++++++++++++++++++++++++-----------------
 tests/sqlparser_common.rs   | 11 +++++++++++
 tests/sqlparser_duckdb.rs   |  7 +------
 tests/sqlparser_mssql.rs    | 14 ++------------
 tests/sqlparser_postgres.rs |  7 +------
 6 files changed, 48 insertions(+), 46 deletions(-)

diff --git a/src/dialect/snowflake.rs b/src/dialect/snowflake.rs
index bb0d4f16..4cfaddce 100644
--- a/src/dialect/snowflake.rs
+++ b/src/dialect/snowflake.rs
@@ -393,7 +393,7 @@ impl Dialect for SnowflakeDialect {
 
     fn is_column_alias(&self, kw: &Keyword, parser: &mut Parser) -> bool {
         match kw {
-            // The following keywords can be considered an alias as long as 
+            // The following keywords can be considered an alias as long as
             // they are not followed by other tokens that may change their 
meaning
             // e.g. `SELECT * EXCEPT (col1) FROM tbl`
             Keyword::EXCEPT
@@ -408,7 +408,7 @@ impl Dialect for SnowflakeDialect {
             Keyword::LIMIT | Keyword::OFFSET if peek_for_limit_options(parser) 
=> false,
 
             // `FETCH` can be considered an alias as long as it's not followed 
by `FIRST`` or `NEXT`
-            // which would give it a different meanings, for example: 
+            // which would give it a different meanings, for example:
             // `SELECT 1 FETCH FIRST 10 ROWS` - not an alias
             // `SELECT 1 FETCH 10` - not an alias
             Keyword::FETCH if parser.peek_one_of_keywords(&[Keyword::FIRST, 
Keyword::NEXT]).is_some()
@@ -417,8 +417,8 @@ impl Dialect for SnowflakeDialect {
                 false
             }
 
-            // Reserved keywords by the Snowflake dialect, which seem to be 
less strictive 
-            // than what is listed in `keywords::RESERVED_FOR_COLUMN_ALIAS`. 
The following 
+            // Reserved keywords by the Snowflake dialect, which seem to be 
less strictive
+            // than what is listed in `keywords::RESERVED_FOR_COLUMN_ALIAS`. 
The following
             // keywords were tested with the this statement: `SELECT 1 <KW>`.
             Keyword::FROM
             | Keyword::GROUP
@@ -688,7 +688,7 @@ pub fn parse_create_table(
         .iceberg(iceberg)
         .global(global)
         .dynamic(dynamic)
-        .hive_formats(Some(Default::default()));
+        .hive_formats(None);
 
     // Snowflake does not enforce order of the parameters in the statement. 
The parser needs to
     // parse the statement in a loop.
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 759e2eef..759f5189 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -5831,15 +5831,19 @@ impl<'a> Parser<'a> {
         let hive_distribution = self.parse_hive_distribution()?;
         let hive_formats = self.parse_hive_formats()?;
 
-        let file_format = if let Some(ff) = &hive_formats.storage {
-            match ff {
-                HiveIOFormat::FileFormat { format } => Some(*format),
-                _ => None,
+        let file_format = if let Some(ref hf) = hive_formats {
+            if let Some(ref ff) = hf.storage {
+                match ff {
+                    HiveIOFormat::FileFormat { format } => Some(*format),
+                    _ => None,
+                }
+            } else {
+                None
             }
         } else {
             None
         };
-        let location = hive_formats.location.clone();
+        let location = hive_formats.as_ref().and_then(|hf| 
hf.location.clone());
         let table_properties = self.parse_options(Keyword::TBLPROPERTIES)?;
         let table_options = if !table_properties.is_empty() {
             CreateTableOptions::TableProperties(table_properties)
@@ -5850,7 +5854,7 @@ impl<'a> Parser<'a> {
             .columns(columns)
             .constraints(constraints)
             .hive_distribution(hive_distribution)
-            .hive_formats(Some(hive_formats))
+            .hive_formats(hive_formats)
             .table_options(table_options)
             .or_replace(or_replace)
             .if_not_exists(if_not_exists)
@@ -7579,8 +7583,8 @@ impl<'a> Parser<'a> {
         }
     }
 
-    pub fn parse_hive_formats(&mut self) -> Result<HiveFormat, ParserError> {
-        let mut hive_format = HiveFormat::default();
+    pub fn parse_hive_formats(&mut self) -> Result<Option<HiveFormat>, 
ParserError> {
+        let mut hive_format: Option<HiveFormat> = None;
         loop {
             match self.parse_one_of_keywords(&[
                 Keyword::ROW,
@@ -7589,7 +7593,9 @@ impl<'a> Parser<'a> {
                 Keyword::WITH,
             ]) {
                 Some(Keyword::ROW) => {
-                    hive_format.row_format = Some(self.parse_row_format()?);
+                    hive_format
+                        .get_or_insert_with(HiveFormat::default)
+                        .row_format = Some(self.parse_row_format()?);
                 }
                 Some(Keyword::STORED) => {
                     self.expect_keyword_is(Keyword::AS)?;
@@ -7597,24 +7603,29 @@ impl<'a> Parser<'a> {
                         let input_format = self.parse_expr()?;
                         self.expect_keyword_is(Keyword::OUTPUTFORMAT)?;
                         let output_format = self.parse_expr()?;
-                        hive_format.storage = Some(HiveIOFormat::IOF {
-                            input_format,
-                            output_format,
-                        });
+                        
hive_format.get_or_insert_with(HiveFormat::default).storage =
+                            Some(HiveIOFormat::IOF {
+                                input_format,
+                                output_format,
+                            });
                     } else {
                         let format = self.parse_file_format()?;
-                        hive_format.storage = Some(HiveIOFormat::FileFormat { 
format });
+                        
hive_format.get_or_insert_with(HiveFormat::default).storage =
+                            Some(HiveIOFormat::FileFormat { format });
                     }
                 }
                 Some(Keyword::LOCATION) => {
-                    hive_format.location = Some(self.parse_literal_string()?);
+                    
hive_format.get_or_insert_with(HiveFormat::default).location =
+                        Some(self.parse_literal_string()?);
                 }
                 Some(Keyword::WITH) => {
                     self.prev_token();
                     let properties = self
                         .parse_options_with_keywords(&[Keyword::WITH, 
Keyword::SERDEPROPERTIES])?;
                     if !properties.is_empty() {
-                        hive_format.serde_properties = Some(properties);
+                        hive_format
+                            .get_or_insert_with(HiveFormat::default)
+                            .serde_properties = Some(properties);
                     } else {
                         break;
                     }
@@ -7829,7 +7840,7 @@ impl<'a> Parser<'a> {
             .if_not_exists(if_not_exists)
             .transient(transient)
             .hive_distribution(hive_distribution)
-            .hive_formats(Some(hive_formats))
+            .hive_formats(hive_formats)
             .global(global)
             .query(query)
             .without_rowid(without_rowid)
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index 3649e8d3..91952b8c 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -4724,6 +4724,17 @@ fn parse_create_external_table_lowercase() {
     assert_matches!(ast, Statement::CreateTable(CreateTable { .. }));
 }
 
+#[test]
+fn parse_create_table_hive_formats_none_when_no_options() {
+    let sql = "CREATE TABLE simple_table (id INT, name VARCHAR(100))";
+    match verified_stmt(sql) {
+        Statement::CreateTable(CreateTable { hive_formats, .. }) => {
+            assert_eq!(hive_formats, None);
+        }
+        _ => unreachable!(),
+    }
+}
+
 #[test]
 fn parse_alter_table() {
     let add_column = "ALTER TABLE tab ADD COLUMN foo TEXT;";
diff --git a/tests/sqlparser_duckdb.rs b/tests/sqlparser_duckdb.rs
index 0f805195..73a1afe2 100644
--- a/tests/sqlparser_duckdb.rs
+++ b/tests/sqlparser_duckdb.rs
@@ -739,12 +739,7 @@ fn test_duckdb_union_datatype() {
             ],
             constraints: Default::default(),
             hive_distribution: HiveDistributionStyle::NONE,
-            hive_formats: Some(HiveFormat {
-                row_format: Default::default(),
-                serde_properties: Default::default(),
-                storage: Default::default(),
-                location: Default::default()
-            }),
+            hive_formats: None,
             file_format: Default::default(),
             location: Default::default(),
             query: Default::default(),
diff --git a/tests/sqlparser_mssql.rs b/tests/sqlparser_mssql.rs
index 99a298f8..37e8e962 100644
--- a/tests/sqlparser_mssql.rs
+++ b/tests/sqlparser_mssql.rs
@@ -1881,12 +1881,7 @@ fn parse_create_table_with_valid_options() {
                 ],
                 constraints: vec![],
                 hive_distribution: HiveDistributionStyle::NONE,
-                hive_formats: Some(HiveFormat {
-                    row_format: None,
-                    serde_properties: None,
-                    storage: None,
-                    location: None,
-                },),
+                hive_formats: None,
                 file_format: None,
                 location: None,
                 query: None,
@@ -2053,12 +2048,7 @@ fn parse_create_table_with_identity_column() {
                 },],
                 constraints: vec![],
                 hive_distribution: HiveDistributionStyle::NONE,
-                hive_formats: Some(HiveFormat {
-                    row_format: None,
-                    serde_properties: None,
-                    storage: None,
-                    location: None,
-                },),
+                hive_formats: None,
                 file_format: None,
                 location: None,
                 query: None,
diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs
index 858e2e80..7309a6ba 100644
--- a/tests/sqlparser_postgres.rs
+++ b/tests/sqlparser_postgres.rs
@@ -6016,12 +6016,7 @@ fn parse_trigger_related_functions() {
             ],
             constraints: vec![],
             hive_distribution: HiveDistributionStyle::NONE,
-            hive_formats: Some(HiveFormat {
-                row_format: None,
-                serde_properties: None,
-                storage: None,
-                location: None
-            }),
+            hive_formats: None,
             file_format: None,
             location: None,
             query: None,


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to