Commit 1b970e94 authored by unknown's avatar unknown

Bug#11338 Fixes from review (identical functionality).


include/my_sys.h:
  Fixes from review (use version in log_event.cc instead)
mysql-test/r/ctype_cp932.result:
  Updated test for bug#11338 (logging of prepared statement w/ blob type)
mysql-test/t/ctype_cp932.test:
  udpated test for bug#11338 (logging of prepared statement w/ blob type)
mysys/charset.c:
  Fixes from review (use version in log_event.cc instead)
sql/item.cc:
  Fixes from review (store character_set_client differently so that
  fix can be merged forward to 5.0)
sql/item.h:
  Fixes from review
sql/log_event.cc:
  Fixes from review, str_to_hex is now used by item.cc
sql/log_event.h:
  Added prototype for str_to_hex (now used by item.cc)
sql/sql_prepare.cc:
  Fixes from review, store character_set_client differently so that 
  Item_param::query_val_str can use it.
parent 496e86da
...@@ -788,7 +788,6 @@ extern my_bool init_compiled_charsets(myf flags); ...@@ -788,7 +788,6 @@ extern my_bool init_compiled_charsets(myf flags);
extern void add_compiled_collation(CHARSET_INFO *cs); extern void add_compiled_collation(CHARSET_INFO *cs);
extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to, extern ulong escape_string_for_mysql(CHARSET_INFO *charset_info, char *to,
const char *from, ulong length); const char *from, ulong length);
extern char *bare_str_to_hex(char *to, const char *from, uint len);
#ifdef __WIN__ #ifdef __WIN__
#define BACKSLASH_MBTAIL #define BACKSLASH_MBTAIL
/* File system character set */ /* File system character set */
......
...@@ -8576,6 +8576,20 @@ FC4B ...@@ -8576,6 +8576,20 @@ FC4B
DROP TABLE t1; DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
DROP TABLE t3; DROP TABLE t3;
CREATE TABLE t1(f1 blob);
PREPARE stmt1 FROM 'INSERT INTO t1 VALUES(?)';
SET @var1= x'8300';
EXECUTE stmt1 USING @var1;
SHOW BINLOG EVENTS FROM 27642;
Log_name Pos Event_type Server_id Orig_log_pos Info
master-bin.000001 27642 Query 1 27642 use `test`; CREATE TABLE t1(f1 blob)
master-bin.000001 27701 Query 1 27701 use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=95,COLLATION_CONNECTION=95,COLLATION_DATABASE=95,COLLATION_SERVER=8
master-bin.000001 27837 User var 1 27837 @`var1`=_binary 0x8300 COLLATE binary
master-bin.000001 27876 Query 1 27876 use `test`; INSERT INTO t1 VALUES(@'var1')
SELECT HEX(f1) FROM t1;
HEX(f1)
8300
DROP table t1;
SET collation_connection='cp932_japanese_ci'; SET collation_connection='cp932_japanese_ci';
create table t1 select repeat('a',4000) a; create table t1 select repeat('a',4000) a;
delete from t1; delete from t1;
......
...@@ -401,6 +401,26 @@ DROP TABLE t2; ...@@ -401,6 +401,26 @@ DROP TABLE t2;
DROP TABLE t3; DROP TABLE t3;
#DROP TABLE t4; #DROP TABLE t4;
# Test prepared statement with 0x8300 sequence in parameter while
# running with cp932 client character set.
CREATE TABLE t1(f1 blob);
PREPARE stmt1 FROM 'INSERT INTO t1 VALUES(?)';
SET @var1= x'8300';
# TODO: Note that this doesn't actually test the code which was added for
# bug#11338 because this syntax for prepared statements causes the PS to
# be replicated differently than if we executed the PS from C or Java.
# Using this syntax, variable names are inserted into the binlog instead
# of values. The real goal of this test is to check the code that was
# added to Item_param::query_val_str() in order to do hex encoding of
# PS parameters when the client character set is cp932;
# Bug#11338 has an example java program which can be used to verify this
# code (and I have used it to test the fix) until there is some way to
# exercise this code from mysql-test-run.
EXECUTE stmt1 USING @var1;
SHOW BINLOG EVENTS FROM 27642;
SELECT HEX(f1) FROM t1;
DROP table t1;
# end test for bug#11338
SET collation_connection='cp932_japanese_ci'; SET collation_connection='cp932_japanese_ci';
-- source include/ctype_filesort.inc -- source include/ctype_filesort.inc
......
...@@ -663,21 +663,3 @@ CHARSET_INFO *fs_character_set() ...@@ -663,21 +663,3 @@ CHARSET_INFO *fs_character_set()
return fs_cset_cache; return fs_cset_cache;
} }
#endif #endif
/*
Transforms a string into hex form.
*/
char *bare_str_to_hex(char *to, const char *from, uint len)
{
char *p= to;
uint i;
for (i= 0; i < len; i++, p+= 2)
{
/* val[i] is char. Casting to uchar helps greatly if val[i] < 0 */
uint tmp= (uint) (uchar) from[i];
p[0]= _dig_vec_upper[tmp >> 4];
p[1]= _dig_vec_upper[tmp & 15];
}
*p= 0;
return p; // pointer to end 0 of 'to'
}
...@@ -1230,7 +1230,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry) ...@@ -1230,7 +1230,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
CHARSET_INFO *tocs= thd->variables.collation_connection; CHARSET_INFO *tocs= thd->variables.collation_connection;
uint32 dummy_offset; uint32 dummy_offset;
value.cs_info.character_set_client= fromcs; value.cs_info.character_set_of_placeholder= fromcs;
/* /*
Setup source and destination character sets so that they Setup source and destination character sets so that they
are different only if conversion is necessary: this will are different only if conversion is necessary: this will
...@@ -1443,7 +1443,7 @@ String *Item_param::val_str(String* str) ...@@ -1443,7 +1443,7 @@ String *Item_param::val_str(String* str)
and avoid one more memcpy/alloc between str and log string. and avoid one more memcpy/alloc between str and log string.
*/ */
const String *Item_param::query_val_str(String* str, THD *thd) const const String *Item_param::query_val_str(String* str) const
{ {
switch (state) { switch (state) {
case INT_VALUE: case INT_VALUE:
...@@ -1482,18 +1482,17 @@ const String *Item_param::query_val_str(String* str, THD *thd) const ...@@ -1482,18 +1482,17 @@ const String *Item_param::query_val_str(String* str, THD *thd) const
buf= str->c_ptr_quick(); buf= str->c_ptr_quick();
ptr= buf; ptr= buf;
if (thd->charset()->escape_with_backslash_is_dangerous) if (value.cs_info.character_set_client->escape_with_backslash_is_dangerous)
{ {
ptr= strmov(ptr, "x\'"); ptr= str_to_hex(ptr, str_value.ptr(), str_value.length());
ptr= bare_str_to_hex(ptr, str_value.ptr(), str_value.length());
} }
else else
{ {
*ptr++= '\''; *ptr++= '\'';
ptr+= escape_string_for_mysql(str_value.charset(), ptr, ptr+= escape_string_for_mysql(str_value.charset(), ptr,
str_value.ptr(), str_value.length()); str_value.ptr(), str_value.length());
*ptr++='\'';
} }
*ptr++='\'';
str->length(ptr - buf); str->length(ptr - buf);
break; break;
} }
...@@ -1523,10 +1522,10 @@ bool Item_param::convert_str_value(THD *thd) ...@@ -1523,10 +1522,10 @@ bool Item_param::convert_str_value(THD *thd)
here only if conversion is really necessary. here only if conversion is really necessary.
*/ */
if (value.cs_info.final_character_set_of_str_value != if (value.cs_info.final_character_set_of_str_value !=
value.cs_info.character_set_client) value.cs_info.character_set_of_placeholder)
{ {
rc= thd->convert_string(&str_value, rc= thd->convert_string(&str_value,
value.cs_info.character_set_client, value.cs_info.character_set_of_placeholder,
value.cs_info.final_character_set_of_str_value); value.cs_info.final_character_set_of_str_value);
} }
else else
......
...@@ -532,6 +532,7 @@ class Item_param :public Item ...@@ -532,6 +532,7 @@ class Item_param :public Item
struct CONVERSION_INFO struct CONVERSION_INFO
{ {
CHARSET_INFO *character_set_client; CHARSET_INFO *character_set_client;
CHARSET_INFO *character_set_of_placeholder;
/* /*
This points at character set of connection if conversion This points at character set of connection if conversion
to it is required (i. e. if placeholder typecode is not BLOB). to it is required (i. e. if placeholder typecode is not BLOB).
...@@ -591,7 +592,7 @@ class Item_param :public Item ...@@ -591,7 +592,7 @@ class Item_param :public Item
*/ */
void (*set_param_func)(Item_param *param, uchar **pos, ulong len); void (*set_param_func)(Item_param *param, uchar **pos, ulong len);
const String *query_val_str(String *str, THD *thd) const; const String *query_val_str(String *str) const;
bool convert_str_value(THD *thd); bool convert_str_value(THD *thd);
......
...@@ -207,7 +207,7 @@ static inline int read_str(char * &buf, char *buf_end, char * &str, ...@@ -207,7 +207,7 @@ static inline int read_str(char * &buf, char *buf_end, char * &str,
/* /*
Transforms a string into "" or its expression in 0x... form. Transforms a string into "" or its expression in 0x... form.
*/ */
static char *str_to_hex(char *to, char *from, uint len) char *str_to_hex(char *to, const char *from, uint len)
{ {
char *p= to; char *p= to;
if (len) if (len)
......
...@@ -1069,5 +1069,5 @@ class Unknown_log_event: public Log_event ...@@ -1069,5 +1069,5 @@ class Unknown_log_event: public Log_event
bool is_valid() { return 1; } bool is_valid() { return 1; }
}; };
#endif #endif
char *str_to_hex(char *to, const char *from, uint len);
#endif /* _log_event_h */ #endif /* _log_event_h */
...@@ -528,7 +528,9 @@ static void setup_one_conversion_function(THD *thd, Item_param *param, ...@@ -528,7 +528,9 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB: case MYSQL_TYPE_BLOB:
param->set_param_func= set_param_str; param->set_param_func= set_param_str;
param->value.cs_info.character_set_client= &my_charset_bin; param->value.cs_info.character_set_of_placeholder= &my_charset_bin;
param->value.cs_info.character_set_client=
thd->variables.character_set_client;
param->value.cs_info.final_character_set_of_str_value= &my_charset_bin; param->value.cs_info.final_character_set_of_str_value= &my_charset_bin;
param->item_type= Item::STRING_ITEM; param->item_type= Item::STRING_ITEM;
param->item_result_type= STRING_RESULT; param->item_result_type= STRING_RESULT;
...@@ -544,6 +546,7 @@ static void setup_one_conversion_function(THD *thd, Item_param *param, ...@@ -544,6 +546,7 @@ static void setup_one_conversion_function(THD *thd, Item_param *param,
CHARSET_INFO *tocs= thd->variables.collation_connection; CHARSET_INFO *tocs= thd->variables.collation_connection;
uint32 dummy_offset; uint32 dummy_offset;
param->value.cs_info.character_set_of_placeholder= fromcs;
param->value.cs_info.character_set_client= fromcs; param->value.cs_info.character_set_client= fromcs;
/* /*
...@@ -601,7 +604,7 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array, ...@@ -601,7 +604,7 @@ static bool insert_params_withlog(Prepared_statement *stmt, uchar *null_array,
param->set_param_func(param, &read_pos, data_end - read_pos); param->set_param_func(param, &read_pos, data_end - read_pos);
} }
} }
res= param->query_val_str(&str, thd); res= param->query_val_str(&str);
if (param->convert_str_value(thd)) if (param->convert_str_value(thd))
DBUG_RETURN(1); /* out of memory */ DBUG_RETURN(1); /* out of memory */
...@@ -749,7 +752,7 @@ static bool emb_insert_params_withlog(Prepared_statement *stmt, String *query) ...@@ -749,7 +752,7 @@ static bool emb_insert_params_withlog(Prepared_statement *stmt, String *query)
client_param->buffer_length); client_param->buffer_length);
} }
} }
res= param->query_val_str(&str, thd); res= param->query_val_str(&str);
if (param->convert_str_value(thd)) if (param->convert_str_value(thd))
DBUG_RETURN(1); /* out of memory */ DBUG_RETURN(1); /* out of memory */
......
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