88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.204 2009/08/0416:08:36 tgl Exp $
11+ * $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.205 2009/08/0418:05:42 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -3058,23 +3058,52 @@ PQescapeString(char *to, const char *from, size_t length)
30583058static_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 [(unsignedchar )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 */
30743103static unsignedchar *
30753104PQescapeByteaInternal (PGconn * conn ,
30763105const unsignedchar * 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{
30793108const unsignedchar * vp ;
30803109unsignedchar * rp ;
@@ -3088,17 +3117,24 @@ PQescapeByteaInternal(PGconn *conn,
30883117 */
30893118len = 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,
31113147return NULL ;
31123148}
31133149
3150+ if (use_hex )
3151+ {
3152+ if (!std_strings )
3153+ * rp ++ = '\\' ;
3154+ * rp ++ = '\\' ;
3155+ * rp ++ = 'x' ;
3156+ }
3157+
31143158vp = from ;
31153159for (i = from_length ;i > 0 ;i -- ,vp ++ )
31163160{
3117- if (* vp < 0x20 || * vp > 0x7e )
3118- {
3119- int val = * vp ;
3161+ unsignedchar 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+ {
31213170if (!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{
31353184if (!std_strings )
31363185{
@@ -3141,7 +3190,7 @@ PQescapeByteaInternal(PGconn *conn,
31413190* rp ++ = '\\' ;
31423191}
31433192else
3144- * rp ++ = * vp ;
3193+ * rp ++ = c ;
31453194}
31463195* rp = '\0' ;
31473196
@@ -3156,37 +3205,16 @@ PQescapeByteaConn(PGconn *conn,
31563205if (!conn )
31573206return NULL ;
31583207return PQescapeByteaInternal (conn ,from ,from_length ,to_length ,
3159- conn -> std_strings );
3208+ conn -> std_strings ,
3209+ (conn -> sversion >=80500 ));
31603210}
31613211
31623212unsignedchar *
31633213PQescapeBytea (const unsignedchar * from ,size_t from_length ,size_t * to_length )
31643214{
31653215return 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 [(unsignedchar )c ];
3188-
3189- return (char )res ;
3216+ static_std_strings ,
3217+ false/* can't use hex */ );
31903218}
31913219
31923220