mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 04:22:27 +01:00
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.
This commit is contained in:
parent
8962ed3c7d
commit
b514e6a8c5
4 changed files with 57 additions and 28 deletions
|
@ -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 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 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 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
|
||||
|
|
|
@ -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 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 551 User var 2 551 @`s1`=_latin1'This is a test' 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 677 User var 2 677 @`s4`=_latin1'abc\\def' COLLATE latin1_swedish_ci
|
||||
slave-bin.000001 719 User var 2 719 @`s5`=_latin1'abc\'def' 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 635 User var 2 635 @`s3`=_latin1 0x61626327646566 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 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 851 User var 2 851 @`n1`=NULL
|
||||
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)
|
|||
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 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 1370 User var 2 1370 @`a`=5
|
||||
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);
|
|||
insert into t2 values (@v);
|
||||
show binlog events from 79;
|
||||
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 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 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)
|
||||
/*!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;
|
||||
SET TIMESTAMP=10000;
|
||||
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;
|
||||
insert into t1 values (@var1);
|
||||
SET TIMESTAMP=10000;
|
||||
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;
|
||||
insert into t2 values (@v);
|
||||
drop table t1, t2;
|
||||
|
|
|
@ -202,6 +202,29 @@ static inline int read_str(char * &buf, char *buf_end, char * &str,
|
|||
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
|
||||
|
@ -2210,9 +2233,9 @@ void User_var_log_event::pack_info(Protocol* protocol)
|
|||
}
|
||||
else
|
||||
{
|
||||
char *p= strxmov(buf + val_offset, "_", cs->csname, "'", NullS);
|
||||
p+= escape_string_for_mysql(&my_charset_bin, p, val, val_len);
|
||||
p= strxmov(p, "' COLLATE ", cs->name, NullS);
|
||||
char *p= strxmov(buf + val_offset, "_", cs->csname, " ", NullS);
|
||||
p= str_to_hex(p, val, val_len);
|
||||
p= strxmov(p, " COLLATE ", cs->name, NullS);
|
||||
event_len= p-buf;
|
||||
}
|
||||
break;
|
||||
|
@ -2341,11 +2364,24 @@ void User_var_log_event::print(FILE* file, bool short_form, char* last_db)
|
|||
break;
|
||||
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'
|
||||
escape_string_for_mysql(&my_charset_bin, p, val, val_len);
|
||||
#if MYSQL_VERSION_ID < 50000
|
||||
str_to_hex(p, val, val_len);
|
||||
/*
|
||||
For proper behaviour when mysqlbinlog|mysql, we need to explicitely
|
||||
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)
|
|||
*/
|
||||
fprintf(file, ":=???;\n");
|
||||
else
|
||||
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
|
||||
fprintf(file, ":=_%s %s COLLATE %s;\n", cs->csname, p, cs->name);
|
||||
my_afree(p);
|
||||
}
|
||||
break;
|
||||
|
|
Loading…
Reference in a new issue