Skip to content

Commit 5b8ee5c

Browse files
committed
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.
1 parent a2a8c7a commit 5b8ee5c

File tree

1 file changed

+75
-47
lines changed

1 file changed

+75
-47
lines changed

src/interfaces/libpq/fe-exec.c

Lines changed: 75 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.204 2009/08/04 16:08:36 tgl Exp $
11+
* $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.205 2009/08/04 18:05:42 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -3058,23 +3058,52 @@ PQescapeString(char *to, const char *from, size_t length)
30583058
static_std_strings);
30593059
}
30603060

3061+
3062+
/* HEX encoding support for bytea */
3063+
static const char hextbl[] = "0123456789abcdef";
3064+
3065+
static const int8 hexlookup[128] = {
3066+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3067+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3068+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3069+
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
3070+
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3071+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3072+
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3073+
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3074+
};
3075+
3076+
static inline char
3077+
get_hex(char c)
3078+
{
3079+
int res = -1;
3080+
3081+
if (c > 0 && c < 127)
3082+
res = hexlookup[(unsigned char) c];
3083+
3084+
return (char) res;
3085+
}
3086+
3087+
30613088
/*
30623089
* PQescapeBytea - converts from binary string to the
30633090
* minimal encoding necessary to include the string in an SQL
30643091
* INSERT statement with a bytea type column as the target.
30653092
*
3066-
* The following transformations are applied
3093+
* We can use either hex or escape (traditional) encoding.
3094+
* In escape mode, the following transformations are applied:
30673095
* '\0' == ASCII 0 == \000
30683096
* '\'' == ASCII 39 == ''
30693097
* '\\' == ASCII 92 == \\
30703098
* anything < 0x20, or > 0x7e ---> \ooo
30713099
* (where ooo is an octal expression)
3100+
*
30723101
* If not std_strings, all backslashes sent to the output are doubled.
30733102
*/
30743103
static unsigned char *
30753104
PQescapeByteaInternal(PGconn *conn,
30763105
const unsigned char *from, size_t from_length,
3077-
size_t *to_length, bool std_strings)
3106+
size_t *to_length, bool std_strings, bool use_hex)
30783107
{
30793108
const unsigned char *vp;
30803109
unsigned char *rp;
@@ -3088,17 +3117,24 @@ PQescapeByteaInternal(PGconn *conn,
30883117
*/
30893118
len = 1;
30903119

3091-
vp = from;
3092-
for (i = from_length; i > 0; i--, vp++)
3120+
if (use_hex)
30933121
{
3094-
if (*vp < 0x20 || *vp > 0x7e)
3095-
len += bslash_len + 3;
3096-
else if (*vp == '\'')
3097-
len += 2;
3098-
else if (*vp == '\\')
3099-
len += bslash_len + bslash_len;
3100-
else
3101-
len++;
3122+
len += bslash_len + 1 + 2 * from_length;
3123+
}
3124+
else
3125+
{
3126+
vp = from;
3127+
for (i = from_length; i > 0; i--, vp++)
3128+
{
3129+
if (*vp < 0x20 || *vp > 0x7e)
3130+
len += bslash_len + 3;
3131+
else if (*vp == '\'')
3132+
len += 2;
3133+
else if (*vp == '\\')
3134+
len += bslash_len + bslash_len;
3135+
else
3136+
len++;
3137+
}
31023138
}
31033139

31043140
*to_length = len;
@@ -3111,26 +3147,39 @@ PQescapeByteaInternal(PGconn *conn,
31113147
return NULL;
31123148
}
31133149

3150+
if (use_hex)
3151+
{
3152+
if (!std_strings)
3153+
*rp++ = '\\';
3154+
*rp++ = '\\';
3155+
*rp++ = 'x';
3156+
}
3157+
31143158
vp = from;
31153159
for (i = from_length; i > 0; i--, vp++)
31163160
{
3117-
if (*vp < 0x20 || *vp > 0x7e)
3118-
{
3119-
int val = *vp;
3161+
unsigned char c = *vp;
31203162

3163+
if (use_hex)
3164+
{
3165+
*rp++ = hextbl[(c >> 4) & 0xF];
3166+
*rp++ = hextbl[c & 0xF];
3167+
}
3168+
else if (c < 0x20 || c > 0x7e)
3169+
{
31213170
if (!std_strings)
31223171
*rp++ = '\\';
31233172
*rp++ = '\\';
3124-
*rp++ = (val >> 6) + '0';
3125-
*rp++ = ((val >> 3) & 07) + '0';
3126-
*rp++ = (val & 07) + '0';
3173+
*rp++ = (c >> 6) + '0';
3174+
*rp++ = ((c >> 3) & 07) + '0';
3175+
*rp++ = (c & 07) + '0';
31273176
}
3128-
else if (*vp == '\'')
3177+
else if (c == '\'')
31293178
{
31303179
*rp++ = '\'';
31313180
*rp++ = '\'';
31323181
}
3133-
else if (*vp == '\\')
3182+
else if (c == '\\')
31343183
{
31353184
if (!std_strings)
31363185
{
@@ -3141,7 +3190,7 @@ PQescapeByteaInternal(PGconn *conn,
31413190
*rp++ = '\\';
31423191
}
31433192
else
3144-
*rp++ = *vp;
3193+
*rp++ = c;
31453194
}
31463195
*rp = '\0';
31473196

@@ -3156,37 +3205,16 @@ PQescapeByteaConn(PGconn *conn,
31563205
if (!conn)
31573206
return NULL;
31583207
return PQescapeByteaInternal(conn, from, from_length, to_length,
3159-
conn->std_strings);
3208+
conn->std_strings,
3209+
(conn->sversion >= 80500));
31603210
}
31613211

31623212
unsigned char *
31633213
PQescapeBytea(const unsigned char *from, size_t from_length, size_t *to_length)
31643214
{
31653215
return PQescapeByteaInternal(NULL, from, from_length, to_length,
3166-
static_std_strings);
3167-
}
3168-
3169-
3170-
static const int8 hexlookup[128] = {
3171-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3172-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3173-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3174-
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1,
3175-
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3176-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3177-
-1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3178-
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
3179-
};
3180-
3181-
static inline char
3182-
get_hex(char c)
3183-
{
3184-
int res = -1;
3185-
3186-
if (c > 0 && c < 127)
3187-
res = hexlookup[(unsigned char) c];
3188-
3189-
return (char) res;
3216+
static_std_strings,
3217+
false /* can't use hex */ );
31903218
}
31913219

31923220

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy