diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result index c1af92c5f8d..dd61396e485 100644 --- a/mysql-test/r/cast.result +++ b/mysql-test/r/cast.result @@ -439,3 +439,16 @@ HOUR(NULL) MINUTE(NULL) SECOND(NULL) NULL NULL NULL DROP TABLE t1; End of 5.0 tests +# +# Bug #44766: valgrind error when using convert() in a subquery +# +CREATE TABLE t1(a tinyint); +INSERT INTO t1 VALUES (127); +SELECT 1 FROM +( +SELECT CONVERT(t2.a USING UTF8) FROM t1, t1 t2 LIMIT 1 +) AS s LIMIT 1; +1 +1 +DROP TABLE t1; +End of 5.1 tests diff --git a/mysql-test/r/func_concat.result b/mysql-test/r/func_concat.result index 7e7c163716e..75b4888fbb2 100644 --- a/mysql-test/r/func_concat.result +++ b/mysql-test/r/func_concat.result @@ -89,3 +89,34 @@ c1 c2 First DROP TABLE t1; # End of 5.0 tests +# +# Bug #44743: Join in combination with concat does not always work +# +CREATE TABLE t1 ( +a VARCHAR(100) NOT NULL DEFAULT '0', +b VARCHAR(2) NOT NULL DEFAULT '', +c VARCHAR(2) NOT NULL DEFAULT '', +d TEXT NOT NULL, +PRIMARY KEY (a, b, c), +KEY (a) +) DEFAULT CHARSET=utf8; +INSERT INTO t1 VALUES ('gui_A', 'a', 'b', 'str1'), +('gui_AB', 'a', 'b', 'str2'), ('gui_ABC', 'a', 'b', 'str3'); +CREATE TABLE t2 ( +a VARCHAR(100) NOT NULL DEFAULT '', +PRIMARY KEY (a) +) DEFAULT CHARSET=latin1; +INSERT INTO t2 VALUES ('A'), ('AB'), ('ABC'); +SELECT CONCAT('gui_', t2.a), t1.d FROM t2 +LEFT JOIN t1 ON t1.a = CONCAT('gui_', t2.a) AND t1.b = 'a' AND t1.c = 'b'; +CONCAT('gui_', t2.a) d +gui_A str1 +gui_AB str2 +gui_ABC str3 +EXPLAIN SELECT CONCAT('gui_', t2.a), t1.d FROM t2 +LEFT JOIN t1 ON t1.a = CONCAT('gui_', t2.a) AND t1.b = 'a' AND t1.c = 'b'; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t2 index NULL PRIMARY 102 NULL 3 Using index +1 SIMPLE t1 eq_ref PRIMARY,a PRIMARY 318 func,const,const 1 +DROP TABLE t1, t2; +# End of 5.1 tests diff --git a/mysql-test/t/cast.test b/mysql-test/t/cast.test index 50865215944..8e60d548c2f 100644 --- a/mysql-test/t/cast.test +++ b/mysql-test/t/cast.test @@ -269,3 +269,18 @@ SELECT HOUR(NULL), DROP TABLE t1; --echo End of 5.0 tests + +--echo # +--echo # Bug #44766: valgrind error when using convert() in a subquery +--echo # + +CREATE TABLE t1(a tinyint); +INSERT INTO t1 VALUES (127); +SELECT 1 FROM +( + SELECT CONVERT(t2.a USING UTF8) FROM t1, t1 t2 LIMIT 1 +) AS s LIMIT 1; +DROP TABLE t1; + + +--echo End of 5.1 tests diff --git a/mysql-test/t/func_concat.test b/mysql-test/t/func_concat.test index f2aa0d004e5..1c7e5823fb2 100644 --- a/mysql-test/t/func_concat.test +++ b/mysql-test/t/func_concat.test @@ -78,3 +78,37 @@ SELECT * FROM t1 WHERE CONCAT(c1,' ',c2) REGEXP 'First.*'; DROP TABLE t1; --echo # End of 5.0 tests + + +--echo # +--echo # Bug #44743: Join in combination with concat does not always work +--echo # +CREATE TABLE t1 ( + a VARCHAR(100) NOT NULL DEFAULT '0', + b VARCHAR(2) NOT NULL DEFAULT '', + c VARCHAR(2) NOT NULL DEFAULT '', + d TEXT NOT NULL, + PRIMARY KEY (a, b, c), + KEY (a) +) DEFAULT CHARSET=utf8; + +INSERT INTO t1 VALUES ('gui_A', 'a', 'b', 'str1'), + ('gui_AB', 'a', 'b', 'str2'), ('gui_ABC', 'a', 'b', 'str3'); + +CREATE TABLE t2 ( + a VARCHAR(100) NOT NULL DEFAULT '', + PRIMARY KEY (a) +) DEFAULT CHARSET=latin1; + +INSERT INTO t2 VALUES ('A'), ('AB'), ('ABC'); + +SELECT CONCAT('gui_', t2.a), t1.d FROM t2 + LEFT JOIN t1 ON t1.a = CONCAT('gui_', t2.a) AND t1.b = 'a' AND t1.c = 'b'; + +EXPLAIN SELECT CONCAT('gui_', t2.a), t1.d FROM t2 + LEFT JOIN t1 ON t1.a = CONCAT('gui_', t2.a) AND t1.b = 'a' AND t1.c = 'b'; + +DROP TABLE t1, t2; + + +--echo # End of 5.1 tests diff --git a/sql/item.cc b/sql/item.cc index 8a8c3610198..62c8bfa3043 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -4873,7 +4873,10 @@ int Item_null::save_safe_in_field(Field *field) /* This implementation can lose str_value content, so if the Item uses str_value to store something, it should - reimplement it's ::save_in_field() as Item_string, for example, does + reimplement it's ::save_in_field() as Item_string, for example, does. + + Note: all Item_XXX::val_str(str) methods must NOT rely on the fact that + str != str_value. For example, see fix for bug #44743. */ int Item::save_in_field(Field *field, bool no_conversions) diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 501b7e85080..a3140b4db64 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2706,8 +2706,15 @@ String *Item_func_conv_charset::val_str(String *str) DBUG_ASSERT(fixed == 1); if (use_cached_value) return null_value ? 0 : &str_value; - String *arg= args[0]->val_str(str); + /* + Here we don't pass 'str' as a parameter to args[0]->val_str() + as 'str' may points to 'str_value' (e.g. see Item::save_in_field()), + which we use below to convert string. + Use argument's 'str_value' instead. + */ + String *arg= args[0]->val_str(&args[0]->str_value);; uint dummy_errors; + arg= args[0]->val_str(&args[0]->str_value); if (!arg) { null_value=1; diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 1dd7b55d136..61731f3b984 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -328,6 +328,9 @@ bool String::copy(const char *str, uint32 arg_length, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs, uint *errors) { uint32 offset; + + DBUG_ASSERT(str != Ptr); + if (!needs_conversion(arg_length, from_cs, to_cs, &offset)) { *errors= 0;