Commit 81de7247 authored by Anurag Shekhar's avatar Anurag Shekhar

Bug #39918 memory (heap) engine crashing with b-tree index and DELETE

         with seg fault

Multiple-table DELETE from a table joined to itself may cause
server crash. This was originally discovered with MEMORY engine,
but may affect other engines with different symptoms.

The problem was that the server violated SE API by performing
parallel table scan in one handler and removing records in
another (delete on the fly optimization).
parent 480fac61
...@@ -336,4 +336,11 @@ a b ...@@ -336,4 +336,11 @@ a b
NULL NULL NULL NULL
NULL 1 NULL 1
drop table t1; drop table t1;
#
# bug#39918 - memory (heap) engine crashing while executing self join with delete
#
CREATE TABLE t1(a INT, KEY USING BTREE (a)) ENGINE=MEMORY;
INSERT INTO t1 VALUES(1),(1);
DELETE a1 FROM t1 AS a1, t1 AS a2 WHERE a1.a=a2.a;
DROP TABLE t1;
End of 5.0 tests End of 5.0 tests
...@@ -253,5 +253,13 @@ insert into t1 values (1, 1), (3, 3), (2, 2), (NULL, 1), (NULL, NULL), (0, 0); ...@@ -253,5 +253,13 @@ insert into t1 values (1, 1), (3, 3), (2, 2), (NULL, 1), (NULL, NULL), (0, 0);
select * from t1 where a is null; select * from t1 where a is null;
drop table t1; drop table t1;
-- echo #
-- echo # bug#39918 - memory (heap) engine crashing while executing self join with delete
-- echo #
CREATE TABLE t1(a INT, KEY USING BTREE (a)) ENGINE=MEMORY;
INSERT INTO t1 VALUES(1),(1);
DELETE a1 FROM t1 AS a1, t1 AS a2 WHERE a1.a=a2.a;
DROP TABLE t1;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -503,6 +503,11 @@ int mysql_multi_delete_prepare(THD *thd) ...@@ -503,6 +503,11 @@ int mysql_multi_delete_prepare(THD *thd)
} }
} }
} }
/*
Reset the exclude flag to false so it doesn't interfare
with further calls to unique_table
*/
lex->select_lex.exclude_from_table_unique_test= FALSE;
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
...@@ -538,11 +543,24 @@ multi_delete::initialize_tables(JOIN *join) ...@@ -538,11 +543,24 @@ multi_delete::initialize_tables(JOIN *join)
DBUG_RETURN(1); DBUG_RETURN(1);
table_map tables_to_delete_from=0; table_map tables_to_delete_from=0;
delete_while_scanning= 1;
for (walk= delete_tables; walk; walk= walk->next_local) for (walk= delete_tables; walk; walk= walk->next_local)
{
tables_to_delete_from|= walk->table->map; tables_to_delete_from|= walk->table->map;
if (delete_while_scanning &&
unique_table(thd, walk, join->tables_list, false))
{
/*
If the table we are going to delete from appears
in join, we need to defer delete. So the delete
doesn't interfers with the scaning of results.
*/
delete_while_scanning= 0;
}
}
walk= delete_tables; walk= delete_tables;
delete_while_scanning= 1;
for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables; for (JOIN_TAB *tab=join->join_tab, *end=join->join_tab+join->tables;
tab < end; tab < end;
tab++) tab++)
......
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