Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11028,8 +11028,12 @@ impl<'a> Parser<'a> {
legacy_options.push(opt);
}
let values = if let CopyTarget::Stdin = target {
self.expect_token(&Token::SemiColon)?;
self.parse_tsv()
if self.peek_token_ref().token == Token::EOF {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this be collapsed to if let copy && self.peek_token() != EOF?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With matches, yes. I cannot use chained if let && because we are still using 2021 and not 2024

vec![]
} else {
self.expect_token(&Token::SemiColon)?;
self.parse_tsv()
}
} else {
vec![]
};
Expand Down
55 changes: 55 additions & 0 deletions tests/sqlparser_postgres.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,61 @@ 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() {
let cases = [
"COPY bool_test FROM STDIN NULL 'null'",
"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().one_statement_parses_to(sql, "") {
Comment thread
LucaCappelletti94 marked this conversation as resolved.
Outdated
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'");
Expand Down