Commit 5b8ee5c1 authored by Tom Lane's avatar Tom Lane

Teach PQescapeByteaConn() to use hex format when the target connection is

to a server >= 8.5.  Per my proposal in discussion of hex-format patch.
parent a2a8c7a6
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -3058,23 +3058,52 @@ PQescapeString(char *to, const char *from, size_t length)
static_std_strings); 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 * PQescapeBytea - converts from binary string to the
* minimal encoding necessary to include the string in an SQL * minimal encoding necessary to include the string in an SQL
* INSERT statement with a bytea type column as the target. * 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 * '\0' == ASCII 0 == \000
* '\'' == ASCII 39 == '' * '\'' == ASCII 39 == ''
* '\\' == ASCII 92 == \\ * '\\' == ASCII 92 == \\
* anything < 0x20, or > 0x7e ---> \ooo * anything < 0x20, or > 0x7e ---> \ooo
* (where ooo is an octal expression) * (where ooo is an octal expression)
*
* If not std_strings, all backslashes sent to the output are doubled. * If not std_strings, all backslashes sent to the output are doubled.
*/ */
static unsigned char * static unsigned char *
PQescapeByteaInternal(PGconn *conn, PQescapeByteaInternal(PGconn *conn,
const unsigned char *from, size_t from_length, 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; const unsigned char *vp;
unsigned char *rp; unsigned char *rp;
...@@ -3088,6 +3117,12 @@ PQescapeByteaInternal(PGconn *conn, ...@@ -3088,6 +3117,12 @@ PQescapeByteaInternal(PGconn *conn,
*/ */
len = 1; len = 1;
if (use_hex)
{
len += bslash_len + 1 + 2 * from_length;
}
else
{
vp = from; vp = from;
for (i = from_length; i > 0; i--, vp++) for (i = from_length; i > 0; i--, vp++)
{ {
...@@ -3100,6 +3135,7 @@ PQescapeByteaInternal(PGconn *conn, ...@@ -3100,6 +3135,7 @@ PQescapeByteaInternal(PGconn *conn,
else else
len++; len++;
} }
}
*to_length = len; *to_length = len;
rp = result = (unsigned char *) malloc(len); rp = result = (unsigned char *) malloc(len);
...@@ -3111,26 +3147,39 @@ PQescapeByteaInternal(PGconn *conn, ...@@ -3111,26 +3147,39 @@ PQescapeByteaInternal(PGconn *conn,
return NULL; return NULL;
} }
if (use_hex)
{
if (!std_strings)
*rp++ = '\\';
*rp++ = '\\';
*rp++ = 'x';
}
vp = from; vp = from;
for (i = from_length; i > 0; i--, vp++) for (i = from_length; i > 0; i--, vp++)
{ {
if (*vp < 0x20 || *vp > 0x7e) unsigned char c = *vp;
{
int val = *vp;
if (use_hex)
{
*rp++ = hextbl[(c >> 4) & 0xF];
*rp++ = hextbl[c & 0xF];
}
else if (c < 0x20 || c > 0x7e)
{
if (!std_strings) if (!std_strings)
*rp++ = '\\'; *rp++ = '\\';
*rp++ = '\\'; *rp++ = '\\';
*rp++ = (val >> 6) + '0'; *rp++ = (c >> 6) + '0';
*rp++ = ((val >> 3) & 07) + '0'; *rp++ = ((c >> 3) & 07) + '0';
*rp++ = (val & 07) + '0'; *rp++ = (c & 07) + '0';
} }
else if (*vp == '\'') else if (c == '\'')
{ {
*rp++ = '\''; *rp++ = '\'';
*rp++ = '\''; *rp++ = '\'';
} }
else if (*vp == '\\') else if (c == '\\')
{ {
if (!std_strings) if (!std_strings)
{ {
...@@ -3141,7 +3190,7 @@ PQescapeByteaInternal(PGconn *conn, ...@@ -3141,7 +3190,7 @@ PQescapeByteaInternal(PGconn *conn,
*rp++ = '\\'; *rp++ = '\\';
} }
else else
*rp++ = *vp; *rp++ = c;
} }
*rp = '\0'; *rp = '\0';
...@@ -3156,37 +3205,16 @@ PQescapeByteaConn(PGconn *conn, ...@@ -3156,37 +3205,16 @@ PQescapeByteaConn(PGconn *conn,
if (!conn) if (!conn)
return NULL; return NULL;
return PQescapeByteaInternal(conn, from, from_length, to_length, return PQescapeByteaInternal(conn, from, from_length, to_length,
conn->std_strings); conn->std_strings,
(conn->sversion >= 80500));
} }
unsigned char * unsigned char *
PQescapeBytea(const unsigned char *from, size_t from_length, size_t *to_length) PQescapeBytea(const unsigned char *from, size_t from_length, size_t *to_length)
{ {
return PQescapeByteaInternal(NULL, from, from_length, to_length, return PQescapeByteaInternal(NULL, from, from_length, to_length,
static_std_strings); static_std_strings,
} false /* can't use hex */ );
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;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment