From 46af63bfe202b62a5665e1aa09d069b5b5613249 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 10 Apr 2023 11:35:38 +0400 Subject: [PATCH] MDEV-31018 Replica of 10.3, 10.4, <10.5.19 and <10.6.12 to 10.11 will not work when using non-default charset MDEV-28769 earlier disabled the use if IDs with non-default collations in statements like: SET character_set_results=2/*latin2_czech_cs*/; SET character_set_client=2/*latin2_czech_cs*/; SET character_set_server=2/*latin2_czech_cs*/; SET character_set_connection=2/*latin2_czech_cs*/; MDEV-30824 later fixed "mysqlbinlog" to dump character set names instead of IDs in these statements: < SET @@session.character_set_client=33, ... /*!*/; > SET @@session.character_set_client=utf8mb3, ... /*!*/; However, mysqlbinlog from old (pre MDEV-30824) distributions can still produce incorrect statements with numeric non-default collation IDs. New servers should still be able to load old dumps. Allowing the use of "SET @@character_set_xxx=ID" with numeric non-default collation IDs but only if: - the current THD is a true slave thread or - the current THD a pseudo slave thread (loading a mysqlbinlog output). --- .../r/character_set_client_basic.result | 11 +++++++++ .../r/character_set_connection_basic.result | 16 +++++++++++++ .../r/character_set_results_basic.result | Bin 16427 -> 16895 bytes .../r/character_set_server_basic.result | 16 +++++++++++++ .../t/character_set_client_basic.test | 9 +++++++ .../t/character_set_connection_basic.test | 13 +++++++++++ .../t/character_set_results_basic.test | 12 ++++++++++ .../t/character_set_server_basic.test | 12 ++++++++++ sql/sys_vars.cc | 22 ++++++++++++++---- 9 files changed, 107 insertions(+), 4 deletions(-) diff --git a/mysql-test/suite/sys_vars/r/character_set_client_basic.result b/mysql-test/suite/sys_vars/r/character_set_client_basic.result index d62d88027c7..14c8bcfd058 100644 --- a/mysql-test/suite/sys_vars/r/character_set_client_basic.result +++ b/mysql-test/suite/sys_vars/r/character_set_client_basic.result @@ -500,5 +500,16 @@ res # SET GLOBAL character_set_client=2; ERROR 42000: Unknown character set: '2' +# +# MDEV-31018 Replica of 10.3, 10.4, <10.5.19 and <10.6.12 to 10.11 will not work when using non-default charset +# +SET @@pseudo_slave_mode=1; +SET character_set_client=2/*latin2_czech_cs*/; +SHOW VARIABLES LIKE 'character_set_client'; +Variable_name Value +character_set_client latin2 +SET @@pseudo_slave_mode=0; +Warnings: +Warning 1231 Slave applier execution mode not active, statement ineffective. SET @@global.character_set_client = @global_start_value; SET @@session.character_set_client = @session_start_value; diff --git a/mysql-test/suite/sys_vars/r/character_set_connection_basic.result b/mysql-test/suite/sys_vars/r/character_set_connection_basic.result index e356d62ed2b..bbb4f4e5f75 100644 --- a/mysql-test/suite/sys_vars/r/character_set_connection_basic.result +++ b/mysql-test/suite/sys_vars/r/character_set_connection_basic.result @@ -494,5 +494,21 @@ SELECT @@session.character_set_connection = WHERE VARIABLE_NAME='character_set_connection') AS res; res 1 +# +# MDEV-31018 Replica of 10.3, 10.4, <10.5.19 and <10.6.12 to 10.11 will not work when using non-default charset +# +SET character_set_connection=2/*latin2_czech_cs*/; +ERROR 42000: Unknown character set: '2' +SET @@pseudo_slave_mode=1; +SET character_set_connection=2/*latin2_czech_cs*/; +SHOW VARIABLES LIKE 'character_set_connection'; +Variable_name Value +character_set_connection latin2 +SHOW VARIABLES LIKE 'collation_connection'; +Variable_name Value +collation_connection latin2_general_ci +SET @@pseudo_slave_mode=0; +Warnings: +Warning 1231 Slave applier execution mode not active, statement ineffective. SET @@global.character_set_connection = @global_start_value; SET @@global.character_set_client = @save_character_set_client; diff --git a/mysql-test/suite/sys_vars/r/character_set_results_basic.result b/mysql-test/suite/sys_vars/r/character_set_results_basic.result index d1c6a52ba177c0b07efa3ba653ea42c1025b3e94..1346c8b42cac7e5b1b44f33f851388c23d7d2573 100644 GIT binary patch delta 394 zcmZ`#!AiqG5Tz7^TMSrJvW*$7g?C)vIuQVLQz>F-aFDxZupAAOj$#(Qf4R zumPu8J2J>IP~jJ#V-O3J%w- zdlf4iFK=ex3@4-E`PiPqcywi_@16ZhPj_g<=sibQ&=56;@&xsily}$K#`0eSv!~B! zB(fCo$={?At4*|Neg)7)_9=`2pU_JblLGR)iZ5ij*b*BME2=O=p@0bt0xW1_lbxlh-*00su)N2a*5) diff --git a/mysql-test/suite/sys_vars/r/character_set_server_basic.result b/mysql-test/suite/sys_vars/r/character_set_server_basic.result index e0a13c729fe..7445be6aef1 100644 --- a/mysql-test/suite/sys_vars/r/character_set_server_basic.result +++ b/mysql-test/suite/sys_vars/r/character_set_server_basic.result @@ -486,5 +486,21 @@ SELECT @@session.character_set_server = WHERE VARIABLE_NAME='character_set_server') AS res; res 1 +# +# MDEV-31018 Replica of 10.3, 10.4, <10.5.19 and <10.6.12 to 10.11 will not work when using non-default charset +# +SET character_set_server=2/*latin2_czech_cs*/; +ERROR 42000: Unknown character set: '2' +SET @@pseudo_slave_mode=1; +SET character_set_server=2/*latin2_czech_cs*/; +SHOW VARIABLES LIKE 'character_set_server'; +Variable_name Value +character_set_server latin2 +SHOW VARIABLES LIKE 'collation_server'; +Variable_name Value +collation_server latin2_general_ci +SET @@pseudo_slave_mode=0; +Warnings: +Warning 1231 Slave applier execution mode not active, statement ineffective. SET @@global.character_set_server = @global_start_value; SET @@session.character_set_server = @session_start_value; diff --git a/mysql-test/suite/sys_vars/t/character_set_client_basic.test b/mysql-test/suite/sys_vars/t/character_set_client_basic.test index 09f758a0316..44c0d240a9d 100644 --- a/mysql-test/suite/sys_vars/t/character_set_client_basic.test +++ b/mysql-test/suite/sys_vars/t/character_set_client_basic.test @@ -350,6 +350,15 @@ SELECT @@session.character_set_client = --error ER_UNKNOWN_CHARACTER_SET SET GLOBAL character_set_client=2; +--echo # +--echo # MDEV-31018 Replica of 10.3, 10.4, <10.5.19 and <10.6.12 to 10.11 will not work when using non-default charset +--echo # + +SET @@pseudo_slave_mode=1; +SET character_set_client=2/*latin2_czech_cs*/; +SHOW VARIABLES LIKE 'character_set_client'; +SET @@pseudo_slave_mode=0; + #################################### # Restore initial value # #################################### diff --git a/mysql-test/suite/sys_vars/t/character_set_connection_basic.test b/mysql-test/suite/sys_vars/t/character_set_connection_basic.test index 3d9094fca04..46bdfcb52e2 100644 --- a/mysql-test/suite/sys_vars/t/character_set_connection_basic.test +++ b/mysql-test/suite/sys_vars/t/character_set_connection_basic.test @@ -275,6 +275,19 @@ SELECT @@session.character_set_connection = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='character_set_connection') AS res; +--echo # +--echo # MDEV-31018 Replica of 10.3, 10.4, <10.5.19 and <10.6.12 to 10.11 will not work when using non-default charset +--echo # + +--error ER_UNKNOWN_CHARACTER_SET +SET character_set_connection=2/*latin2_czech_cs*/; +SET @@pseudo_slave_mode=1; +SET character_set_connection=2/*latin2_czech_cs*/; +SHOW VARIABLES LIKE 'character_set_connection'; +SHOW VARIABLES LIKE 'collation_connection'; +SET @@pseudo_slave_mode=0; + + #################################### # Restore initial value # #################################### diff --git a/mysql-test/suite/sys_vars/t/character_set_results_basic.test b/mysql-test/suite/sys_vars/t/character_set_results_basic.test index 617332b9780..41090be6657 100644 --- a/mysql-test/suite/sys_vars/t/character_set_results_basic.test +++ b/mysql-test/suite/sys_vars/t/character_set_results_basic.test @@ -272,6 +272,18 @@ SELECT @@session.character_set_results = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='character_set_results') AS res; +--echo # +--echo # MDEV-31018 Replica of 10.3, 10.4, <10.5.19 and <10.6.12 to 10.11 will not work when using non-default charset +--echo # + +--error ER_UNKNOWN_CHARACTER_SET +SET character_set_results=2/*latin2_czech_cs*/; +SET @@pseudo_slave_mode=1; +SET character_set_results=2; +SHOW VARIABLES LIKE 'character_set_results'; +SET @@pseudo_slave_mode=0; + + #################################### # Restore initial value # #################################### diff --git a/mysql-test/suite/sys_vars/t/character_set_server_basic.test b/mysql-test/suite/sys_vars/t/character_set_server_basic.test index b2f4788fdae..929dbfaf143 100644 --- a/mysql-test/suite/sys_vars/t/character_set_server_basic.test +++ b/mysql-test/suite/sys_vars/t/character_set_server_basic.test @@ -266,6 +266,18 @@ SELECT @@session.character_set_server = (SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME='character_set_server') AS res; +--echo # +--echo # MDEV-31018 Replica of 10.3, 10.4, <10.5.19 and <10.6.12 to 10.11 will not work when using non-default charset +--echo # + +--error ER_UNKNOWN_CHARACTER_SET +SET character_set_server=2/*latin2_czech_cs*/; +SET @@pseudo_slave_mode=1; +SET character_set_server=2/*latin2_czech_cs*/; +SHOW VARIABLES LIKE 'character_set_server'; +SHOW VARIABLES LIKE 'collation_server'; +SET @@pseudo_slave_mode=0; + #################################### # Restore initial value # #################################### diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 10f9de106f8..45b5fe20ff6 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -791,12 +791,26 @@ static bool check_charset(sys_var *self, THD *thd, set_var *var) { int csno= (int)var->value->val_int(); CHARSET_INFO *cs; - if (!(var->save_result.ptr= cs= get_charset(csno, MYF(0))) || - !(cs->state & MY_CS_PRIMARY)) + if ((var->save_result.ptr= cs= get_charset(csno, MYF(0)))) { - my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), llstr(csno, buff)); - return true; + /* + Backward compatibility: pre MDEV-30824 servers + can write non-default collation IDs to binary log: + SET character_set_client=83; -- utf8mb3_bin + Convert a non-default collation to the compiled default collation, + e.g. utf8mb3_bin to utf8mb3_general_ci, but only if + - THD is a slave thread or + - is processing a mysqlbinlog output. + */ + if ((cs->state & MY_CS_PRIMARY) || + ((thd->variables.pseudo_slave_mode || thd->slave_thread) && + (var->save_result.ptr= + Lex_exact_charset_opt_extended_collate(cs, true). + find_default_collation()))) + return false; } + my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), llstr(csno, buff)); + return true; } return false; }