From: Alexander Barkov Date: March 1 2011 12:10pm Subject: bzr commit into mysql-5.5 branch (alexander.barkov:3360) Bug#44793 Bug#11753363 List-Archive: http://lists.mysql.com/commits/132192 X-Bug: 44793,11753363 Message-Id: <201103011210.p21CAGXn009777@bar.myoffice.izhnet.ru> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============3109057074837294893==" --===============3109057074837294893== MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Content-Disposition: inline #At file:///home/bar/mysql-bzr/mysql-5.5.b44793/ based on revid:magne.mahre@stripped 3360 Alexander Barkov 2011-03-01 Bug#11753363 (bug#44793) CHARACTER SETS: CASE CLAUSE, UCS2 OR UTF32, FAILURE Problem: in case of string CASE/WHEN arguments with different character sets, Item_func_case::find_item() called comparator cmp_items[x] on mixed character set Items, so a 8-bit value could be errouneously referenced to as being utf16/utf32 value, which led to crash on DBUG_ASSERT() because of wrong value length. This was wrong, as string comparator expects arguments in the same character set. Fix: modify Item_func_case's argument list after calling agg_arg_charsets_for_comparison() - put the Items in "agg" array back to "args", because some of the Items in the "agg" array might have been changed to character set converters: - to Item_func_conv_charset for non-constant items - to Item_string for constant items In other words, perform the same substitution which is done in all other operations string comparison or string result operations: Replace CASE latin1_item WHEN utf16_item THEN ... END to CASE CONVERT(latin1_item USING utf16) WHEN utf16_item THEN ... END Replace CASE utf16_item WHEN latin1_item THEN ... END to CASE utf16_item WHEN CONVERT(latin1_item USING utf16) THEN ... END @ mysql-test/r/ctype_utf16.result @ mysql-test/r/ctype_utf32.result @ mysql-test/t/ctype_utf16.test @ mysql-test/t/ctype_utf32.test Adding tests @ sql/item_cmpfunc.cc Put "agg" back to "args". @ sql/sql_string.cc Backporting a fix for String::set_or_copy_aligned() from 5.6, for better test coverage: "SELECT _utf16 0x61" should expand the string to 0x0061 rather than to 0x000061. This fix was made in 5.6 under terms of "WL#4616 Implement UTF16-LE". modified: mysql-test/r/ctype_utf16.result mysql-test/r/ctype_utf32.result mysql-test/t/ctype_utf16.test mysql-test/t/ctype_utf32.test sql/item_cmpfunc.cc sql/sql_string.cc === modified file 'mysql-test/r/ctype_utf16.result' --- a/mysql-test/r/ctype_utf16.result 2010-11-24 14:52:57 +0000 +++ b/mysql-test/r/ctype_utf16.result 2011-03-01 12:09:37 +0000 @@ -30,13 +30,13 @@ binary 'a a' > 'a' binary 'a \0' > 'a' 1 1 1 select hex(_utf16 0x44); hex(_utf16 0x44) -00000044 +0044 select hex(_utf16 0x3344); hex(_utf16 0x3344) 3344 select hex(_utf16 0x113344); hex(_utf16 0x113344) -000000113344 +00113344 CREATE TABLE t1 (word VARCHAR(64), word2 CHAR(64)) CHARACTER SET utf16; INSERT INTO t1 VALUES (_koi8r 0xF2, _koi8r 0xF2), (X'2004',X'2004'); SELECT hex(word) FROM t1 ORDER BY word; @@ -434,10 +434,10 @@ aardvarz DROP TABLE t1; SELECT hex(cast(0xAA as char character set utf16)); hex(cast(0xAA as char character set utf16)) -000000AA +00AA SELECT hex(convert(0xAA using utf16)); hex(convert(0xAA using utf16)) -000000AA +00AA CREATE TABLE t1 (a char(10) character set utf16); INSERT INTO t1 VALUES (0x1),(0x11),(0x111),(0x1111),(0x11111); SELECT HEX(a) FROM t1; @@ -1102,5 +1102,20 @@ t2 CREATE TABLE `t2` ( ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1, t2; # +# Bug#11753363 (Bug#44793) Character sets: case clause, ucs2 or utf32, failure +# +SELECT CASE _latin1'a' WHEN _utf16'a' THEN 'A' END; +CASE _latin1'a' WHEN _utf16'a' THEN 'A' END +A +SELECT CASE _utf16'a' WHEN _latin1'a' THEN 'A' END; +CASE _utf16'a' WHEN _latin1'a' THEN 'A' END +A +CREATE TABLE t1 (s1 CHAR(5) CHARACTER SET utf16); +INSERT INTO t1 VALUES ('a'); +SELECT CASE s1 WHEN 'a' THEN 'b' ELSE 'c' END FROM t1; +CASE s1 WHEN 'a' THEN 'b' ELSE 'c' END +b +DROP TABLE t1; +# # End of 5.5 tests # === modified file 'mysql-test/r/ctype_utf32.result' --- a/mysql-test/r/ctype_utf32.result 2010-09-28 15:15:58 +0000 +++ b/mysql-test/r/ctype_utf32.result 2011-03-01 12:09:37 +0000 @@ -1152,5 +1152,20 @@ d f DROP TABLE t1; # +# Bug#11753363 (Bug#44793) Character sets: case clause, ucs2 or utf32, failure +# +SELECT CASE _latin1'a' WHEN _utf32'a' THEN 'A' END; +CASE _latin1'a' WHEN _utf32'a' THEN 'A' END +A +SELECT CASE _utf32'a' WHEN _latin1'a' THEN 'A' END; +CASE _utf32'a' WHEN _latin1'a' THEN 'A' END +A +CREATE TABLE t1 (s1 CHAR(5) CHARACTER SET utf32); +INSERT INTO t1 VALUES ('a'); +SELECT CASE s1 WHEN 'a' THEN 'b' ELSE 'c' END FROM t1; +CASE s1 WHEN 'a' THEN 'b' ELSE 'c' END +b +DROP TABLE t1; +# # End of 5.5 tests # === modified file 'mysql-test/t/ctype_utf16.test' --- a/mysql-test/t/ctype_utf16.test 2010-09-28 15:15:58 +0000 +++ b/mysql-test/t/ctype_utf16.test 2011-03-01 12:09:37 +0000 @@ -745,6 +745,15 @@ CREATE TABLE t2 AS SELECT CONCAT(s1) FRO SHOW CREATE TABLE t2; DROP TABLE t1, t2; +--echo # +--echo # Bug#11753363 (Bug#44793) Character sets: case clause, ucs2 or utf32, failure +--echo # +SELECT CASE _latin1'a' WHEN _utf16'a' THEN 'A' END; +SELECT CASE _utf16'a' WHEN _latin1'a' THEN 'A' END; +CREATE TABLE t1 (s1 CHAR(5) CHARACTER SET utf16); +INSERT INTO t1 VALUES ('a'); +SELECT CASE s1 WHEN 'a' THEN 'b' ELSE 'c' END FROM t1; +DROP TABLE t1; # ## TODO: add tests for all engines === modified file 'mysql-test/t/ctype_utf32.test' --- a/mysql-test/t/ctype_utf32.test 2010-09-28 15:15:58 +0000 +++ b/mysql-test/t/ctype_utf32.test 2011-03-01 12:09:37 +0000 @@ -831,5 +831,15 @@ SELECT * FROM t1 WHERE b BETWEEN 'a' AND DROP TABLE t1; --echo # +--echo # Bug#11753363 (Bug#44793) Character sets: case clause, ucs2 or utf32, failure +--echo # +SELECT CASE _latin1'a' WHEN _utf32'a' THEN 'A' END; +SELECT CASE _utf32'a' WHEN _latin1'a' THEN 'A' END; +CREATE TABLE t1 (s1 CHAR(5) CHARACTER SET utf32); +INSERT INTO t1 VALUES ('a'); +SELECT CASE s1 WHEN 'a' THEN 'b' ELSE 'c' END FROM t1; +DROP TABLE t1; + +--echo # --echo # End of 5.5 tests --echo # === modified file 'sql/item_cmpfunc.cc' --- a/sql/item_cmpfunc.cc 2011-02-18 07:32:40 +0000 +++ b/sql/item_cmpfunc.cc 2011-03-01 12:09:37 +0000 @@ -3054,20 +3054,59 @@ void Item_func_case::fix_length_and_dec( agg[0]= args[first_expr_num]; left_result_type= agg[0]->result_type(); + /* + As the first expression and WHEN expressions + are intermixed in args[] array THEN and ELSE items, + extract the first expression and all WHEN expressions into + a temporary array, to process them easier. + */ for (nagg= 0; nagg < ncases/2 ; nagg++) agg[nagg+1]= args[nagg*2]; nagg++; if (!(found_types= collect_cmp_types(agg, nagg))) return; + if (found_types & (1 << STRING_RESULT)) + { + /* + If we'll do string comparison, we also need to aggregate + character set and collation for first/WHEN items and + install converters for some of them to cmp_collation when necessary. + This is done because cmp_item compatators cannot compare + strings in two different character sets. + Some examples when we install converters: + + 1. Converter installed for the first expression: + + CASE latin1_item WHEN utf16_item THEN ... END + + is replaced to: + + CASE CONVERT(latin1_item USING utf16) WHEN utf16_item THEN ... END + + 2. Converter installed for the left WHEN item: + CASE utf16_item WHEN latin1_item THEN ... END + + is replaced to: + + CASE utf16_item WHEN CONVERT(latin1_item USING utf16) THEN ... END + */ + if (agg_arg_charsets_for_comparison(cmp_collation, agg, nagg)) + return; + /* + Now copy first expression and all WHEN expressions back to args[] + arrray, because some of the items might have been changed to converters + (e.g. Item_func_conv_charset, or Item_string for constants). + */ + args[first_expr_num]= agg[0]; + for (nagg= 0; nagg < ncases / 2; nagg++) + args[nagg * 2]= agg[nagg + 1]; + } for (i= 0; i <= (uint)DECIMAL_RESULT; i++) { if (found_types & (1 << i) && !cmp_items[i]) { DBUG_ASSERT((Item_result)i != ROW_RESULT); - if ((Item_result)i == STRING_RESULT && - agg_arg_charsets_for_comparison(cmp_collation, agg, nagg)) - return; if (!(cmp_items[i]= cmp_item::get_comparator((Item_result)i, cmp_collation.collation))) === modified file 'sql/sql_string.cc' --- a/sql/sql_string.cc 2011-01-13 08:07:21 +0000 +++ b/sql/sql_string.cc 2011-03-01 12:09:37 +0000 @@ -252,8 +252,8 @@ bool String::copy_aligned(const char *st CHARSET_INFO *cs) { /* How many bytes are in incomplete character */ - offset= cs->mbmaxlen - offset; /* How many zeros we should prepend */ - DBUG_ASSERT(offset && offset != cs->mbmaxlen); + offset= cs->mbminlen - offset; /* How many zeros we should prepend */ + DBUG_ASSERT(offset && offset != cs->mbminlen); uint32 aligned_length= arg_length + offset; if (alloc(aligned_length)) --===============3109057074837294893== MIME-Version: 1.0 Content-Type: text/bzr-bundle; charset="us-ascii"; name="bzr/alexander.barkov@stripped" Content-Transfer-Encoding: 7bit Content-Disposition: inline # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: alexander.barkov@stripped\ # k4bscs7hb2diqa7k # target_branch: file:///home/bar/mysql-bzr/mysql-5.5.b44793/ # testament_sha1: ed0465fa826a39cfd1c641757b4710c42ceebb11 # timestamp: 2011-03-01 15:10:16 +0300 # base_revision_id: magne.mahre@stripped\ # k1tj8dfiyh1skdyt # # Begin bundle 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 --===============3109057074837294893==--