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]

Reply via email to