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 */
30743103static unsigned char *
30753104PQescapeByteaInternal (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
31623212unsigned char *
31633213PQescapeBytea (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