diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 5b3f4c65..d11c2fcd 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -2047,7 +2047,7 @@ impl<'a> Tokenizer<'a> { return self.tokenizer_error( start_quote_loc, format!( - "Invalid space, tab, newline, or EOF after '{}''.", + "Invalid space, tab, newline, or EOF after '{}''", String::from_iter(literal_prefix) ), ); diff --git a/tests/sqlparser_oracle.rs b/tests/sqlparser_oracle.rs index a194b875..8a0d8721 100644 --- a/tests/sqlparser_oracle.rs +++ b/tests/sqlparser_oracle.rs @@ -21,9 +21,7 @@ use pretty_assertions::assert_eq; use sqlparser::{ - ast::{BinaryOperator, Expr, Ident, QuoteDelimitedString, Value, ValueWithSpan}, - dialect::OracleDialect, - tokenizer::Span, + ast::{BinaryOperator, Expr, Ident, QuoteDelimitedString, Value, ValueWithSpan}, dialect::OracleDialect, parser::ParserError, tokenizer::Span }; use test_utils::{expr_from_projection, number, TestedDialects}; @@ -184,6 +182,27 @@ fn parse_quote_delimited_string() { ); } +#[test] +fn parse_invalid_quote_delimited_strings() { + // ~ invalid quote delimiter + for q in [' ', '\t', '\r', '\n'] { + assert_eq!( + oracle().parse_sql_statements(&format!("SELECT Q'{q}abc{q}' FROM dual")), + Err(ParserError::TokenizerError("Invalid space, tab, newline, or EOF after 'Q'' at Line: 1, Column: 10".into())), + "with quote char {q:?}"); + } + // ~ invalid eof after quote + assert_eq!( + oracle().parse_sql_statements("SELECT Q'"), + Err(ParserError::TokenizerError("Invalid space, tab, newline, or EOF after 'Q'' at Line: 1, Column: 10".into())), + "with EOF quote char"); + // ~ unterminated string + assert_eq!( + oracle().parse_sql_statements("SELECT Q'|asdfa...."), + Err(ParserError::TokenizerError("Unterminated string literal at Line: 1, Column: 9".into())), + "with EOF quote char"); +} + #[test] fn parse_quote_delimited_string_lowercase() { let sql = "select q'!a'b'c!d!' from dual";