diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index f1318a4a942d1ffec46d7b5ffe3991d5f47a57f3..df9ece0c0c49f3a4f5e75bdc4789b06b7293caba 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.204 2009/08/04 16:08:36 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.205 2009/08/04 18:05:42 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -3058,23 +3058,52 @@ PQescapeString(char *to, const char *from, size_t length)
 								  static_std_strings);
 }
 
+
+/* HEX encoding support for bytea */
+static const char hextbl[] = "0123456789abcdef";
+
+static const int8 hexlookup[128] = {
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
+	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+};
+
+static inline char
+get_hex(char c)
+{
+	int			res = -1;
+
+	if (c > 0 && c < 127)
+		res = hexlookup[(unsigned char) c];
+
+	return (char) res;
+}
+
+
 /*
  *		PQescapeBytea	- converts from binary string to the
  *		minimal encoding necessary to include the string in an SQL
  *		INSERT statement with a bytea type column as the target.
  *
- *		The following transformations are applied
+ *		We can use either hex or escape (traditional) encoding.
+ *		In escape mode, the following transformations are applied:
  *		'\0' == ASCII  0 == \000
  *		'\'' == ASCII 39 == ''
  *		'\\' == ASCII 92 == \\
  *		anything < 0x20, or > 0x7e ---> \ooo
  *										(where ooo is an octal expression)
+ *
  *		If not std_strings, all backslashes sent to the output are doubled.
  */
 static unsigned char *
 PQescapeByteaInternal(PGconn *conn,
 					  const unsigned char *from, size_t from_length,
-					  size_t *to_length, bool std_strings)
+					  size_t *to_length, bool std_strings, bool use_hex)
 {
 	const unsigned char *vp;
 	unsigned char *rp;
@@ -3088,17 +3117,24 @@ PQescapeByteaInternal(PGconn *conn,
 	 */
 	len = 1;
 
-	vp = from;
-	for (i = from_length; i > 0; i--, vp++)
+	if (use_hex)
 	{
-		if (*vp < 0x20 || *vp > 0x7e)
-			len += bslash_len + 3;
-		else if (*vp == '\'')
-			len += 2;
-		else if (*vp == '\\')
-			len += bslash_len + bslash_len;
-		else
-			len++;
+		len += bslash_len + 1 + 2 * from_length;
+	}
+	else
+	{
+		vp = from;
+		for (i = from_length; i > 0; i--, vp++)
+		{
+			if (*vp < 0x20 || *vp > 0x7e)
+				len += bslash_len + 3;
+			else if (*vp == '\'')
+				len += 2;
+			else if (*vp == '\\')
+				len += bslash_len + bslash_len;
+			else
+				len++;
+		}
 	}
 
 	*to_length = len;
@@ -3111,26 +3147,39 @@ PQescapeByteaInternal(PGconn *conn,
 		return NULL;
 	}
 
+	if (use_hex)
+	{
+		if (!std_strings)
+			*rp++ = '\\';
+		*rp++ = '\\';
+		*rp++ = 'x';
+	}
+
 	vp = from;
 	for (i = from_length; i > 0; i--, vp++)
 	{
-		if (*vp < 0x20 || *vp > 0x7e)
-		{
-			int			val = *vp;
+		unsigned char c = *vp;
 
+		if (use_hex)
+		{
+			*rp++ = hextbl[(c >> 4) & 0xF];
+			*rp++ = hextbl[c & 0xF];
+		}
+		else if (c < 0x20 || c > 0x7e)
+		{
 			if (!std_strings)
 				*rp++ = '\\';
 			*rp++ = '\\';
-			*rp++ = (val >> 6) + '0';
-			*rp++ = ((val >> 3) & 07) + '0';
-			*rp++ = (val & 07) + '0';
+			*rp++ = (c >> 6) + '0';
+			*rp++ = ((c >> 3) & 07) + '0';
+			*rp++ = (c & 07) + '0';
 		}
-		else if (*vp == '\'')
+		else if (c == '\'')
 		{
 			*rp++ = '\'';
 			*rp++ = '\'';
 		}
-		else if (*vp == '\\')
+		else if (c == '\\')
 		{
 			if (!std_strings)
 			{
@@ -3141,7 +3190,7 @@ PQescapeByteaInternal(PGconn *conn,
 			*rp++ = '\\';
 		}
 		else
-			*rp++ = *vp;
+			*rp++ = c;
 	}
 	*rp = '\0';
 
@@ -3156,37 +3205,16 @@ PQescapeByteaConn(PGconn *conn,
 	if (!conn)
 		return NULL;
 	return PQescapeByteaInternal(conn, from, from_length, to_length,
-								 conn->std_strings);
+								 conn->std_strings,
+								 (conn->sversion >= 80500));
 }
 
 unsigned char *
 PQescapeBytea(const unsigned char *from, size_t from_length, size_t *to_length)
 {
 	return PQescapeByteaInternal(NULL, from, from_length, to_length,
-								 static_std_strings);
-}
-
-
-static const int8 hexlookup[128] = {
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
-	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-	-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-	-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-};
-
-static inline char
-get_hex(char c)
-{
-	int			res = -1;
-
-	if (c > 0 && c < 127)
-		res = hexlookup[(unsigned char) c];
-
-	return (char) res;
+								 static_std_strings,
+								 false /* can't use hex */ );
 }