From: Alexander Barkov Date: April 8 2011 1:17pm Subject: bzr commit into mysql-5.5 branch (alexander.barkov:3430) Bug#60625 Bug#11926811 List-Archive: http://lists.mysql.com/commits/135079 X-Bug: 60625,11926811 Message-Id: <201104081317.p38DHrfj003377@bar.myoffice.izhnet.ru> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="===============4660459588261070005==" --===============4660459588261070005== 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.b60625v2/ based on revid:alexander.nozdrin@stripped 3430 Alexander Barkov 2011-04-08 Bug#11926811 / Bug#60625 Illegal mix of collations Problem: comparison of a DATETIME sp variable and NOW() led to Illegal mix of collations error when character_set_connection=utf8. Introduced by "WL#2649 Number-to-string conversions". Error happened in Arg_comparator::set_compare_func(), because the first argument was errouneously converted to utf8, while the second argument was not. Fix: separate agg_arg_charsets_for_comparison() into two functions: - agg_arg_charsets_for_comparison() - for pure comparison, when we don't need to return any string result and therefore don't need to convert arguments to @@character_set_connection: SELECT a = b; - agg_arg_charsets_for_string_results_with_comparison() - when we need to return a string result, but we also need to do comparison internally: SELECT REPLACE(a,b,c) If all arguments are numbers: SELECT REPLACE(123,2,3) -> 133 we convert arguments to @@character_set_connection. @ mysql-test/include/ctype_numconv.inc @ mysql-test/r/ctype_binary.result @ mysql-test/r/ctype_cp1251.result @ mysql-test/r/ctype_latin1.result @ mysql-test/r/ctype_ucs.result @ mysql-test/r/ctype_utf8.result Adding tests @ sql/item.cc @ sql/item.h @ sql/item_func.cc @ sql/item_func.h @ sql/item_strfunc.cc Introducing and using new function agg_item_charsets_for_string_result_with_comparison() and its Item_func wrapper agg_arg_charsets_for_string_result_with_comparison(). modified: mysql-test/include/ctype_numconv.inc mysql-test/r/ctype_binary.result mysql-test/r/ctype_cp1251.result mysql-test/r/ctype_latin1.result mysql-test/r/ctype_ucs.result mysql-test/r/ctype_utf8.result sql/item.cc sql/item.h sql/item_func.cc sql/item_func.h sql/item_strfunc.cc === modified file 'mysql-test/include/ctype_numconv.inc' --- a/mysql-test/include/ctype_numconv.inc 2011-02-10 13:38:18 +0000 +++ b/mysql-test/include/ctype_numconv.inc 2011-04-08 13:15:23 +0000 @@ -1765,6 +1765,22 @@ SELECT HEX(DATE_SUB(DATE('2007-08-03'), INTERVAL 1 DAY)) AS field_date, HEX(DATE_SUB(CAST('2007-08-03 17:33:00' AS DATETIME), INTERVAL 1 MINUTE)) AS field_datetime; +--echo # +--echo # Bug#11926811 / Bug#60625 Illegal mix of collations +--echo # +SELECT @@collation_connection; +DELIMITER //; +CREATE PROCEDURE p1() +BEGIN + DECLARE v_LastPaymentDate DATETIME DEFAULT NULL; + SELECT v_LastPaymentDate < NOW(); + EXPLAIN EXTENDED SELECT v_LastPaymentDate < NOW(); + SHOW WARNINGS; + EXPLAIN EXTENDED SELECT CONCAT(v_LastPaymentDate, NOW()); +END// +DELIMITER ;// +CALL p1; +DROP PROCEDURE p1; --echo # --echo # Bug#52159 returning time type from function and empty left join causes debug assertion === modified file 'mysql-test/r/ctype_binary.result' --- a/mysql-test/r/ctype_binary.result 2011-02-10 08:18:08 +0000 +++ b/mysql-test/r/ctype_binary.result 2011-04-08 13:15:23 +0000 @@ -2807,6 +2807,32 @@ HEX(DATE_SUB(CAST('2007-08-03 17:33:00' field_str1 field1_str2 field_date field_datetime 323030372D30382D30322032333A35393A3030 323030372D30382D30332031373A33323A3030 323030372D30382D3032 323030372D30382D30332031373A33323A3030 # +# Bug#11926811 / Bug#60625 Illegal mix of collations +# +SELECT @@collation_connection; +@@collation_connection +binary +CREATE PROCEDURE p1() +BEGIN +DECLARE v_LastPaymentDate DATETIME DEFAULT NULL; +SELECT v_LastPaymentDate < NOW(); +EXPLAIN EXTENDED SELECT v_LastPaymentDate < NOW(); +SHOW WARNINGS; +EXPLAIN EXTENDED SELECT CONCAT(v_LastPaymentDate, NOW()); +END// +CALL p1; +v_LastPaymentDate < NOW() +NULL +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Level Code Message +Note 1003 select (v_LastPaymentDate@0 < now()) AS `v_LastPaymentDate < NOW()` +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select concat(v_LastPaymentDate@0,now()) AS `CONCAT(v_LastPaymentDate, NOW())` +DROP PROCEDURE p1; +# # Bug#52159 returning time type from function and empty left join causes debug assertion # CREATE FUNCTION f1() RETURNS TIME RETURN 1; === modified file 'mysql-test/r/ctype_cp1251.result' --- a/mysql-test/r/ctype_cp1251.result 2011-02-18 07:32:40 +0000 +++ b/mysql-test/r/ctype_cp1251.result 2011-04-08 13:15:23 +0000 @@ -3199,6 +3199,32 @@ HEX(DATE_SUB(CAST('2007-08-03 17:33:00' field_str1 field1_str2 field_date field_datetime 323030372D30382D30322032333A35393A3030 323030372D30382D30332031373A33323A3030 323030372D30382D3032 323030372D30382D30332031373A33323A3030 # +# Bug#11926811 / Bug#60625 Illegal mix of collations +# +SELECT @@collation_connection; +@@collation_connection +cp1251_general_ci +CREATE PROCEDURE p1() +BEGIN +DECLARE v_LastPaymentDate DATETIME DEFAULT NULL; +SELECT v_LastPaymentDate < NOW(); +EXPLAIN EXTENDED SELECT v_LastPaymentDate < NOW(); +SHOW WARNINGS; +EXPLAIN EXTENDED SELECT CONCAT(v_LastPaymentDate, NOW()); +END// +CALL p1; +v_LastPaymentDate < NOW() +NULL +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Level Code Message +Note 1003 select (v_LastPaymentDate@0 < now()) AS `v_LastPaymentDate < NOW()` +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select concat(convert(v_LastPaymentDate@0 using cp1251),now()) AS `CONCAT(v_LastPaymentDate, NOW())` +DROP PROCEDURE p1; +# # Bug#52159 returning time type from function and empty left join causes debug assertion # CREATE FUNCTION f1() RETURNS TIME RETURN 1; === modified file 'mysql-test/r/ctype_latin1.result' --- a/mysql-test/r/ctype_latin1.result 2011-03-04 15:43:28 +0000 +++ b/mysql-test/r/ctype_latin1.result 2011-04-08 13:15:23 +0000 @@ -3226,6 +3226,32 @@ HEX(DATE_SUB(CAST('2007-08-03 17:33:00' field_str1 field1_str2 field_date field_datetime 323030372D30382D30322032333A35393A3030 323030372D30382D30332031373A33323A3030 323030372D30382D3032 323030372D30382D30332031373A33323A3030 # +# Bug#11926811 / Bug#60625 Illegal mix of collations +# +SELECT @@collation_connection; +@@collation_connection +latin1_swedish_ci +CREATE PROCEDURE p1() +BEGIN +DECLARE v_LastPaymentDate DATETIME DEFAULT NULL; +SELECT v_LastPaymentDate < NOW(); +EXPLAIN EXTENDED SELECT v_LastPaymentDate < NOW(); +SHOW WARNINGS; +EXPLAIN EXTENDED SELECT CONCAT(v_LastPaymentDate, NOW()); +END// +CALL p1; +v_LastPaymentDate < NOW() +NULL +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Level Code Message +Note 1003 select (v_LastPaymentDate@0 < now()) AS `v_LastPaymentDate < NOW()` +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select concat(v_LastPaymentDate@0,now()) AS `CONCAT(v_LastPaymentDate, NOW())` +DROP PROCEDURE p1; +# # Bug#52159 returning time type from function and empty left join causes debug assertion # CREATE FUNCTION f1() RETURNS TIME RETURN 1; === modified file 'mysql-test/r/ctype_ucs.result' --- a/mysql-test/r/ctype_ucs.result 2011-03-03 15:46:30 +0000 +++ b/mysql-test/r/ctype_ucs.result 2011-04-08 13:15:23 +0000 @@ -4060,6 +4060,32 @@ HEX(DATE_SUB(CAST('2007-08-03 17:33:00' field_str1 field1_str2 field_date field_datetime 0032003000300037002D00300038002D00300032002000320033003A00350039003A00300030 0032003000300037002D00300038002D00300033002000310037003A00330032003A00300030 323030372D30382D3032 323030372D30382D30332031373A33323A3030 # +# Bug#11926811 / Bug#60625 Illegal mix of collations +# +SELECT @@collation_connection; +@@collation_connection +ucs2_general_ci +CREATE PROCEDURE p1() +BEGIN +DECLARE v_LastPaymentDate DATETIME DEFAULT NULL; +SELECT v_LastPaymentDate < NOW(); +EXPLAIN EXTENDED SELECT v_LastPaymentDate < NOW(); +SHOW WARNINGS; +EXPLAIN EXTENDED SELECT CONCAT(v_LastPaymentDate, NOW()); +END// +CALL p1; +v_LastPaymentDate < NOW() +NULL +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Level Code Message +Note 1003 select (v_LastPaymentDate@0 < now()) AS `v_LastPaymentDate < NOW()` +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select concat(convert(v_LastPaymentDate@0 using ucs2),convert(now() using ucs2)) AS `CONCAT(v_LastPaymentDate, NOW())` +DROP PROCEDURE p1; +# # Bug#52159 returning time type from function and empty left join causes debug assertion # CREATE FUNCTION f1() RETURNS TIME RETURN 1; === modified file 'mysql-test/r/ctype_utf8.result' --- a/mysql-test/r/ctype_utf8.result 2011-03-04 15:43:28 +0000 +++ b/mysql-test/r/ctype_utf8.result 2011-04-08 13:15:23 +0000 @@ -4938,6 +4938,32 @@ HEX(DATE_SUB(CAST('2007-08-03 17:33:00' field_str1 field1_str2 field_date field_datetime 323030372D30382D30322032333A35393A3030 323030372D30382D30332031373A33323A3030 323030372D30382D3032 323030372D30382D30332031373A33323A3030 # +# Bug#11926811 / Bug#60625 Illegal mix of collations +# +SELECT @@collation_connection; +@@collation_connection +utf8_general_ci +CREATE PROCEDURE p1() +BEGIN +DECLARE v_LastPaymentDate DATETIME DEFAULT NULL; +SELECT v_LastPaymentDate < NOW(); +EXPLAIN EXTENDED SELECT v_LastPaymentDate < NOW(); +SHOW WARNINGS; +EXPLAIN EXTENDED SELECT CONCAT(v_LastPaymentDate, NOW()); +END// +CALL p1; +v_LastPaymentDate < NOW() +NULL +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Level Code Message +Note 1003 select (v_LastPaymentDate@0 < now()) AS `v_LastPaymentDate < NOW()` +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL No tables used +Warnings: +Note 1003 select concat(convert(v_LastPaymentDate@0 using utf8),now()) AS `CONCAT(v_LastPaymentDate, NOW())` +DROP PROCEDURE p1; +# # Bug#52159 returning time type from function and empty left join causes debug assertion # CREATE FUNCTION f1() RETURNS TIME RETURN 1; === modified file 'sql/item.cc' --- a/sql/item.cc 2011-04-08 08:09:24 +0000 +++ b/sql/item.cc 2011-04-08 13:15:23 +0000 @@ -1746,7 +1746,8 @@ bool agg_item_collations(DTCollation &c, } /* If all arguments where numbers, reset to @@collation_connection */ - if (c.derivation == DERIVATION_NUMERIC) + if (flags & MY_COLL_ALLOW_NUMERIC_CONV && + c.derivation == DERIVATION_NUMERIC) c.set(Item::default_charset(), DERIVATION_COERCIBLE, MY_REPERTOIRE_NUMERIC); return FALSE; === modified file 'sql/item.h' --- a/sql/item.h 2011-04-08 08:09:24 +0000 +++ b/sql/item.h 2011-04-08 13:15:23 +0000 @@ -53,6 +53,8 @@ char_to_byte_length_safe(uint32 char_len (i.e. constant). MY_COLL_ALLOW_CONV - allow any kind of conversion (combination of the above two) + MY_COLL_ALLOW_NUMERIC_CONV - if all items were numbers, convert to + @@character_set_connection MY_COLL_DISALLOW_NONE - don't allow return DERIVATION_NONE (e.g. when aggregating for comparison) MY_COLL_CMP_CONV - combination of MY_COLL_ALLOW_CONV @@ -62,6 +64,7 @@ char_to_byte_length_safe(uint32 char_len #define MY_COLL_ALLOW_SUPERSET_CONV 1 #define MY_COLL_ALLOW_COERCIBLE_CONV 2 #define MY_COLL_DISALLOW_NONE 4 +#define MY_COLL_ALLOW_NUMERIC_CONV 8 #define MY_COLL_ALLOW_CONV (MY_COLL_ALLOW_SUPERSET_CONV | MY_COLL_ALLOW_COERCIBLE_CONV) #define MY_COLL_CMP_CONV (MY_COLL_ALLOW_CONV | MY_COLL_DISALLOW_NONE) @@ -1561,7 +1564,8 @@ agg_item_charsets_for_string_result(DTCo int item_sep= 1) { uint flags= MY_COLL_ALLOW_SUPERSET_CONV | - MY_COLL_ALLOW_COERCIBLE_CONV; + MY_COLL_ALLOW_COERCIBLE_CONV | + MY_COLL_ALLOW_NUMERIC_CONV; return agg_item_charsets(c, name, items, nitems, flags, item_sep); } inline bool @@ -1574,6 +1578,19 @@ agg_item_charsets_for_comparison(DTColla MY_COLL_DISALLOW_NONE; return agg_item_charsets(c, name, items, nitems, flags, item_sep); } +inline bool +agg_item_charsets_for_string_result_with_comparison(DTCollation &c, + const char *name, + Item **items, uint nitems, + int item_sep= 1) +{ + uint flags= MY_COLL_ALLOW_SUPERSET_CONV | + MY_COLL_ALLOW_COERCIBLE_CONV | + MY_COLL_ALLOW_NUMERIC_CONV | + MY_COLL_DISALLOW_NONE; + return agg_item_charsets(c, name, items, nitems, flags, item_sep); +} + class Item_num: public Item_basic_constant { === modified file 'sql/item_func.cc' --- a/sql/item_func.cc 2011-03-28 13:33:35 +0000 +++ b/sql/item_func.cc 2011-04-08 13:15:23 +0000 @@ -2537,7 +2537,8 @@ void Item_func_min_max::fix_length_and_d } if (cmp_type == STRING_RESULT) { - agg_arg_charsets_for_comparison(collation, args, arg_count); + agg_arg_charsets_for_string_result_with_comparison(collation, + args, arg_count); if (datetime_found) { thd= current_thd; === modified file 'sql/item_func.h' --- a/sql/item_func.h 2011-03-08 17:39:25 +0000 +++ b/sql/item_func.h 2011-04-08 13:15:23 +0000 @@ -165,6 +165,11 @@ public: { return agg_item_charsets(c, func_name(), items, nitems, flags, item_sep); } + /* + Aggregate arguments for string result, e.g: CONCAT(a,b) + - convert to @@character_set_connection if all arguments are numbers + - allow DERIVATION_NONE + */ bool agg_arg_charsets_for_string_result(DTCollation &c, Item **items, uint nitems, int item_sep= 1) @@ -172,6 +177,11 @@ public: return agg_item_charsets_for_string_result(c, func_name(), items, nitems, item_sep); } + /* + Aggregate arguments for comparison, e.g: a=b, a LIKE b, a RLIKE b + - don't convert to @@character_set_connection if all arguments are numbers + - don't allow DERIVATION_NONE + */ bool agg_arg_charsets_for_comparison(DTCollation &c, Item **items, uint nitems, int item_sep= 1) @@ -179,6 +189,21 @@ public: return agg_item_charsets_for_comparison(c, func_name(), items, nitems, item_sep); } + /* + Aggregate arguments for string result, when some comparison + is involved internally, e.g: REPLACE(a,b,c) + - convert to @@character_set_connection if all arguments are numbers + - disallow DERIVATION_NONE + */ + bool agg_arg_charsets_for_string_result_with_comparison(DTCollation &c, + Item **items, + uint nitems, + int item_sep= 1) + { + return agg_item_charsets_for_string_result_with_comparison(c, func_name(), + items, nitems, + item_sep); + } bool walk(Item_processor processor, bool walk_subquery, uchar *arg); Item *transform(Item_transformer transformer, uchar *arg); Item* compile(Item_analyzer analyzer, uchar **arg_p, === modified file 'sql/item_strfunc.cc' --- a/sql/item_strfunc.cc 2011-03-03 15:46:30 +0000 +++ b/sql/item_strfunc.cc 2011-04-08 13:15:23 +0000 @@ -1168,7 +1168,7 @@ void Item_func_replace::fix_length_and_d char_length+= max_substrs * (uint) diff; } - if (agg_arg_charsets_for_comparison(collation, args, 3)) + if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 3)) return; fix_char_length_ulonglong(char_length); } @@ -1458,7 +1458,7 @@ void Item_func_substr::fix_length_and_de void Item_func_substr_index::fix_length_and_dec() { - if (agg_arg_charsets_for_comparison(collation, args, 2)) + if (agg_arg_charsets_for_string_result_with_comparison(collation, args, 2)) return; fix_char_length(args[0]->max_char_length()); } @@ -1797,7 +1797,8 @@ void Item_func_trim::fix_length_and_dec( { // Handle character set for args[1] and args[0]. // Note that we pass args[1] as the first item, and args[0] as the second. - if (agg_arg_charsets_for_comparison(collation, &args[1], 2, -1)) + if (agg_arg_charsets_for_string_result_with_comparison(collation, + &args[1], 2, -1)) return; } fix_char_length(args[0]->max_char_length()); --===============4660459588261070005== 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\ # 1d7jq0ibki5rmcib # target_branch: file:///home/bar/mysql-bzr/mysql-5.5.b60625v2/ # testament_sha1: 23548e25dab7c6627efef91c94c72618ed07e1d5 # timestamp: 2011-04-08 17:17:52 +0400 # base_revision_id: alexander.nozdrin@stripped\ # ho3jrxz2r5nfinrj # # Begin bundle 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 lxx7ICI/+LuSKcKEhXSm7rg= --===============4660459588261070005==--