diff options
-rw-r--r-- | mysql-test/r/lock_multi.result | 18 | ||||
-rw-r--r-- | mysql-test/t/lock_multi.test | 201 | ||||
-rw-r--r-- | sql/sql_union.cc | 1 | ||||
-rw-r--r-- | sql/sql_update.cc | 20 |
4 files changed, 239 insertions, 1 deletions
diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result index 088f09801e9..a0e3d9fad06 100644 --- a/mysql-test/r/lock_multi.result +++ b/mysql-test/r/lock_multi.result @@ -112,6 +112,24 @@ CREATE TABLE t3 SELECT * FROM t1; # normal mode # PS mode DROP TABLE t1, t2, t3; +CREATE TABLE t1( a INT, b INT ); +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4); +# 1. test regular tables +# 1.1. test altering of columns that multiupdate doesn't use +# 1.1.1. normal mode +# 1.1.2. PS mode +# 1.2. test altering of columns that multiupdate uses +# 1.2.1. normal mode +# 1.2.2. PS mode +ALTER TABLE t1 ADD COLUMN a INT; +# 2. test UNIONs +# 2.1. test altering of columns that multiupdate doesn't use +# 2.1.1. normal mode +# 2.1.2. PS mode +# 2.2. test altering of columns that multiupdate uses +# 2.2.1. normal mode +# 2.2.2. PS mode +DROP TABLE t1; End of 5.0 tests create table t1 (i int); lock table t1 read; diff --git a/mysql-test/t/lock_multi.test b/mysql-test/t/lock_multi.test index 1ab7ef6721f..08747b0f92e 100644 --- a/mysql-test/t/lock_multi.test +++ b/mysql-test/t/lock_multi.test @@ -412,6 +412,207 @@ while ($i) { DROP TABLE t1, t2, t3; # +# Bug#38499: flush tables and multitable table update with derived table cause +# crash +# + +CREATE TABLE t1( a INT, b INT ); +INSERT INTO t1 VALUES (1, 1), (2, 2), (3, 3), (4, 4); + +--echo # 1. test regular tables +--echo # 1.1. test altering of columns that multiupdate doesn't use +--echo # 1.1.1. normal mode + +--disable_query_log +let $i = 100; +while ($i) { +--dec $i + +--connection writer + send UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0; + +--connection locker + ALTER TABLE t1 ADD COLUMN (c INT); + ALTER TABLE t1 DROP COLUMN c; + +--connection writer +--reap +} + +--echo # 1.1.2. PS mode + +--connection writer +PREPARE stmt FROM 'UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0'; + +let $i = 100; +while ($i) { +--dec $i + +--connection writer +--send EXECUTE stmt + +--connection locker + ALTER TABLE t1 ADD COLUMN (c INT); + ALTER TABLE t1 DROP COLUMN c; + +--connection writer +--reap +} +--enable_query_log + +--echo # 1.2. test altering of columns that multiupdate uses +--echo # 1.2.1. normal mode + +--connection default + +--disable_query_log +let $i = 100; +while ($i) { + dec $i; + +--connection locker +--error 0,1060 + ALTER TABLE t1 ADD COLUMN a int(11) unsigned default NULL; + UPDATE t1 SET a=b; + +--connection writer +--send UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0; + +--connection locker +--error 0,1091 + ALTER TABLE t1 DROP COLUMN a; + +--connection writer +--error 0,1054 # unknown column error +--reap +} +--enable_query_log + +--echo # 1.2.2. PS mode + +--disable_query_log +let $i = 100; +while ($i) { + dec $i; + +--connection locker +--error 0,1060 + ALTER TABLE t1 ADD COLUMN a INT; + UPDATE t1 SET a=b; + +--connection writer + PREPARE stmt FROM 'UPDATE t1, (SELECT 1 FROM t1 t1i) d SET a = 0 WHERE 1=0'; +--send EXECUTE stmt + +--connection locker +--error 0,1091 + ALTER TABLE t1 DROP COLUMN a; + +--connection writer +--error 0,1054 # Unknown column 'a' in 'field list' +--reap +} +--enable_query_log +--connection default +ALTER TABLE t1 ADD COLUMN a INT; + +--echo # 2. test UNIONs +--echo # 2.1. test altering of columns that multiupdate doesn't use +--echo # 2.1.1. normal mode + +--disable_query_log +let $i = 100; +while ($i) { +--dec $i + +--connection writer + send UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0; + +--connection locker + ALTER TABLE t1 ADD COLUMN (c INT); + ALTER TABLE t1 DROP COLUMN c; + +--connection writer +--reap +} + +--echo # 2.1.2. PS mode + +--connection writer +PREPARE stmt FROM 'UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0'; + +let $i = 100; +while ($i) { +--dec $i + +--connection writer +--send EXECUTE stmt + +--connection locker + ALTER TABLE t1 ADD COLUMN (c INT); + ALTER TABLE t1 DROP COLUMN c; + +--connection writer +--reap +} +--enable_query_log + +--echo # 2.2. test altering of columns that multiupdate uses +--echo # 2.2.1. normal mode + +--connection default + +--disable_query_log +let $i = 100; +while ($i) { + dec $i; + +--connection locker +--error 0,1060 + ALTER TABLE t1 ADD COLUMN a int(11) unsigned default NULL; + UPDATE t1 SET a=b; + +--connection writer +--send UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0; + +--connection locker +--error 0,1091 + ALTER TABLE t1 DROP COLUMN a; + +--connection writer +--error 0,1054 # Unknown column 'a' in 'field list' +--reap +} +--enable_query_log + +--echo # 2.2.2. PS mode + +--disable_query_log +let $i = 100; +while ($i) { + dec $i; + +--connection locker +--error 0,1060 + ALTER TABLE t1 ADD COLUMN a INT; + UPDATE t1 SET a=b; + +--connection writer + PREPARE stmt FROM 'UPDATE t1, ((SELECT 1 FROM t1 t1i) UNION (SELECT 2 FROM t1 t1ii)) e SET a = 0 WHERE 1=0'; +--send EXECUTE stmt + +--connection locker +--error 0,1091 + ALTER TABLE t1 DROP COLUMN a; + +--connection writer +--error 0,1054 # Unknown column 'a' in 'field list' +--reap +} +--enable_query_log +--connection default +DROP TABLE t1; + --echo End of 5.0 tests diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 5f7e3c5b620..2f3282f58f6 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -399,7 +399,6 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result, } else { - DBUG_ASSERT(!thd->stmt_arena->is_conventional()); /* We're in execution of a prepared statement or stored procedure: reset field items to point at fields from the created temporary table. diff --git a/sql/sql_update.cc b/sql/sql_update.cc index bfc69618c2b..197e5290aba 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1100,6 +1100,26 @@ reopen_tables: tbl->cleanup_items(); /* + To not to hog memory (as a result of the + unit->reinit_exec_mechanism() call below): + */ + lex->unit.cleanup(); + + for (SELECT_LEX *sl= lex->all_selects_list; + sl; + sl= sl->next_select_in_list()) + { + SELECT_LEX_UNIT *unit= sl->master_unit(); + unit->reinit_exec_mechanism(); // reset unit->prepared flags + /* + Reset 'clean' flag back to force normal execution of + unit->cleanup() in Prepared_statement::cleanup_stmt() + (call to lex->unit.cleanup() above sets this flag to TRUE). + */ + unit->unclean(); + } + + /* Also we need to cleanup Natural_join_column::table_field items. To not to traverse a join tree we will cleanup whole thd->free_list (in PS execution mode that list may not contain |