summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/main/ctype_utf32.result23
-rw-r--r--mysql-test/main/ctype_utf32.test19
-rw-r--r--mysql-test/main/ctype_utf32_uca.result15
-rw-r--r--mysql-test/main/ctype_utf32_uca.test13
-rw-r--r--mysql-test/suite/gcol/inc/gcol_supported_sql_funcs_main.inc3
-rw-r--r--sql/sql_class.cc52
-rw-r--r--sql/sql_class.h4
7 files changed, 129 insertions, 0 deletions
diff --git a/mysql-test/main/ctype_utf32.result b/mysql-test/main/ctype_utf32.result
index 584ca12f8c3..143fff9e419 100644
--- a/mysql-test/main/ctype_utf32.result
+++ b/mysql-test/main/ctype_utf32.result
@@ -2890,5 +2890,28 @@ HEX(c1)
0000006100000063
DROP TABLE t1;
#
+# MDEV-23210 Assertion `(length % 4) == 0' failed in my_lengthsp_utf32 on ALTER TABLE, SELECT and INSERT
+#
+CREATE TABLE t1 (a CHAR(1));
+SET COLLATION_CONNECTION=utf32_general_ci, CHARACTER_SET_CLIENT=binary;
+ALTER TABLE t1 CHANGE a a ENUM('a','a') CHARACTER SET utf32;
+ERROR HY000: Column 'a' has duplicated value 'a' in ENUM
+ALTER TABLE t1 CHANGE a a ENUM('aaa') CHARACTER SET utf32;
+ERROR HY000: Invalid utf32 character string: '\x00aaa'
+ALTER TABLE t1 CHANGE a a ENUM('aa') CHARACTER SET utf32;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` enum('慡') CHARACTER SET utf32 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+ALTER TABLE t1 CHANGE a a ENUM('a','b') CHARACTER SET utf32;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` enum('a','b') CHARACTER SET utf32 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+SET NAMES utf8;
+#
# End of 10.2 tests
#
diff --git a/mysql-test/main/ctype_utf32.test b/mysql-test/main/ctype_utf32.test
index 891fd14d15f..46ff333b5f7 100644
--- a/mysql-test/main/ctype_utf32.test
+++ b/mysql-test/main/ctype_utf32.test
@@ -1048,6 +1048,25 @@ INSERT INTO t1 (c1) VALUES (1),(2),(3);
SELECT HEX(c1) FROM t1 ORDER BY c1;
DROP TABLE t1;
+
+--echo #
+--echo # MDEV-23210 Assertion `(length % 4) == 0' failed in my_lengthsp_utf32 on ALTER TABLE, SELECT and INSERT
+--echo #
+
+CREATE TABLE t1 (a CHAR(1));
+SET COLLATION_CONNECTION=utf32_general_ci, CHARACTER_SET_CLIENT=binary;
+--error ER_DUPLICATED_VALUE_IN_TYPE
+ALTER TABLE t1 CHANGE a a ENUM('a','a') CHARACTER SET utf32;
+--error ER_INVALID_CHARACTER_STRING
+ALTER TABLE t1 CHANGE a a ENUM('aaa') CHARACTER SET utf32;
+ALTER TABLE t1 CHANGE a a ENUM('aa') CHARACTER SET utf32;
+SHOW CREATE TABLE t1;
+ALTER TABLE t1 CHANGE a a ENUM('a','b') CHARACTER SET utf32;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+SET NAMES utf8;
+
+
--echo #
--echo # End of 10.2 tests
--echo #
diff --git a/mysql-test/main/ctype_utf32_uca.result b/mysql-test/main/ctype_utf32_uca.result
index 46ca6e7baee..2f6e44dc402 100644
--- a/mysql-test/main/ctype_utf32_uca.result
+++ b/mysql-test/main/ctype_utf32_uca.result
@@ -7941,5 +7941,20 @@ EXECUTE s;
DEALLOCATE PREPARE s;
SET NAMES utf8;
#
+# MDEV-23210 Assertion `(length % 4) == 0' failed in my_lengthsp_utf32 on ALTER TABLE, SELECT and INSERT
+#
+CREATE TABLE t1 (a CHAR(1));
+SET COLLATION_CONNECTION=utf32_myanmar_ci, CHARACTER_SET_CLIENT=binary;
+ALTER TABLE t1 CHANGE a a ENUM('a','a') CHARACTER SET utf32;
+ERROR HY000: Column 'a' has duplicated value 'a' in ENUM
+ALTER TABLE t1 CHANGE a a ENUM('a','b') CHARACTER SET utf32;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` enum('a','b') CHARACTER SET utf32 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+SET NAMES utf8;
+#
# End of 10.2 tests
#
diff --git a/mysql-test/main/ctype_utf32_uca.test b/mysql-test/main/ctype_utf32_uca.test
index 2969480b0ef..9073d8c57f5 100644
--- a/mysql-test/main/ctype_utf32_uca.test
+++ b/mysql-test/main/ctype_utf32_uca.test
@@ -290,6 +290,19 @@ EXECUTE s;
DEALLOCATE PREPARE s;
SET NAMES utf8;
+--echo #
+--echo # MDEV-23210 Assertion `(length % 4) == 0' failed in my_lengthsp_utf32 on ALTER TABLE, SELECT and INSERT
+--echo #
+
+CREATE TABLE t1 (a CHAR(1));
+SET COLLATION_CONNECTION=utf32_myanmar_ci, CHARACTER_SET_CLIENT=binary;
+--error ER_DUPLICATED_VALUE_IN_TYPE
+ALTER TABLE t1 CHANGE a a ENUM('a','a') CHARACTER SET utf32;
+ALTER TABLE t1 CHANGE a a ENUM('a','b') CHARACTER SET utf32;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+SET NAMES utf8;
+
--echo #
--echo # End of 10.2 tests
diff --git a/mysql-test/suite/gcol/inc/gcol_supported_sql_funcs_main.inc b/mysql-test/suite/gcol/inc/gcol_supported_sql_funcs_main.inc
index 88268ddd6c4..3f48f86ce7c 100644
--- a/mysql-test/suite/gcol/inc/gcol_supported_sql_funcs_main.inc
+++ b/mysql-test/suite/gcol/inc/gcol_supported_sql_funcs_main.inc
@@ -12,6 +12,9 @@
# Change Date: #
# Change: #
################################################################################
+
+--source include/have_des.inc
+
set time_zone="+03:00";
--echo #
--echo # NUMERIC FUNCTIONS
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index c808a2c997c..6203e5672fe 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -2307,6 +2307,58 @@ bool THD::convert_string(LEX_STRING *to, CHARSET_INFO *to_cs,
/*
+ Reinterpret a binary string to a character string
+
+ @param[OUT] to The result will be written here,
+ either the original string as is,
+ or a newly alloced fixed string with
+ some zero bytes prepended.
+ @param cs The destination character set
+ @param str The binary string
+ @param length The length of the binary string
+
+ @return false on success
+ @return true on error
+*/
+
+bool THD::reinterpret_string_from_binary(LEX_CSTRING *to, CHARSET_INFO *cs,
+ const char *str, size_t length)
+{
+ /*
+ When reinterpreting from binary to tricky character sets like
+ UCS2, UTF16, UTF32, we may need to prepend some zero bytes.
+ This is possible in scenarios like this:
+ SET COLLATION_CONNECTION=utf32_general_ci, CHARACTER_SET_CLIENT=binary;
+ This code is similar to String::copy_aligned().
+ */
+ size_t incomplete= length % cs->mbminlen; // Bytes in an incomplete character
+ if (incomplete)
+ {
+ size_t zeros= cs->mbminlen - incomplete;
+ size_t aligned_length= zeros + length;
+ char *dst= (char*) alloc(aligned_length + 1);
+ if (!dst)
+ {
+ to->str= NULL; // Safety
+ to->length= 0;
+ return true;
+ }
+ bzero(dst, zeros);
+ memcpy(dst + zeros, str, length);
+ dst[aligned_length]= '\0';
+ to->str= dst;
+ to->length= aligned_length;
+ }
+ else
+ {
+ to->str= str;
+ to->length= length;
+ }
+ return check_string_for_wellformedness(to->str, to->length, cs);
+}
+
+
+/*
Convert a string between two character sets.
dstcs and srccs cannot be &my_charset_bin.
*/
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 2c43d1a229d..311b47aea61 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -3717,6 +3717,8 @@ public:
bool convert_string(LEX_STRING *to, CHARSET_INFO *to_cs,
const char *from, size_t from_length,
CHARSET_INFO *from_cs);
+ bool reinterpret_string_from_binary(LEX_CSTRING *to, CHARSET_INFO *to_cs,
+ const char *from, size_t from_length);
bool convert_string(LEX_CSTRING *to, CHARSET_INFO *to_cs,
const char *from, size_t from_length,
CHARSET_INFO *from_cs)
@@ -3733,6 +3735,8 @@ public:
{
if (!simple_copy_is_possible)
return unlikely(convert_string(to, tocs, from->str, from->length, fromcs));
+ if (fromcs == &my_charset_bin)
+ return reinterpret_string_from_binary(to, tocs, from->str, from->length);
*to= *from;
return false;
}