Back-patch fix for \r\n line endings in psql's COPY support.
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 14 Aug 2004 22:24:49 +0000 (22:24 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 14 Aug 2004 22:24:49 +0000 (22:24 +0000)
Andrew Dunstan.

src/bin/psql/copy.c

index b3c07ffab53494f7c421fc45083951d4e74772bb..aed8b3196aed74ef4a7c0ae403982159dff49e59 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2000-2003, PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/copy.c,v 1.33 2003/08/04 23:59:39 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/copy.c,v 1.33.4.1 2004/08/14 22:24:49 tgl Exp $
  */
 #include "postgres_fe.h"
 #include "copy.h"
@@ -496,6 +496,7 @@ handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt)
    bool        copydone = false;
    bool        firstload;
    bool        linedone;
+   bool        saw_cr = false;
    char        copybuf[COPYBUFSIZ];
    char       *s;
    int         bufleft;
@@ -521,30 +522,49 @@ handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt)
 
        while (!linedone)
        {                       /* for each bufferload in line ... */
+           /* Fetch string until \n, EOF, or buffer full */
            s = copybuf;
            for (bufleft = COPYBUFSIZ - 1; bufleft > 0; bufleft--)
            {
                c = getc(copystream);
-               if (c == '\n' || c == EOF)
+               if (c == EOF)
                {
                    linedone = true;
                    break;
                }
                *s++ = c;
+               if (c == '\n')
+               {
+                   linedone = true;
+                   break;
+               }
+               if (c == '\r')
+                   saw_cr = true;
            }
            *s = '\0';
+           /* EOF with empty line-so-far? */
            if (c == EOF && s == copybuf && firstload)
            {
-               PQputline(conn, "\\.");
+               /*
+                * We are guessing a little bit as to the right line-ending
+                * here...
+                */
+               if (saw_cr)
+                   PQputline(conn, "\\.\r\n");
+               else
+                   PQputline(conn, "\\.\n");
                copydone = true;
                if (pset.cur_cmd_interactive)
                    puts("\\.");
                break;
            }
+           /* No, so pass the data to the backend */
            PQputline(conn, copybuf);
+           /* Check for line consisting only of \. */
            if (firstload)
            {
-               if (!strcmp(copybuf, "\\."))
+               if (strcmp(copybuf, "\\.\n") == 0 ||
+                   strcmp(copybuf, "\\.\r\n") == 0)
                {
                    copydone = true;
                    break;
@@ -552,7 +572,6 @@ handleCopyIn(PGconn *conn, FILE *copystream, const char *prompt)
                firstload = false;
            }
        }
-       PQputline(conn, "\n");
        linecount++;
    }
    ret = !PQendcopy(conn);