Re: [HACKERS] psql \copy warning - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: [HACKERS] psql \copy warning
Date
Msg-id 200605280325.k4S3PNW06832@candle.pha.pa.us
Whole thread Raw
Responses Re: [HACKERS] psql \copy warning  (Tom Lane <tgl@sss.pgh.pa.us>)
Re: [HACKERS] psql \copy warning  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-patches
Jeremy Drake wrote:
> I use the \copy command from psql to load data into postgres.  I was
> fiddling with setting up a database on a HEAD build, and I got the
> following new warning
>
> testy=# \copy episodes from 'episodes.data' with delimiter as '\t'
> WARNING:  nonstandard use of escape in a string literal
> LINE 1: COPY episodes FROM STDIN USING DELIMITERS '\t'
>                                                   ^
> HINT:  Use the escape string syntax for escapes, e.g., E'\r\n'.
>
>
> I figured that this is the new standards conforming strings feature, and I
> guess I should get used to the new escape syntax.  So I tried the hint
>
> testy=# \copy episodes FROM 'episodes.data' with delimiter as E'\t'
> \copy: parse error at "'\t'"
>
> So is it just me, or is this decidedly non-helpful?  I assume someone
> missed this place for the new syntax tweaks?

Interesting bug report.  The basic question is whether \copy should
follow the quoting rules of the SQL server, or of psql.  Most psql
arguments have backslashes enabled, so I am thinking \copy should as
well, and not match COPY if standard_compliant_strings is on.

The attached patch fixes the warning you received by adding E'' strings
to the \copy arguments, and adds it for the other backslash commands
like \d.

I don't think we want a psql escape control setting, nor do we want to
remove backslash controls from psql commands (they are not SQL
standard).

--
  Bruce Momjian   http://candle.pha.pa.us
  EnterpriseDB    http://www.enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +
Index: src/bin/psql/command.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/command.c,v
retrieving revision 1.166
diff -c -c -r1.166 command.c
*** src/bin/psql/command.c    2 Apr 2006 20:08:22 -0000    1.166
--- src/bin/psql/command.c    28 May 2006 03:22:10 -0000
***************
*** 681,688 ****
                  PGresult   *res;

                  initPQExpBuffer(&buf);
!                 printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD '%s';",
!                                   fmtId(user), encrypted_password);
                  res = PSQLexec(buf.data, false);
                  termPQExpBuffer(&buf);
                  if (!res)
--- 681,689 ----
                  PGresult   *res;

                  initPQExpBuffer(&buf);
!                 printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD %c'%s';",
!                                   fmtId(user), NEED_E_STR(encrypted_password),
!                                   encrypted_password);
                  res = PSQLexec(buf.data, false);
                  termPQExpBuffer(&buf);
                  if (!res)
Index: src/bin/psql/common.h
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/common.h,v
retrieving revision 1.47
diff -c -c -r1.47 common.h
*** src/bin/psql/common.h    6 Mar 2006 19:49:20 -0000    1.47
--- src/bin/psql/common.h    28 May 2006 03:22:10 -0000
***************
*** 22,27 ****
--- 22,29 ----

  #define atooid(x)  ((Oid) strtoul((x), NULL, 10))

+ #define    NEED_E_STR(str)        (strchr(str, '\\') ? ESCAPE_STRING_SYNTAX : ' ')
+
  /*
   * Safer versions of some standard C library functions. If an
   * out-of-memory condition occurs, these functions will bail out
Index: src/bin/psql/copy.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/copy.c,v
retrieving revision 1.61
diff -c -c -r1.61 copy.c
*** src/bin/psql/copy.c    26 May 2006 19:51:29 -0000    1.61
--- src/bin/psql/copy.c    28 May 2006 03:22:10 -0000
***************
*** 462,481 ****
      if (options->delim)
      {
          if (options->delim[0] == '\'')
!             appendPQExpBuffer(&query, " USING DELIMITERS %s",
!                               options->delim);
          else
!             appendPQExpBuffer(&query, " USING DELIMITERS '%s'",
!                               options->delim);
      }

      /* There is no backward-compatible CSV syntax */
      if (options->null)
      {
          if (options->null[0] == '\'')
!             appendPQExpBuffer(&query, " WITH NULL AS %s", options->null);
          else
!             appendPQExpBuffer(&query, " WITH NULL AS '%s'", options->null);
      }

      if (options->csv_mode)
--- 462,483 ----
      if (options->delim)
      {
          if (options->delim[0] == '\'')
!             appendPQExpBuffer(&query, " USING DELIMITERS %c%s",
!                               NEED_E_STR(options->delim), options->delim);
          else
!             appendPQExpBuffer(&query, " USING DELIMITERS %c'%s'",
!                               NEED_E_STR(options->delim), options->delim);
      }

      /* There is no backward-compatible CSV syntax */
      if (options->null)
      {
          if (options->null[0] == '\'')
!             appendPQExpBuffer(&query, " WITH NULL AS %c%s",
!                               NEED_E_STR(options->null), options->null);
          else
!             appendPQExpBuffer(&query, " WITH NULL AS %c'%s'",
!                               NEED_E_STR(options->null), options->null);
      }

      if (options->csv_mode)
***************
*** 487,503 ****
      if (options->quote)
      {
          if (options->quote[0] == '\'')
!             appendPQExpBuffer(&query, " QUOTE AS %s", options->quote);
          else
!             appendPQExpBuffer(&query, " QUOTE AS '%s'", options->quote);
      }

      if (options->escape)
      {
          if (options->escape[0] == '\'')
!             appendPQExpBuffer(&query, " ESCAPE AS %s", options->escape);
          else
!             appendPQExpBuffer(&query, " ESCAPE AS '%s'", options->escape);
      }

      if (options->force_quote_list)
--- 489,509 ----
      if (options->quote)
      {
          if (options->quote[0] == '\'')
!             appendPQExpBuffer(&query, " QUOTE AS %c%s",
!                               NEED_E_STR(options->quote), options->quote);
          else
!             appendPQExpBuffer(&query, " QUOTE AS %c'%s'",
!                               NEED_E_STR(options->quote), options->quote);
      }

      if (options->escape)
      {
          if (options->escape[0] == '\'')
!             appendPQExpBuffer(&query, " ESCAPE AS %c%s",
!                               NEED_E_STR(options->escape), options->escape);
          else
!             appendPQExpBuffer(&query, " ESCAPE AS %c'%s'",
!                               NEED_E_STR(options->escape), options->escape);
      }

      if (options->force_quote_list)
Index: src/bin/psql/describe.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/describe.c,v
retrieving revision 1.136
diff -c -c -r1.136 describe.c
*** src/bin/psql/describe.c    28 May 2006 02:27:08 -0000    1.136
--- src/bin/psql/describe.c    28 May 2006 03:22:11 -0000
***************
*** 1902,1915 ****
              WHEREAND();
              if (altnamevar)
                  appendPQExpBuffer(buf,
!                                   "(%s ~ '^%s'\n"
!                                   "        OR %s ~ '^%s')\n",
!                                   namevar, namebuf.data,
!                                   altnamevar, namebuf.data);
              else
                  appendPQExpBuffer(buf,
!                                   "%s ~ '^%s'\n",
!                                   namevar, namebuf.data);
          }
      }

--- 1902,1917 ----
              WHEREAND();
              if (altnamevar)
                  appendPQExpBuffer(buf,
!                                   "(%s ~ %c'^%s'\n"
!                                   "        OR %s ~ %c'^%s')\n",
!                                   namevar, NEED_E_STR(namebuf.data),
!                                   namebuf.data, altnamevar,
!                                   NEED_E_STR(namebuf.data), namebuf.data);
              else
                  appendPQExpBuffer(buf,
!                                   "%s ~ %c'^%s'\n",
!                                   namevar, NEED_E_STR(namebuf.data),
!                                   namebuf.data);
          }
      }

***************
*** 1926,1933 ****
          if (schemabuf.data[0] && schemavar)
          {
              WHEREAND();
!             appendPQExpBuffer(buf, "%s ~ '^%s'\n",
!                               schemavar, schemabuf.data);
          }
      }
      else
--- 1928,1936 ----
          if (schemabuf.data[0] && schemavar)
          {
              WHEREAND();
!             appendPQExpBuffer(buf, "%s ~ %c'^%s'\n",
!                               schemavar, NEED_E_STR(schemabuf.data),
!                               schemabuf.data);
          }
      }
      else

pgsql-patches by date:

Previous
From: Andrew Dunstan
Date:
Subject: Re: tg_table_name and tg_table_schema for plpgsql
Next
From: Tom Lane
Date:
Subject: Re: [HACKERS] psql \copy warning