From 8055b91676ee453abe6dc9fa339f6e40030cf3bb Mon Sep 17 00:00:00 2001 From: Maciej Obuchowski Date: Tue, 14 Feb 2023 17:12:53 +0100 Subject: [PATCH 1/2] snowflake: add support for TRANSIENT keyword Signed-off-by: Maciej Obuchowski --- src/ast/helpers/stmt_create_table.rs | 10 ++++++++++ src/ast/mod.rs | 5 ++++- src/keywords.rs | 1 + src/parser.rs | 5 ++++- tests/sqlparser_snowflake.rs | 14 ++++++++++++++ 5 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/ast/helpers/stmt_create_table.rs b/src/ast/helpers/stmt_create_table.rs index 14bcd3633..60307d4ef 100644 --- a/src/ast/helpers/stmt_create_table.rs +++ b/src/ast/helpers/stmt_create_table.rs @@ -50,6 +50,7 @@ pub struct CreateTableBuilder { pub external: bool, pub global: Option, pub if_not_exists: bool, + pub transient: bool, pub name: ObjectName, pub columns: Vec, pub constraints: Vec, @@ -78,6 +79,7 @@ impl CreateTableBuilder { external: false, global: None, if_not_exists: false, + transient: false, name, columns: vec![], constraints: vec![], @@ -123,6 +125,11 @@ impl CreateTableBuilder { self } + pub fn transient(mut self, transient: bool) -> Self { + self.transient = transient; + self + } + pub fn columns(mut self, columns: Vec) -> Self { self.columns = columns; self @@ -213,6 +220,7 @@ impl CreateTableBuilder { external: self.external, global: self.global, if_not_exists: self.if_not_exists, + transient: self.transient, name: self.name, columns: self.columns, constraints: self.constraints, @@ -248,6 +256,7 @@ impl TryFrom for CreateTableBuilder { external, global, if_not_exists, + transient, name, columns, constraints, @@ -272,6 +281,7 @@ impl TryFrom for CreateTableBuilder { external, global, if_not_exists, + transient, name, columns, constraints, diff --git a/src/ast/mod.rs b/src/ast/mod.rs index b8d5cf042..25f0ac22a 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -1231,6 +1231,7 @@ pub enum Statement { external: bool, global: Option, if_not_exists: bool, + transient: bool, /// Table name #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] name: ObjectName, @@ -2033,6 +2034,7 @@ impl fmt::Display for Statement { with_options, or_replace, if_not_exists, + transient, hive_distribution, hive_formats, external, @@ -2059,7 +2061,7 @@ impl fmt::Display for Statement { // `CREATE TABLE t (a INT) AS SELECT a from t2` write!( f, - "CREATE {or_replace}{external}{global}{temporary}TABLE {if_not_exists}{name}", + "CREATE {or_replace}{external}{global}{temporary}{transient}TABLE {if_not_exists}{name}", or_replace = if *or_replace { "OR REPLACE " } else { "" }, external = if *external { "EXTERNAL " } else { "" }, global = global @@ -2073,6 +2075,7 @@ impl fmt::Display for Statement { .unwrap_or(""), if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" }, temporary = if *temporary { "TEMPORARY " } else { "" }, + transient = if *transient { "TRANSIENT " } else { "" }, name = name, )?; if let Some(on_cluster) = on_cluster { diff --git a/src/keywords.rs b/src/keywords.rs index ad4e51e14..d43f8ebf0 100644 --- a/src/keywords.rs +++ b/src/keywords.rs @@ -570,6 +570,7 @@ define_keywords!( TOP, TRAILING, TRANSACTION, + TRANSIENT, TRANSLATE, TRANSLATE_REGEX, TRANSLATION, diff --git a/src/parser.rs b/src/parser.rs index 3883a333d..107c6197b 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -2256,6 +2256,7 @@ impl<'a> Parser<'a> { let or_replace = self.parse_keywords(&[Keyword::OR, Keyword::REPLACE]); let local = self.parse_one_of_keywords(&[Keyword::LOCAL]).is_some(); let global = self.parse_one_of_keywords(&[Keyword::GLOBAL]).is_some(); + let transient = self.parse_one_of_keywords(&[Keyword::TRANSIENT]).is_some(); let global: Option = if global { Some(true) } else if local { @@ -2267,7 +2268,7 @@ impl<'a> Parser<'a> { .parse_one_of_keywords(&[Keyword::TEMP, Keyword::TEMPORARY]) .is_some(); if self.parse_keyword(Keyword::TABLE) { - self.parse_create_table(or_replace, temporary, global) + self.parse_create_table(or_replace, temporary, global, transient) } else if self.parse_keyword(Keyword::MATERIALIZED) || self.parse_keyword(Keyword::VIEW) { self.prev_token(); self.parse_create_view(or_replace) @@ -3238,6 +3239,7 @@ impl<'a> Parser<'a> { or_replace: bool, temporary: bool, global: Option, + transient: bool, ) -> Result { let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]); let table_name = self.parse_object_name()?; @@ -3342,6 +3344,7 @@ impl<'a> Parser<'a> { .table_properties(table_properties) .or_replace(or_replace) .if_not_exists(if_not_exists) + .transient(transient) .hive_distribution(hive_distribution) .hive_formats(Some(hive_formats)) .global(global) diff --git a/tests/sqlparser_snowflake.rs b/tests/sqlparser_snowflake.rs index 78a31e383..57a801fc0 100644 --- a/tests/sqlparser_snowflake.rs +++ b/tests/sqlparser_snowflake.rs @@ -34,6 +34,20 @@ fn test_snowflake_create_table() { } } +#[test] +fn test_snowflake_create_transient_table() { + let sql = "CREATE TRANSIENT TABLE CUSTOMER (id INT, name VARCHAR(255))"; + match snowflake_and_generic().verified_stmt(sql) { + Statement::CreateTable { + name, transient, .. + } => { + assert_eq!("CUSTOMER", name.to_string()); + assert_eq!(true, transient) + } + _ => unreachable!(), + } +} + #[test] fn test_snowflake_single_line_tokenize() { let sql = "CREATE TABLE# this is a comment \ntable_1"; From d21a765ed6e8307708a60e801ac290cd51bf61e0 Mon Sep 17 00:00:00 2001 From: Andrew Lamb Date: Fri, 17 Feb 2023 13:51:31 -0500 Subject: [PATCH 2/2] fix clippy --- tests/sqlparser_snowflake.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sqlparser_snowflake.rs b/tests/sqlparser_snowflake.rs index 57a801fc0..ec43e030c 100644 --- a/tests/sqlparser_snowflake.rs +++ b/tests/sqlparser_snowflake.rs @@ -42,7 +42,7 @@ fn test_snowflake_create_transient_table() { name, transient, .. } => { assert_eq!("CUSTOMER", name.to_string()); - assert_eq!(true, transient) + assert!(transient) } _ => unreachable!(), }