From ffeca58cbdd622aa1a65c24726a999b68ce63f26 Mon Sep 17 00:00:00 2001 From: osipovartem Date: Fri, 31 Jan 2025 15:41:09 +0300 Subject: [PATCH 1/5] DFParser should skip unsupported COPY INTO --- datafusion/sql/src/parser.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/datafusion/sql/src/parser.rs b/datafusion/sql/src/parser.rs index f185d65fa194..e3a137939d18 100644 --- a/datafusion/sql/src/parser.rs +++ b/datafusion/sql/src/parser.rs @@ -354,6 +354,14 @@ impl<'a> DFParser<'a> { self.parse_create() } Keyword::COPY => { + if let Token::Word(w) = self.parser.peek_nth_token(1).token { + // use native parser for COPY INTO + if w.keyword == Keyword::INTO { + return Ok(Statement::Statement(Box::from( + self.parser.parse_statement()?, + ))); + } + } self.parser.next_token(); // COPY self.parse_copy() } From f615c1ae49196c1498f4d805288ce9d2f7f2e1f1 Mon Sep 17 00:00:00 2001 From: osipovartem Date: Fri, 31 Jan 2025 16:13:39 +0300 Subject: [PATCH 2/5] Add tests --- datafusion/sql/src/parser.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/datafusion/sql/src/parser.rs b/datafusion/sql/src/parser.rs index e3a137939d18..7f5134406114 100644 --- a/datafusion/sql/src/parser.rs +++ b/datafusion/sql/src/parser.rs @@ -885,6 +885,7 @@ mod tests { use super::*; use sqlparser::ast::Expr::Identifier; use sqlparser::ast::{BinaryOperator, DataType, Expr, Ident}; + use sqlparser::dialect::{dialect_from_str, SnowflakeDialect}; use sqlparser::tokenizer::Span; fn expect_parse_ok(sql: &str, expected: Statement) -> Result<(), ParserError> { @@ -1411,6 +1412,23 @@ mod tests { Ok(()) } + + #[test] + fn skip_copy_into_snowflake() -> Result<(), ParserError> { + let sql = "COPY INTO foo FROM @~/staged FILE_FORMAT = (FORMAT_NAME = 'mycsv');"; + let dialect = Box::new(SnowflakeDialect); + let statements = DFParser::parse_sql_with_dialect(sql, dialect.as_ref())?; + + assert_eq!( statements.len(), 1, "Expected to parse exactly one statement"); + if let Statement::CopyTo(_) = &statements[0] { + panic!( + "Expected non COPY TO statement, but was successful: {statements:?}" + ); + } + Ok(()) + } + + #[test] fn explain_copy_to_table_to_table() -> Result<(), ParserError> { let cases = vec![ From efbdd742b41344e731397a73aa640667042c4425 Mon Sep 17 00:00:00 2001 From: osipovartem Date: Fri, 31 Jan 2025 16:14:18 +0300 Subject: [PATCH 3/5] Add tests --- datafusion/sql/src/parser.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/datafusion/sql/src/parser.rs b/datafusion/sql/src/parser.rs index 7f5134406114..5da0cf764f90 100644 --- a/datafusion/sql/src/parser.rs +++ b/datafusion/sql/src/parser.rs @@ -1411,8 +1411,7 @@ mod tests { assert_eq!(verified_stmt(sql), expected); Ok(()) } - - + #[test] fn skip_copy_into_snowflake() -> Result<(), ParserError> { let sql = "COPY INTO foo FROM @~/staged FILE_FORMAT = (FORMAT_NAME = 'mycsv');"; @@ -1428,7 +1427,6 @@ mod tests { Ok(()) } - #[test] fn explain_copy_to_table_to_table() -> Result<(), ParserError> { let cases = vec![ From dc91a82ef6549b641f862e3b28c30bd5abd5c56b Mon Sep 17 00:00:00 2001 From: osipovartem Date: Fri, 31 Jan 2025 18:51:44 +0300 Subject: [PATCH 4/5] Fix typo --- datafusion/sql/src/parser.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datafusion/sql/src/parser.rs b/datafusion/sql/src/parser.rs index 5da0cf764f90..43fbb789407a 100644 --- a/datafusion/sql/src/parser.rs +++ b/datafusion/sql/src/parser.rs @@ -885,7 +885,7 @@ mod tests { use super::*; use sqlparser::ast::Expr::Identifier; use sqlparser::ast::{BinaryOperator, DataType, Expr, Ident}; - use sqlparser::dialect::{dialect_from_str, SnowflakeDialect}; + use sqlparser::dialect::SnowflakeDialect; use sqlparser::tokenizer::Span; fn expect_parse_ok(sql: &str, expected: Statement) -> Result<(), ParserError> { @@ -1418,7 +1418,7 @@ mod tests { let dialect = Box::new(SnowflakeDialect); let statements = DFParser::parse_sql_with_dialect(sql, dialect.as_ref())?; - assert_eq!( statements.len(), 1, "Expected to parse exactly one statement"); + assert_eq!(statements.len(), 1, "Expected to parse exactly one statement"); if let Statement::CopyTo(_) = &statements[0] { panic!( "Expected non COPY TO statement, but was successful: {statements:?}" From e1728d8921de8e36b9383ffd260ecd54bed6943c Mon Sep 17 00:00:00 2001 From: osipovartem Date: Mon, 3 Feb 2025 15:36:38 +0300 Subject: [PATCH 5/5] Fix cargo fmt --- datafusion/sql/src/parser.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/datafusion/sql/src/parser.rs b/datafusion/sql/src/parser.rs index 43fbb789407a..74eed6325120 100644 --- a/datafusion/sql/src/parser.rs +++ b/datafusion/sql/src/parser.rs @@ -1411,18 +1411,20 @@ mod tests { assert_eq!(verified_stmt(sql), expected); Ok(()) } - + #[test] fn skip_copy_into_snowflake() -> Result<(), ParserError> { let sql = "COPY INTO foo FROM @~/staged FILE_FORMAT = (FORMAT_NAME = 'mycsv');"; let dialect = Box::new(SnowflakeDialect); let statements = DFParser::parse_sql_with_dialect(sql, dialect.as_ref())?; - - assert_eq!(statements.len(), 1, "Expected to parse exactly one statement"); + + assert_eq!( + statements.len(), + 1, + "Expected to parse exactly one statement" + ); if let Statement::CopyTo(_) = &statements[0] { - panic!( - "Expected non COPY TO statement, but was successful: {statements:?}" - ); + panic!("Expected non COPY TO statement, but was successful: {statements:?}"); } Ok(()) }