This is an automated email from the ASF dual-hosted git repository.
github-bot pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git
The following commit(s) were added to refs/heads/main by this push:
new 915448cf Add support for parsing COPY statements from STDIN without a
semicolon (#2245)
915448cf is described below
commit 915448cf335863da73dee8e3fe0e3275189d703c
Author: Luca Cappelletti <[email protected]>
AuthorDate: Wed Mar 4 14:24:57 2026 +0100
Add support for parsing COPY statements from STDIN without a semicolon
(#2245)
---
src/parser/mod.rs | 13 ++++++-----
tests/sqlparser_postgres.rs | 56 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 63 insertions(+), 6 deletions(-)
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index 7764fab2..688d1d02 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -11081,12 +11081,13 @@ impl<'a> Parser<'a> {
while let Some(opt) = self.maybe_parse(|parser|
parser.parse_copy_legacy_option())? {
legacy_options.push(opt);
}
- let values = if let CopyTarget::Stdin = target {
- self.expect_token(&Token::SemiColon)?;
- self.parse_tsv()
- } else {
- vec![]
- };
+ let values =
+ if matches!(target, CopyTarget::Stdin) &&
self.peek_token_ref().token != Token::EOF {
+ self.expect_token(&Token::SemiColon)?;
+ self.parse_tsv()
+ } else {
+ vec![]
+ };
Ok(Statement::Copy {
source,
to,
diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs
index ecf7b6bf..c83860ff 100644
--- a/tests/sqlparser_postgres.rs
+++ b/tests/sqlparser_postgres.rs
@@ -1123,6 +1123,62 @@ PHP ₱ USD $
pg_and_generic().one_statement_parses_to(sql, "");
}
+#[test]
+fn parse_copy_from_stdin_without_semicolon() {
+ let stmt = pg().verified_stmt("COPY bitwise_test FROM STDIN NULL 'null'");
+ assert_eq!(
+ stmt,
+ Statement::Copy {
+ source: CopySource::Table {
+ table_name: ObjectName::from(vec!["bitwise_test".into()]),
+ columns: vec![],
+ },
+ to: false,
+ target: CopyTarget::Stdin,
+ options: vec![],
+ legacy_options: vec![CopyLegacyOption::Null("null".into())],
+ values: vec![],
+ }
+ );
+}
+
+#[test]
+fn parse_copy_from_stdin_without_semicolon_variants() {
+ // This covers additional COPY ... FROM STDIN shapes without inline
payload.
+ // `parse_copy_from_stdin_without_semicolon` asserts the legacy NULL
option details.
+ let cases = [
+ "COPY varbit_table FROM STDIN",
+ "COPY bit_table FROM STDIN",
+ "COPY copytest2 (test) FROM STDIN",
+ "COPY copytest3 FROM STDIN CSV HEADER",
+ "COPY copytest4 FROM STDIN (HEADER)",
+ "COPY parted_copytest FROM STDIN",
+ "COPY tab_progress_reporting FROM STDIN",
+ "COPY oversized_column_default FROM STDIN",
+ "COPY x (a, b, c, d, e) FROM STDIN",
+ "COPY header_copytest (c, a) FROM STDIN",
+ "COPY atest5 (two) FROM STDIN",
+ "COPY main_table (a, b) FROM STDIN",
+ ];
+
+ for sql in cases {
+ match pg().verified_stmt(sql) {
+ Statement::Copy {
+ to: false,
+ target: CopyTarget::Stdin,
+ values,
+ ..
+ } => {
+ assert!(
+ values.is_empty(),
+ "expected no inline COPY payload for `{sql}`"
+ );
+ }
+ _ => panic!("expected COPY ... FROM STDIN statement for `{sql}`"),
+ }
+ }
+}
+
#[test]
fn test_copy_from() {
let stmt = pg().verified_stmt("COPY users FROM 'data.csv'");
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]