Thread: Cleanup for new escape handling

Cleanup for new escape handling

From
Bruce Momjian
Date:
This patch cleans up the use of E'' strings in 8.2.  8.2 is the first
release where standard_conforming_strings can be 'on', and when 'on',
escape_string_warning is disabled.

In 8.1, the behavior was to use E'' strings for any case where
backslashes exist.  For 8.2, per suggestion from Tom, we should use E''
strings only for standard_conforming_strings = 'off'.  This would allow
pg_dump output with standard_conforming_strings = 'on' to generate
proper strings that can be loaded into other databases without the
backslash doubling we typically do.  I have added the dumping of the
standard_conforming_strings to pg_dump, like we do now for
client_encoding.  The only risk of the patch is that someone will use
one of the adt/ruleutils.c functions like pg_get_constraintdef() with
one setting of standard_conforming_strings and then try to load it into
a database with a different standard_conforming_strings setting.

I also added standard backslash handling for plpgsql.

I also checked ecpg and that uses E'' for all strings that have \
because it doesn't know if the target database is going to have
standard_conforming_strings on or off.  That seems best, and no one
expects the _output_ of ecpg to be portable.

The macros we use for escape processing really makes these changes easy.

--
  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/backend/utils/adt/quote.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/quote.c,v
retrieving revision 1.18
diff -c -c -r1.18 quote.c
*** src/backend/utils/adt/quote.c    5 Mar 2006 15:58:43 -0000    1.18
--- src/backend/utils/adt/quote.c    25 May 2006 22:15:36 -0000
***************
*** 14,19 ****
--- 14,20 ----
  #include "postgres.h"

  #include "utils/builtins.h"
+ #include "parser/gramparse.h"


  /*
***************
*** 65,83 ****
      cp1 = VARDATA(t);
      cp2 = VARDATA(result);

!     for (; len-- > 0; cp1++)
!         if (*cp1 == '\\')
!         {
!             *cp2++ = ESCAPE_STRING_SYNTAX;
!             break;
!         }

      len = VARSIZE(t) - VARHDRSZ;
      cp1 = VARDATA(t);
      *cp2++ = '\'';
      while (len-- > 0)
      {
!         if (SQL_STR_DOUBLE(*cp1))
              *cp2++ = *cp1;
          *cp2++ = *cp1++;
      }
--- 66,85 ----
      cp1 = VARDATA(t);
      cp2 = VARDATA(result);

!     if (!standard_conforming_strings)
!         for (; len-- > 0; cp1++)
!             if (*cp1 == '\\')
!             {
!                 *cp2++ = ESCAPE_STRING_SYNTAX;
!                 break;
!             }

      len = VARSIZE(t) - VARHDRSZ;
      cp1 = VARDATA(t);
      *cp2++ = '\'';
      while (len-- > 0)
      {
!         if (SQL_STR_DOUBLE(*cp1, !standard_conforming_strings))
              *cp2++ = *cp1;
          *cp2++ = *cp1++;
      }
Index: src/backend/utils/adt/ruleutils.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v
retrieving revision 1.221
diff -c -c -r1.221 ruleutils.c
*** src/backend/utils/adt/ruleutils.c    30 Apr 2006 18:30:40 -0000    1.221
--- src/backend/utils/adt/ruleutils.c    25 May 2006 22:15:41 -0000
***************
*** 31,36 ****
--- 31,37 ----
  #include "nodes/makefuncs.h"
  #include "optimizer/clauses.h"
  #include "optimizer/tlist.h"
+ #include "parser/gramparse.h"
  #include "parser/keywords.h"
  #include "parser/parse_expr.h"
  #include "parser/parse_func.h"
***************
*** 533,545 ****
          {
              if (i > 0)
                  appendStringInfo(&buf, ", ");
!             if (strchr(p, '\\') != NULL)
                  appendStringInfoChar(&buf, ESCAPE_STRING_SYNTAX);
              appendStringInfoChar(&buf, '\'');

              while (*p)
              {
!                 if (SQL_STR_DOUBLE(*p))
                      appendStringInfoChar(&buf, *p);
                  appendStringInfoChar(&buf, *p++);
              }
--- 534,546 ----
          {
              if (i > 0)
                  appendStringInfo(&buf, ", ");
!             if (!standard_conforming_strings && strchr(p, '\\') != NULL)
                  appendStringInfoChar(&buf, ESCAPE_STRING_SYNTAX);
              appendStringInfoChar(&buf, '\'');

              while (*p)
              {
!                 if (SQL_STR_DOUBLE(*p, !standard_conforming_strings))
                      appendStringInfoChar(&buf, *p);
                  appendStringInfoChar(&buf, *p++);
              }
***************
*** 3882,3888 ****
      char       *valptr;
      bool        isfloat = false;
      bool        needlabel;
!
      if (constval->constisnull)
      {
          /*
--- 3883,3890 ----
      char       *valptr;
      bool        isfloat = false;
      bool        needlabel;
!     bool        is_e_string = false;
!
      if (constval->constisnull)
      {
          /*
***************
*** 3948,3957 ****
               * representation. XXX Any MULTIBYTE considerations here?
               */
              for (valptr = extval; *valptr; valptr++)
!                 if (*valptr == '\\' ||
                      (unsigned char) *valptr < (unsigned char) ' ')
                  {
                      appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
                      break;
                  }

--- 3950,3960 ----
               * representation. XXX Any MULTIBYTE considerations here?
               */
              for (valptr = extval; *valptr; valptr++)
!                 if ((!standard_conforming_strings && *valptr == '\\') ||
                      (unsigned char) *valptr < (unsigned char) ' ')
                  {
                      appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
+                     is_e_string = true;
                      break;
                  }

***************
*** 3960,3966 ****
              {
                  char        ch = *valptr;

!                 if (SQL_STR_DOUBLE(ch))
                  {
                      appendStringInfoChar(buf, ch);
                      appendStringInfoChar(buf, ch);
--- 3963,3969 ----
              {
                  char        ch = *valptr;

!                 if (SQL_STR_DOUBLE(ch, is_e_string))
                  {
                      appendStringInfoChar(buf, ch);
                      appendStringInfoChar(buf, ch);
Index: src/bin/initdb/initdb.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/initdb/initdb.c,v
retrieving revision 1.114
diff -c -c -r1.114 initdb.c
*** src/bin/initdb/initdb.c    21 Mar 2006 17:54:28 -0000    1.114
--- src/bin/initdb/initdb.c    25 May 2006 22:15:48 -0000
***************
*** 2103,2109 ****
  }

  /*
!  * Escape any single quotes or backslashes in given string
   */
  static char *
  escape_quotes(const char *src)
--- 2103,2110 ----
  }

  /*
!  * Escape any single quotes or backslashes in given string;
!  * postgresql.conf always enables backslash escapes
   */
  static char *
  escape_quotes(const char *src)
***************
*** 2115,2121 ****

      for (i = 0, j = 0; i < len; i++)
      {
!         if (SQL_STR_DOUBLE(src[i]))
              result[j++] = src[i];
          result[j++] = src[i];
      }
--- 2116,2122 ----

      for (i = 0, j = 0; i < len; i++)
      {
!         if (SQL_STR_DOUBLE(src[i], true))
              result[j++] = src[i];
          result[j++] = src[i];
      }
Index: src/bin/pg_dump/dumputils.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v
retrieving revision 1.27
diff -c -c -r1.27 dumputils.c
*** src/bin/pg_dump/dumputils.c    30 Apr 2006 21:15:33 -0000    1.27
--- src/bin/pg_dump/dumputils.c    25 May 2006 22:15:49 -0000
***************
*** 105,128 ****
   * Special characters are escaped. Quote mark ' goes to '' per SQL
   * standard, other stuff goes to \ sequences.  If escapeAll is false,
   * whitespace characters are not escaped (tabs, newlines, etc.).  This
!  * is appropriate for dump file output.
   */
  void
! appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll)
  {
      char        ch;
      const char *p;

      for (p = str; *p; p++)
      {
          ch = *p;
!         if (ch == '\\' ||
              ((unsigned char) ch < (unsigned char) ' ' &&
               (escapeAll ||
                (ch != '\t' && ch != '\n' && ch != '\v' &&
                 ch != '\f' && ch != '\r'))))
          {
              appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX);
              break;
          }
      }
--- 105,133 ----
   * Special characters are escaped. Quote mark ' goes to '' per SQL
   * standard, other stuff goes to \ sequences.  If escapeAll is false,
   * whitespace characters are not escaped (tabs, newlines, etc.).  This
!  * is appropriate for dump file output.  Using E'' strings for
!  * backslashes is always safe for standard_conforming_strings on or off.
   */
  void
! appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll,
!                     bool e_string_for_backslash)
  {
      char        ch;
      const char *p;
+     bool        is_e_string = false;

      for (p = str; *p; p++)
      {
          ch = *p;
!
!         if ((e_string_for_backslash && ch == '\\') ||
              ((unsigned char) ch < (unsigned char) ' ' &&
               (escapeAll ||
                (ch != '\t' && ch != '\n' && ch != '\v' &&
                 ch != '\f' && ch != '\r'))))
          {
              appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX);
+             is_e_string = true;
              break;
          }
      }
***************
*** 131,137 ****
      for (p = str; *p; p++)
      {
          ch = *p;
!         if (SQL_STR_DOUBLE(ch))
          {
              appendPQExpBufferChar(buf, ch);
              appendPQExpBufferChar(buf, ch);
--- 136,142 ----
      for (p = str; *p; p++)
      {
          ch = *p;
!         if (SQL_STR_DOUBLE(ch, is_e_string))
          {
              appendPQExpBufferChar(buf, ch);
              appendPQExpBufferChar(buf, ch);
***************
*** 208,214 ****
                           bool escapeAll, const char *dqprefix)
  {
      if (strchr(str, '\'') == NULL && strchr(str, '\\') == NULL)
!         appendStringLiteral(buf, str, escapeAll);
      else
          appendStringLiteralDQ(buf, str, dqprefix);
  }
--- 213,219 ----
                           bool escapeAll, const char *dqprefix)
  {
      if (strchr(str, '\'') == NULL && strchr(str, '\\') == NULL)
!         appendStringLiteral(buf, str, escapeAll, true);
      else
          appendStringLiteralDQ(buf, str, dqprefix);
  }
Index: src/bin/pg_dump/dumputils.h
===================================================================
RCS file: /cvsroot/pgsql/src/bin/pg_dump/dumputils.h,v
retrieving revision 1.15
diff -c -c -r1.15 dumputils.h
*** src/bin/pg_dump/dumputils.h    5 Mar 2006 15:58:50 -0000    1.15
--- src/bin/pg_dump/dumputils.h    25 May 2006 22:15:49 -0000
***************
*** 17,26 ****

  #include "pqexpbuffer.h"

-
  extern const char *fmtId(const char *identifier);
  extern void appendStringLiteral(PQExpBuffer buf, const char *str,
!                     bool escapeAll);
  extern void appendStringLiteralDQ(PQExpBuffer buf, const char *str,
                        const char *dqprefix);
  extern void appendStringLiteralDQOpt(PQExpBuffer buf, const char *str,
--- 17,25 ----

  #include "pqexpbuffer.h"

  extern const char *fmtId(const char *identifier);
  extern void appendStringLiteral(PQExpBuffer buf, const char *str,
!                     bool escapeAll, bool e_string_for_backslash);
  extern void appendStringLiteralDQ(PQExpBuffer buf, const char *str,
                        const char *dqprefix);
  extern void appendStringLiteralDQOpt(PQExpBuffer buf, const char *str,
Index: src/bin/pg_dump/pg_backup_archiver.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v
retrieving revision 1.129
diff -c -c -r1.129 pg_backup_archiver.c
*** src/bin/pg_dump/pg_backup_archiver.c    24 May 2006 21:20:11 -0000    1.129
--- src/bin/pg_dump/pg_backup_archiver.c    25 May 2006 22:15:50 -0000
***************
*** 1900,1908 ****
  {
      teReqs        res = REQ_ALL;

!     /* ENCODING objects are dumped specially, so always reject here */
      if (strcmp(te->desc, "ENCODING") == 0)
          return 0;

      /* If it's an ACL, maybe ignore it */
      if ((!include_acls || ropt->aclsSkip) && strcmp(te->desc, "ACL") == 0)
--- 1900,1910 ----
  {
      teReqs        res = REQ_ALL;

!     /* ENCODING and STDSTRINGS objects are dumped specially, so always reject */
      if (strcmp(te->desc, "ENCODING") == 0)
          return 0;
+     if (strcmp(te->desc, "STDSTRINGS") == 0)
+         return 0;

      /* If it's an ACL, maybe ignore it */
      if ((!include_acls || ropt->aclsSkip) && strcmp(te->desc, "ACL") == 0)
***************
*** 2005,2019 ****
  {
      TocEntry   *te;

!     /* If we have an encoding setting, emit that */
      te = AH->toc->next;
      while (te != AH->toc)
      {
          if (strcmp(te->desc, "ENCODING") == 0)
-         {
              ahprintf(AH, "%s", te->defn);
!             break;
!         }
          te = te->next;
      }

--- 2007,2020 ----
  {
      TocEntry   *te;

!     /* If we have an encoding or std_strings setting, emit that */
      te = AH->toc->next;
      while (te != AH->toc)
      {
          if (strcmp(te->desc, "ENCODING") == 0)
              ahprintf(AH, "%s", te->defn);
!         if (strcmp(te->desc, "STDSTRINGS") == 0)
!             ahprintf(AH, "%s", te->defn);
          te = te->next;
      }

***************
*** 2042,2048 ****
       * SQL requires a string literal here.    Might as well be correct.
       */
      if (user && *user)
!         appendStringLiteral(cmd, user, false);
      else
          appendPQExpBuffer(cmd, "DEFAULT");
      appendPQExpBuffer(cmd, ";");
--- 2043,2049 ----
       * SQL requires a string literal here.    Might as well be correct.
       */
      if (user && *user)
!         appendStringLiteral(cmd, user, false, true);
      else
          appendPQExpBuffer(cmd, "DEFAULT");
      appendPQExpBuffer(cmd, ";");
Index: src/bin/pg_dump/pg_dump.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v
retrieving revision 1.433
diff -c -c -r1.433 pg_dump.c
*** src/bin/pg_dump/pg_dump.c    5 Mar 2006 15:58:50 -0000    1.433
--- src/bin/pg_dump/pg_dump.c    25 May 2006 22:15:57 -0000
***************
*** 82,87 ****
--- 82,88 ----
                                   * activities. */
  Archive    *g_fout;                /* the script file */
  PGconn       *g_conn;                /* the database connection */
+ bool        std_strings = false;        /* GUC variable */

  /* various user-settable parameters */
  bool        dumpInserts;        /* dump data using proper insert strings */
***************
*** 174,179 ****
--- 175,181 ----
  static int    dumpBlobComments(Archive *AH, void *arg);
  static void dumpDatabase(Archive *AH);
  static void dumpEncoding(Archive *AH);
+ static void dumpStdStrings(Archive *AH);
  static const char *getAttrName(int attrnum, TableInfo *tblInfo);
  static const char *fmtCopyColumnList(const TableInfo *ti);
  static void do_sql_command(PGconn *conn, const char *query);
***************
*** 619,624 ****
--- 621,628 ----
      /* First the special encoding entry. */
      dumpEncoding(g_fout);

+     dumpStdStrings(g_fout);
+
      /* The database item is always second, unless we don't want it at all */
      if (!dataOnly && selectTableName == NULL && selectSchemaName == NULL)
          dumpDatabase(g_fout);
***************
*** 1084,1090 ****
                      default:
                          /* All other types are printed as string literals. */
                          resetPQExpBuffer(q);
!                         appendStringLiteral(q, PQgetvalue(res, tuple, field), false);
                          archputs(q->data, fout);
                          break;
                  }
--- 1088,1094 ----
                      default:
                          /* All other types are printed as string literals. */
                          resetPQExpBuffer(q);
!                         appendStringLiteral(q, PQgetvalue(res, tuple, field), false, !std_strings);
                          archputs(q->data, fout);
                          break;
                  }
***************
*** 1236,1242 ****
                            "FROM pg_database "
                            "WHERE datname = ",
                            username_subquery);
!         appendStringLiteral(dbQry, datname, true);
      }
      else if (g_fout->remoteVersion >= 80000)
      {
--- 1240,1246 ----
                            "FROM pg_database "
                            "WHERE datname = ",
                            username_subquery);
!         appendStringLiteral(dbQry, datname, true, !std_strings);
      }
      else if (g_fout->remoteVersion >= 80000)
      {
***************
*** 1247,1253 ****
                            "FROM pg_database "
                            "WHERE datname = ",
                            username_subquery);
!         appendStringLiteral(dbQry, datname, true);
      }
      else if (g_fout->remoteVersion >= 70100)
      {
--- 1251,1257 ----
                            "FROM pg_database "
                            "WHERE datname = ",
                            username_subquery);
!         appendStringLiteral(dbQry, datname, true, !std_strings);
      }
      else if (g_fout->remoteVersion >= 70100)
      {
***************
*** 1258,1264 ****
                            "FROM pg_database "
                            "WHERE datname = ",
                            username_subquery);
!         appendStringLiteral(dbQry, datname, true);
      }
      else
      {
--- 1262,1268 ----
                            "FROM pg_database "
                            "WHERE datname = ",
                            username_subquery);
!         appendStringLiteral(dbQry, datname, true, !std_strings);
      }
      else
      {
***************
*** 1271,1277 ****
                            "FROM pg_database "
                            "WHERE datname = ",
                            username_subquery);
!         appendStringLiteral(dbQry, datname, true);
      }

      res = PQexec(g_conn, dbQry->data);
--- 1275,1281 ----
                            "FROM pg_database "
                            "WHERE datname = ",
                            username_subquery);
!         appendStringLiteral(dbQry, datname, true, !std_strings);
      }

      res = PQexec(g_conn, dbQry->data);
***************
*** 1310,1316 ****
      if (strlen(encoding) > 0)
      {
          appendPQExpBuffer(creaQry, " ENCODING = ");
!         appendStringLiteral(creaQry, encoding, true);
      }
      if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0)
          appendPQExpBuffer(creaQry, " TABLESPACE = %s",
--- 1314,1320 ----
      if (strlen(encoding) > 0)
      {
          appendPQExpBuffer(creaQry, " ENCODING = ");
!         appendStringLiteral(creaQry, encoding, true, !std_strings);
      }
      if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0)
          appendPQExpBuffer(creaQry, " TABLESPACE = %s",
***************
*** 1349,1355 ****
          if (comment && strlen(comment)) {
              resetPQExpBuffer(dbQry);
              appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname));
!             appendStringLiteral(dbQry, comment, false);
              appendPQExpBuffer(dbQry, ";\n");

              ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL,
--- 1353,1359 ----
          if (comment && strlen(comment)) {
              resetPQExpBuffer(dbQry);
              appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname));
!             appendStringLiteral(dbQry, comment, false, !std_strings);
              appendPQExpBuffer(dbQry, ";\n");

              ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL,
***************
*** 1398,1404 ****
      resetPQExpBuffer(qry);

      appendPQExpBuffer(qry, "SET client_encoding = ");
!     appendStringLiteral(qry, PQgetvalue(res, 0, 0), true);
      appendPQExpBuffer(qry, ";\n");

      ArchiveEntry(AH, nilCatalogId, createDumpId(),
--- 1402,1408 ----
      resetPQExpBuffer(qry);

      appendPQExpBuffer(qry, "SET client_encoding = ");
!     appendStringLiteral(qry, PQgetvalue(res, 0, 0), true, !std_strings);
      appendPQExpBuffer(qry, ";\n");

      ArchiveEntry(AH, nilCatalogId, createDumpId(),
***************
*** 1414,1419 ****
--- 1418,1473 ----


  /*
+  * dumpStdStrings: put the correct escape string behavior into the archive
+  */
+ static void
+ dumpStdStrings(Archive *AH)
+ {
+     PQExpBuffer qry;
+     PGresult   *res;
+
+     if (g_verbose)
+         write_msg(NULL, "saving standard_conforming_strings setting\n");
+
+     qry = createPQExpBuffer();
+
+     /* standard_conforming_strings not used in pre-8.2 servers */
+     if (AH->remoteVersion < 80200)
+     {
+         appendPQExpBuffer(qry, "SET standard_conforming_strings = 'off';\n");
+         std_strings = false;
+     }
+     else
+     {
+         appendPQExpBuffer(qry, "SHOW standard_conforming_strings");
+
+         res = PQexec(g_conn, qry->data);
+
+         check_sql_result(res, g_conn, qry->data, PGRES_TUPLES_OK);
+
+         PQclear(res);
+
+         resetPQExpBuffer(qry);
+
+         std_strings = (strcmp(PQgetvalue(res, 0, 0), "on") == 0);
+         appendPQExpBuffer(qry, "SET standard_conforming_strings = ");
+         appendStringLiteral(qry, PQgetvalue(res, 0, 0), true, !std_strings);
+         appendPQExpBuffer(qry, ";\n");
+         puts(PQgetvalue(res, 0, 0));
+
+     }
+
+     ArchiveEntry(AH, nilCatalogId, createDumpId(),
+                  "STDSTRINGS", NULL, NULL, "",
+                  false, "STDSTRINGS", qry->data, "", NULL,
+                  NULL, 0,
+                  NULL, NULL);
+
+     destroyPQExpBuffer(qry);
+ }
+
+
+ /*
   * hasBlobs:
   *    Test whether database contains any large objects
   */
***************
*** 1586,1592 ****

              printfPQExpBuffer(commentcmd, "COMMENT ON LARGE OBJECT %u IS ",
                                blobOid);
!             appendStringLiteral(commentcmd, comment, false);
              appendPQExpBuffer(commentcmd, ";\n");

              archputs(commentcmd->data, AH);
--- 1640,1646 ----

              printfPQExpBuffer(commentcmd, "COMMENT ON LARGE OBJECT %u IS ",
                                blobOid);
!             appendStringLiteral(commentcmd, comment, false, !std_strings);
              appendPQExpBuffer(commentcmd, ";\n");

              archputs(commentcmd->data, AH);
***************
*** 4340,4346 ****
          PQExpBuffer query = createPQExpBuffer();

          appendPQExpBuffer(query, "COMMENT ON %s IS ", target);
!         appendStringLiteral(query, comments->descr, false);
          appendPQExpBuffer(query, ";\n");

          ArchiveEntry(fout, nilCatalogId, createDumpId(),
--- 4394,4400 ----
          PQExpBuffer query = createPQExpBuffer();

          appendPQExpBuffer(query, "COMMENT ON %s IS ", target);
!         appendStringLiteral(query, comments->descr, false, !std_strings);
          appendPQExpBuffer(query, ";\n");

          ArchiveEntry(fout, nilCatalogId, createDumpId(),
***************
*** 4398,4404 ****

              resetPQExpBuffer(query);
              appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
!             appendStringLiteral(query, descr, false);
              appendPQExpBuffer(query, ";\n");

              ArchiveEntry(fout, nilCatalogId, createDumpId(),
--- 4452,4458 ----

              resetPQExpBuffer(query);
              appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
!             appendStringLiteral(query, descr, false, !std_strings);
              appendPQExpBuffer(query, ";\n");

              ArchiveEntry(fout, nilCatalogId, createDumpId(),
***************
*** 4420,4426 ****

              resetPQExpBuffer(query);
              appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
!             appendStringLiteral(query, descr, false);
              appendPQExpBuffer(query, ";\n");

              ArchiveEntry(fout, nilCatalogId, createDumpId(),
--- 4474,4480 ----

              resetPQExpBuffer(query);
              appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
!             appendStringLiteral(query, descr, false, !std_strings);
              appendPQExpBuffer(query, ";\n");

              ArchiveEntry(fout, nilCatalogId, createDumpId(),
***************
*** 4986,4992 ****
      {
          appendPQExpBuffer(q, ",\n    DEFAULT = ");
          if (typdefault_is_literal)
!             appendStringLiteral(q, typdefault, true);
          else
              appendPQExpBufferStr(q, typdefault);
      }
--- 5040,5046 ----
      {
          appendPQExpBuffer(q, ",\n    DEFAULT = ");
          if (typdefault_is_literal)
!             appendStringLiteral(q, typdefault, true, !std_strings);
          else
              appendPQExpBufferStr(q, typdefault);
      }
***************
*** 5005,5011 ****
      if (typdelim && strcmp(typdelim, ",") != 0)
      {
          appendPQExpBuffer(q, ",\n    DELIMITER = ");
!         appendStringLiteral(q, typdelim, true);
      }

      if (strcmp(typalign, "c") == 0)
--- 5059,5065 ----
      if (typdelim && strcmp(typdelim, ",") != 0)
      {
          appendPQExpBuffer(q, ",\n    DELIMITER = ");
!         appendStringLiteral(q, typdelim, true, !std_strings);
      }

      if (strcmp(typalign, "c") == 0)
***************
*** 5120,5126 ****
      {
          appendPQExpBuffer(q, " DEFAULT ");
          if (typdefault_is_literal)
!             appendStringLiteral(q, typdefault, true);
          else
              appendPQExpBufferStr(q, typdefault);
      }
--- 5174,5180 ----
      {
          appendPQExpBuffer(q, " DEFAULT ");
          if (typdefault_is_literal)
!             appendStringLiteral(q, typdefault, true, !std_strings);
          else
              appendPQExpBufferStr(q, typdefault);
      }
***************
*** 5690,5696 ****
      if (strcmp(probin, "-") != 0)
      {
          appendPQExpBuffer(asPart, "AS ");
!         appendStringLiteral(asPart, probin, true);
          if (strcmp(prosrc, "-") != 0)
          {
              appendPQExpBuffer(asPart, ", ");
--- 5744,5750 ----
      if (strcmp(probin, "-") != 0)
      {
          appendPQExpBuffer(asPart, "AS ");
!         appendStringLiteral(asPart, probin, true, !std_strings);
          if (strcmp(prosrc, "-") != 0)
          {
              appendPQExpBuffer(asPart, ", ");
***************
*** 5700,5706 ****
               * contains quote or backslash; else use regular quoting.
               */
              if (disable_dollar_quoting)
!                 appendStringLiteral(asPart, prosrc, false);
              else
                  appendStringLiteralDQOpt(asPart, prosrc, false, NULL);
          }
--- 5754,5760 ----
               * contains quote or backslash; else use regular quoting.
               */
              if (disable_dollar_quoting)
!                 appendStringLiteral(asPart, prosrc, false, !std_strings);
              else
                  appendStringLiteralDQOpt(asPart, prosrc, false, NULL);
          }
***************
*** 5712,5718 ****
              appendPQExpBuffer(asPart, "AS ");
              /* with no bin, dollar quote src unconditionally if allowed */
              if (disable_dollar_quoting)
!                 appendStringLiteral(asPart, prosrc, false);
              else
                  appendStringLiteralDQ(asPart, prosrc, NULL);
          }
--- 5766,5772 ----
              appendPQExpBuffer(asPart, "AS ");
              /* with no bin, dollar quote src unconditionally if allowed */
              if (disable_dollar_quoting)
!                 appendStringLiteral(asPart, prosrc, false, !std_strings);
              else
                  appendStringLiteralDQ(asPart, prosrc, NULL);
          }
***************
*** 6628,6636 ****
      appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ",
                        (condefault) ? "DEFAULT " : "",
                        fmtId(convinfo->dobj.name));
!     appendStringLiteral(q, conforencoding, true);
      appendPQExpBuffer(q, " TO ");
!     appendStringLiteral(q, contoencoding, true);
      /* regproc is automatically quoted in 7.3 and above */
      appendPQExpBuffer(q, " FROM %s;\n", conproc);

--- 6682,6690 ----
      appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ",
                        (condefault) ? "DEFAULT " : "",
                        fmtId(convinfo->dobj.name));
!     appendStringLiteral(q, conforencoding, true, !std_strings);
      appendPQExpBuffer(q, " TO ");
!     appendStringLiteral(q, contoencoding, true, !std_strings);
      /* regproc is automatically quoted in 7.3 and above */
      appendPQExpBuffer(q, " FROM %s;\n", conproc);

***************
*** 6871,6877 ****
      if (!PQgetisnull(res, 0, i_agginitval))
      {
          appendPQExpBuffer(details, ",\n    INITCOND = ");
!         appendStringLiteral(details, agginitval, true);
      }

      if (strcmp(aggfinalfn, "-") != 0)
--- 6925,6931 ----
      if (!PQgetisnull(res, 0, i_agginitval))
      {
          appendPQExpBuffer(details, ",\n    INITCOND = ");
!         appendStringLiteral(details, agginitval, true, !std_strings);
      }

      if (strcmp(aggfinalfn, "-") != 0)
***************
*** 7058,7064 ****
          {
              appendPQExpBuffer(query, "SELECT definition as viewdef "
                                " from pg_views where viewname = ");
!             appendStringLiteral(query, tbinfo->dobj.name, true);
              appendPQExpBuffer(query, ";");
          }

--- 7112,7118 ----
          {
              appendPQExpBuffer(query, "SELECT definition as viewdef "
                                " from pg_views where viewname = ");
!             appendStringLiteral(query, tbinfo->dobj.name, true, !std_strings);
              appendPQExpBuffer(query, ";");
          }

***************
*** 7707,7713 ****

      resetPQExpBuffer(query);
      appendPQExpBuffer(query, "SELECT datlastsysoid from pg_database where datname = ");
!     appendStringLiteral(query, dbname, true);

      res = PQexec(g_conn, query->data);
      check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
--- 7761,7767 ----

      resetPQExpBuffer(query);
      appendPQExpBuffer(query, "SELECT datlastsysoid from pg_database where datname = ");
!     appendStringLiteral(query, dbname, true, !std_strings);

      res = PQexec(g_conn, query->data);
      check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
***************
*** 7908,7920 ****
              (owning_tab = findTableByOid(tbinfo->owning_tab)) != NULL)
          {
              appendPQExpBuffer(query, "pg_catalog.pg_get_serial_sequence(");
!             appendStringLiteral(query, fmtId(owning_tab->dobj.name), true);
              appendPQExpBuffer(query, ", ");
!             appendStringLiteral(query, owning_tab->attnames[tbinfo->owning_col - 1], true);
              appendPQExpBuffer(query, ")");
          }
          else
!             appendStringLiteral(query, fmtId(tbinfo->dobj.name), true);
          appendPQExpBuffer(query, ", %s, %s);\n",
                            last, (called ? "true" : "false"));

--- 7962,7974 ----
              (owning_tab = findTableByOid(tbinfo->owning_tab)) != NULL)
          {
              appendPQExpBuffer(query, "pg_catalog.pg_get_serial_sequence(");
!             appendStringLiteral(query, fmtId(owning_tab->dobj.name), true, !std_strings);
              appendPQExpBuffer(query, ", ");
!             appendStringLiteral(query, owning_tab->attnames[tbinfo->owning_col - 1], true, !std_strings);
              appendPQExpBuffer(query, ")");
          }
          else
!             appendStringLiteral(query, fmtId(tbinfo->dobj.name), true, !std_strings);
          appendPQExpBuffer(query, ", %s, %s);\n",
                            last, (called ? "true" : "false"));

***************
*** 8083,8090 ****
          appendPQExpBufferChar(query, '\'');
          while (s < p)
          {
!             if (*s == '\'')        /* bytea already doubles backslashes */
                  appendPQExpBufferChar(query, '\'');
              appendPQExpBufferChar(query, *s++);
          }
          appendPQExpBufferChar(query, '\'');
--- 8137,8150 ----
          appendPQExpBufferChar(query, '\'');
          while (s < p)
          {
!             if (*s == '\'')
                  appendPQExpBufferChar(query, '\'');
+             /*
+              *    bytea unconditionally doubles backslashes, so we suppress
+              *    the doubling for standard_conforming_strings.
+              */
+             if (std_strings && *s == '\\')
+                 s++;
              appendPQExpBufferChar(query, *s++);
          }
          appendPQExpBufferChar(query, '\'');
Index: src/bin/pg_dump/pg_dumpall.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/pg_dump/pg_dumpall.c,v
retrieving revision 1.75
diff -c -c -r1.75 pg_dumpall.c
*** src/bin/pg_dump/pg_dumpall.c    22 May 2006 11:21:54 -0000    1.75
--- src/bin/pg_dump/pg_dumpall.c    25 May 2006 22:15:58 -0000
***************
*** 535,541 ****
          if (!PQgetisnull(res, i, i_rolpassword))
          {
              appendPQExpBuffer(buf, " PASSWORD ");
!             appendStringLiteral(buf, PQgetvalue(res, i, i_rolpassword), true);
          }

          if (!PQgetisnull(res, i, i_rolvaliduntil))
--- 535,541 ----
          if (!PQgetisnull(res, i, i_rolpassword))
          {
              appendPQExpBuffer(buf, " PASSWORD ");
!             appendStringLiteral(buf, PQgetvalue(res, i, i_rolpassword), true, true);
          }

          if (!PQgetisnull(res, i, i_rolvaliduntil))
***************
*** 546,552 ****

          if (!PQgetisnull(res, i, i_rolcomment)) {
              appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename));
!             appendStringLiteral(buf, PQgetvalue(res, i, i_rolcomment), true);
              appendPQExpBuffer(buf, ";\n");
          }

--- 546,552 ----

          if (!PQgetisnull(res, i, i_rolcomment)) {
              appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename));
!             appendStringLiteral(buf, PQgetvalue(res, i, i_rolcomment), true, true);
              appendPQExpBuffer(buf, ";\n");
          }

***************
*** 730,736 ****
          appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner));

          appendPQExpBuffer(buf, " LOCATION ");
!         appendStringLiteral(buf, spclocation, true);
          appendPQExpBuffer(buf, ";\n");

          if (!skip_acls &&
--- 730,736 ----
          appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner));

          appendPQExpBuffer(buf, " LOCATION ");
!         appendStringLiteral(buf, spclocation, true, true);
          appendPQExpBuffer(buf, ";\n");

          if (!skip_acls &&
***************
*** 745,751 ****

          if (spccomment && strlen(spccomment)) {
              appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname);
!             appendStringLiteral(buf, spccomment, true);
              appendPQExpBuffer(buf, ";\n");
          }

--- 745,751 ----

          if (spccomment && strlen(spccomment)) {
              appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname);
!             appendStringLiteral(buf, spccomment, true, true);
              appendPQExpBuffer(buf, ";\n");
          }

***************
*** 868,874 ****
                  appendPQExpBuffer(buf, " OWNER = %s", fmtId(dbowner));

              appendPQExpBuffer(buf, " ENCODING = ");
!             appendStringLiteral(buf, dbencoding, true);

              /* Output tablespace if it isn't default */
              if (strcmp(dbtablespace, "pg_default") != 0)
--- 868,874 ----
                  appendPQExpBuffer(buf, " OWNER = %s", fmtId(dbowner));

              appendPQExpBuffer(buf, " ENCODING = ");
!             appendStringLiteral(buf, dbencoding, true, true);

              /* Output tablespace if it isn't default */
              if (strcmp(dbtablespace, "pg_default") != 0)
***************
*** 884,890 ****
              if (strcmp(dbistemplate, "t") == 0)
              {
                  appendPQExpBuffer(buf, "UPDATE pg_database SET datistemplate = 't' WHERE datname = ");
!                 appendStringLiteral(buf, dbname, true);
                  appendPQExpBuffer(buf, ";\n");
              }
          }
--- 884,890 ----
              if (strcmp(dbistemplate, "t") == 0)
              {
                  appendPQExpBuffer(buf, "UPDATE pg_database SET datistemplate = 't' WHERE datname = ");
!                 appendStringLiteral(buf, dbname, true, true);
                  appendPQExpBuffer(buf, ";\n");
              }
          }
***************
*** 929,935 ****
          PGresult   *res;

          printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count);
!         appendStringLiteral(buf, dbname, true);
          appendPQExpBuffer(buf, ";");

          res = executeQuery(conn, buf->data);
--- 929,935 ----
          PGresult   *res;

          printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count);
!         appendStringLiteral(buf, dbname, true, true);
          appendPQExpBuffer(buf, ";");

          res = executeQuery(conn, buf->data);
***************
*** 968,974 ****
              printfPQExpBuffer(buf, "SELECT rolconfig[%d] FROM pg_authid WHERE rolname = ", count);
          else
              printfPQExpBuffer(buf, "SELECT useconfig[%d] FROM pg_shadow WHERE usename = ", count);
!         appendStringLiteral(buf, username, true);

          res = executeQuery(conn, buf->data);
          if (PQntuples(res) == 1 &&
--- 968,974 ----
              printfPQExpBuffer(buf, "SELECT rolconfig[%d] FROM pg_authid WHERE rolname = ", count);
          else
              printfPQExpBuffer(buf, "SELECT useconfig[%d] FROM pg_shadow WHERE usename = ", count);
!         appendStringLiteral(buf, username, true, true);

          res = executeQuery(conn, buf->data);
          if (PQntuples(res) == 1 &&
***************
*** 1016,1022 ****
          || pg_strcasecmp(mine, "search_path") == 0)
          appendPQExpBuffer(buf, "%s", pos + 1);
      else
!         appendStringLiteral(buf, pos + 1, false);
      appendPQExpBuffer(buf, ";\n");

      printf("%s", buf->data);
--- 1016,1022 ----
          || pg_strcasecmp(mine, "search_path") == 0)
          appendPQExpBuffer(buf, "%s", pos + 1);
      else
!         appendStringLiteral(buf, pos + 1, false, true);
      appendPQExpBuffer(buf, ";\n");

      printf("%s", buf->data);
Index: src/bin/psql/describe.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/describe.c,v
retrieving revision 1.134
diff -c -c -r1.134 describe.c
*** src/bin/psql/describe.c    26 Apr 2006 23:15:45 -0000    1.134
--- src/bin/psql/describe.c    25 May 2006 22:15:59 -0000
***************
*** 1867,1873 ****
                  appendPQExpBuffer(&namebuf, "\\\\");

              /* Ensure chars special to string literals are passed properly */
!             if (SQL_STR_DOUBLE(*cp))
                  appendPQExpBufferChar(&namebuf, *cp);

              i = PQmblen(cp, pset.encoding);
--- 1867,1873 ----
                  appendPQExpBuffer(&namebuf, "\\\\");

              /* Ensure chars special to string literals are passed properly */
!             if (SQL_STR_DOUBLE(*cp, true))
                  appendPQExpBufferChar(&namebuf, *cp);

              i = PQmblen(cp, pset.encoding);
Index: src/bin/psql/large_obj.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/large_obj.c,v
retrieving revision 1.41
diff -c -c -r1.41 large_obj.c
*** src/bin/psql/large_obj.c    5 Mar 2006 15:58:51 -0000    1.41
--- src/bin/psql/large_obj.c    25 May 2006 22:15:59 -0000
***************
*** 178,187 ****

          if (strchr(comment_arg, '\\') != NULL)
              *bufptr++ = ESCAPE_STRING_SYNTAX;
          *bufptr++ = '\'';
          for (i = 0; i < slen; i++)
          {
!             if (SQL_STR_DOUBLE(comment_arg[i]))
                  *bufptr++ = comment_arg[i];
              *bufptr++ = comment_arg[i];
          }
--- 178,188 ----

          if (strchr(comment_arg, '\\') != NULL)
              *bufptr++ = ESCAPE_STRING_SYNTAX;
+
          *bufptr++ = '\'';
          for (i = 0; i < slen; i++)
          {
!             if (SQL_STR_DOUBLE(comment_arg[i], true))
                  *bufptr++ = comment_arg[i];
              *bufptr++ = comment_arg[i];
          }
Index: src/bin/scripts/createdb.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/scripts/createdb.c,v
retrieving revision 1.16
diff -c -c -r1.16 createdb.c
*** src/bin/scripts/createdb.c    5 Mar 2006 15:58:52 -0000    1.16
--- src/bin/scripts/createdb.c    25 May 2006 22:15:59 -0000
***************
*** 184,190 ****
      if (comment)
      {
          printfPQExpBuffer(&sql, "COMMENT ON DATABASE %s IS ", fmtId(dbname));
!         appendStringLiteral(&sql, comment, false);
          appendPQExpBuffer(&sql, ";\n");

          conn = connectDatabase(dbname, host, port, username, password, progname);
--- 184,190 ----
      if (comment)
      {
          printfPQExpBuffer(&sql, "COMMENT ON DATABASE %s IS ", fmtId(dbname));
!         appendStringLiteral(&sql, comment, false, true);
          appendPQExpBuffer(&sql, ";\n");

          conn = connectDatabase(dbname, host, port, username, password, progname);
Index: src/bin/scripts/createuser.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/scripts/createuser.c,v
retrieving revision 1.27
diff -c -c -r1.27 createuser.c
*** src/bin/scripts/createuser.c    5 Mar 2006 15:58:52 -0000    1.27
--- src/bin/scripts/createuser.c    25 May 2006 22:15:59 -0000
***************
*** 258,268 ****
                  fprintf(stderr, _("Password encryption failed.\n"));
                  exit(1);
              }
!             appendStringLiteral(&sql, encrypted_password, false);
              PQfreemem(encrypted_password);
          }
          else
!             appendStringLiteral(&sql, newpassword, false);
      }
      if (superuser == TRI_YES)
          appendPQExpBuffer(&sql, " SUPERUSER");
--- 258,268 ----
                  fprintf(stderr, _("Password encryption failed.\n"));
                  exit(1);
              }
!             appendStringLiteral(&sql, encrypted_password, false, true);
              PQfreemem(encrypted_password);
          }
          else
!             appendStringLiteral(&sql, newpassword, false, true);
      }
      if (superuser == TRI_YES)
          appendPQExpBuffer(&sql, " SUPERUSER");
Index: src/include/c.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/c.h,v
retrieving revision 1.200
diff -c -c -r1.200 c.h
*** src/include/c.h    14 Apr 2006 03:38:56 -0000    1.200
--- src/include/c.h    25 May 2006 22:15:59 -0000
***************
*** 472,478 ****

  #define NameStr(name)    ((name).data)

! #define SQL_STR_DOUBLE(ch)    ((ch) == '\'' || (ch) == '\\')
  #define ESCAPE_STRING_SYNTAX    'E'

  /* ----------------------------------------------------------------
--- 472,485 ----

  #define NameStr(name)    ((name).data)

! /*
!  *    In 8.2, we are warning for \ in a non-E string if std_strings are off.
!  *    For this reason, we use E for \ strings, unless standard_conforming_strings
!  *    is on.
!  */
! #define SQL_STR_DOUBLE(ch, escape_backslash)    \
!                     ((ch) == '\'' || ((escape_backslash) && (ch) == '\\'))
!
  #define ESCAPE_STRING_SYNTAX    'E'

  /* ----------------------------------------------------------------
Index: src/interfaces/ecpg/ecpglib/execute.c
===================================================================
RCS file: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v
retrieving revision 1.45
diff -c -c -r1.45 execute.c
*** src/interfaces/ecpg/ecpglib/execute.c    24 Apr 2006 09:45:22 -0000    1.45
--- src/interfaces/ecpg/ecpglib/execute.c    25 May 2006 22:16:02 -0000
***************
*** 32,39 ****
  #include "pgtypes_timestamp.h"
  #include "pgtypes_interval.h"

! /* This function returns a newly malloced string that has the  \
!    in the argument quoted with \ and the ' quoted with ' as SQL92 says.
   */
  static char *
  quote_postgres(char *arg, int lineno)
--- 32,40 ----
  #include "pgtypes_timestamp.h"
  #include "pgtypes_interval.h"

! /*
!  *    This function returns a newly malloced string that has ' and \
!  *    escaped.
   */
  static char *
  quote_postgres(char *arg, int lineno)
***************
*** 45,57 ****
      if (!res)
          return (res);

      if (strchr(arg, '\\') != NULL)
          res[ri++] = ESCAPE_STRING_SYNTAX;
      res[ri++] = '\'';

      for (i = 0; arg[i]; i++, ri++)
      {
!         if (SQL_STR_DOUBLE(arg[i]))
              res[ri++] = arg[i];
          res[ri] = arg[i];
      }
--- 46,62 ----
      if (!res)
          return (res);

+     /*
+      *    We don't know if the target database is using
+      *    standard_conforming_strings, so we always use E'' strings.
+      */
      if (strchr(arg, '\\') != NULL)
          res[ri++] = ESCAPE_STRING_SYNTAX;
      res[ri++] = '\'';

      for (i = 0; arg[i]; i++, ri++)
      {
!         if (SQL_STR_DOUBLE(arg[i], true))
              res[ri++] = arg[i];
          res[ri] = arg[i];
      }
Index: src/pl/plpgsql/src/gram.y
===================================================================
RCS file: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v
retrieving revision 1.88
diff -c -c -r1.88 gram.y
*** src/pl/plpgsql/src/gram.y    23 Mar 2006 04:22:36 -0000    1.88
--- src/pl/plpgsql/src/gram.y    25 May 2006 22:16:05 -0000
***************
*** 17,22 ****
--- 17,23 ----
  #include "plpgsql.h"

  #include "parser/parser.h"
+ #include "parser/gramparse.h"

  static PLpgSQL_expr        *read_sql_construct(int until,
                                              int until2,
***************
*** 376,387 ****
                          strcpy(buf, "SELECT ");
                          cp1 = new->refname;
                          cp2 = buf + strlen(buf);
!                         if (strchr(cp1, '\\') != NULL)
                              *cp2++ = ESCAPE_STRING_SYNTAX;
                          *cp2++ = '\'';
                          while (*cp1)
                          {
!                             if (SQL_STR_DOUBLE(*cp1))
                                  *cp2++ = *cp1;
                              *cp2++ = *cp1++;
                          }
--- 377,388 ----
                          strcpy(buf, "SELECT ");
                          cp1 = new->refname;
                          cp2 = buf + strlen(buf);
!                         if (!standard_conforming_strings && strchr(cp1, '\\') != NULL)
                              *cp2++ = ESCAPE_STRING_SYNTAX;
                          *cp2++ = '\'';
                          while (*cp1)
                          {
!                             if (SQL_STR_DOUBLE(*cp1, !standard_conforming_strings))
                                  *cp2++ = *cp1;
                              *cp2++ = *cp1++;
                          }

Re: Cleanup for new escape handling

From
Bruce Momjian
Date:
Patch applied.

---------------------------------------------------------------------------


Bruce Momjian wrote:
> This patch cleans up the use of E'' strings in 8.2.  8.2 is the first
> release where standard_conforming_strings can be 'on', and when 'on',
> escape_string_warning is disabled.
>
> In 8.1, the behavior was to use E'' strings for any case where
> backslashes exist.  For 8.2, per suggestion from Tom, we should use E''
> strings only for standard_conforming_strings = 'off'.  This would allow
> pg_dump output with standard_conforming_strings = 'on' to generate
> proper strings that can be loaded into other databases without the
> backslash doubling we typically do.  I have added the dumping of the
> standard_conforming_strings to pg_dump, like we do now for
> client_encoding.  The only risk of the patch is that someone will use
> one of the adt/ruleutils.c functions like pg_get_constraintdef() with
> one setting of standard_conforming_strings and then try to load it into
> a database with a different standard_conforming_strings setting.
>
> I also added standard backslash handling for plpgsql.
>
> I also checked ecpg and that uses E'' for all strings that have \
> because it doesn't know if the target database is going to have
> standard_conforming_strings on or off.  That seems best, and no one
> expects the _output_ of ecpg to be portable.
>
> The macros we use for escape processing really makes these changes easy.
>
> --
>   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/backend/utils/adt/quote.c
> ===================================================================
> RCS file: /cvsroot/pgsql/src/backend/utils/adt/quote.c,v
> retrieving revision 1.18
> diff -c -c -r1.18 quote.c
> *** src/backend/utils/adt/quote.c    5 Mar 2006 15:58:43 -0000    1.18
> --- src/backend/utils/adt/quote.c    25 May 2006 22:15:36 -0000
> ***************
> *** 14,19 ****
> --- 14,20 ----
>   #include "postgres.h"
>
>   #include "utils/builtins.h"
> + #include "parser/gramparse.h"
>
>
>   /*
> ***************
> *** 65,83 ****
>       cp1 = VARDATA(t);
>       cp2 = VARDATA(result);
>
> !     for (; len-- > 0; cp1++)
> !         if (*cp1 == '\\')
> !         {
> !             *cp2++ = ESCAPE_STRING_SYNTAX;
> !             break;
> !         }
>
>       len = VARSIZE(t) - VARHDRSZ;
>       cp1 = VARDATA(t);
>       *cp2++ = '\'';
>       while (len-- > 0)
>       {
> !         if (SQL_STR_DOUBLE(*cp1))
>               *cp2++ = *cp1;
>           *cp2++ = *cp1++;
>       }
> --- 66,85 ----
>       cp1 = VARDATA(t);
>       cp2 = VARDATA(result);
>
> !     if (!standard_conforming_strings)
> !         for (; len-- > 0; cp1++)
> !             if (*cp1 == '\\')
> !             {
> !                 *cp2++ = ESCAPE_STRING_SYNTAX;
> !                 break;
> !             }
>
>       len = VARSIZE(t) - VARHDRSZ;
>       cp1 = VARDATA(t);
>       *cp2++ = '\'';
>       while (len-- > 0)
>       {
> !         if (SQL_STR_DOUBLE(*cp1, !standard_conforming_strings))
>               *cp2++ = *cp1;
>           *cp2++ = *cp1++;
>       }
> Index: src/backend/utils/adt/ruleutils.c
> ===================================================================
> RCS file: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v
> retrieving revision 1.221
> diff -c -c -r1.221 ruleutils.c
> *** src/backend/utils/adt/ruleutils.c    30 Apr 2006 18:30:40 -0000    1.221
> --- src/backend/utils/adt/ruleutils.c    25 May 2006 22:15:41 -0000
> ***************
> *** 31,36 ****
> --- 31,37 ----
>   #include "nodes/makefuncs.h"
>   #include "optimizer/clauses.h"
>   #include "optimizer/tlist.h"
> + #include "parser/gramparse.h"
>   #include "parser/keywords.h"
>   #include "parser/parse_expr.h"
>   #include "parser/parse_func.h"
> ***************
> *** 533,545 ****
>           {
>               if (i > 0)
>                   appendStringInfo(&buf, ", ");
> !             if (strchr(p, '\\') != NULL)
>                   appendStringInfoChar(&buf, ESCAPE_STRING_SYNTAX);
>               appendStringInfoChar(&buf, '\'');
>
>               while (*p)
>               {
> !                 if (SQL_STR_DOUBLE(*p))
>                       appendStringInfoChar(&buf, *p);
>                   appendStringInfoChar(&buf, *p++);
>               }
> --- 534,546 ----
>           {
>               if (i > 0)
>                   appendStringInfo(&buf, ", ");
> !             if (!standard_conforming_strings && strchr(p, '\\') != NULL)
>                   appendStringInfoChar(&buf, ESCAPE_STRING_SYNTAX);
>               appendStringInfoChar(&buf, '\'');
>
>               while (*p)
>               {
> !                 if (SQL_STR_DOUBLE(*p, !standard_conforming_strings))
>                       appendStringInfoChar(&buf, *p);
>                   appendStringInfoChar(&buf, *p++);
>               }
> ***************
> *** 3882,3888 ****
>       char       *valptr;
>       bool        isfloat = false;
>       bool        needlabel;
> !
>       if (constval->constisnull)
>       {
>           /*
> --- 3883,3890 ----
>       char       *valptr;
>       bool        isfloat = false;
>       bool        needlabel;
> !     bool        is_e_string = false;
> !
>       if (constval->constisnull)
>       {
>           /*
> ***************
> *** 3948,3957 ****
>                * representation. XXX Any MULTIBYTE considerations here?
>                */
>               for (valptr = extval; *valptr; valptr++)
> !                 if (*valptr == '\\' ||
>                       (unsigned char) *valptr < (unsigned char) ' ')
>                   {
>                       appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
>                       break;
>                   }
>
> --- 3950,3960 ----
>                * representation. XXX Any MULTIBYTE considerations here?
>                */
>               for (valptr = extval; *valptr; valptr++)
> !                 if ((!standard_conforming_strings && *valptr == '\\') ||
>                       (unsigned char) *valptr < (unsigned char) ' ')
>                   {
>                       appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
> +                     is_e_string = true;
>                       break;
>                   }
>
> ***************
> *** 3960,3966 ****
>               {
>                   char        ch = *valptr;
>
> !                 if (SQL_STR_DOUBLE(ch))
>                   {
>                       appendStringInfoChar(buf, ch);
>                       appendStringInfoChar(buf, ch);
> --- 3963,3969 ----
>               {
>                   char        ch = *valptr;
>
> !                 if (SQL_STR_DOUBLE(ch, is_e_string))
>                   {
>                       appendStringInfoChar(buf, ch);
>                       appendStringInfoChar(buf, ch);
> Index: src/bin/initdb/initdb.c
> ===================================================================
> RCS file: /cvsroot/pgsql/src/bin/initdb/initdb.c,v
> retrieving revision 1.114
> diff -c -c -r1.114 initdb.c
> *** src/bin/initdb/initdb.c    21 Mar 2006 17:54:28 -0000    1.114
> --- src/bin/initdb/initdb.c    25 May 2006 22:15:48 -0000
> ***************
> *** 2103,2109 ****
>   }
>
>   /*
> !  * Escape any single quotes or backslashes in given string
>    */
>   static char *
>   escape_quotes(const char *src)
> --- 2103,2110 ----
>   }
>
>   /*
> !  * Escape any single quotes or backslashes in given string;
> !  * postgresql.conf always enables backslash escapes
>    */
>   static char *
>   escape_quotes(const char *src)
> ***************
> *** 2115,2121 ****
>
>       for (i = 0, j = 0; i < len; i++)
>       {
> !         if (SQL_STR_DOUBLE(src[i]))
>               result[j++] = src[i];
>           result[j++] = src[i];
>       }
> --- 2116,2122 ----
>
>       for (i = 0, j = 0; i < len; i++)
>       {
> !         if (SQL_STR_DOUBLE(src[i], true))
>               result[j++] = src[i];
>           result[j++] = src[i];
>       }
> Index: src/bin/pg_dump/dumputils.c
> ===================================================================
> RCS file: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v
> retrieving revision 1.27
> diff -c -c -r1.27 dumputils.c
> *** src/bin/pg_dump/dumputils.c    30 Apr 2006 21:15:33 -0000    1.27
> --- src/bin/pg_dump/dumputils.c    25 May 2006 22:15:49 -0000
> ***************
> *** 105,128 ****
>    * Special characters are escaped. Quote mark ' goes to '' per SQL
>    * standard, other stuff goes to \ sequences.  If escapeAll is false,
>    * whitespace characters are not escaped (tabs, newlines, etc.).  This
> !  * is appropriate for dump file output.
>    */
>   void
> ! appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll)
>   {
>       char        ch;
>       const char *p;
>
>       for (p = str; *p; p++)
>       {
>           ch = *p;
> !         if (ch == '\\' ||
>               ((unsigned char) ch < (unsigned char) ' ' &&
>                (escapeAll ||
>                 (ch != '\t' && ch != '\n' && ch != '\v' &&
>                  ch != '\f' && ch != '\r'))))
>           {
>               appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX);
>               break;
>           }
>       }
> --- 105,133 ----
>    * Special characters are escaped. Quote mark ' goes to '' per SQL
>    * standard, other stuff goes to \ sequences.  If escapeAll is false,
>    * whitespace characters are not escaped (tabs, newlines, etc.).  This
> !  * is appropriate for dump file output.  Using E'' strings for
> !  * backslashes is always safe for standard_conforming_strings on or off.
>    */
>   void
> ! appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll,
> !                     bool e_string_for_backslash)
>   {
>       char        ch;
>       const char *p;
> +     bool        is_e_string = false;
>
>       for (p = str; *p; p++)
>       {
>           ch = *p;
> !
> !         if ((e_string_for_backslash && ch == '\\') ||
>               ((unsigned char) ch < (unsigned char) ' ' &&
>                (escapeAll ||
>                 (ch != '\t' && ch != '\n' && ch != '\v' &&
>                  ch != '\f' && ch != '\r'))))
>           {
>               appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX);
> +             is_e_string = true;
>               break;
>           }
>       }
> ***************
> *** 131,137 ****
>       for (p = str; *p; p++)
>       {
>           ch = *p;
> !         if (SQL_STR_DOUBLE(ch))
>           {
>               appendPQExpBufferChar(buf, ch);
>               appendPQExpBufferChar(buf, ch);
> --- 136,142 ----
>       for (p = str; *p; p++)
>       {
>           ch = *p;
> !         if (SQL_STR_DOUBLE(ch, is_e_string))
>           {
>               appendPQExpBufferChar(buf, ch);
>               appendPQExpBufferChar(buf, ch);
> ***************
> *** 208,214 ****
>                            bool escapeAll, const char *dqprefix)
>   {
>       if (strchr(str, '\'') == NULL && strchr(str, '\\') == NULL)
> !         appendStringLiteral(buf, str, escapeAll);
>       else
>           appendStringLiteralDQ(buf, str, dqprefix);
>   }
> --- 213,219 ----
>                            bool escapeAll, const char *dqprefix)
>   {
>       if (strchr(str, '\'') == NULL && strchr(str, '\\') == NULL)
> !         appendStringLiteral(buf, str, escapeAll, true);
>       else
>           appendStringLiteralDQ(buf, str, dqprefix);
>   }
> Index: src/bin/pg_dump/dumputils.h
> ===================================================================
> RCS file: /cvsroot/pgsql/src/bin/pg_dump/dumputils.h,v
> retrieving revision 1.15
> diff -c -c -r1.15 dumputils.h
> *** src/bin/pg_dump/dumputils.h    5 Mar 2006 15:58:50 -0000    1.15
> --- src/bin/pg_dump/dumputils.h    25 May 2006 22:15:49 -0000
> ***************
> *** 17,26 ****
>
>   #include "pqexpbuffer.h"
>
> -
>   extern const char *fmtId(const char *identifier);
>   extern void appendStringLiteral(PQExpBuffer buf, const char *str,
> !                     bool escapeAll);
>   extern void appendStringLiteralDQ(PQExpBuffer buf, const char *str,
>                         const char *dqprefix);
>   extern void appendStringLiteralDQOpt(PQExpBuffer buf, const char *str,
> --- 17,25 ----
>
>   #include "pqexpbuffer.h"
>
>   extern const char *fmtId(const char *identifier);
>   extern void appendStringLiteral(PQExpBuffer buf, const char *str,
> !                     bool escapeAll, bool e_string_for_backslash);
>   extern void appendStringLiteralDQ(PQExpBuffer buf, const char *str,
>                         const char *dqprefix);
>   extern void appendStringLiteralDQOpt(PQExpBuffer buf, const char *str,
> Index: src/bin/pg_dump/pg_backup_archiver.c
> ===================================================================
> RCS file: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v
> retrieving revision 1.129
> diff -c -c -r1.129 pg_backup_archiver.c
> *** src/bin/pg_dump/pg_backup_archiver.c    24 May 2006 21:20:11 -0000    1.129
> --- src/bin/pg_dump/pg_backup_archiver.c    25 May 2006 22:15:50 -0000
> ***************
> *** 1900,1908 ****
>   {
>       teReqs        res = REQ_ALL;
>
> !     /* ENCODING objects are dumped specially, so always reject here */
>       if (strcmp(te->desc, "ENCODING") == 0)
>           return 0;
>
>       /* If it's an ACL, maybe ignore it */
>       if ((!include_acls || ropt->aclsSkip) && strcmp(te->desc, "ACL") == 0)
> --- 1900,1910 ----
>   {
>       teReqs        res = REQ_ALL;
>
> !     /* ENCODING and STDSTRINGS objects are dumped specially, so always reject */
>       if (strcmp(te->desc, "ENCODING") == 0)
>           return 0;
> +     if (strcmp(te->desc, "STDSTRINGS") == 0)
> +         return 0;
>
>       /* If it's an ACL, maybe ignore it */
>       if ((!include_acls || ropt->aclsSkip) && strcmp(te->desc, "ACL") == 0)
> ***************
> *** 2005,2019 ****
>   {
>       TocEntry   *te;
>
> !     /* If we have an encoding setting, emit that */
>       te = AH->toc->next;
>       while (te != AH->toc)
>       {
>           if (strcmp(te->desc, "ENCODING") == 0)
> -         {
>               ahprintf(AH, "%s", te->defn);
> !             break;
> !         }
>           te = te->next;
>       }
>
> --- 2007,2020 ----
>   {
>       TocEntry   *te;
>
> !     /* If we have an encoding or std_strings setting, emit that */
>       te = AH->toc->next;
>       while (te != AH->toc)
>       {
>           if (strcmp(te->desc, "ENCODING") == 0)
>               ahprintf(AH, "%s", te->defn);
> !         if (strcmp(te->desc, "STDSTRINGS") == 0)
> !             ahprintf(AH, "%s", te->defn);
>           te = te->next;
>       }
>
> ***************
> *** 2042,2048 ****
>        * SQL requires a string literal here.    Might as well be correct.
>        */
>       if (user && *user)
> !         appendStringLiteral(cmd, user, false);
>       else
>           appendPQExpBuffer(cmd, "DEFAULT");
>       appendPQExpBuffer(cmd, ";");
> --- 2043,2049 ----
>        * SQL requires a string literal here.    Might as well be correct.
>        */
>       if (user && *user)
> !         appendStringLiteral(cmd, user, false, true);
>       else
>           appendPQExpBuffer(cmd, "DEFAULT");
>       appendPQExpBuffer(cmd, ";");
> Index: src/bin/pg_dump/pg_dump.c
> ===================================================================
> RCS file: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v
> retrieving revision 1.433
> diff -c -c -r1.433 pg_dump.c
> *** src/bin/pg_dump/pg_dump.c    5 Mar 2006 15:58:50 -0000    1.433
> --- src/bin/pg_dump/pg_dump.c    25 May 2006 22:15:57 -0000
> ***************
> *** 82,87 ****
> --- 82,88 ----
>                                    * activities. */
>   Archive    *g_fout;                /* the script file */
>   PGconn       *g_conn;                /* the database connection */
> + bool        std_strings = false;        /* GUC variable */
>
>   /* various user-settable parameters */
>   bool        dumpInserts;        /* dump data using proper insert strings */
> ***************
> *** 174,179 ****
> --- 175,181 ----
>   static int    dumpBlobComments(Archive *AH, void *arg);
>   static void dumpDatabase(Archive *AH);
>   static void dumpEncoding(Archive *AH);
> + static void dumpStdStrings(Archive *AH);
>   static const char *getAttrName(int attrnum, TableInfo *tblInfo);
>   static const char *fmtCopyColumnList(const TableInfo *ti);
>   static void do_sql_command(PGconn *conn, const char *query);
> ***************
> *** 619,624 ****
> --- 621,628 ----
>       /* First the special encoding entry. */
>       dumpEncoding(g_fout);
>
> +     dumpStdStrings(g_fout);
> +
>       /* The database item is always second, unless we don't want it at all */
>       if (!dataOnly && selectTableName == NULL && selectSchemaName == NULL)
>           dumpDatabase(g_fout);
> ***************
> *** 1084,1090 ****
>                       default:
>                           /* All other types are printed as string literals. */
>                           resetPQExpBuffer(q);
> !                         appendStringLiteral(q, PQgetvalue(res, tuple, field), false);
>                           archputs(q->data, fout);
>                           break;
>                   }
> --- 1088,1094 ----
>                       default:
>                           /* All other types are printed as string literals. */
>                           resetPQExpBuffer(q);
> !                         appendStringLiteral(q, PQgetvalue(res, tuple, field), false, !std_strings);
>                           archputs(q->data, fout);
>                           break;
>                   }
> ***************
> *** 1236,1242 ****
>                             "FROM pg_database "
>                             "WHERE datname = ",
>                             username_subquery);
> !         appendStringLiteral(dbQry, datname, true);
>       }
>       else if (g_fout->remoteVersion >= 80000)
>       {
> --- 1240,1246 ----
>                             "FROM pg_database "
>                             "WHERE datname = ",
>                             username_subquery);
> !         appendStringLiteral(dbQry, datname, true, !std_strings);
>       }
>       else if (g_fout->remoteVersion >= 80000)
>       {
> ***************
> *** 1247,1253 ****
>                             "FROM pg_database "
>                             "WHERE datname = ",
>                             username_subquery);
> !         appendStringLiteral(dbQry, datname, true);
>       }
>       else if (g_fout->remoteVersion >= 70100)
>       {
> --- 1251,1257 ----
>                             "FROM pg_database "
>                             "WHERE datname = ",
>                             username_subquery);
> !         appendStringLiteral(dbQry, datname, true, !std_strings);
>       }
>       else if (g_fout->remoteVersion >= 70100)
>       {
> ***************
> *** 1258,1264 ****
>                             "FROM pg_database "
>                             "WHERE datname = ",
>                             username_subquery);
> !         appendStringLiteral(dbQry, datname, true);
>       }
>       else
>       {
> --- 1262,1268 ----
>                             "FROM pg_database "
>                             "WHERE datname = ",
>                             username_subquery);
> !         appendStringLiteral(dbQry, datname, true, !std_strings);
>       }
>       else
>       {
> ***************
> *** 1271,1277 ****
>                             "FROM pg_database "
>                             "WHERE datname = ",
>                             username_subquery);
> !         appendStringLiteral(dbQry, datname, true);
>       }
>
>       res = PQexec(g_conn, dbQry->data);
> --- 1275,1281 ----
>                             "FROM pg_database "
>                             "WHERE datname = ",
>                             username_subquery);
> !         appendStringLiteral(dbQry, datname, true, !std_strings);
>       }
>
>       res = PQexec(g_conn, dbQry->data);
> ***************
> *** 1310,1316 ****
>       if (strlen(encoding) > 0)
>       {
>           appendPQExpBuffer(creaQry, " ENCODING = ");
> !         appendStringLiteral(creaQry, encoding, true);
>       }
>       if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0)
>           appendPQExpBuffer(creaQry, " TABLESPACE = %s",
> --- 1314,1320 ----
>       if (strlen(encoding) > 0)
>       {
>           appendPQExpBuffer(creaQry, " ENCODING = ");
> !         appendStringLiteral(creaQry, encoding, true, !std_strings);
>       }
>       if (strlen(tablespace) > 0 && strcmp(tablespace, "pg_default") != 0)
>           appendPQExpBuffer(creaQry, " TABLESPACE = %s",
> ***************
> *** 1349,1355 ****
>           if (comment && strlen(comment)) {
>               resetPQExpBuffer(dbQry);
>               appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname));
> !             appendStringLiteral(dbQry, comment, false);
>               appendPQExpBuffer(dbQry, ";\n");
>
>               ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL,
> --- 1353,1359 ----
>           if (comment && strlen(comment)) {
>               resetPQExpBuffer(dbQry);
>               appendPQExpBuffer(dbQry, "COMMENT ON DATABASE %s IS ", fmtId(datname));
> !             appendStringLiteral(dbQry, comment, false, !std_strings);
>               appendPQExpBuffer(dbQry, ";\n");
>
>               ArchiveEntry(AH, dbCatId, createDumpId(), datname, NULL, NULL,
> ***************
> *** 1398,1404 ****
>       resetPQExpBuffer(qry);
>
>       appendPQExpBuffer(qry, "SET client_encoding = ");
> !     appendStringLiteral(qry, PQgetvalue(res, 0, 0), true);
>       appendPQExpBuffer(qry, ";\n");
>
>       ArchiveEntry(AH, nilCatalogId, createDumpId(),
> --- 1402,1408 ----
>       resetPQExpBuffer(qry);
>
>       appendPQExpBuffer(qry, "SET client_encoding = ");
> !     appendStringLiteral(qry, PQgetvalue(res, 0, 0), true, !std_strings);
>       appendPQExpBuffer(qry, ";\n");
>
>       ArchiveEntry(AH, nilCatalogId, createDumpId(),
> ***************
> *** 1414,1419 ****
> --- 1418,1473 ----
>
>
>   /*
> +  * dumpStdStrings: put the correct escape string behavior into the archive
> +  */
> + static void
> + dumpStdStrings(Archive *AH)
> + {
> +     PQExpBuffer qry;
> +     PGresult   *res;
> +
> +     if (g_verbose)
> +         write_msg(NULL, "saving standard_conforming_strings setting\n");
> +
> +     qry = createPQExpBuffer();
> +
> +     /* standard_conforming_strings not used in pre-8.2 servers */
> +     if (AH->remoteVersion < 80200)
> +     {
> +         appendPQExpBuffer(qry, "SET standard_conforming_strings = 'off';\n");
> +         std_strings = false;
> +     }
> +     else
> +     {
> +         appendPQExpBuffer(qry, "SHOW standard_conforming_strings");
> +
> +         res = PQexec(g_conn, qry->data);
> +
> +         check_sql_result(res, g_conn, qry->data, PGRES_TUPLES_OK);
> +
> +         PQclear(res);
> +
> +         resetPQExpBuffer(qry);
> +
> +         std_strings = (strcmp(PQgetvalue(res, 0, 0), "on") == 0);
> +         appendPQExpBuffer(qry, "SET standard_conforming_strings = ");
> +         appendStringLiteral(qry, PQgetvalue(res, 0, 0), true, !std_strings);
> +         appendPQExpBuffer(qry, ";\n");
> +         puts(PQgetvalue(res, 0, 0));
> +
> +     }
> +
> +     ArchiveEntry(AH, nilCatalogId, createDumpId(),
> +                  "STDSTRINGS", NULL, NULL, "",
> +                  false, "STDSTRINGS", qry->data, "", NULL,
> +                  NULL, 0,
> +                  NULL, NULL);
> +
> +     destroyPQExpBuffer(qry);
> + }
> +
> +
> + /*
>    * hasBlobs:
>    *    Test whether database contains any large objects
>    */
> ***************
> *** 1586,1592 ****
>
>               printfPQExpBuffer(commentcmd, "COMMENT ON LARGE OBJECT %u IS ",
>                                 blobOid);
> !             appendStringLiteral(commentcmd, comment, false);
>               appendPQExpBuffer(commentcmd, ";\n");
>
>               archputs(commentcmd->data, AH);
> --- 1640,1646 ----
>
>               printfPQExpBuffer(commentcmd, "COMMENT ON LARGE OBJECT %u IS ",
>                                 blobOid);
> !             appendStringLiteral(commentcmd, comment, false, !std_strings);
>               appendPQExpBuffer(commentcmd, ";\n");
>
>               archputs(commentcmd->data, AH);
> ***************
> *** 4340,4346 ****
>           PQExpBuffer query = createPQExpBuffer();
>
>           appendPQExpBuffer(query, "COMMENT ON %s IS ", target);
> !         appendStringLiteral(query, comments->descr, false);
>           appendPQExpBuffer(query, ";\n");
>
>           ArchiveEntry(fout, nilCatalogId, createDumpId(),
> --- 4394,4400 ----
>           PQExpBuffer query = createPQExpBuffer();
>
>           appendPQExpBuffer(query, "COMMENT ON %s IS ", target);
> !         appendStringLiteral(query, comments->descr, false, !std_strings);
>           appendPQExpBuffer(query, ";\n");
>
>           ArchiveEntry(fout, nilCatalogId, createDumpId(),
> ***************
> *** 4398,4404 ****
>
>               resetPQExpBuffer(query);
>               appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
> !             appendStringLiteral(query, descr, false);
>               appendPQExpBuffer(query, ";\n");
>
>               ArchiveEntry(fout, nilCatalogId, createDumpId(),
> --- 4452,4458 ----
>
>               resetPQExpBuffer(query);
>               appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
> !             appendStringLiteral(query, descr, false, !std_strings);
>               appendPQExpBuffer(query, ";\n");
>
>               ArchiveEntry(fout, nilCatalogId, createDumpId(),
> ***************
> *** 4420,4426 ****
>
>               resetPQExpBuffer(query);
>               appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
> !             appendStringLiteral(query, descr, false);
>               appendPQExpBuffer(query, ";\n");
>
>               ArchiveEntry(fout, nilCatalogId, createDumpId(),
> --- 4474,4480 ----
>
>               resetPQExpBuffer(query);
>               appendPQExpBuffer(query, "COMMENT ON %s IS ", target->data);
> !             appendStringLiteral(query, descr, false, !std_strings);
>               appendPQExpBuffer(query, ";\n");
>
>               ArchiveEntry(fout, nilCatalogId, createDumpId(),
> ***************
> *** 4986,4992 ****
>       {
>           appendPQExpBuffer(q, ",\n    DEFAULT = ");
>           if (typdefault_is_literal)
> !             appendStringLiteral(q, typdefault, true);
>           else
>               appendPQExpBufferStr(q, typdefault);
>       }
> --- 5040,5046 ----
>       {
>           appendPQExpBuffer(q, ",\n    DEFAULT = ");
>           if (typdefault_is_literal)
> !             appendStringLiteral(q, typdefault, true, !std_strings);
>           else
>               appendPQExpBufferStr(q, typdefault);
>       }
> ***************
> *** 5005,5011 ****
>       if (typdelim && strcmp(typdelim, ",") != 0)
>       {
>           appendPQExpBuffer(q, ",\n    DELIMITER = ");
> !         appendStringLiteral(q, typdelim, true);
>       }
>
>       if (strcmp(typalign, "c") == 0)
> --- 5059,5065 ----
>       if (typdelim && strcmp(typdelim, ",") != 0)
>       {
>           appendPQExpBuffer(q, ",\n    DELIMITER = ");
> !         appendStringLiteral(q, typdelim, true, !std_strings);
>       }
>
>       if (strcmp(typalign, "c") == 0)
> ***************
> *** 5120,5126 ****
>       {
>           appendPQExpBuffer(q, " DEFAULT ");
>           if (typdefault_is_literal)
> !             appendStringLiteral(q, typdefault, true);
>           else
>               appendPQExpBufferStr(q, typdefault);
>       }
> --- 5174,5180 ----
>       {
>           appendPQExpBuffer(q, " DEFAULT ");
>           if (typdefault_is_literal)
> !             appendStringLiteral(q, typdefault, true, !std_strings);
>           else
>               appendPQExpBufferStr(q, typdefault);
>       }
> ***************
> *** 5690,5696 ****
>       if (strcmp(probin, "-") != 0)
>       {
>           appendPQExpBuffer(asPart, "AS ");
> !         appendStringLiteral(asPart, probin, true);
>           if (strcmp(prosrc, "-") != 0)
>           {
>               appendPQExpBuffer(asPart, ", ");
> --- 5744,5750 ----
>       if (strcmp(probin, "-") != 0)
>       {
>           appendPQExpBuffer(asPart, "AS ");
> !         appendStringLiteral(asPart, probin, true, !std_strings);
>           if (strcmp(prosrc, "-") != 0)
>           {
>               appendPQExpBuffer(asPart, ", ");
> ***************
> *** 5700,5706 ****
>                * contains quote or backslash; else use regular quoting.
>                */
>               if (disable_dollar_quoting)
> !                 appendStringLiteral(asPart, prosrc, false);
>               else
>                   appendStringLiteralDQOpt(asPart, prosrc, false, NULL);
>           }
> --- 5754,5760 ----
>                * contains quote or backslash; else use regular quoting.
>                */
>               if (disable_dollar_quoting)
> !                 appendStringLiteral(asPart, prosrc, false, !std_strings);
>               else
>                   appendStringLiteralDQOpt(asPart, prosrc, false, NULL);
>           }
> ***************
> *** 5712,5718 ****
>               appendPQExpBuffer(asPart, "AS ");
>               /* with no bin, dollar quote src unconditionally if allowed */
>               if (disable_dollar_quoting)
> !                 appendStringLiteral(asPart, prosrc, false);
>               else
>                   appendStringLiteralDQ(asPart, prosrc, NULL);
>           }
> --- 5766,5772 ----
>               appendPQExpBuffer(asPart, "AS ");
>               /* with no bin, dollar quote src unconditionally if allowed */
>               if (disable_dollar_quoting)
> !                 appendStringLiteral(asPart, prosrc, false, !std_strings);
>               else
>                   appendStringLiteralDQ(asPart, prosrc, NULL);
>           }
> ***************
> *** 6628,6636 ****
>       appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ",
>                         (condefault) ? "DEFAULT " : "",
>                         fmtId(convinfo->dobj.name));
> !     appendStringLiteral(q, conforencoding, true);
>       appendPQExpBuffer(q, " TO ");
> !     appendStringLiteral(q, contoencoding, true);
>       /* regproc is automatically quoted in 7.3 and above */
>       appendPQExpBuffer(q, " FROM %s;\n", conproc);
>
> --- 6682,6690 ----
>       appendPQExpBuffer(q, "CREATE %sCONVERSION %s FOR ",
>                         (condefault) ? "DEFAULT " : "",
>                         fmtId(convinfo->dobj.name));
> !     appendStringLiteral(q, conforencoding, true, !std_strings);
>       appendPQExpBuffer(q, " TO ");
> !     appendStringLiteral(q, contoencoding, true, !std_strings);
>       /* regproc is automatically quoted in 7.3 and above */
>       appendPQExpBuffer(q, " FROM %s;\n", conproc);
>
> ***************
> *** 6871,6877 ****
>       if (!PQgetisnull(res, 0, i_agginitval))
>       {
>           appendPQExpBuffer(details, ",\n    INITCOND = ");
> !         appendStringLiteral(details, agginitval, true);
>       }
>
>       if (strcmp(aggfinalfn, "-") != 0)
> --- 6925,6931 ----
>       if (!PQgetisnull(res, 0, i_agginitval))
>       {
>           appendPQExpBuffer(details, ",\n    INITCOND = ");
> !         appendStringLiteral(details, agginitval, true, !std_strings);
>       }
>
>       if (strcmp(aggfinalfn, "-") != 0)
> ***************
> *** 7058,7064 ****
>           {
>               appendPQExpBuffer(query, "SELECT definition as viewdef "
>                                 " from pg_views where viewname = ");
> !             appendStringLiteral(query, tbinfo->dobj.name, true);
>               appendPQExpBuffer(query, ";");
>           }
>
> --- 7112,7118 ----
>           {
>               appendPQExpBuffer(query, "SELECT definition as viewdef "
>                                 " from pg_views where viewname = ");
> !             appendStringLiteral(query, tbinfo->dobj.name, true, !std_strings);
>               appendPQExpBuffer(query, ";");
>           }
>
> ***************
> *** 7707,7713 ****
>
>       resetPQExpBuffer(query);
>       appendPQExpBuffer(query, "SELECT datlastsysoid from pg_database where datname = ");
> !     appendStringLiteral(query, dbname, true);
>
>       res = PQexec(g_conn, query->data);
>       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
> --- 7761,7767 ----
>
>       resetPQExpBuffer(query);
>       appendPQExpBuffer(query, "SELECT datlastsysoid from pg_database where datname = ");
> !     appendStringLiteral(query, dbname, true, !std_strings);
>
>       res = PQexec(g_conn, query->data);
>       check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
> ***************
> *** 7908,7920 ****
>               (owning_tab = findTableByOid(tbinfo->owning_tab)) != NULL)
>           {
>               appendPQExpBuffer(query, "pg_catalog.pg_get_serial_sequence(");
> !             appendStringLiteral(query, fmtId(owning_tab->dobj.name), true);
>               appendPQExpBuffer(query, ", ");
> !             appendStringLiteral(query, owning_tab->attnames[tbinfo->owning_col - 1], true);
>               appendPQExpBuffer(query, ")");
>           }
>           else
> !             appendStringLiteral(query, fmtId(tbinfo->dobj.name), true);
>           appendPQExpBuffer(query, ", %s, %s);\n",
>                             last, (called ? "true" : "false"));
>
> --- 7962,7974 ----
>               (owning_tab = findTableByOid(tbinfo->owning_tab)) != NULL)
>           {
>               appendPQExpBuffer(query, "pg_catalog.pg_get_serial_sequence(");
> !             appendStringLiteral(query, fmtId(owning_tab->dobj.name), true, !std_strings);
>               appendPQExpBuffer(query, ", ");
> !             appendStringLiteral(query, owning_tab->attnames[tbinfo->owning_col - 1], true, !std_strings);
>               appendPQExpBuffer(query, ")");
>           }
>           else
> !             appendStringLiteral(query, fmtId(tbinfo->dobj.name), true, !std_strings);
>           appendPQExpBuffer(query, ", %s, %s);\n",
>                             last, (called ? "true" : "false"));
>
> ***************
> *** 8083,8090 ****
>           appendPQExpBufferChar(query, '\'');
>           while (s < p)
>           {
> !             if (*s == '\'')        /* bytea already doubles backslashes */
>                   appendPQExpBufferChar(query, '\'');
>               appendPQExpBufferChar(query, *s++);
>           }
>           appendPQExpBufferChar(query, '\'');
> --- 8137,8150 ----
>           appendPQExpBufferChar(query, '\'');
>           while (s < p)
>           {
> !             if (*s == '\'')
>                   appendPQExpBufferChar(query, '\'');
> +             /*
> +              *    bytea unconditionally doubles backslashes, so we suppress
> +              *    the doubling for standard_conforming_strings.
> +              */
> +             if (std_strings && *s == '\\')
> +                 s++;
>               appendPQExpBufferChar(query, *s++);
>           }
>           appendPQExpBufferChar(query, '\'');
> Index: src/bin/pg_dump/pg_dumpall.c
> ===================================================================
> RCS file: /cvsroot/pgsql/src/bin/pg_dump/pg_dumpall.c,v
> retrieving revision 1.75
> diff -c -c -r1.75 pg_dumpall.c
> *** src/bin/pg_dump/pg_dumpall.c    22 May 2006 11:21:54 -0000    1.75
> --- src/bin/pg_dump/pg_dumpall.c    25 May 2006 22:15:58 -0000
> ***************
> *** 535,541 ****
>           if (!PQgetisnull(res, i, i_rolpassword))
>           {
>               appendPQExpBuffer(buf, " PASSWORD ");
> !             appendStringLiteral(buf, PQgetvalue(res, i, i_rolpassword), true);
>           }
>
>           if (!PQgetisnull(res, i, i_rolvaliduntil))
> --- 535,541 ----
>           if (!PQgetisnull(res, i, i_rolpassword))
>           {
>               appendPQExpBuffer(buf, " PASSWORD ");
> !             appendStringLiteral(buf, PQgetvalue(res, i, i_rolpassword), true, true);
>           }
>
>           if (!PQgetisnull(res, i, i_rolvaliduntil))
> ***************
> *** 546,552 ****
>
>           if (!PQgetisnull(res, i, i_rolcomment)) {
>               appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename));
> !             appendStringLiteral(buf, PQgetvalue(res, i, i_rolcomment), true);
>               appendPQExpBuffer(buf, ";\n");
>           }
>
> --- 546,552 ----
>
>           if (!PQgetisnull(res, i, i_rolcomment)) {
>               appendPQExpBuffer(buf, "COMMENT ON ROLE %s IS ", fmtId(rolename));
> !             appendStringLiteral(buf, PQgetvalue(res, i, i_rolcomment), true, true);
>               appendPQExpBuffer(buf, ";\n");
>           }
>
> ***************
> *** 730,736 ****
>           appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner));
>
>           appendPQExpBuffer(buf, " LOCATION ");
> !         appendStringLiteral(buf, spclocation, true);
>           appendPQExpBuffer(buf, ";\n");
>
>           if (!skip_acls &&
> --- 730,736 ----
>           appendPQExpBuffer(buf, " OWNER %s", fmtId(spcowner));
>
>           appendPQExpBuffer(buf, " LOCATION ");
> !         appendStringLiteral(buf, spclocation, true, true);
>           appendPQExpBuffer(buf, ";\n");
>
>           if (!skip_acls &&
> ***************
> *** 745,751 ****
>
>           if (spccomment && strlen(spccomment)) {
>               appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname);
> !             appendStringLiteral(buf, spccomment, true);
>               appendPQExpBuffer(buf, ";\n");
>           }
>
> --- 745,751 ----
>
>           if (spccomment && strlen(spccomment)) {
>               appendPQExpBuffer(buf, "COMMENT ON TABLESPACE %s IS ", fspcname);
> !             appendStringLiteral(buf, spccomment, true, true);
>               appendPQExpBuffer(buf, ";\n");
>           }
>
> ***************
> *** 868,874 ****
>                   appendPQExpBuffer(buf, " OWNER = %s", fmtId(dbowner));
>
>               appendPQExpBuffer(buf, " ENCODING = ");
> !             appendStringLiteral(buf, dbencoding, true);
>
>               /* Output tablespace if it isn't default */
>               if (strcmp(dbtablespace, "pg_default") != 0)
> --- 868,874 ----
>                   appendPQExpBuffer(buf, " OWNER = %s", fmtId(dbowner));
>
>               appendPQExpBuffer(buf, " ENCODING = ");
> !             appendStringLiteral(buf, dbencoding, true, true);
>
>               /* Output tablespace if it isn't default */
>               if (strcmp(dbtablespace, "pg_default") != 0)
> ***************
> *** 884,890 ****
>               if (strcmp(dbistemplate, "t") == 0)
>               {
>                   appendPQExpBuffer(buf, "UPDATE pg_database SET datistemplate = 't' WHERE datname = ");
> !                 appendStringLiteral(buf, dbname, true);
>                   appendPQExpBuffer(buf, ";\n");
>               }
>           }
> --- 884,890 ----
>               if (strcmp(dbistemplate, "t") == 0)
>               {
>                   appendPQExpBuffer(buf, "UPDATE pg_database SET datistemplate = 't' WHERE datname = ");
> !                 appendStringLiteral(buf, dbname, true, true);
>                   appendPQExpBuffer(buf, ";\n");
>               }
>           }
> ***************
> *** 929,935 ****
>           PGresult   *res;
>
>           printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count);
> !         appendStringLiteral(buf, dbname, true);
>           appendPQExpBuffer(buf, ";");
>
>           res = executeQuery(conn, buf->data);
> --- 929,935 ----
>           PGresult   *res;
>
>           printfPQExpBuffer(buf, "SELECT datconfig[%d] FROM pg_database WHERE datname = ", count);
> !         appendStringLiteral(buf, dbname, true, true);
>           appendPQExpBuffer(buf, ";");
>
>           res = executeQuery(conn, buf->data);
> ***************
> *** 968,974 ****
>               printfPQExpBuffer(buf, "SELECT rolconfig[%d] FROM pg_authid WHERE rolname = ", count);
>           else
>               printfPQExpBuffer(buf, "SELECT useconfig[%d] FROM pg_shadow WHERE usename = ", count);
> !         appendStringLiteral(buf, username, true);
>
>           res = executeQuery(conn, buf->data);
>           if (PQntuples(res) == 1 &&
> --- 968,974 ----
>               printfPQExpBuffer(buf, "SELECT rolconfig[%d] FROM pg_authid WHERE rolname = ", count);
>           else
>               printfPQExpBuffer(buf, "SELECT useconfig[%d] FROM pg_shadow WHERE usename = ", count);
> !         appendStringLiteral(buf, username, true, true);
>
>           res = executeQuery(conn, buf->data);
>           if (PQntuples(res) == 1 &&
> ***************
> *** 1016,1022 ****
>           || pg_strcasecmp(mine, "search_path") == 0)
>           appendPQExpBuffer(buf, "%s", pos + 1);
>       else
> !         appendStringLiteral(buf, pos + 1, false);
>       appendPQExpBuffer(buf, ";\n");
>
>       printf("%s", buf->data);
> --- 1016,1022 ----
>           || pg_strcasecmp(mine, "search_path") == 0)
>           appendPQExpBuffer(buf, "%s", pos + 1);
>       else
> !         appendStringLiteral(buf, pos + 1, false, true);
>       appendPQExpBuffer(buf, ";\n");
>
>       printf("%s", buf->data);
> Index: src/bin/psql/describe.c
> ===================================================================
> RCS file: /cvsroot/pgsql/src/bin/psql/describe.c,v
> retrieving revision 1.134
> diff -c -c -r1.134 describe.c
> *** src/bin/psql/describe.c    26 Apr 2006 23:15:45 -0000    1.134
> --- src/bin/psql/describe.c    25 May 2006 22:15:59 -0000
> ***************
> *** 1867,1873 ****
>                   appendPQExpBuffer(&namebuf, "\\\\");
>
>               /* Ensure chars special to string literals are passed properly */
> !             if (SQL_STR_DOUBLE(*cp))
>                   appendPQExpBufferChar(&namebuf, *cp);
>
>               i = PQmblen(cp, pset.encoding);
> --- 1867,1873 ----
>                   appendPQExpBuffer(&namebuf, "\\\\");
>
>               /* Ensure chars special to string literals are passed properly */
> !             if (SQL_STR_DOUBLE(*cp, true))
>                   appendPQExpBufferChar(&namebuf, *cp);
>
>               i = PQmblen(cp, pset.encoding);
> Index: src/bin/psql/large_obj.c
> ===================================================================
> RCS file: /cvsroot/pgsql/src/bin/psql/large_obj.c,v
> retrieving revision 1.41
> diff -c -c -r1.41 large_obj.c
> *** src/bin/psql/large_obj.c    5 Mar 2006 15:58:51 -0000    1.41
> --- src/bin/psql/large_obj.c    25 May 2006 22:15:59 -0000
> ***************
> *** 178,187 ****
>
>           if (strchr(comment_arg, '\\') != NULL)
>               *bufptr++ = ESCAPE_STRING_SYNTAX;
>           *bufptr++ = '\'';
>           for (i = 0; i < slen; i++)
>           {
> !             if (SQL_STR_DOUBLE(comment_arg[i]))
>                   *bufptr++ = comment_arg[i];
>               *bufptr++ = comment_arg[i];
>           }
> --- 178,188 ----
>
>           if (strchr(comment_arg, '\\') != NULL)
>               *bufptr++ = ESCAPE_STRING_SYNTAX;
> +
>           *bufptr++ = '\'';
>           for (i = 0; i < slen; i++)
>           {
> !             if (SQL_STR_DOUBLE(comment_arg[i], true))
>                   *bufptr++ = comment_arg[i];
>               *bufptr++ = comment_arg[i];
>           }
> Index: src/bin/scripts/createdb.c
> ===================================================================
> RCS file: /cvsroot/pgsql/src/bin/scripts/createdb.c,v
> retrieving revision 1.16
> diff -c -c -r1.16 createdb.c
> *** src/bin/scripts/createdb.c    5 Mar 2006 15:58:52 -0000    1.16
> --- src/bin/scripts/createdb.c    25 May 2006 22:15:59 -0000
> ***************
> *** 184,190 ****
>       if (comment)
>       {
>           printfPQExpBuffer(&sql, "COMMENT ON DATABASE %s IS ", fmtId(dbname));
> !         appendStringLiteral(&sql, comment, false);
>           appendPQExpBuffer(&sql, ";\n");
>
>           conn = connectDatabase(dbname, host, port, username, password, progname);
> --- 184,190 ----
>       if (comment)
>       {
>           printfPQExpBuffer(&sql, "COMMENT ON DATABASE %s IS ", fmtId(dbname));
> !         appendStringLiteral(&sql, comment, false, true);
>           appendPQExpBuffer(&sql, ";\n");
>
>           conn = connectDatabase(dbname, host, port, username, password, progname);
> Index: src/bin/scripts/createuser.c
> ===================================================================
> RCS file: /cvsroot/pgsql/src/bin/scripts/createuser.c,v
> retrieving revision 1.27
> diff -c -c -r1.27 createuser.c
> *** src/bin/scripts/createuser.c    5 Mar 2006 15:58:52 -0000    1.27
> --- src/bin/scripts/createuser.c    25 May 2006 22:15:59 -0000
> ***************
> *** 258,268 ****
>                   fprintf(stderr, _("Password encryption failed.\n"));
>                   exit(1);
>               }
> !             appendStringLiteral(&sql, encrypted_password, false);
>               PQfreemem(encrypted_password);
>           }
>           else
> !             appendStringLiteral(&sql, newpassword, false);
>       }
>       if (superuser == TRI_YES)
>           appendPQExpBuffer(&sql, " SUPERUSER");
> --- 258,268 ----
>                   fprintf(stderr, _("Password encryption failed.\n"));
>                   exit(1);
>               }
> !             appendStringLiteral(&sql, encrypted_password, false, true);
>               PQfreemem(encrypted_password);
>           }
>           else
> !             appendStringLiteral(&sql, newpassword, false, true);
>       }
>       if (superuser == TRI_YES)
>           appendPQExpBuffer(&sql, " SUPERUSER");
> Index: src/include/c.h
> ===================================================================
> RCS file: /cvsroot/pgsql/src/include/c.h,v
> retrieving revision 1.200
> diff -c -c -r1.200 c.h
> *** src/include/c.h    14 Apr 2006 03:38:56 -0000    1.200
> --- src/include/c.h    25 May 2006 22:15:59 -0000
> ***************
> *** 472,478 ****
>
>   #define NameStr(name)    ((name).data)
>
> ! #define SQL_STR_DOUBLE(ch)    ((ch) == '\'' || (ch) == '\\')
>   #define ESCAPE_STRING_SYNTAX    'E'
>
>   /* ----------------------------------------------------------------
> --- 472,485 ----
>
>   #define NameStr(name)    ((name).data)
>
> ! /*
> !  *    In 8.2, we are warning for \ in a non-E string if std_strings are off.
> !  *    For this reason, we use E for \ strings, unless standard_conforming_strings
> !  *    is on.
> !  */
> ! #define SQL_STR_DOUBLE(ch, escape_backslash)    \
> !                     ((ch) == '\'' || ((escape_backslash) && (ch) == '\\'))
> !
>   #define ESCAPE_STRING_SYNTAX    'E'
>
>   /* ----------------------------------------------------------------
> Index: src/interfaces/ecpg/ecpglib/execute.c
> ===================================================================
> RCS file: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v
> retrieving revision 1.45
> diff -c -c -r1.45 execute.c
> *** src/interfaces/ecpg/ecpglib/execute.c    24 Apr 2006 09:45:22 -0000    1.45
> --- src/interfaces/ecpg/ecpglib/execute.c    25 May 2006 22:16:02 -0000
> ***************
> *** 32,39 ****
>   #include "pgtypes_timestamp.h"
>   #include "pgtypes_interval.h"
>
> ! /* This function returns a newly malloced string that has the  \
> !    in the argument quoted with \ and the ' quoted with ' as SQL92 says.
>    */
>   static char *
>   quote_postgres(char *arg, int lineno)
> --- 32,40 ----
>   #include "pgtypes_timestamp.h"
>   #include "pgtypes_interval.h"
>
> ! /*
> !  *    This function returns a newly malloced string that has ' and \
> !  *    escaped.
>    */
>   static char *
>   quote_postgres(char *arg, int lineno)
> ***************
> *** 45,57 ****
>       if (!res)
>           return (res);
>
>       if (strchr(arg, '\\') != NULL)
>           res[ri++] = ESCAPE_STRING_SYNTAX;
>       res[ri++] = '\'';
>
>       for (i = 0; arg[i]; i++, ri++)
>       {
> !         if (SQL_STR_DOUBLE(arg[i]))
>               res[ri++] = arg[i];
>           res[ri] = arg[i];
>       }
> --- 46,62 ----
>       if (!res)
>           return (res);
>
> +     /*
> +      *    We don't know if the target database is using
> +      *    standard_conforming_strings, so we always use E'' strings.
> +      */
>       if (strchr(arg, '\\') != NULL)
>           res[ri++] = ESCAPE_STRING_SYNTAX;
>       res[ri++] = '\'';
>
>       for (i = 0; arg[i]; i++, ri++)
>       {
> !         if (SQL_STR_DOUBLE(arg[i], true))
>               res[ri++] = arg[i];
>           res[ri] = arg[i];
>       }
> Index: src/pl/plpgsql/src/gram.y
> ===================================================================
> RCS file: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v
> retrieving revision 1.88
> diff -c -c -r1.88 gram.y
> *** src/pl/plpgsql/src/gram.y    23 Mar 2006 04:22:36 -0000    1.88
> --- src/pl/plpgsql/src/gram.y    25 May 2006 22:16:05 -0000
> ***************
> *** 17,22 ****
> --- 17,23 ----
>   #include "plpgsql.h"
>
>   #include "parser/parser.h"
> + #include "parser/gramparse.h"
>
>   static PLpgSQL_expr        *read_sql_construct(int until,
>                                               int until2,
> ***************
> *** 376,387 ****
>                           strcpy(buf, "SELECT ");
>                           cp1 = new->refname;
>                           cp2 = buf + strlen(buf);
> !                         if (strchr(cp1, '\\') != NULL)
>                               *cp2++ = ESCAPE_STRING_SYNTAX;
>                           *cp2++ = '\'';
>                           while (*cp1)
>                           {
> !                             if (SQL_STR_DOUBLE(*cp1))
>                                   *cp2++ = *cp1;
>                               *cp2++ = *cp1++;
>                           }
> --- 377,388 ----
>                           strcpy(buf, "SELECT ");
>                           cp1 = new->refname;
>                           cp2 = buf + strlen(buf);
> !                         if (!standard_conforming_strings && strchr(cp1, '\\') != NULL)
>                               *cp2++ = ESCAPE_STRING_SYNTAX;
>                           *cp2++ = '\'';
>                           while (*cp1)
>                           {
> !                             if (SQL_STR_DOUBLE(*cp1, !standard_conforming_strings))
>                                   *cp2++ = *cp1;
>                               *cp2++ = *cp1++;
>                           }

>
> ---------------------------(end of broadcast)---------------------------
> TIP 6: explain analyze is your friend

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

  + If your life is a hard drive, Christ can be your backup. +