Re: Cleanup for new escape handling - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: Cleanup for new escape handling
Date
Msg-id 200605262348.k4QNmmZ28474@candle.pha.pa.us
Whole thread Raw
In response to Cleanup for new escape handling  (Bruce Momjian <pgman@candle.pha.pa.us>)
List pgsql-patches
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. +

pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: AIX FAQ - IPv6 Fun
Next
From: Andrew Dunstan
Date:
Subject: tg_table_name and tg_table_schema for plpgsql