LucaCappelletti94 commented on code in PR #2618:
URL:
https://github.com/apache/datafusion-sqlparser-rs/pull/2618#discussion_r4460750922
##########
src/parser/mod.rs:
##########
@@ -1546,6 +1547,47 @@ impl<'a> Parser<'a> {
Ok(Statement::UNLISTEN { channel })
}
+ /// Parse `DO` statement.
+ pub fn parse_do(&mut self) -> Result<Statement, ParserError> {
+ let mut options = Vec::new();
+ loop {
+ let language = self.parse_keyword(Keyword::LANGUAGE);
+ let string_literal = matches!(
+ self.peek_token_ref().token,
+ Token::SingleQuotedString(_)
+ | Token::DollarQuotedString(_)
+ | Token::EscapedStringLiteral(_)
+ | Token::UnicodeStringLiteral(_)
+ );
+ let option = match (language, string_literal) {
+ (true, true) => DoOption::LanguageLiteral(self.parse_value()?),
+ (true, false) => match self.next_token() {
+ // PostgreSQL lexes `N'...'` as the `NCHAR` keyword
followed
+ // by a string literal, so `LANGUAGE N'...'` is the
language
+ // name `nchar` followed by the code block.
+ TokenWithSpan {
+ token: Token::NationalStringLiteral(code),
+ span,
+ } => {
+ options.push(DoOption::Language(Ident::with_span(span,
"nchar")));
+
DoOption::Code(Value::SingleQuotedString(code).with_span(span))
Review Comment:
You should split the `N'...'` token's span between the two items it
produces. Both currently get the whole token's span, so `get_source` on the
`nchar` language returns `N'BEGIN NULL; END'` instead of `N`. `N` is always a
single character on the token's first line, so the quote starts one column
later.
```suggestion
let quote = Location::new(span.start.line,
span.start.column + 1);
let language =
Ident::with_span(Span::new(span.start, quote), "nchar");
options.push(DoOption::Language(language));
let code = Value::SingleQuotedString(code);
DoOption::Code(code.with_span(Span::new(quote,
span.end)))
```
##########
src/ast/spans.rs:
##########
@@ -3594,4 +3610,13 @@ SETTINGS update_parallel_mode = 'auto'"#;
assert_eq!(test.get_source(stmt.span()), expected, "{sql}");
}
}
+
+ #[test]
+ fn test_do_statement_span() {
+ let dialect = &crate::dialect::PostgreSqlDialect {};
+ let sql = "DO LANGUAGE plpgsql $$BEGIN NULL; END$$";
+ let test = SpanTest::new(dialect, sql);
+ let r = Parser::parse_sql(dialect, sql).unwrap();
+ assert_eq!(test.get_source(r[0].span()), "plpgsql $$BEGIN NULL;
END$$");
+ }
Review Comment:
You should cover the split, since this test fails on the current head
because the language's span covers the whole literal.
```suggestion
assert_eq!(test.get_source(r[0].span()), "plpgsql $$BEGIN NULL;
END$$");
let sql = "DO LANGUAGE N'BEGIN NULL; END'";
let test = SpanTest::new(dialect, sql);
let options = match Parser::parse_sql(dialect,
sql).unwrap().remove(0) {
Statement::Do(DoStatement { options }) => options,
stmt => panic!("expected DO, got {stmt:?}"),
};
assert_eq!(test.get_source(options[0].span()), "N");
assert_eq!(test.get_source(options[1].span()), "'BEGIN NULL; END'");
}
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]