Commit bd5c45dc authored by unknown's avatar unknown

Fix for LP BUG#676411 and MySQL BUG#52317

This is a backport of the fix for
MySQL BUG#52317: Assertion failing in Field_varstring::store () at field.cc:6833

The orginal comment by Oystein is:

In order for EXPLAIN to print const-refs, a Store_key_const_item object
is created. This is different for normal execution of subqueries where
a temporary store_key_item object is used instead. The problem is that
EXPLAIN will execute subqueries.  This leads to a scenario where a
store_key_const_item object it told to write to its underlying field.
This results in a failing assert since the write set of the underlying
table does not reflect this.  

The resolution is to do the same trick as for store_key_item::copy_inner().
That is, temporarily change the write set to allow writes to all columns.
This is only necessary in debug version since non-debug version does not
contain asserts on write_set.

sql/sql_select.h:
  Temporarily change write_set in store_key_const_item::copy_inner() to
  allow initialization of underlying field.  This is necessary since 
  subqueries are executed for EXPLAIN.  (For normal execution, 
  store_key_item::copy_inner is used.)
parent b1c6dc6e
...@@ -436,3 +436,18 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -436,3 +436,18 @@ id select_type table type possible_keys key key_len ref rows Extra
SELECT * FROM t4 LEFT JOIN t2 ON t4.c1 WHERE 's' IN (SELECT c1 FROM t2); SELECT * FROM t4 LEFT JOIN t2 ON t4.c1 WHERE 's' IN (SELECT c1 FROM t2);
c1 c1 c1 c1
drop table t1, t2, t3, t4; drop table t1, t2, t3, t4;
#
# BUG#52317: Assertion failing in Field_varstring::store()
# at field.cc:6833
#
CREATE TABLE t1 (i INTEGER);
INSERT INTO t1 VALUES (1);
CREATE TABLE t2 (i INTEGER, KEY k(i));
INSERT INTO t2 VALUES (1), (2);
EXPLAIN
SELECT i FROM t1 WHERE (1) NOT IN (SELECT i FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
2 DEPENDENT SUBQUERY t2 index_subquery k k 5 const 2 Using index
DROP TABLE t2;
DROP TABLE t1;
...@@ -396,3 +396,19 @@ EXPLAIN ...@@ -396,3 +396,19 @@ EXPLAIN
SELECT * FROM t4 LEFT JOIN t2 ON t4.c1 WHERE 's' IN (SELECT c1 FROM t2); SELECT * FROM t4 LEFT JOIN t2 ON t4.c1 WHERE 's' IN (SELECT c1 FROM t2);
SELECT * FROM t4 LEFT JOIN t2 ON t4.c1 WHERE 's' IN (SELECT c1 FROM t2); SELECT * FROM t4 LEFT JOIN t2 ON t4.c1 WHERE 's' IN (SELECT c1 FROM t2);
drop table t1, t2, t3, t4; drop table t1, t2, t3, t4;
--echo #
--echo # BUG#52317: Assertion failing in Field_varstring::store()
--echo # at field.cc:6833
--echo #
CREATE TABLE t1 (i INTEGER);
INSERT INTO t1 VALUES (1);
CREATE TABLE t2 (i INTEGER, KEY k(i));
INSERT INTO t2 VALUES (1), (2);
EXPLAIN
SELECT i FROM t1 WHERE (1) NOT IN (SELECT i FROM t2);
DROP TABLE t2;
DROP TABLE t1;
...@@ -1990,6 +1990,9 @@ class store_key_const_item :public store_key_item ...@@ -1990,6 +1990,9 @@ class store_key_const_item :public store_key_item
if (!inited) if (!inited)
{ {
inited=1; inited=1;
TABLE *table= to_field->table;
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table,
table->write_set);
if ((res= item->save_in_field(to_field, 1))) if ((res= item->save_in_field(to_field, 1)))
{ {
if (!err) if (!err)
...@@ -2001,6 +2004,7 @@ class store_key_const_item :public store_key_item ...@@ -2001,6 +2004,7 @@ class store_key_const_item :public store_key_item
*/ */
if (!err && to_field->table->in_use->is_error()) if (!err && to_field->table->in_use->is_error())
err= 1; /* STORE_KEY_FATAL */ err= 1; /* STORE_KEY_FATAL */
dbug_tmp_restore_column_map(table->write_set, old_map);
} }
null_key= to_field->is_null() || item->null_value; null_key= to_field->is_null() || item->null_value;
return (err > 2 ? STORE_KEY_FATAL : (store_key_result) err); return (err > 2 ? STORE_KEY_FATAL : (store_key_result) err);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment