From: Alexander Barkov Date: March 1 2011 12:02pm Subject: bzr commit into mysql-5.5 branch (alexander.barkov:3358) Bug#44793 Bug#11753363 List-Archive: http://lists.mysql.com/commits/132191 X-Bug: 44793,11753363 Message-Id: <201103011202.p21C2R0s003916@bar.myoffice.izhnet.ru> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============3777180567376081203==" --===============3777180567376081203== 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:serge.kozlov@stripped 3358 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:01: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:01: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:01: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:01: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:01: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:01: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)) --===============3777180567376081203== 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\ # qrfmk05eyj0jl9q8 # target_branch: file:///home/bar/mysql-bzr/mysql-5.5.b44793/ # testament_sha1: 09cc0affc59fc193dbe63626e4775027b09694d4 # timestamp: 2011-03-01 15:02:27 +0300 # base_revision_id: serge.kozlov@stripped\ # rrpsfqau637hhd3y # # Begin bundle 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 --===============3777180567376081203==--