diff --git a/mysql-test/main/ctype_filename.result b/mysql-test/main/ctype_filename.result index aaccea917934239ff1bb65ebf0199dc002336d2f..9cf1c07e00d35257e68a740cc8b0acdbe1e6fc5f 100644 --- a/mysql-test/main/ctype_filename.result +++ b/mysql-test/main/ctype_filename.result @@ -132,4 +132,31 @@ a c @002d1 @002d1 DROP TABLE t1; SET NAMES utf8; +# +# MDEV-25900 Assertion `octets < 1024' failed in Binlog_type_info_fixed_string::Binlog_type_info_fixed_string OR Assertion `field_length < 1024' failed in Field_string::save_field_metadata +# +CREATE TABLE t1 (a CHAR(204)) CHARACTER SET filename; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` char(204) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=filename COLLATE=filename +DROP TABLE t1; +CREATE TABLE t1 (a CHAR(205)) CHARACTER SET filename; +ERROR 42000: Column length too big for column 'a' (max = 204); use BLOB or TEXT instead +SET sql_mode=''; +CREATE TABLE t1 (a CHAR(205)) CHARACTER SET filename; +Warnings: +Note 1246 Converting column 'a' from CHAR to VARCHAR +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `a` varchar(205) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=filename COLLATE=filename +DROP TABLE t1; +SET sql_mode=DEFAULT; +CREATE TABLE t1 (a CHAR(205) CHARACTER SET latin1); +ALTER TABLE t1 CONVERT TO CHARACTER SET filename; +ERROR 42000: Column length too big for column 'a' (max = 204); use BLOB or TEXT instead +DROP TABLE t1; # End of 10.5 tests diff --git a/mysql-test/main/ctype_filename.test b/mysql-test/main/ctype_filename.test index bfafe4d437fa354acb3635fe501b05108aeb76f3..185d4ca641abade3e0fd06b82b928dee0568bcec 100644 --- a/mysql-test/main/ctype_filename.test +++ b/mysql-test/main/ctype_filename.test @@ -141,4 +141,26 @@ SET NAMES utf8; --enable_ps_protocol +--echo # +--echo # MDEV-25900 Assertion `octets < 1024' failed in Binlog_type_info_fixed_string::Binlog_type_info_fixed_string OR Assertion `field_length < 1024' failed in Field_string::save_field_metadata +--echo # + +CREATE TABLE t1 (a CHAR(204)) CHARACTER SET filename; +SHOW CREATE TABLE t1; +DROP TABLE t1; + +--error ER_TOO_BIG_FIELDLENGTH +CREATE TABLE t1 (a CHAR(205)) CHARACTER SET filename; + +SET sql_mode=''; +CREATE TABLE t1 (a CHAR(205)) CHARACTER SET filename; +SHOW CREATE TABLE t1; +DROP TABLE t1; +SET sql_mode=DEFAULT; + +CREATE TABLE t1 (a CHAR(205) CHARACTER SET latin1); +--error ER_TOO_BIG_FIELDLENGTH +ALTER TABLE t1 CONVERT TO CHARACTER SET filename; +DROP TABLE t1; + --echo # End of 10.5 tests diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 1ef0a6e3bef09d8fe0de72b6ba5f202a8cfb217f..0a0ea7acb2e62687bceba7d72187e30b3fa1fdf6 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -4734,6 +4734,33 @@ bool Column_definition::prepare_blob_field(THD *thd) { DBUG_ENTER("Column_definition::prepare_blob_field"); + if (real_field_type() == FIELD_TYPE_STRING && length > 1024) + { + DBUG_ASSERT(charset->mbmaxlen > 4); + /* + Convert long CHAR columns to VARCHAR. + CHAR has an octet length limit of 1024 bytes. + The code in Binlog_type_info_fixed_string::Binlog_type_info_fixed_string + relies on this limit. If octet length of a CHAR column is greater + than 1024, then it cannot write its metadata to binlog properly. + In case of the filename character set with mbmaxlen=5, + the maximum possible character length is 1024/5=204 characters. + Upgrade to VARCHAR if octet length is greater than 1024. + */ + char warn_buff[MYSQL_ERRMSG_SIZE]; + if (thd->is_strict_mode()) + { + my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), field_name.str, + static_cast<ulong>(1024 / charset->mbmaxlen)); + DBUG_RETURN(1); + } + set_handler(&type_handler_varchar); + my_snprintf(warn_buff, sizeof(warn_buff), ER_THD(thd, ER_AUTO_CONVERT), + field_name.str, "CHAR", "VARCHAR"); + push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, ER_AUTO_CONVERT, + warn_buff); + } + if (length > MAX_FIELD_VARCHARLENGTH && !(flags & BLOB_FLAG)) { /* Convert long VARCHAR columns to TEXT or BLOB */