← Back to team overview

maria-developers team mailing list archive

5.5.44 Sprint: MDEV-8067 correct fix for MySQL Bug # 19699237: UNINITIALIZED VARIABLE IN ITEM_FIELD::STR_RESULT

 

Hi Sergei,

Please review my patch for MDEV-8067.

Some subselect_(mat|sj) test chanted "EXPLAIN" output.
Perhaps the new results are correct. Please advise.

Thanks.
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index b8ecc05..a964384 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -5762,5 +5762,20 @@ DROP TABLE t1;
 # End of ctype_utf8_ilseq.inc
 #
 #
+# MDEV-8067 correct fix for MySQL Bug # 19699237: UNINITIALIZED VARIABLE IN ITEM_FIELD::STR_RESULT
+#
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8);
+CREATE TABLE t2 (a VARCHAR(10) CHARACTER SET latin1);
+INSERT INTO t1 VALUES ('aaa');
+INSERT INTO t2 VALUES ('aaa');
+SELECT (SELECT CONCAT(a),1 FROM t1) <=> (SELECT CONCAT(a),1 FROM t2);
+(SELECT CONCAT(a),1 FROM t1) <=> (SELECT CONCAT(a),1 FROM t2)
+1
+INSERT INTO t1 VALUES ('aaa');
+INSERT INTO t2 VALUES ('aaa');
+SELECT (SELECT CONCAT(a),1 FROM t1) <=> (SELECT CONCAT(a),1 FROM t2);
+ERROR 21000: Subquery returns more than 1 row
+DROP TABLE t1, t2;
+#
 # End of 5.5 tests
 #
diff --git a/mysql-test/r/subselect_mat.result b/mysql-test/r/subselect_mat.result
index 7039bbf..4549504 100644
--- a/mysql-test/r/subselect_mat.result
+++ b/mysql-test/r/subselect_mat.result
@@ -2336,7 +2336,7 @@ EXPLAIN
 SELECT (SELECT f3a, f3b FROM t3) NOT IN (SELECT f1a, f1b FROM t1);
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
 1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No tables used
-3	SUBQUERY	t1	ALL	NULL	NULL	NULL	NULL	2	Using where
+3	DEPENDENT SUBQUERY	t1	ALL	NULL	NULL	NULL	NULL	2	Using where
 2	SUBQUERY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	no matching row in const table
 SELECT (SELECT f3a, f3b FROM t3) NOT IN (SELECT f1a, f1b FROM t1);
 (SELECT f3a, f3b FROM t3) NOT IN (SELECT f1a, f1b FROM t1)
diff --git a/mysql-test/r/subselect_sj2.result b/mysql-test/r/subselect_sj2.result
index 9a5da71..b94359e 100644
--- a/mysql-test/r/subselect_sj2.result
+++ b/mysql-test/r/subselect_sj2.result
@@ -1121,7 +1121,10 @@ INSERT INTO t2 VALUES (4),(5);
 explain
 SELECT * FROM t1 WHERE 9 IN ( SELECT b FROM t2 WHERE 1 IN ( SELECT MIN(c) FROM t3 ) );
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE
+1	PRIMARY	<subquery3>	system	NULL	NULL	NULL	NULL	1	
+1	PRIMARY	<subquery2>	eq_ref	distinct_key	distinct_key	4	func	1	
+1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	2	Using where; Using join buffer (flat, BNL join)
+2	MATERIALIZED	t2	ALL	NULL	NULL	NULL	NULL	4	Using where
 3	MATERIALIZED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No matching min/max row
 SELECT * FROM t1 WHERE 9 IN ( SELECT b FROM t2 WHERE 1 IN ( SELECT MIN(c) FROM t3 ) );
 a
diff --git a/mysql-test/r/subselect_sj2_jcl6.result b/mysql-test/r/subselect_sj2_jcl6.result
index c10b550..4d0d79f 100644
--- a/mysql-test/r/subselect_sj2_jcl6.result
+++ b/mysql-test/r/subselect_sj2_jcl6.result
@@ -1136,7 +1136,10 @@ INSERT INTO t2 VALUES (4),(5);
 explain
 SELECT * FROM t1 WHERE 9 IN ( SELECT b FROM t2 WHERE 1 IN ( SELECT MIN(c) FROM t3 ) );
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE
+1	PRIMARY	<subquery3>	system	NULL	NULL	NULL	NULL	1	
+1	PRIMARY	<subquery2>	eq_ref	distinct_key	distinct_key	4	func	1	
+1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	2	Using where; Using join buffer (flat, BNL join)
+2	MATERIALIZED	t2	ALL	NULL	NULL	NULL	NULL	4	Using where
 3	MATERIALIZED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No matching min/max row
 SELECT * FROM t1 WHERE 9 IN ( SELECT b FROM t2 WHERE 1 IN ( SELECT MIN(c) FROM t3 ) );
 a
diff --git a/mysql-test/r/subselect_sj2_mat.result b/mysql-test/r/subselect_sj2_mat.result
index 4e75aee..a5f0fa8 100644
--- a/mysql-test/r/subselect_sj2_mat.result
+++ b/mysql-test/r/subselect_sj2_mat.result
@@ -1123,7 +1123,10 @@ INSERT INTO t2 VALUES (4),(5);
 explain
 SELECT * FROM t1 WHERE 9 IN ( SELECT b FROM t2 WHERE 1 IN ( SELECT MIN(c) FROM t3 ) );
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
-1	PRIMARY	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE
+1	PRIMARY	<subquery3>	system	NULL	NULL	NULL	NULL	1	
+1	PRIMARY	<subquery2>	eq_ref	distinct_key	distinct_key	4	func	1	
+1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	2	Using where; Using join buffer (flat, BNL join)
+2	MATERIALIZED	t2	ALL	NULL	NULL	NULL	NULL	4	Using where
 3	MATERIALIZED	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No matching min/max row
 SELECT * FROM t1 WHERE 9 IN ( SELECT b FROM t2 WHERE 1 IN ( SELECT MIN(c) FROM t3 ) );
 a
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index f4b16c9..bed026a 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -1617,5 +1617,21 @@ SET NAMES utf8 COLLATE utf8_general_ci;
 --source include/ctype_utf8_ilseq.inc
 
 --echo #
+--echo # MDEV-8067 correct fix for MySQL Bug # 19699237: UNINITIALIZED VARIABLE IN ITEM_FIELD::STR_RESULT
+--echo #
+CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET utf8);
+CREATE TABLE t2 (a VARCHAR(10) CHARACTER SET latin1);
+INSERT INTO t1 VALUES ('aaa');
+INSERT INTO t2 VALUES ('aaa');
+SELECT (SELECT CONCAT(a),1 FROM t1) <=> (SELECT CONCAT(a),1 FROM t2);
+INSERT INTO t1 VALUES ('aaa');
+INSERT INTO t2 VALUES ('aaa');
+# Running the below query crashed with two rows
+--error ER_SUBQUERY_NO_1_ROW
+SELECT (SELECT CONCAT(a),1 FROM t1) <=> (SELECT CONCAT(a),1 FROM t2);
+DROP TABLE t1, t2;
+
+
+--echo #
 --echo # End of 5.5 tests
 --echo #
diff --git a/sql/item.cc b/sql/item.cc
index 87336dc..93feb0e 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1136,6 +1136,31 @@ Item *Item::safe_charset_converter(CHARSET_INFO *tocs)
 
 
 /**
+  Some Items do not support changing of Item_cache to other Item types.
+
+  Example:
+  Item_singlerow_subselect has "Item_cache **row".
+  THD::change_item_tree() should not change row[i] from Item_cache
+  directly to Item_func_conv_charset, because Item_singlerow_subselect
+  later calls Item_cache-specific methods, e.g. like row[i]->store() and
+  row[i]->cache_value().
+
+  Let's wrap Item_func_conv_charset to another Item_cache,
+  so the Item_cache-specific methods can be used for row[i] safely.
+*/
+Item *Item_cache::safe_charset_converter(CHARSET_INFO *tocs)
+{
+  Item_func_conv_charset *conv= new Item_func_conv_charset(example, tocs, 1);
+  if (!conv || !conv->safe)
+    return NULL; // Safe conversion is not possible, or OEM
+  Item_cache *cache= new Item_cache_str(conv);
+  cache->setup(conv);
+  cache->fixed= false; // Make Item::fix_fields() happy
+  return cache;
+}
+
+
+/**
   @details
   Created mostly for mysql_prepare_table(). Important
   when a string ENUM/SET column is described with a numeric default value:
diff --git a/sql/item.h b/sql/item.h
index ac4fa86..16e2ee2 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -4104,6 +4104,7 @@ class Item_cache: public Item_basic_constant
     unsigned_flag= item->unsigned_flag;
     if (item->type() == FIELD_ITEM)
       cached_field= ((Item_field *)item)->field;
+    used_table_map= item->used_tables();
     return 0;
   };
   enum Type type() const { return CACHE_ITEM; }
@@ -4161,6 +4162,7 @@ class Item_cache: public Item_basic_constant
       return TRUE;
     return (this->*processor)(arg);
   }
+  virtual Item *safe_charset_converter(CHARSET_INFO *tocs);
 };