LucaCappelletti94 commented on code in PR #2428:
URL: 
https://github.com/apache/datafusion-sqlparser-rs/pull/2428#discussion_r4318326950


##########
src/parser/mod.rs:
##########
@@ -12548,40 +12548,50 @@ impl<'a> Parser<'a> {
         Ok(s.chars().next().unwrap())
     }
 
-    /// Parse a tab separated values in
-    /// COPY payload
-    pub fn parse_tsv(&mut self) -> Vec<Option<String>> {
-        self.parse_tab_value()
-    }
-
-    /// Parse a single tab-separated value row used by `COPY` payload parsing.
-    pub fn parse_tab_value(&mut self) -> Vec<Option<String>> {
-        let mut values = vec![];
-        let mut content = String::new();
-        while let Some(t) = self.next_token_no_skip().map(|t| &t.token) {
-            match t {
-                Token::Whitespace(Whitespace::Tab) => {
-                    values.push(Some(core::mem::take(&mut content)));
-                }
-                Token::Whitespace(Whitespace::Newline) => {
-                    values.push(Some(core::mem::take(&mut content)));
-                }
+    /// Parse the inline payload of `COPY ... FROM STDIN` as written.
+    ///
+    /// The payload is data rather than SQL, so it is captured uninterpreted.
+    /// It starts on the line following the command and runs up to the `\.`
+    /// terminator, which is consumed but not returned. Field
+    /// separators, escapes and the `\N` null marker are left to the caller.
+    ///
+    /// Returns `None` when nothing but the statement delimiter follows, so a
+    /// bare `COPY t FROM STDIN;` is not given a payload it never carried.
+    fn parse_copy_payload(&mut self) -> Option<String> {
+        use core::fmt::Write;
+
+        let mut payload = String::new();
+        // The newline ending the command line is a delimiter, not data.
+        if self.peek_nth_token_no_skip_ref(0).token == 
Token::Whitespace(Whitespace::Newline) {
+            let _ = self.next_token_no_skip();
+        }
+        while let Some(token) = self.next_token_no_skip().map(|t| &t.token) {
+            match token {
                 Token::Backslash => {
-                    if self.consume_token(&Token::Period) {
-                        return values;
-                    }
-                    if let Token::Word(w) = self.next_token().token {
-                        if w.value == "N" {
-                            values.push(None);
-                        }
+                    // `\.` terminates the payload, every other backslash is 
data.
+                    if self.peek_nth_token_no_skip_ref(0).token == 
Token::Period {

Review Comment:
   The payload now ends only at a line holding just `\.`, and a statement after 
it parses.
   
   That said, while your claim is very reasonable, PostgreSQL 16.15 rejects 
`1\tfoo\.bar` in text format with `end-of-copy marker corrupt`, so a mid-line 
`\.` stays in the payload and lets the server decides.



-- 
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