More E'' changes - Mailing list pgsql-patches

From Bruce Momjian
Subject More E'' changes
Date
Msg-id 200507021659.j62GxOR22486@candle.pha.pa.us
Whole thread Raw
List pgsql-patches
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");

pgsql-patches by date:

Previous
From: Victor Yegorov
Date:
Subject: Bitmap index AM
Next
From: Bruce Momjian
Date:
Subject: Re: Constraint Exclusion (Partitioning) - Initial Review requested