Commit b514e6a8 authored by guilhem@mysql.com's avatar guilhem@mysql.com

Correction to replication of charsets in 4.1:

In mysqlbinlog, there was a problem with how we escaped the content of a string user variable.
To be perfect, we should have escaped with character_set_client. But this charset is unknown
to mysqlbinlog. So the simplest is to print the string in hex. This is unreadable but
100% safe with any charset (checked with Bar), no more need to bother with character_set_client.
parent 8962ed3c
...@@ -153,7 +153,7 @@ master-bin.000001 4413 Query 1 4413 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIE ...@@ -153,7 +153,7 @@ master-bin.000001 4413 Query 1 4413 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIE
master-bin.000001 4549 Query 1 4549 use `test2`; truncate table t1 master-bin.000001 4549 Query 1 4549 use `test2`; truncate table t1
master-bin.000001 4602 Query 1 4602 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64 master-bin.000001 4602 Query 1 4602 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
master-bin.000001 4738 Intvar 1 4738 INSERT_ID=1 master-bin.000001 4738 Intvar 1 4738 INSERT_ID=1
master-bin.000001 4766 User var 1 4766 @`a`=_cp850'Müller' COLLATE cp850_general_ci master-bin.000001 4766 User var 1 4766 @`a`=_cp850 0x4DFC6C6C6572 COLLATE cp850_general_ci
master-bin.000001 4806 Query 1 4806 use `test2`; insert into t1 (b) values(collation(@a)) master-bin.000001 4806 Query 1 4806 use `test2`; insert into t1 (b) values(collation(@a))
master-bin.000001 4882 Query 1 4882 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64 master-bin.000001 4882 Query 1 4882 use `test2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
master-bin.000001 5018 Query 1 5018 use `test2`; drop database test2 master-bin.000001 5018 Query 1 5018 use `test2`; drop database test2
......
...@@ -86,11 +86,11 @@ slave-bin.000001 313 Query 1 313 use `test`; insert into t1 values (@i1), (@i2), ...@@ -86,11 +86,11 @@ slave-bin.000001 313 Query 1 313 use `test`; insert into t1 values (@i1), (@i2),
slave-bin.000001 396 User var 2 396 @`r1`=12.5 slave-bin.000001 396 User var 2 396 @`r1`=12.5
slave-bin.000001 439 User var 2 439 @`r2`=-12.5 slave-bin.000001 439 User var 2 439 @`r2`=-12.5
slave-bin.000001 482 Query 1 482 use `test`; insert into t1 values (@r1), (@r2) slave-bin.000001 482 Query 1 482 use `test`; insert into t1 values (@r1), (@r2)
slave-bin.000001 551 User var 2 551 @`s1`=_latin1'This is a test' COLLATE latin1_swedish_ci slave-bin.000001 551 User var 2 551 @`s1`=_latin1 0x5468697320697320612074657374 COLLATE latin1_swedish_ci
slave-bin.000001 600 User var 2 600 @`s2`=_latin1'' COLLATE latin1_swedish_ci slave-bin.000001 600 User var 2 600 @`s2`=_latin1 "" COLLATE latin1_swedish_ci
slave-bin.000001 635 User var 2 635 @`s3`=_latin1'abc\'def' COLLATE latin1_swedish_ci slave-bin.000001 635 User var 2 635 @`s3`=_latin1 0x61626327646566 COLLATE latin1_swedish_ci
slave-bin.000001 677 User var 2 677 @`s4`=_latin1'abc\\def' COLLATE latin1_swedish_ci slave-bin.000001 677 User var 2 677 @`s4`=_latin1 0x6162635C646566 COLLATE latin1_swedish_ci
slave-bin.000001 719 User var 2 719 @`s5`=_latin1'abc\'def' COLLATE latin1_swedish_ci slave-bin.000001 719 User var 2 719 @`s5`=_latin1 0x61626327646566 COLLATE latin1_swedish_ci
slave-bin.000001 761 Query 1 761 use `test`; insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5) slave-bin.000001 761 Query 1 761 use `test`; insert into t1 values (@s1), (@s2), (@s3), (@s4), (@s5)
slave-bin.000001 851 User var 2 851 @`n1`=NULL slave-bin.000001 851 User var 2 851 @`n1`=NULL
slave-bin.000001 877 Query 1 877 use `test`; insert into t1 values (@n1) slave-bin.000001 877 Query 1 877 use `test`; insert into t1 values (@n1)
...@@ -99,7 +99,7 @@ slave-bin.000001 965 Query 1 965 use `test`; insert into t1 values (@n2) ...@@ -99,7 +99,7 @@ slave-bin.000001 965 Query 1 965 use `test`; insert into t1 values (@n2)
slave-bin.000001 1027 Query 1 1027 use `test`; insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1) slave-bin.000001 1027 Query 1 1027 use `test`; insert into t1 values (@a:=0), (@a:=@a+1), (@a:=@a+1)
slave-bin.000001 1115 User var 2 1115 @`a`=2 slave-bin.000001 1115 User var 2 1115 @`a`=2
slave-bin.000001 1157 Query 1 1157 use `test`; insert into t1 values (@a+(@b:=@a+1)) slave-bin.000001 1157 Query 1 1157 use `test`; insert into t1 values (@a+(@b:=@a+1))
slave-bin.000001 1229 User var 2 1229 @`q`=_latin1'abc' COLLATE latin1_swedish_ci slave-bin.000001 1229 User var 2 1229 @`q`=_latin1 0x616263 COLLATE latin1_swedish_ci
slave-bin.000001 1266 Query 1 1266 use `test`; insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2')) slave-bin.000001 1266 Query 1 1266 use `test`; insert t1 values (@q), (@q:=concat(@q, 'n1')), (@q:=concat(@q, 'n2'))
slave-bin.000001 1370 User var 2 1370 @`a`=5 slave-bin.000001 1370 User var 2 1370 @`a`=5
slave-bin.000001 1412 Query 1 1412 use `test`; insert into t1 values (@a),(@a) slave-bin.000001 1412 Query 1 1412 use `test`; insert into t1 values (@a),(@a)
......
...@@ -174,24 +174,24 @@ set @v=convert('abc' using ucs2); ...@@ -174,24 +174,24 @@ set @v=convert('abc' using ucs2);
insert into t2 values (@v); insert into t2 values (@v);
show binlog events from 79; show binlog events from 79;
Log_name Pos Event_type Server_id Orig_log_pos Info Log_name Pos Event_type Server_id Orig_log_pos Info
master-bin.000001 79 User var 1 79 @`a b`=_latin1'hello' COLLATE latin1_swedish_ci master-bin.000001 79 User var 1 79 @`a b`=_latin1 0x68656C6C6F COLLATE latin1_swedish_ci
master-bin.000001 120 Query 1 120 use `test`; INSERT INTO t1 VALUES(@`a b`) master-bin.000001 120 Query 1 120 use `test`; INSERT INTO t1 VALUES(@`a b`)
master-bin.000001 184 User var 1 184 @`var1`=_latin1'\';aaa' COLLATE latin1_swedish_ci master-bin.000001 184 User var 1 184 @`var1`=_latin1 0x273B616161 COLLATE latin1_swedish_ci
master-bin.000001 226 Query 1 226 use `test`; insert into t1 values (@var1) master-bin.000001 226 Query 1 226 use `test`; insert into t1 values (@var1)
master-bin.000001 290 Query 1 290 use `test`; create table t2 (c char(30)) charset=ucs2 master-bin.000001 290 Query 1 290 use `test`; create table t2 (c char(30)) charset=ucs2
master-bin.000001 366 User var 1 366 @`v`=_ucs2'\0a\0b\0c' COLLATE ucs2_general_ci master-bin.000001 366 User var 1 366 @`v`=_ucs2 0x006100620063 COLLATE ucs2_general_ci
master-bin.000001 406 Query 1 406 use `test`; insert into t2 values (@v) master-bin.000001 406 Query 1 406 use `test`; insert into t2 values (@v)
/*!40019 SET @@session.max_insert_delayed_threads=0*/; /*!40019 SET @@session.max_insert_delayed_threads=0*/;
SET @`a b`:=_latin1'hello' COLLATE latin1_swedish_ci; SET @`a b`:=_latin1 0x68656C6C6F COLLATE latin1_swedish_ci;
use test; use test;
SET TIMESTAMP=10000; SET TIMESTAMP=10000;
INSERT INTO t1 VALUES(@`a b`); INSERT INTO t1 VALUES(@`a b`);
SET @`var1`:=_latin1'\';aaa' COLLATE latin1_swedish_ci; SET @`var1`:=_latin1 0x273B616161 COLLATE latin1_swedish_ci;
SET TIMESTAMP=10000; SET TIMESTAMP=10000;
insert into t1 values (@var1); insert into t1 values (@var1);
SET TIMESTAMP=10000; SET TIMESTAMP=10000;
create table t2 (c char(30)) charset=ucs2; create table t2 (c char(30)) charset=ucs2;
SET @`v`:=_ucs2'\0a\0b\0c' COLLATE ucs2_general_ci; SET @`v`:=_ucs2 0x006100620063 COLLATE ucs2_general_ci;
SET TIMESTAMP=10000; SET TIMESTAMP=10000;
insert into t2 values (@v); insert into t2 values (@v);
drop table t1, t2; drop table t1, t2;
...@@ -202,6 +202,29 @@ static inline int read_str(char * &buf, char *buf_end, char * &str, ...@@ -202,6 +202,29 @@ static inline int read_str(char * &buf, char *buf_end, char * &str,
return 0; return 0;
} }
/*
Transforms a string into "" or its expression in 0x... form.
*/
static char *str_to_hex(char *to, char *from, uint len)
{
char *p= to;
if (len)
{
p= strmov(p, "0x");
for (uint 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;
}
else
p= strmov(p, "\"\"");
return p; // pointer to end 0 of 'to'
}
/************************************************************************** /**************************************************************************
Log_event methods Log_event methods
...@@ -2210,9 +2233,9 @@ void User_var_log_event::pack_info(Protocol* protocol) ...@@ -2210,9 +2233,9 @@ void User_var_log_event::pack_info(Protocol* protocol)
} }
else else
{ {
char *p= strxmov(buf + val_offset, "_", cs->csname, "'", NullS); char *p= strxmov(buf + val_offset, "_", cs->csname, " ", NullS);
p+= escape_string_for_mysql(&my_charset_bin, p, val, val_len); p= str_to_hex(p, val, val_len);
p= strxmov(p, "' COLLATE ", cs->name, NullS); p= strxmov(p, " COLLATE ", cs->name, NullS);
event_len= p-buf; event_len= p-buf;
} }
break; break;
...@@ -2341,11 +2364,24 @@ void User_var_log_event::print(FILE* file, bool short_form, char* last_db) ...@@ -2341,11 +2364,24 @@ void User_var_log_event::print(FILE* file, bool short_form, char* last_db)
break; break;
case STRING_RESULT: case STRING_RESULT:
{ {
char *p; /*
if (!(p= (char *)my_alloca(2*val_len+1))) Let's express the string in hex. That's the most robust way. If we
print it in character form instead, we need to escape it with
character_set_client which we don't know (we will know it in 5.0, but
in 4.1 we don't know it easily when we are printing
User_var_log_event). Explanation why we would need to bother with
character_set_client (quoting Bar):
> Note, the parser doesn't switch to another unescaping mode after
> it has met a character set introducer.
> For example, if an SJIS client says something like:
> SET @a= _ucs2 \0a\0b'
> the string constant is still unescaped according to SJIS, not
> according to UCS2.
*/
char *p, *q;
if (!(p= (char *)my_alloca(2*val_len+1+2))) // 2 hex digits per byte
break; // no error, as we are 'void' break; // no error, as we are 'void'
escape_string_for_mysql(&my_charset_bin, p, val, val_len); str_to_hex(p, val, val_len);
#if MYSQL_VERSION_ID < 50000
/* /*
For proper behaviour when mysqlbinlog|mysql, we need to explicitely For proper behaviour when mysqlbinlog|mysql, we need to explicitely
specify the variable's collation. It will however cause problems when specify the variable's collation. It will however cause problems when
...@@ -2360,14 +2396,7 @@ void User_var_log_event::print(FILE* file, bool short_form, char* last_db) ...@@ -2360,14 +2396,7 @@ void User_var_log_event::print(FILE* file, bool short_form, char* last_db)
*/ */
fprintf(file, ":=???;\n"); fprintf(file, ":=???;\n");
else else
fprintf(file, ":=_%s'%s' COLLATE %s;\n", cs->csname, p, cs->name); fprintf(file, ":=_%s %s COLLATE %s;\n", cs->csname, p, cs->name);
#else
/*
In 5.0 we will have some SET CHARACTER_SET_ect automatically printed
for all events where it's needed.
*/
fprintf(file, ":='%s';\n", p);
#endif
my_afree(p); my_afree(p);
} }
break; break;
......
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