Re: \copy (query) delimiter syntax error - Mailing list pgsql-hackers

From Andrew Dunstan
Subject Re: \copy (query) delimiter syntax error
Date
Msg-id 45C4E870.8080202@dunslane.net
Whole thread Raw
In response to Re: \copy (query) delimiter syntax error  (Michael Fuhr <mike@fuhr.org>)
Responses Re: \copy (query) delimiter syntax error  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers

Michael Fuhr wrote:
> On Sat, Feb 03, 2007 at 10:52:29AM -0600, Andrew Dunstan wrote:
>
>> I'd say fix psql. Not sure how far back we should backpatch it. It's
>> interesting that this has been there since 8.0 and is only now discovered.
>>
>
> The problem is new in 8.2 because COPY (query) doesn't support USING
> DELIMITERS.  COPY tablename does, so it has worked all along.
>
>

oh, good point. OK, I have cut this quick patch that will continue to
accept the legacy syntax in psql in non-inline-query cases, but will
make psql unreservedly emit new style syntax for COPY to the backend.
Does that seem reasonable, or is it too much of a change for the stable
branch?

cheers

andrew
Index: src/bin/psql/copy.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/copy.c,v
retrieving revision 1.72
diff -c -r1.72 copy.c
*** src/bin/psql/copy.c    5 Jan 2007 22:19:49 -0000    1.72
--- src/bin/psql/copy.c    3 Feb 2007 19:37:34 -0000
***************
*** 118,123 ****
--- 118,124 ----
      char       *token;
      const char *whitespace = " \t\n\r";
      char        nonstd_backslash = standard_strings() ? 0 : '\\';
+     bool        have_query = false;

      if (args)
          line = pg_strdup(args);
***************
*** 163,168 ****
--- 164,170 ----
              xstrcat(&result->table, " ");
              xstrcat(&result->table, token);
          }
+         have_query = true;
      }

      token = strtokx(NULL, whitespace, ".,()", "\"",
***************
*** 268,291 ****
                      0, false, false, pset.encoding);

      /*
!      * Allows old COPY syntax for backward compatibility 2002-06-19
       */
!     if (token && pg_strcasecmp(token, "using") == 0)
!     {
!         token = strtokx(NULL, whitespace, NULL, NULL,
!                         0, false, false, pset.encoding);
!         if (!(token && pg_strcasecmp(token, "delimiters") == 0))
!             goto error;
!     }
!     if (token && pg_strcasecmp(token, "delimiters") == 0)
      {
!         token = strtokx(NULL, whitespace, NULL, "'",
!                         nonstd_backslash, true, false, pset.encoding);
!         if (!token)
!             goto error;
!         result->delim = pg_strdup(token);
!         token = strtokx(NULL, whitespace, NULL, NULL,
!                         0, false, false, pset.encoding);
      }

      if (token)
--- 270,297 ----
                      0, false, false, pset.encoding);

      /*
!      * Allows old COPY syntax for backward compatibility.
!      * Skip if we have an inline query instead of a table name.
       */
!     if (! have_query)
      {
!         if (token && pg_strcasecmp(token, "using") == 0)
!         {
!             token = strtokx(NULL, whitespace, NULL, NULL,
!                             0, false, false, pset.encoding);
!             if (!(token && pg_strcasecmp(token, "delimiters") == 0))
!                 goto error;
!         }
!         if (token && pg_strcasecmp(token, "delimiters") == 0)
!         {
!             token = strtokx(NULL, whitespace, NULL, "'",
!                             nonstd_backslash, true, false, pset.encoding);
!             if (!token)
!                 goto error;
!             result->delim = pg_strdup(token);
!             token = strtokx(NULL, whitespace, NULL, NULL,
!                             0, false, false, pset.encoding);
!         }
      }

      if (token)
***************
*** 480,511 ****

      printfPQExpBuffer(&query, "COPY ");

-     /* Uses old COPY syntax for backward compatibility 2002-06-19 */
-     if (options->binary)
-         appendPQExpBuffer(&query, "BINARY ");
-
      appendPQExpBuffer(&query, "%s ", options->table);

      if (options->column_list)
          appendPQExpBuffer(&query, "%s ", options->column_list);

-     /* Uses old COPY syntax for backward compatibility 2002-06-19 */
-     if (options->oids)
-         appendPQExpBuffer(&query, "WITH OIDS ");
-
      if (options->from)
          appendPQExpBuffer(&query, "FROM STDIN");
      else
          appendPQExpBuffer(&query, "TO STDOUT");


!     /* Uses old COPY syntax for backward compatibility 2002-06-19 */
      if (options->delim)
!         emit_copy_option(&query, " USING DELIMITERS ", options->delim);

-     /* There is no backward-compatible CSV syntax */
      if (options->null)
!         emit_copy_option(&query, " WITH NULL AS ", options->null);

      if (options->csv_mode)
          appendPQExpBuffer(&query, " CSV");
--- 486,513 ----

      printfPQExpBuffer(&query, "COPY ");

      appendPQExpBuffer(&query, "%s ", options->table);

      if (options->column_list)
          appendPQExpBuffer(&query, "%s ", options->column_list);

      if (options->from)
          appendPQExpBuffer(&query, "FROM STDIN");
      else
          appendPQExpBuffer(&query, "TO STDOUT");


!     if (options->binary)
!         appendPQExpBuffer(&query, " BINARY ");
!
!     if (options->oids)
!         appendPQExpBuffer(&query, " OIDS ");
!
      if (options->delim)
!         emit_copy_option(&query, " DELIMITER ", options->delim);

      if (options->null)
!         emit_copy_option(&query, " NULL AS ", options->null);

      if (options->csv_mode)
          appendPQExpBuffer(&query, " CSV");

pgsql-hackers by date:

Previous
From: Matthias Luedtke
Date:
Subject: Re: --enable-debug does not work with gcc
Next
From: Jan Wieck
Date:
Subject: Re: Proposal: Commit timestamp