diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 2d34d1d77..0d322c194 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -3201,6 +3201,7 @@ impl fmt::Display for Statement { if let Some(HiveFormat { row_format, + serde_properties, storage, location, }) = hive_formats @@ -3225,6 +3226,13 @@ impl fmt::Display for Statement { } _ => (), } + if let Some(serde_properties) = serde_properties.as_ref() { + write!( + f, + " WITH SERDEPROPERTIES ({})", + display_comma_separated(serde_properties) + )?; + } if !*external { if let Some(loc) = location { write!(f, " LOCATION '{loc}'")?; @@ -4875,6 +4883,7 @@ pub enum HiveIOFormat { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct HiveFormat { pub row_format: Option, + pub serde_properties: Option>, pub storage: Option, pub location: Option, } diff --git a/src/keywords.rs b/src/keywords.rs index 3b98b2367..10a136278 100644 --- a/src/keywords.rs +++ b/src/keywords.rs @@ -596,6 +596,7 @@ define_keywords!( SEQUENCEFILE, SEQUENCES, SERDE, + SERDEPROPERTIES, SERIALIZABLE, SESSION, SESSION_USER, diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 9d1f11691..f1fa7bc98 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -4353,7 +4353,12 @@ impl<'a> Parser<'a> { pub fn parse_hive_formats(&mut self) -> Result { let mut hive_format = HiveFormat::default(); loop { - match self.parse_one_of_keywords(&[Keyword::ROW, Keyword::STORED, Keyword::LOCATION]) { + match self.parse_one_of_keywords(&[ + Keyword::ROW, + Keyword::STORED, + Keyword::LOCATION, + Keyword::WITH, + ]) { Some(Keyword::ROW) => { hive_format.row_format = Some(self.parse_row_format()?); } @@ -4375,6 +4380,16 @@ impl<'a> Parser<'a> { Some(Keyword::LOCATION) => { hive_format.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); + } else { + break; + } + } None => break, _ => break, } diff --git a/tests/sqlparser_hive.rs b/tests/sqlparser_hive.rs index 934d25a4b..acf6c5829 100644 --- a/tests/sqlparser_hive.rs +++ b/tests/sqlparser_hive.rs @@ -27,9 +27,11 @@ use sqlparser::test_utils::*; fn parse_table_create() { let sql = r#"CREATE TABLE IF NOT EXISTS db.table (a BIGINT, b STRING, c TIMESTAMP) PARTITIONED BY (d STRING, e TIMESTAMP) STORED AS ORC LOCATION 's3://...' TBLPROPERTIES ("prop" = "2", "asdf" = '1234', 'asdf' = "1234", "asdf" = 2)"#; let iof = r#"CREATE TABLE IF NOT EXISTS db.table (a BIGINT, b STRING, c TIMESTAMP) PARTITIONED BY (d STRING, e TIMESTAMP) STORED AS INPUTFORMAT 'org.apache.hadoop.hive.ql.io.orc.OrcInputFormat' OUTPUTFORMAT 'org.apache.hadoop.hive.ql.io.orc.OrcOutputFormat' LOCATION 's3://...'"#; + let serdeproperties = r#"CREATE EXTERNAL TABLE IF NOT EXISTS db.table (a STRING, b STRING, c STRING) PARTITIONED BY (d STRING, e STRING) ROW FORMAT SERDE 'org.apache.hadoop.hive.serde.config' WITH SERDEPROPERTIES ('prop_a' = 'a', 'prop_b' = 'b') STORED AS TEXTFILE LOCATION 's3://...' TBLPROPERTIES ('prop_c' = 'c')"#; hive().verified_stmt(sql); hive().verified_stmt(iof); + hive().verified_stmt(serdeproperties); } fn generic(options: Option) -> TestedDialects {