From: Tom Lane Date: Tue, 4 Aug 2009 18:05:42 +0000 (+0000) Subject: Teach PQescapeByteaConn() to use hex format when the target connection is X-Git-Tag: REL9_0_0~1751 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=5b8ee5c128cc90c13d909db72f93eb9674ac7aed;p=pg-rex%2Fsyncrep.git 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. --- diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c index f1318a4a94..df9ece0c0c 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 */ ); }