From c23c38fa31ff9f7350c342a3fb8142e04b10e121 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 9 May 2006 23:01:31 +0300 Subject: [PATCH 1/6] BUG#14157: utf8 encoding in binlog without set character_set_client e.g DROP temporary Binlog lacks encoding info about DROPped temporary table. Idea of the fix is to switch temporary to system_charset_info when a temporary table is DROPped for binlog. Since that is the server, that automatically, but not the client, who generates the query the binlog should be updated on the server's encoding for the coming DROP. The `write_binlog_with_system_charset()' is introduced to replace similar problematic places in the code. mysql-test/r/drop_temp_table.result: results changed mysql-test/r/mix_innodb_myisam_binlog.result: results changed mysql-test/r/mysqlbinlog.result: results changed mysql-test/r/rpl_temporary.result: results changed mysql-test/t/mysqlbinlog.test: Check roll-forward recovery from binlog where there are DROP temporary tables created in koi8r. mysql-test/t/rpl_temporary.test: Check slave digests binlog with DROP temporary tables created in koi8r. sql/mysql_priv.h: `write_binlog_with_system_charset()' is added to be called when a binlog event is created "implicitly" like DROP temporary table is case of closing connection. sql/sql_base.cc: Idea of the fix is to switch temporary to system_charset_info when a temporary table is DROPped for binlog. Since that is the server, not the client, who generates the query the binlog should be updated on server's encoding for the coming DROP. --- mysql-test/r/drop_temp_table.result | 1 + mysql-test/r/mix_innodb_myisam_binlog.result | 5 +++-- mysql-test/r/mysqlbinlog.result | 7 ++++++- mysql-test/r/rpl_temporary.result | 4 ++++ mysql-test/t/mysqlbinlog.test | 11 ++++++++++- mysql-test/t/rpl_temporary.test | 12 ++++++++++++ sql/mysql_priv.h | 7 +++++++ sql/sql_base.cc | 2 +- 8 files changed, 44 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/drop_temp_table.result b/mysql-test/r/drop_temp_table.result index 5f1f142cde5..40afd621676 100644 --- a/mysql-test/r/drop_temp_table.result +++ b/mysql-test/r/drop_temp_table.result @@ -17,6 +17,7 @@ master-bin.000001 # Query 1 # create database `drop-temp+table-test` master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table shortn1 (a int) master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table `table:name` (a int) master-bin.000001 # Query 1 # use `drop-temp+table-test`; create temporary table shortn2 (a int) +master-bin.000001 # Query 1 # use `drop-temp+table-test`; SET ONE_SHOT CHARACTER_SET_CLIENT=33,COLLATION_CONNECTION=8,COLLATION_DATABASE=8,COLLATION_SERVER=8 master-bin.000001 # Query 1 # use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`shortn2`,`drop-temp+table-test`.`table:name`,`drop-temp+table-test`.`shortn1` master-bin.000001 # Query 1 # use `drop-temp+table-test`; DO RELEASE_LOCK("a") drop database `drop-temp+table-test`; diff --git a/mysql-test/r/mix_innodb_myisam_binlog.result b/mysql-test/r/mix_innodb_myisam_binlog.result index e9613bac833..8cf99e8d623 100644 --- a/mysql-test/r/mix_innodb_myisam_binlog.result +++ b/mysql-test/r/mix_innodb_myisam_binlog.result @@ -249,7 +249,8 @@ master-bin.000001 1056 Query 1 1056 use `test`; insert t0 select * from t1 master-bin.000001 1117 Query 1 1117 use `test`; DO RELEASE_LOCK("a") master-bin.000001 1172 Query 1 1172 use `test`; insert into t0 select GET_LOCK("lock1",null) master-bin.000001 1251 Query 1 1251 use `test`; create table t2 (n int) engine=innodb -master-bin.000001 1323 Query 1 1323 use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `test`.`t1`,`test`.`ti` -master-bin.000001 1424 Query 1 1424 use `test`; DO RELEASE_LOCK("lock1") +master-bin.000001 1323 Query 1 1323 use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=33,COLLATION_CONNECTION=8,COLLATION_DATABASE=8,COLLATION_SERVER=8 +master-bin.000001 1457 Query 1 1457 use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `test`.`t1`,`test`.`ti` +master-bin.000001 1558 Query 1 1558 use `test`; DO RELEASE_LOCK("lock1") do release_lock("lock1"); drop table t0,t2; diff --git a/mysql-test/r/mysqlbinlog.result b/mysql-test/r/mysqlbinlog.result index adaf0dad56b..bade0ca9b46 100644 --- a/mysql-test/r/mysqlbinlog.result +++ b/mysql-test/r/mysqlbinlog.result @@ -101,4 +101,9 @@ HEX(f) select HEX(f) from t4; HEX(f) 835C -drop table t1, t2, t03, t04, t3, t4; +flush logs; +select * from t5 /* must be (1),(1) */; +a +1 +1 +drop table t1, t2, t03, t04, t3, t4, t5; diff --git a/mysql-test/r/rpl_temporary.result b/mysql-test/r/rpl_temporary.result index cd67d2592a8..8c6d3f232b1 100644 --- a/mysql-test/r/rpl_temporary.result +++ b/mysql-test/r/rpl_temporary.result @@ -103,3 +103,7 @@ select * from t1 /* must be 1 */; f 1 drop table t1; +select * from t1; +a +1 +drop table t1; diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test index 871886331f6..11aa5814bda 100644 --- a/mysql-test/t/mysqlbinlog.test +++ b/mysql-test/t/mysqlbinlog.test @@ -114,8 +114,17 @@ select HEX(f) from t3; select HEX(f) from t04; select HEX(f) from t4; +# +#14157: utf8 encoding in binlog without set character_set_client +# +flush logs; +--exec $MYSQL --default-character-set=koi8r test -e 'create table if not exists t5 (a int); set names koi8r; create temporary table `только герои срезают рашпилем грим` (a int); insert into `только герои срезают рашпилем грим` values (1); insert into t5 select * from `только герои срезают рашпилем грим`' + +# resulted log is client charset insensitive (latin1 not koi8r) as it must be +--exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000006 | $MYSQL --default-character-set=latin1 +select * from t5 /* must be (1),(1) */; # clean up -drop table t1, t2, t03, t04, t3, t4; +drop table t1, t2, t03, t04, t3, t4, t5; # End of 4.1 tests diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test index 71d7b32b7c9..af952760d6b 100644 --- a/mysql-test/t/rpl_temporary.test +++ b/mysql-test/t/rpl_temporary.test @@ -156,4 +156,16 @@ select * from t1 /* must be 1 */; connection master; drop table t1; +# +#14157: utf8 encoding in binlog without set character_set_client +# +--exec $MYSQL --default-character-set=koi8r test -e 'create table t1 (a int); set names koi8r; create temporary table `только герои срезают рашпилем грим` (a int); insert into `только герои срезают рашпилем грим` values (1); insert into t1 select * from `только герои срезают рашпилем грим`' + +sync_slave_with_master; +#connection slave; +select * from t1; + +connection master; +drop table t1; + # End of 4.1 tests diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 6676d994cfa..aab65bca82f 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1275,6 +1275,13 @@ inline int hexchar_to_int(char c) return -1; } +inline void write_binlog_with_system_charset(THD * thd, Query_log_event * qinfo) +{ + CHARSET_INFO * cs_save= thd->variables.character_set_client; + thd->variables.character_set_client= system_charset_info; + mysql_bin_log.write(qinfo); + thd->variables.character_set_client= cs_save; +} /* Some functions that are different in the embedded library and the normal diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 60e91aff3f9..6365b8c8e40 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -615,7 +615,7 @@ void close_temporary_tables(THD *thd) rightfully causing the slave to stop. */ qinfo.error_code= 0; - mysql_bin_log.write(&qinfo); + write_binlog_with_system_charset(thd, &qinfo); } else { From c212cb25ede28515c588d52061e67286bd3bb7d3 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 12 May 2006 21:29:06 +0300 Subject: [PATCH 2/6] BUG#19188: incorrect temporary table name of DROP query in replication A pattern to generate binlog for DROPped temp table in close_temporary_tables was buggy: could not deal with a grave-accent-in-name table. The fix exploits `append_identifier()' for quoting and duplicating accents. mysql-test/r/rpl_temporary.result: results changed mysql-test/t/rpl_temporary.test: more correct internal table emulation; typo of @@session in bug#17263. sql/mysql_priv.h: bool is_user_table(TABLE * table) is added to answer wheather temporary table was created explicitly. sql/sql_base.cc: Utilizing `append_identifier' to quote. `close_temporary_tables' once again recoded I hope to become much simplier than previously. No-binlog branch is separated completely the rest that adopts String's methods. --- mysql-test/r/rpl_temporary.result | 13 ++- mysql-test/t/rpl_temporary.test | 15 ++- sql/mysql_priv.h | 12 +++ sql/sql_base.cc | 147 ++++++++++++++---------------- 4 files changed, 99 insertions(+), 88 deletions(-) diff --git a/mysql-test/r/rpl_temporary.result b/mysql-test/r/rpl_temporary.result index cd67d2592a8..0442109c016 100644 --- a/mysql-test/r/rpl_temporary.result +++ b/mysql-test/r/rpl_temporary.result @@ -89,14 +89,17 @@ f 7 drop table t1,t2; create temporary table t3 (f int); -set @session.pseudo_thread_id=100; +set @@session.pseudo_thread_id=100; create temporary table t101 (id int); create temporary table t102 (id int); -set @session.pseudo_thread_id=200; +set @@session.pseudo_thread_id=200; create temporary table t201 (id int); -create temporary table `#not_user_table_prefixed_with_hash_sign_no_harm` (id int); -set @con1_id=connection_id(); -kill @con1_id; +create temporary table `t``201` (id int); +create temporary table `#sql_not_user_table202` (id int); +set @@session.pseudo_thread_id=300; +create temporary table t301 (id int); +create temporary table t302 (id int); +create temporary table `#sql_not_user_table303` (id int); create table t1(f int); insert into t1 values (1); select * from t1 /* must be 1 */; diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test index 71d7b32b7c9..e1dd1f32546 100644 --- a/mysql-test/t/rpl_temporary.test +++ b/mysql-test/t/rpl_temporary.test @@ -135,14 +135,19 @@ sync_with_master; # value was set up at the moment of temp table creation # connection con1; -set @session.pseudo_thread_id=100; +set @@session.pseudo_thread_id=100; create temporary table t101 (id int); create temporary table t102 (id int); -set @session.pseudo_thread_id=200; +set @@session.pseudo_thread_id=200; create temporary table t201 (id int); -create temporary table `#not_user_table_prefixed_with_hash_sign_no_harm` (id int); -set @con1_id=connection_id(); -kill @con1_id; +create temporary table `t``201` (id int); +# emulate internal temp table not to come to binlog +create temporary table `#sql_not_user_table202` (id int); +set @@session.pseudo_thread_id=300; +create temporary table t301 (id int); +create temporary table t302 (id int); +create temporary table `#sql_not_user_table303` (id int); +disconnect con1; #now do something to show that slave is ok after DROP temp tables connection master; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 6676d994cfa..634e7bad738 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1275,6 +1275,18 @@ inline int hexchar_to_int(char c) return -1; } +/* + is_user_table() + return true if the table was created explicitly +*/ + +inline bool is_user_table(TABLE * table) +{ + const char *name= table->real_name; + return strncmp(name, tmp_file_prefix, tmp_file_prefix_length); +} + + /* Some functions that are different in the embedded library and the normal diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 60e91aff3f9..3df9cbace78 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -493,118 +493,107 @@ static inline uint tmpkeyval(THD *thd, TABLE *table) void close_temporary_tables(THD *thd) { - TABLE *next, - *prev_table /* prev link is not maintained in TABLE's double-linked list */, - *table; - char *query= (gptr) 0, *end; - uint query_buf_size, max_names_len; - bool found_user_tables; - + TABLE *table; if (!thd->temporary_tables) return; - LINT_INIT(end); - query_buf_size= 50; // Enough for DROP ... TABLE IF EXISTS + if (!mysql_bin_log.is_open()) + { + for (table= thd->temporary_tables; table; table= table->next) + { + close_temporary(table, 1); + } + thd->temporary_tables= 0; + return; + } + TABLE *next, + *prev_table /* prev link is not maintained in TABLE's double-linked list */; + bool was_quote_show= true; /* to assume thd->options has OPTION_QUOTE_SHOW_CREATE */ + // Better add "if exists", in case a RESET MASTER has been done + const char stub[]= "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS "; + uint stub_len= sizeof(stub) - 1; + char buf[256]; + memcpy(buf, stub, stub_len); + String s_query= String(buf, sizeof(buf), system_charset_info); + bool found_user_tables= false; + LINT_INIT(next); + /* insertion sort of temp tables by pseudo_thread_id to build ordered list of sublists of equal pseudo_thread_id */ - for (prev_table= thd->temporary_tables, - table= prev_table->next, - found_user_tables= (prev_table->real_name[0] != '#'); + + for (prev_table= thd->temporary_tables, table= prev_table->next; table; prev_table= table, table= table->next) { - TABLE *prev_sorted /* same as for prev_table */, - *sorted; - /* - table not created directly by the user is moved to the tail. - Fixme/todo: nothing (I checked the manual) prevents user to create temp - with `#' - */ - if (table->real_name[0] == '#') - continue; - else + TABLE *prev_sorted /* same as for prev_table */, *sorted; + if (is_user_table(table)) { - found_user_tables = 1; - } - for (prev_sorted= NULL, sorted= thd->temporary_tables; sorted != table; - prev_sorted= sorted, sorted= sorted->next) - { - if (sorted->real_name[0] == '#' || tmpkeyval(thd, sorted) > tmpkeyval(thd, table)) + if (!found_user_tables) + found_user_tables= true; + for (prev_sorted= NULL, sorted= thd->temporary_tables; sorted != table; + prev_sorted= sorted, sorted= sorted->next) { - /* move into the sorted part of the list from the unsorted */ - prev_table->next= table->next; - table->next= sorted; - if (prev_sorted) + if (!is_user_table(sorted) || + tmpkeyval(thd, sorted) > tmpkeyval(thd, table)) { - prev_sorted->next= table; + /* move into the sorted part of the list from the unsorted */ + prev_table->next= table->next; + table->next= sorted; + if (prev_sorted) + { + prev_sorted->next= table; + } + else + { + thd->temporary_tables= table; + } + table= prev_table; + break; } - else - { - thd->temporary_tables= table; - } - table= prev_table; - break; } } - } - /* - calc query_buf_size as max per sublists, one sublist per pseudo thread id. - Also stop at first occurence of `#'-named table that starts - all implicitly created temp tables - */ - for (max_names_len= 0, table=thd->temporary_tables; - table && table->real_name[0] != '#'; - table=table->next) + } + + /* We always quote db,table names though it is slight overkill */ + if (found_user_tables && + !(was_quote_show= (thd->options & OPTION_QUOTE_SHOW_CREATE))) { - uint tmp_names_len; - for (tmp_names_len= table->key_length + 1; - table->next && table->real_name[0] != '#' && - tmpkeyval(thd, table) == tmpkeyval(thd, table->next); - table=table->next) - { - /* - We are going to add 4 ` around the db/table names, so 1 might not look - enough; indeed it is enough, because table->key_length is greater (by 8, - because of server_id and thread_id) than db||table. - */ - tmp_names_len += table->next->key_length + 1; - } - if (tmp_names_len > max_names_len) max_names_len= tmp_names_len; + thd->options |= OPTION_QUOTE_SHOW_CREATE; } - /* allocate */ - if (found_user_tables && mysql_bin_log.is_open() && - (query = alloc_root(thd->mem_root, query_buf_size+= max_names_len))) - // Better add "if exists", in case a RESET MASTER has been done - end= strmov(query, "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS "); - /* scan sorted tmps to generate sequence of DROP */ - for (table=thd->temporary_tables; table; table= next) + for (table= thd->temporary_tables; table; table= next) { - if (query // we might be out of memory, but this is not fatal - && table->real_name[0] != '#') + if (is_user_table(table)) { - char *end_cur; /* Set pseudo_thread_id to be that of the processed table */ thd->variables.pseudo_thread_id= tmpkeyval(thd, table); /* Loop forward through all tables within the sublist of common pseudo_thread_id to create single DROP query */ - for (end_cur= end; - table && table->real_name[0] != '#' && + for (s_query.length(stub_len); + table && is_user_table(table) && tmpkeyval(thd, table) == thd->variables.pseudo_thread_id; table= next) { - end_cur= strxmov(end_cur, "`", table->table_cache_key, "`.`", - table->real_name, "`,", NullS); + /* + We are going to add 4 ` around the db/table names and possible more + due to special characters in the names + */ + append_identifier(thd, &s_query, table->table_cache_key, strlen(table->table_cache_key)); + s_query.q_append('.'); + append_identifier(thd, &s_query, table->real_name, + strlen(table->real_name)); + s_query.q_append(','); next= table->next; close_temporary(table, 1); } thd->clear_error(); - /* The -1 is to remove last ',' */ - Query_log_event qinfo(thd, query, (ulong)(end_cur - query) - 1, 0, FALSE); + Query_log_event qinfo(thd, s_query.ptr(), + s_query.length() - 1 /* to remove trailing ',' */, + 0, FALSE); /* Imagine the thread had created a temp table, then was doing a SELECT, and the SELECT was killed. Then it's not clever to mark the statement above as @@ -623,6 +612,8 @@ void close_temporary_tables(THD *thd) close_temporary(table, 1); } } + if (!was_quote_show) + thd->options &= ~OPTION_QUOTE_SHOW_CREATE; /* restore option */ thd->temporary_tables=0; } From 62be79a2e6208873240fb0a3dafbb99f24c9e577 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 13 May 2006 12:14:20 +0300 Subject: [PATCH 3/6] BUG#14157: utf8 encoding in binlog without set character_set_client fixing a path to find charset by $MYSQL client. I believe the fix is done what should be by default. mysql-test/t/mysqlbinlog.test: --character-sets-dir=../sql/share/charsets is added otherwise client/.libs/lt-mysql searches in /usr/local/mysql ... A bug? mysql-test/t/rpl_temporary.test: --character-sets-dir=../sql/share/charsets/ --- mysql-test/t/mysqlbinlog.test | 2 +- mysql-test/t/rpl_temporary.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test index 11aa5814bda..7b6c36bb8c9 100644 --- a/mysql-test/t/mysqlbinlog.test +++ b/mysql-test/t/mysqlbinlog.test @@ -118,7 +118,7 @@ select HEX(f) from t4; #14157: utf8 encoding in binlog without set character_set_client # flush logs; ---exec $MYSQL --default-character-set=koi8r test -e 'create table if not exists t5 (a int); set names koi8r; create temporary table `только герои срезают рашпилем грим` (a int); insert into `только герои срезают рашпилем грим` values (1); insert into t5 select * from `только герои срезают рашпилем грим`' +--exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=koi8r test -e 'create table if not exists t5 (a int); set names koi8r; create temporary table `только герои срезают рашпилем грим` (a int); insert into `только герои срезают рашпилем грим` values (1); insert into t5 select * from `только герои срезают рашпилем грим`' # resulted log is client charset insensitive (latin1 not koi8r) as it must be --exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000006 | $MYSQL --default-character-set=latin1 diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test index 1276b635b74..609e8533849 100644 --- a/mysql-test/t/rpl_temporary.test +++ b/mysql-test/t/rpl_temporary.test @@ -164,7 +164,7 @@ drop table t1; # #14157: utf8 encoding in binlog without set character_set_client # ---exec $MYSQL --default-character-set=koi8r test -e 'create table t1 (a int); set names koi8r; create temporary table `только герои срезают рашпилем грим` (a int); insert into `только герои срезают рашпилем грим` values (1); insert into t1 select * from `только герои срезают рашпилем грим`' +--exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=koi8r test -e 'create table t1 (a int); set names koi8r; create temporary table `только герои срезают рашпилем грим` (a int); insert into `только герои срезают рашпилем грим` values (1); insert into t1 select * from `только герои срезают рашпилем грим`' sync_slave_with_master; #connection slave; From d388da989e538cfd68a1d606f7e4d109a0263906 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 14 May 2006 20:09:09 +0300 Subject: [PATCH 4/6] BUG#14157: utf8 encoding in binlog without set character_set_client fixing names length. Got an issue when merged to 5.0, decided to fix starting from 4.1 mysql-test/t/mysqlbinlog.test: fixing temp table name to fit to 64 bytes for 5.0 mysql-test/t/rpl_temporary.test: fixing temp table name to fit to 64 bytes for 5.0 --- mysql-test/t/mysqlbinlog.test | 2 +- mysql-test/t/rpl_temporary.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/t/mysqlbinlog.test b/mysql-test/t/mysqlbinlog.test index 7b6c36bb8c9..6e3daaef0c3 100644 --- a/mysql-test/t/mysqlbinlog.test +++ b/mysql-test/t/mysqlbinlog.test @@ -118,7 +118,7 @@ select HEX(f) from t4; #14157: utf8 encoding in binlog without set character_set_client # flush logs; ---exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=koi8r test -e 'create table if not exists t5 (a int); set names koi8r; create temporary table `только герои срезают рашпилем грим` (a int); insert into `только герои срезают рашпилем грим` values (1); insert into t5 select * from `только герои срезают рашпилем грим`' +--exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=koi8r test -e 'create table if not exists t5 (a int); set names koi8r; create temporary table `ящик` (a int); insert into `ящик` values (1); insert into t5 select * from `ящик`' # resulted log is client charset insensitive (latin1 not koi8r) as it must be --exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000006 | $MYSQL --default-character-set=latin1 diff --git a/mysql-test/t/rpl_temporary.test b/mysql-test/t/rpl_temporary.test index 609e8533849..871ff096476 100644 --- a/mysql-test/t/rpl_temporary.test +++ b/mysql-test/t/rpl_temporary.test @@ -164,7 +164,7 @@ drop table t1; # #14157: utf8 encoding in binlog without set character_set_client # ---exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=koi8r test -e 'create table t1 (a int); set names koi8r; create temporary table `только герои срезают рашпилем грим` (a int); insert into `только герои срезают рашпилем грим` values (1); insert into t1 select * from `только герои срезают рашпилем грим`' +--exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=koi8r test -e 'create table t1 (a int); set names koi8r; create temporary table `ящик` (a int); insert into `ящик` values (1); insert into t1 select * from `ящик`' sync_slave_with_master; #connection slave; From b9558d8bdaf68c923d2f9940b37eb161fd116e73 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 14 May 2006 20:31:42 +0300 Subject: [PATCH 5/6] BUG#19188: incorrect temporary table name of DROP query in replication manual merge to account 5.0 specific names of TABLE class sql/mysql_priv.h: manual merge: changing to 5.0's TABLE class names sql/sql_base.cc: manual merge: whitespaces and 5.0 TABLE's names --- sql/mysql_priv.h | 2 +- sql/sql_base.cc | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 9aa5c3e41d5..776c23a21a6 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1602,7 +1602,7 @@ inline void write_binlog_with_system_charset(THD * thd, Query_log_event * qinfo) inline bool is_user_table(TABLE * table) { - const char *name= table->real_name; + const char *name= table->s->table_name; return strncmp(name, tmp_file_prefix, tmp_file_prefix_length); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index f0480a1c616..b6694edea78 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -620,7 +620,7 @@ void close_temporary_tables(THD *thd) TABLE *table; if (!thd->temporary_tables) return; - + if (!mysql_bin_log.is_open()) { for (table= thd->temporary_tables; table; table= table->next) @@ -642,12 +642,12 @@ void close_temporary_tables(THD *thd) String s_query= String(buf, sizeof(buf), system_charset_info); bool found_user_tables= false; LINT_INIT(next); - - /* - insertion sort of temp tables by pseudo_thread_id to build ordered list + + /* + insertion sort of temp tables by pseudo_thread_id to build ordered list of sublists of equal pseudo_thread_id */ - + for (prev_table= thd->temporary_tables, table= prev_table->next; table; prev_table= table, table= table->next) @@ -657,7 +657,7 @@ void close_temporary_tables(THD *thd) { if (!found_user_tables) found_user_tables= true; - for (prev_sorted= NULL, sorted= thd->temporary_tables; sorted != table; + for (prev_sorted= NULL, sorted= thd->temporary_tables; sorted != table; prev_sorted= sorted, sorted= sorted->next) { if (!is_user_table(sorted) || @@ -666,7 +666,7 @@ void close_temporary_tables(THD *thd) /* move into the sorted part of the list from the unsorted */ prev_table->next= table->next; table->next= sorted; - if (prev_sorted) + if (prev_sorted) { prev_sorted->next= table; } @@ -687,11 +687,11 @@ void close_temporary_tables(THD *thd) { thd->options |= OPTION_QUOTE_SHOW_CREATE; } - + /* scan sorted tmps to generate sequence of DROP */ for (table= thd->temporary_tables; table; table= next) { - if (is_user_table(table)) + if (is_user_table(table)) { /* Set pseudo_thread_id to be that of the processed table */ thd->variables.pseudo_thread_id= tmpkeyval(thd, table); @@ -706,10 +706,10 @@ void close_temporary_tables(THD *thd) We are going to add 4 ` around the db/table names and possible more due to special characters in the names */ - append_identifier(thd, &s_query, table->table_cache_key, strlen(table->table_cache_key)); + append_identifier(thd, &s_query, table->s->db, strlen(table->s->db)); s_query.q_append('.'); - append_identifier(thd, &s_query, table->real_name, - strlen(table->real_name)); + append_identifier(thd, &s_query, table->s->table_name, + strlen(table->s->table_name)); s_query.q_append(','); next= table->next; close_temporary(table, 1); @@ -730,7 +730,7 @@ void close_temporary_tables(THD *thd) qinfo.error_code= 0; write_binlog_with_system_charset(thd, &qinfo); } - else + else { next= table->next; close_temporary(table, 1); From b6c7f5f2a80e6123f0106254c6c56af8f33f12d7 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 15 May 2006 18:05:23 +0300 Subject: [PATCH 6/6] BUG#14157: utf8 encoding in binlog without set character_set_client: e.g DROP temporary specific to 5.0 version of the patch is motivated by the fact that a wrapper over MYSQLLOG::write can not help in 5.0 where query's charset is embedded into event instance in the constructor. sql/mysql_priv.h: this 4.1 specific code does not help in 5.0 sql/sql_base.cc: No wrapper similar to 4.1's version is done since Query_log_event constructor takes care of encodings in 5.0 whereas log::write method does it in 4.1. We can introduce an additional constuctor for Query_log_event to pass desired (i.e system_character_info) charset different from THD's version. But I am delaying this while there are not more bugs similar to this one reported. --- sql/mysql_priv.h | 13 ------------- sql/sql_base.cc | 5 ++++- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 776c23a21a6..0290c0178e0 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1582,19 +1582,6 @@ inline int hexchar_to_int(char c) return -1; } -/* - wrapper to use instead of mysql_bin_log.write when - query is generated by the server using system_charset encoding -*/ - -inline void write_binlog_with_system_charset(THD * thd, Query_log_event * qinfo) -{ - CHARSET_INFO * cs_save= thd->variables.character_set_client; - thd->variables.character_set_client= system_charset_info; - mysql_bin_log.write(qinfo); - thd->variables.character_set_client= cs_save; -} - /* is_user_table() return true if the table was created explicitly diff --git a/sql/sql_base.cc b/sql/sql_base.cc index b6694edea78..c83e847bc8a 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -715,9 +715,12 @@ void close_temporary_tables(THD *thd) close_temporary(table, 1); } thd->clear_error(); + CHARSET_INFO *cs_save= thd->variables.character_set_client; + thd->variables.character_set_client= system_charset_info; Query_log_event qinfo(thd, s_query.ptr(), s_query.length() - 1 /* to remove trailing ',' */, 0, FALSE); + thd->variables.character_set_client= cs_save; /* Imagine the thread had created a temp table, then was doing a SELECT, and the SELECT was killed. Then it's not clever to mark the statement above as @@ -728,7 +731,7 @@ void close_temporary_tables(THD *thd) rightfully causing the slave to stop. */ qinfo.error_code= 0; - write_binlog_with_system_charset(thd, &qinfo); + mysql_bin_log.write(&qinfo); } else {