The following attached, applied patch adds E'' to internally created SQL
strings that contain backslashes.  I also added two macros to improve
code clarity.

-- 
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
Index: src/backend/utils/adt/quote.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/quote.c,v
retrieving revision 1.15
diff -c -c -r1.15 quote.c
*** src/backend/utils/adt/quote.c       21 Mar 2005 16:29:20 -0000      1.15
--- src/backend/utils/adt/quote.c       2 Jul 2005 16:55:47 -0000
***************
*** 60,78 ****
  
        len = VARSIZE(t) - VARHDRSZ;
        /* We make a worst-case result area; wasting a little space is OK */
!       result = (text *) palloc(len * 2 + 2 + VARHDRSZ);
  
        cp1 = VARDATA(t);
        cp2 = VARDATA(result);
  
        *cp2++ = '\'';
        while (len-- > 0)
        {
!               if (*cp1 == '\'')
!                       *cp2++ = '\'';
!               else if (*cp1 == '\\')
!                       *cp2++ = '\\';
! 
                *cp2++ = *cp1++;
        }
        *cp2++ = '\'';
--- 60,84 ----
  
        len = VARSIZE(t) - VARHDRSZ;
        /* We make a worst-case result area; wasting a little space is OK */
!       result = (text *) palloc(len * 2 + 3 + VARHDRSZ);
  
        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++;
        }
        *cp2++ = '\'';
Index: src/backend/utils/adt/ruleutils.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v
retrieving revision 1.202
diff -c -c -r1.202 ruleutils.c
*** src/backend/utils/adt/ruleutils.c   28 Jun 2005 05:09:01 -0000      1.202
--- src/backend/utils/adt/ruleutils.c   2 Jul 2005 16:55:48 -0000
***************
*** 564,575 ****
                {
                        if (i > 0)
                                appendStringInfo(&buf, ", ");
                        appendStringInfoChar(&buf, '\'');
                        while (*p)
                        {
!                               /* escape quotes and backslashes */
!                               if (*p == '\'' || *p == '\\')
!                                       appendStringInfoChar(&buf, '\\');
                                appendStringInfoChar(&buf, *p++);
                        }
                        p++;
--- 564,577 ----
                {
                        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++);
                        }
                        p++;
***************
*** 3869,3890 ****
                        break;
  
                default:
- 
                        /*
                         * We must quote any funny characters in the constant's
                         * representation. XXX Any MULTIBYTE considerations 
here?
                         */
                        appendStringInfoChar(buf, '\'');
                        for (valptr = extval; *valptr; valptr++)
                        {
                                char            ch = *valptr;
  
!                               if (ch == '\'' || ch == '\\')
                                {
!                                       appendStringInfoChar(buf, '\\');
                                        appendStringInfoChar(buf, ch);
                                }
!                               else if (((unsigned char) ch) < ((unsigned 
char) ' '))
                                        appendStringInfo(buf, "\\%03o", (int) 
ch);
                                else
                                        appendStringInfoChar(buf, ch);
--- 3871,3899 ----
                        break;
  
                default:
                        /*
                         * We must quote any funny characters in the constant's
                         * representation. XXX Any MULTIBYTE considerations 
here?
                         */
+                       for (valptr = extval; *valptr; valptr++)
+                               if (*valptr == '\\' ||
+                                       (unsigned char)*valptr < (unsigned 
char)' ')
+                               {
+                                       appendStringInfoChar(buf, 
ESCAPE_STRING_SYNTAX);
+                                       break;
+                               }
+ 
                        appendStringInfoChar(buf, '\'');
                        for (valptr = extval; *valptr; valptr++)
                        {
                                char            ch = *valptr;
  
!                               if (SQL_STR_DOUBLE(ch))
                                {
!                                       appendStringInfoChar(buf, ch);
                                        appendStringInfoChar(buf, ch);
                                }
!                               else if ((unsigned char)ch < (unsigned char)' ')
                                        appendStringInfo(buf, "\\%03o", (int) 
ch);
                                else
                                        appendStringInfoChar(buf, ch);
Index: src/bin/initdb/initdb.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/initdb/initdb.c,v
retrieving revision 1.89
diff -c -c -r1.89 initdb.c
*** src/bin/initdb/initdb.c     1 Jul 2005 17:40:28 -0000       1.89
--- src/bin/initdb/initdb.c     2 Jul 2005 16:55:49 -0000
***************
*** 1986,1993 ****
        
        for (i = 0, j = 0; i < len; i++)
        {
!               if (src[i] == '\\' || src[i] == '\'')
!                       result[j++] = src[i];   /* double these */
                result[j++] = src[i];
        }
        result[j] = '\0';
--- 1986,1993 ----
        
        for (i = 0, j = 0; i < len; i++)
        {
!               if (SQL_STR_DOUBLE(src[i]))
!                       result[j++] = src[i];
                result[j++] = src[i];
        }
        result[j] = '\0';
Index: src/bin/pg_dump/dumputils.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/pg_dump/dumputils.c,v
retrieving revision 1.18
diff -c -c -r1.18 dumputils.c
*** src/bin/pg_dump/dumputils.c 1 Jul 2005 21:03:25 -0000       1.18
--- src/bin/pg_dump/dumputils.c 2 Jul 2005 16:55:50 -0000
***************
*** 111,148 ****
  void
  appendStringLiteral(PQExpBuffer buf, const char *str, bool escapeAll)
  {
!       bool has_escapes = false;
!       const char *str2 = str;
  
!       while (*str2)
        {
!               char            ch = *str2++;
! 
                if (ch == '\\' ||
!                   ((unsigned char) ch < (unsigned char) ' ' &&
                         (escapeAll ||
                          (ch != '\t' && ch != '\n' && ch != '\v' &&
                           ch != '\f' && ch != '\r'))))
                {
!                       has_escapes = true;
                        break;
                }
        }
        
-       if (has_escapes)
-               appendPQExpBufferChar(buf, 'E');
-       
        appendPQExpBufferChar(buf, '\'');
!       while (*str)
        {
!               char            ch = *str++;
! 
!               if (ch == '\\' || ch == '\'')
                {
!                       appendPQExpBufferChar(buf, ch);         /* double these 
*/
                        appendPQExpBufferChar(buf, ch);
                }
!               else if ((unsigned char) ch < (unsigned char) ' ' &&
                                 (escapeAll ||
                                  (ch != '\t' && ch != '\n' && ch != '\v' &&
                                   ch != '\f' && ch != '\r')))
--- 111,143 ----
  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;
                }
        }
        
        appendPQExpBufferChar(buf, '\'');
!       for (p = str; *p; p++)
        {
!               ch = *p;
!               if (SQL_STR_DOUBLE(ch))
                {
!                       appendPQExpBufferChar(buf, ch);
                        appendPQExpBufferChar(buf, ch);
                }
!               else if ((unsigned char)ch < (unsigned char)' ' &&
                                 (escapeAll ||
                                  (ch != '\t' && ch != '\n' && ch != '\v' &&
                                   ch != '\f' && ch != '\r')))
Index: src/bin/pg_dump/pg_dump.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v
retrieving revision 1.412
diff -c -c -r1.412 pg_dump.c
*** src/bin/pg_dump/pg_dump.c   1 Jul 2005 21:03:25 -0000       1.412
--- src/bin/pg_dump/pg_dump.c   2 Jul 2005 16:55:54 -0000
***************
*** 7792,7809 ****
                }
                p--;
  
-               /* do we need E''? */
                while (s2 < p)
                        if (*s2++ == '\\')
                        {
!                               appendPQExpBufferChar(query, 'E');
                                break;
                        }
  
                appendPQExpBufferChar(query, '\'');
                while (s < p)
                {
!                       if (*s == '\'')
                                appendPQExpBufferChar(query, '\'');
                        appendPQExpBufferChar(query, *s++);
                }
--- 7792,7808 ----
                }
                p--;
  
                while (s2 < p)
                        if (*s2++ == '\\')
                        {
!                               appendPQExpBufferChar(query, 
ESCAPE_STRING_SYNTAX);
                                break;
                        }
  
                appendPQExpBufferChar(query, '\'');
                while (s < p)
                {
!                       if (*s == '\'')         /* bytea already doubles 
backslashes */
                                appendPQExpBufferChar(query, '\'');
                        appendPQExpBufferChar(query, *s++);
                }
Index: src/bin/psql/describe.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/describe.c,v
retrieving revision 1.119
diff -c -c -r1.119 describe.c
*** src/bin/psql/describe.c     1 Jul 2005 17:40:28 -0000       1.119
--- src/bin/psql/describe.c     2 Jul 2005 16:55:54 -0000
***************
*** 1898,1905 ****
                                appendPQExpBuffer(&namebuf, "\\\\");
  
                        /* Ensure chars special to string literals are passed 
properly */
!                       if (*cp == '\'' || *cp == '\\')
!                               appendPQExpBufferChar(&namebuf, *cp);   /* 
double these */
  
                        i = PQmblen(cp, pset.encoding);
                        while (i--)
--- 1898,1905 ----
                                appendPQExpBuffer(&namebuf, "\\\\");
  
                        /* Ensure chars special to string literals are passed 
properly */
!                       if (SQL_STR_DOUBLE(*cp))
!                               appendPQExpBufferChar(&namebuf, *cp);
  
                        i = PQmblen(cp, pset.encoding);
                        while (i--)
Index: src/bin/psql/large_obj.c
===================================================================
RCS file: /cvsroot/pgsql/src/bin/psql/large_obj.c,v
retrieving revision 1.38
diff -c -c -r1.38 large_obj.c
*** src/bin/psql/large_obj.c    1 Jul 2005 17:40:28 -0000       1.38
--- src/bin/psql/large_obj.c    2 Jul 2005 16:55:55 -0000
***************
*** 172,184 ****
                if (!cmdbuf)
                        return fail_lo_xact("\\lo_import", own_transaction);
                sprintf(cmdbuf,
!                               "COMMENT ON LARGE OBJECT %u IS '",
                                loid);
                bufptr = cmdbuf + strlen(cmdbuf);
                for (i = 0; i < slen; i++)
                {
!                       if (comment_arg[i] == '\'' || comment_arg[i] == '\\')
!                               *bufptr++ = comment_arg[i];     /* double these 
*/
                        *bufptr++ = comment_arg[i];
                }
                strcpy(bufptr, "'");
--- 172,188 ----
                if (!cmdbuf)
                        return fail_lo_xact("\\lo_import", own_transaction);
                sprintf(cmdbuf,
!                               "COMMENT ON LARGE OBJECT %u IS ",
                                loid);
                bufptr = cmdbuf + strlen(cmdbuf);
+ 
+               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];
                }
                strcpy(bufptr, "'");
Index: src/include/c.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/c.h,v
retrieving revision 1.186
diff -c -c -r1.186 c.h
*** src/include/c.h     28 Jun 2005 05:09:04 -0000      1.186
--- src/include/c.h     2 Jul 2005 16:55:55 -0000
***************
*** 479,484 ****
--- 479,486 ----
  
  #define NameStr(name) ((name).data)
  
+ #define SQL_STR_DOUBLE(ch)    ((ch) == '\'' || (ch) == '\\')
+ #define ESCAPE_STRING_SYNTAX  'E'
  
  /* ----------------------------------------------------------------
   *                            Section 4:      IsValid macros for system types
Index: src/interfaces/ecpg/ecpglib/execute.c
===================================================================
RCS file: /cvsroot/pgsql/src/interfaces/ecpg/ecpglib/execute.c,v
retrieving revision 1.40
diff -c -c -r1.40 execute.c
*** src/interfaces/ecpg/ecpglib/execute.c       2 Jun 2005 12:35:11 -0000       
1.40
--- src/interfaces/ecpg/ecpglib/execute.c       2 Jul 2005 16:55:56 -0000
***************
*** 45,65 ****
        if (!res)
                return (res);
  
        res[ri++] = '\'';
  
        for (i = 0; arg[i]; i++, ri++)
        {
!               switch (arg[i])
!               {
!                       case '\'':
!                               res[ri++] = '\'';
!                               break;
!                       case '\\':
!                               res[ri++] = '\\';
!                               break;
!                       default:
!                               ;
!               }
                res[ri] = arg[i];
        }
  
--- 45,58 ----
        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];
        }
  
Index: src/interfaces/ecpg/preproc/preproc.y
===================================================================
RCS file: /cvsroot/pgsql/src/interfaces/ecpg/preproc/preproc.y,v
retrieving revision 1.307
diff -c -c -r1.307 preproc.y
*** src/interfaces/ecpg/preproc/preproc.y       10 Feb 2005 08:06:35 -0000      
1.307
--- src/interfaces/ecpg/preproc/preproc.y       2 Jul 2005 16:56:01 -0000
***************
*** 4216,4226 ****
  Xconst:  XCONST                               { $$ = make_name();};
  Sconst:  SCONST
                {
!                       $$ = (char *)mm_alloc(strlen($1) + 3);
!                       $$[0]='\'';
!                                       strcpy($$+1, $1);
!                       $$[strlen($1)+2]='\0';
!                       $$[strlen($1)+1]='\'';
                        free($1);
                }
                ;
--- 4216,4231 ----
  Xconst:  XCONST                               { $$ = make_name();};
  Sconst:  SCONST
                {
!                       char *ret;
!                       
!                       $$ = ret = (char *)mm_alloc(strlen($1) + 4);
!                       if (strchr($1, '\\') != NULL)
!                               *ret++ = ESCAPE_STRING_SYNTAX;
!                       *ret++ = '\'';
!                       strcpy(ret, $1);
!                       ret += strlen($1);
!                       *ret++ = '\'';
!                       *ret++ = '\0';
                        free($1);
                }
                ;
Index: src/interfaces/libpq/fe-exec.c
===================================================================
RCS file: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v
retrieving revision 1.169
diff -c -c -r1.169 fe-exec.c
*** src/interfaces/libpq/fe-exec.c      12 Jun 2005 00:00:21 -0000      1.169
--- src/interfaces/libpq/fe-exec.c      2 Jul 2005 16:56:03 -0000
***************
*** 2368,2390 ****
  
        while (remaining > 0 && *source != '\0')
        {
!               switch (*source)
!               {
!                       case '\\':
!                               *target++ = '\\';
!                               *target++ = '\\';
!                               break;
! 
!                       case '\'':
!                               *target++ = '\'';
!                               *target++ = '\'';
!                               break;
! 
!                       default:
!                               *target++ = *source;
!                               break;
!               }
!               source++;
                remaining--;
        }
  
--- 2368,2376 ----
  
        while (remaining > 0 && *source != '\0')
        {
!               if (SQL_STR_DOUBLE(*source))
!                       *target++ = *source;
!               *target++ = *source++;
                remaining--;
        }
  
***************
*** 2449,2455 ****
                }
                else if (*vp == '\'')
                {
!                       rp[0] = '\\';
                        rp[1] = '\'';
                        rp += 2;
                }
--- 2435,2441 ----
                }
                else if (*vp == '\'')
                {
!                       rp[0] = '\'';
                        rp[1] = '\'';
                        rp += 2;
                }
Index: src/pl/plpgsql/src/gram.y
===================================================================
RCS file: /cvsroot/pgsql/src/pl/plpgsql/src/gram.y,v
retrieving revision 1.78
diff -c -c -r1.78 gram.y
*** src/pl/plpgsql/src/gram.y   1 Jul 2005 17:40:29 -0000       1.78
--- src/pl/plpgsql/src/gram.y   2 Jul 2005 16:56:04 -0000
***************
*** 381,393 ****
                                                curname_def = 
palloc0(sizeof(PLpgSQL_expr));
  
                                                curname_def->dtype = 
PLPGSQL_DTYPE_EXPR;
!                                               strcpy(buf, "SELECT '");
                                                cp1 = new->refname;
                                                cp2 = buf + strlen(buf);
!                                               while (*cp1 != '\0')
                                                {
!                                                       if (*cp1 == '\\' || 
*cp1 == '\'')
!                                                               *cp2++ = *cp1;  
/* double these */
                                                        *cp2++ = *cp1++;
                                                }
                                                strcpy(cp2, "'::refcursor");
--- 381,396 ----
                                                curname_def = 
palloc0(sizeof(PLpgSQL_expr));
  
                                                curname_def->dtype = 
PLPGSQL_DTYPE_EXPR;
!                                               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++;
                                                }
                                                strcpy(cp2, "'::refcursor");
---------------------------(end of broadcast)---------------------------
TIP 7: don't forget to increase your free space map settings

Reply via email to