From: Alexander Barkov Date: March 1 2011 12:21pm Subject: bzr commit into mysql-trunk branch (alexander.barkov:3713) List-Archive: http://lists.mysql.com/commits/132195 Message-Id: <201103011221.p21CL4Ox021389@bar.myoffice.izhnet.ru> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit #At file:///home/bar/mysql-bzr/mysql-trunk/ based on revid:magne.mahre@stripped 3713 Alexander Barkov 2011-03-01 [merge] Merging from mysql-5.5 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 === modified file 'mysql-test/r/ctype_utf16.result' --- a/mysql-test/r/ctype_utf16.result 2010-12-16 18:50:46 +0000 +++ b/mysql-test/r/ctype_utf16.result 2011-03-01 12:20:38 +0000 @@ -1109,6 +1109,21 @@ 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-12-14 13:26:35 +0000 +++ b/mysql-test/r/ctype_utf32.result 2011-03-01 12:20:38 +0000 @@ -1173,6 +1173,21 @@ 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:29:26 +0000 +++ b/mysql-test/t/ctype_utf16.test 2011-03-01 12:20:38 +0000 @@ -746,6 +746,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:30:47 +0000 +++ b/mysql-test/t/ctype_utf32.test 2011-03-01 12:20:38 +0000 @@ -842,6 +842,16 @@ 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-21 10:36:31 +0000 +++ b/sql/item_cmpfunc.cc 2011-03-01 12:20:38 +0000 @@ -3140,20 +3140,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))) No bundle (reason: revision is a merge (you can force generation of a bundle with env var BZR_FORCE_BUNDLE=1)).