From b003b0c934cf6b59358e31144c4f69cf34622fb8 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Mon, 3 Jun 2019 12:42:36 +0400 Subject: [PATCH] MDEV-19675 Wrong charset is chosen when opening a pre-4.1 table --- mysql-test/r/ctype_utf8_def_upgrade.result | 99 ++++++++++++++++++++++ mysql-test/t/ctype_utf8_def_upgrade.opt | 1 + mysql-test/t/ctype_utf8_def_upgrade.test | 61 +++++++++++++ sql/table.cc | 5 +- 4 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 mysql-test/r/ctype_utf8_def_upgrade.result create mode 100644 mysql-test/t/ctype_utf8_def_upgrade.opt create mode 100644 mysql-test/t/ctype_utf8_def_upgrade.test diff --git a/mysql-test/r/ctype_utf8_def_upgrade.result b/mysql-test/r/ctype_utf8_def_upgrade.result new file mode 100644 index 00000000000..1b921289af6 --- /dev/null +++ b/mysql-test/r/ctype_utf8_def_upgrade.result @@ -0,0 +1,99 @@ +# +# Start of 10.1 tests +# +# +# MDEV-19675 Wrong charset is chosen when opening a pre-4.1 table +# +# Test with a saved table from 3.23 +SELECT @@character_set_database; +@@character_set_database +utf8 +SET @@character_set_database="latin1"; +SELECT COUNT(*) FROM t1; +ERROR HY000: Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You have to dump an" from storage engine MyISAM +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check Error Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You have to dump an" from storage engine MyISAM +test.t1 check error Corrupt +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair Error Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You have to dump an" from storage engine MyISAM +test.t1 repair error Corrupt +REPAIR TABLE t1 USE_FRM; +Table Op Msg_type Msg_text +test.t1 repair status OK +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `Host` char(60) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '', + `Db` char(64) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') NOT NULL DEFAULT 'N', + PRIMARY KEY (`Host`,`Db`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Host privileges; Merged with database privileges' +DROP TABLE t1; +SET @@character_set_database=DEFAULT; +# Now do the same, but doing 'ALTER DATABASE' to create the db.opt file, +# instead of setting variables directly. +# Emulate a pre-4.1 database without db.opt +SHOW CREATE DATABASE db1; +Database Create Database +db1 CREATE DATABASE `db1` /*!40100 DEFAULT CHARACTER SET utf8 */ +USE db1; +SELECT @@character_set_database, 'taken from defaults' AS comment; +@@character_set_database comment +utf8 taken from defaults +USE test; +ALTER DATABASE db1 DEFAULT CHARACTER SET latin1; +USE db1; +SELECT @@character_set_database, 'taken from db.opt' AS comment; +@@character_set_database comment +latin1 taken from db.opt +SELECT COUNT(*) FROM t1; +ERROR HY000: Got error 190 "Incompatible key or row definition between the MariaDB .frm file and the information in the storage engine. You have to dump an" from storage engine MyISAM +REPAIR TABLE t1 USE_FRM; +Table Op Msg_type Msg_text +db1.t1 repair status OK +SELECT COUNT(*) FROM t1; +COUNT(*) +0 +CHECK TABLE t1; +Table Op Msg_type Msg_text +db1.t1 check status OK +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `Host` char(60) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '', + `Db` char(64) CHARACTER SET latin1 COLLATE latin1_bin NOT NULL DEFAULT '', + `Select_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `Insert_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `Update_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `Delete_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `Create_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `Drop_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `Grant_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `References_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `Index_priv` enum('N','Y') NOT NULL DEFAULT 'N', + `Alter_priv` enum('N','Y') NOT NULL DEFAULT 'N', + PRIMARY KEY (`Host`,`Db`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='Host privileges; Merged with database privileges' +DROP TABLE t1; +DROP DATABASE db1; +USE test; +# +# End of 10.1 tests +# diff --git a/mysql-test/t/ctype_utf8_def_upgrade.opt b/mysql-test/t/ctype_utf8_def_upgrade.opt new file mode 100644 index 00000000000..61a472b45c5 --- /dev/null +++ b/mysql-test/t/ctype_utf8_def_upgrade.opt @@ -0,0 +1 @@ +--character-set-server=utf8 diff --git a/mysql-test/t/ctype_utf8_def_upgrade.test b/mysql-test/t/ctype_utf8_def_upgrade.test new file mode 100644 index 00000000000..4751faa0622 --- /dev/null +++ b/mysql-test/t/ctype_utf8_def_upgrade.test @@ -0,0 +1,61 @@ +let $MYSQLD_DATADIR= `select @@datadir`; + +--echo # +--echo # Start of 10.1 tests +--echo # + +--echo # +--echo # MDEV-19675 Wrong charset is chosen when opening a pre-4.1 table +--echo # + +--echo # Test with a saved table from 3.23 + +SELECT @@character_set_database; +SET @@character_set_database="latin1"; +--copy_file std_data/host_old.frm $MYSQLD_DATADIR/test/t1.frm +--copy_file std_data/host_old.MYD $MYSQLD_DATADIR/test/t1.MYD +--copy_file std_data/host_old.MYI $MYSQLD_DATADIR/test/t1.MYI + +--error ER_GET_ERRNO +SELECT COUNT(*) FROM t1; +CHECK TABLE t1; +REPAIR TABLE t1; +REPAIR TABLE t1 USE_FRM; +SELECT COUNT(*) FROM t1; +CHECK TABLE t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; +SET @@character_set_database=DEFAULT; + + +--echo # Now do the same, but doing 'ALTER DATABASE' to create the db.opt file, +--echo # instead of setting variables directly. + +--echo # Emulate a pre-4.1 database without db.opt +--mkdir $MYSQLD_DATADIR/db1 +SHOW CREATE DATABASE db1; +USE db1; +SELECT @@character_set_database, 'taken from defaults' AS comment; +USE test; +ALTER DATABASE db1 DEFAULT CHARACTER SET latin1; +USE db1; +SELECT @@character_set_database, 'taken from db.opt' AS comment; + +--copy_file std_data/host_old.frm $MYSQLD_DATADIR/db1/t1.frm +--copy_file std_data/host_old.MYD $MYSQLD_DATADIR/db1/t1.MYD +--copy_file std_data/host_old.MYI $MYSQLD_DATADIR/db1/t1.MYI + +--error ER_GET_ERRNO +SELECT COUNT(*) FROM t1; +REPAIR TABLE t1 USE_FRM; +SELECT COUNT(*) FROM t1; +CHECK TABLE t1; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +DROP DATABASE db1; +USE test; + +--echo # +--echo # End of 10.1 tests +--echo # diff --git a/sql/table.cc b/sql/table.cc index 55b505a0cc0..12b23304acd 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1104,8 +1104,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, } if (!share->table_charset) { + const CHARSET_INFO *cs= thd->variables.collation_database; /* unknown charset in frm_image[38] or pre-3.23 frm */ - if (use_mb(default_charset_info)) + if (use_mb(cs)) { /* Warn that we may be changing the size of character columns */ sql_print_warning("'%s' had no or invalid character set, " @@ -1113,7 +1114,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, "so character column sizes may have changed", share->path.str); } - share->table_charset= default_charset_info; + share->table_charset= cs; } share->db_record_offset= 1;