From af113783d3b377f3be08f55826947f88fc11d57c Mon Sep 17 00:00:00 2001 From: Yoav Cohen Date: Tue, 8 Jul 2025 22:29:23 +0200 Subject: [PATCH 1/2] Add support for more create table options after AS --- src/dialect/snowflake.rs | 5 ++--- tests/sqlparser_snowflake.rs | 10 ++++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/dialect/snowflake.rs b/src/dialect/snowflake.rs index 212cf217d..5b14fd7e5 100644 --- a/src/dialect/snowflake.rs +++ b/src/dialect/snowflake.rs @@ -452,7 +452,6 @@ pub fn parse_create_table( Keyword::AS => { let query = parser.parse_query()?; builder = builder.query(Some(query)); - break; } Keyword::CLONE => { let clone = parser.parse_object_name(false).ok(); @@ -588,7 +587,7 @@ pub fn parse_create_table( builder = builder.columns(columns).constraints(constraints); } Token::EOF => { - if builder.columns.is_empty() { + if builder.columns.is_empty() && builder.query.is_none() { return Err(ParserError::ParserError( "unexpected end of input".to_string(), )); @@ -597,7 +596,7 @@ pub fn parse_create_table( break; } Token::SemiColon => { - if builder.columns.is_empty() { + if builder.columns.is_empty() && builder.query.is_none() { return Err(ParserError::ParserError( "unexpected end of input".to_string(), )); diff --git a/tests/sqlparser_snowflake.rs b/tests/sqlparser_snowflake.rs index e7393d3f8..4b21bb787 100644 --- a/tests/sqlparser_snowflake.rs +++ b/tests/sqlparser_snowflake.rs @@ -995,6 +995,16 @@ fn test_snowflake_create_iceberg_table_without_location() { ); } +#[test] +fn test_snowflake_create_table_as() { + // Test additional options after AS (query) + snowflake() + .parse_sql_statements( + "CREATE TEMP TABLE dst AS (SELECT * FROM src) ON COMMIT PRESERVE ROWS", + ) + .unwrap(); +} + #[test] fn parse_sf_create_or_replace_view_with_comment_missing_equal() { assert!(snowflake_and_generic() From dd8ad087101da79aee032523f6ec6f08b1c83287 Mon Sep 17 00:00:00 2001 From: Yoav Cohen Date: Tue, 8 Jul 2025 22:44:47 +0200 Subject: [PATCH 2/2] Add support for more create table options after AS --- src/ast/helpers/stmt_create_table.rs | 10 ++++++++++ src/dialect/snowflake.rs | 6 ++---- tests/sqlparser_snowflake.rs | 9 +++++++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/ast/helpers/stmt_create_table.rs b/src/ast/helpers/stmt_create_table.rs index d66a869bf..543f8f2c9 100644 --- a/src/ast/helpers/stmt_create_table.rs +++ b/src/ast/helpers/stmt_create_table.rs @@ -383,6 +383,16 @@ impl CreateTableBuilder { self } + /// Returns true if information on the structure of the table + /// to be created was provided to the builder. If not, the + /// statement is invalid. + pub fn has_schema_info(&self) -> bool { + !self.columns.is_empty() + || self.query.is_some() + || self.like.is_some() + || self.clone.is_some() + } + pub fn build(self) -> Statement { Statement::CreateTable(CreateTable { or_replace: self.or_replace, diff --git a/src/dialect/snowflake.rs b/src/dialect/snowflake.rs index 5b14fd7e5..63746efeb 100644 --- a/src/dialect/snowflake.rs +++ b/src/dialect/snowflake.rs @@ -456,12 +456,10 @@ pub fn parse_create_table( Keyword::CLONE => { let clone = parser.parse_object_name(false).ok(); builder = builder.clone_clause(clone); - break; } Keyword::LIKE => { let like = parser.parse_object_name(false).ok(); builder = builder.like(like); - break; } Keyword::CLUSTER => { parser.expect_keyword_is(Keyword::BY)?; @@ -587,7 +585,7 @@ pub fn parse_create_table( builder = builder.columns(columns).constraints(constraints); } Token::EOF => { - if builder.columns.is_empty() && builder.query.is_none() { + if !builder.has_schema_info() { return Err(ParserError::ParserError( "unexpected end of input".to_string(), )); @@ -596,7 +594,7 @@ pub fn parse_create_table( break; } Token::SemiColon => { - if builder.columns.is_empty() && builder.query.is_none() { + if !builder.has_schema_info() { return Err(ParserError::ParserError( "unexpected end of input".to_string(), )); diff --git a/tests/sqlparser_snowflake.rs b/tests/sqlparser_snowflake.rs index 4b21bb787..c4eebdb5e 100644 --- a/tests/sqlparser_snowflake.rs +++ b/tests/sqlparser_snowflake.rs @@ -996,13 +996,18 @@ fn test_snowflake_create_iceberg_table_without_location() { } #[test] -fn test_snowflake_create_table_as() { - // Test additional options after AS (query) +fn test_snowflake_create_table_trailing_options() { snowflake() .parse_sql_statements( "CREATE TEMP TABLE dst AS (SELECT * FROM src) ON COMMIT PRESERVE ROWS", ) .unwrap(); + snowflake() + .parse_sql_statements("CREATE TEMP TABLE tbl LIKE customers ON COMMIT PRESERVE ROWS;") + .unwrap(); + snowflake() + .parse_sql_statements("CREATE TEMP TABLE tbl CLONE customers ON COMMIT PRESERVE ROWS;") + .unwrap(); } #[test]