*
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/utils/adt/encode.c,v 1.20 2008/01/01 19:45:52 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/utils/adt/encode.c,v 1.20.2.1 2008/02/26 02:54:14 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
    unsigned    (*decode) (const char *data, unsigned dlen, char *res);
 };
 
-static struct pg_encoding *pg_find_encoding(const char *name);
+static const struct pg_encoding *pg_find_encoding(const char *name);
 
 /*
  * SQL functions.
    int         datalen,
                resultlen,
                res;
-   struct pg_encoding *enc;
+   const struct pg_encoding *enc;
 
    datalen = VARSIZE(data) - VARHDRSZ;
 
    int         datalen,
                resultlen,
                res;
-   struct pg_encoding *enc;
+   const struct pg_encoding *enc;
 
    datalen = VARSIZE(data) - VARHDRSZ;
 
  * Minimally escape bytea to text.
  * De-escape text to bytea.
  *
- * Only two characters are escaped:
- * \0 (null) and \\ (backslash)
+ * We must escape zero bytes and high-bit-set bytes to avoid generating
+ * text that might be invalid in the current encoding, or that might
+ * change to something else if passed through an encoding conversion
+ * (leading to failing to de-escape to the original bytea value).
+ * Also of course backslash itself has to be escaped.
  *
- * De-escapes \\ and any \### octal
+ * De-escaping processes \\ and any \### octal
  */
 
 #define VAL(CH)            ((CH) - '0')
 
    while (src < end)
    {
-       if (*src == '\0')
+       unsigned char c = (unsigned char) *src;
+
+       if (c == '\0' || IS_HIGHBIT_SET(c))
        {
            rp[0] = '\\';
-           rp[1] = '0';
-           rp[2] = '0';
-           rp[3] = '0';
+           rp[1] = DIG(c >> 6);
+           rp[2] = DIG((c >> 3) & 7);
+           rp[3] = DIG(c & 7);
            rp += 4;
            len += 4;
        }
-       else if (*src == '\\')
+       else if (c == '\\')
        {
            rp[0] = '\\';
            rp[1] = '\\';
        }
        else
        {
-           *rp++ = *src;
+           *rp++ = c;
            len++;
        }
 
 
    while (src < end)
    {
-       if (*src == '\0')
+       if (*src == '\0' || IS_HIGHBIT_SET(*src))
            len += 4;
        else if (*src == '\\')
            len += 2;
  * Common
  */
 
-static struct
+static const struct
 {
    const char *name;
    struct pg_encoding enc;
    }
 };
 
-static struct pg_encoding *
+static const struct pg_encoding *
 pg_find_encoding(const char *name)
 {
    int         i;