Only set `hive_formats` on `CreateTable` if formats are present (#2105)
diff --git a/src/dialect/snowflake.rs b/src/dialect/snowflake.rs
index bb0d4f1..4cfaddc 100644
--- a/src/dialect/snowflake.rs
+++ b/src/dialect/snowflake.rs
@@ -393,7 +393,7 @@
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 @@
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 @@
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 @@
.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 759e2ee..759f518 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -5831,15 +5831,19 @@
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 @@
.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 @@
}
}
- 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 @@
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 @@
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 @@
.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 3649e8d..91952b8 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -4725,6 +4725,17 @@
}
#[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;";
match alter_table_op(one_statement_parses_to(
diff --git a/tests/sqlparser_duckdb.rs b/tests/sqlparser_duckdb.rs
index 0f80519..73a1afe 100644
--- a/tests/sqlparser_duckdb.rs
+++ b/tests/sqlparser_duckdb.rs
@@ -739,12 +739,7 @@
],
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 99a298f..37e8e96 100644
--- a/tests/sqlparser_mssql.rs
+++ b/tests/sqlparser_mssql.rs
@@ -1881,12 +1881,7 @@
],
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 @@
},],
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 858e2e8..7309a6b 100644
--- a/tests/sqlparser_postgres.rs
+++ b/tests/sqlparser_postgres.rs
@@ -6016,12 +6016,7 @@
],
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,