diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index d5a0c320d60..a86eabc3192 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -412,3 +412,18 @@ MIN(i) 1 DROP TABLE t1; # End of 5.0 tests +# +# Bug#58730 Assertion failed: table->key_read == 0 in close_thread_table, +# temptable views +# +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (b INT, KEY (b)); +INSERT INTO t1 VALUES (1),(1); +INSERT INTO t2 VALUES (1),(1); +CREATE algorithm=temptable VIEW v1 AS +SELECT 1 FROM t1 LEFT JOIN t1 t3 ON 1 > (SELECT 1 FROM t1); +CREATE algorithm=temptable VIEW v2 AS SELECT 1 FROM t2; +EXPLAIN SELECT 1 FROM t1 JOIN v1 ON 1 > (SELECT 1 FROM v2); +ERROR 21000: Subquery returns more than 1 row +DROP TABLE t1, t2; +DROP VIEW v1, v2; diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index 939d370cc78..9711482c639 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -313,3 +313,25 @@ WHERE j = SUBSTRING('12', (SELECT * FROM (SELECT MIN(j) FROM t1) t2))) t3; DROP TABLE t1; --echo # End of 5.0 tests + + +--echo # +--echo # Bug#58730 Assertion failed: table->key_read == 0 in close_thread_table, +--echo # temptable views +--echo # + +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (b INT, KEY (b)); +INSERT INTO t1 VALUES (1),(1); +INSERT INTO t2 VALUES (1),(1); + +CREATE algorithm=temptable VIEW v1 AS + SELECT 1 FROM t1 LEFT JOIN t1 t3 ON 1 > (SELECT 1 FROM t1); +CREATE algorithm=temptable VIEW v2 AS SELECT 1 FROM t2; + +# This caused the assert to be triggered. +--error ER_SUBQUERY_NO_1_ROW +EXPLAIN SELECT 1 FROM t1 JOIN v1 ON 1 > (SELECT 1 FROM v2); + +DROP TABLE t1, t2; +DROP VIEW v1, v2; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 60c32a1a376..82302d9da30 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5408,11 +5408,19 @@ bool open_and_lock_tables(THD *thd, TABLE_LIST *tables, if (lock_tables(thd, tables, counter, flags)) goto err; - if (derived && - (mysql_handle_derived(thd->lex, &mysql_derived_prepare) || - (thd->fill_derived_tables() && - mysql_handle_derived(thd->lex, &mysql_derived_filling)))) - goto err; + if (derived) + { + if (mysql_handle_derived(thd->lex, &mysql_derived_prepare)) + goto err; + if (thd->fill_derived_tables() && + mysql_handle_derived(thd->lex, &mysql_derived_filling)) + { + mysql_handle_derived(thd->lex, &mysql_derived_cleanup); + goto err; + } + if (!thd->lex->describe) + mysql_handle_derived(thd->lex, &mysql_derived_cleanup); + } DBUG_RETURN(FALSE); err: diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 4a7b3e98935..9b1b9353a23 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -307,13 +307,21 @@ bool mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list) */ if (derived_result->flush()) res= TRUE; - - if (!lex->describe) - unit->cleanup(); } - else - unit->cleanup(); lex->current_select= save_current_select; } return res; } + + +/** + Cleans up the SELECT_LEX_UNIT for the derived table (if any). +*/ + +bool mysql_derived_cleanup(THD *thd, LEX *lex, TABLE_LIST *derived) +{ + SELECT_LEX_UNIT *unit= derived->derived; + if (unit) + unit->cleanup(); + return false; +} diff --git a/sql/sql_derived.h b/sql/sql_derived.h index 0d4eddedf22..11a6fd4105e 100644 --- a/sql/sql_derived.h +++ b/sql/sql_derived.h @@ -26,4 +26,16 @@ bool mysql_handle_derived(LEX *lex, bool (*processor)(THD *thd, bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *t); bool mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *t); +/** + Cleans up the SELECT_LEX_UNIT for the derived table (if any). + + @param thd Thread handler + @param lex LEX for this thread + @param derived TABLE_LIST for the derived table + + @retval false Success + @retval true Failure +*/ +bool mysql_derived_cleanup(THD *thd, LEX *lex, TABLE_LIST *derived); + #endif /* SQL_DERIVED_INCLUDED */ diff --git a/sql/sql_update.cc b/sql/sql_update.cc index b49ed2beafe..082c603bb5a 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -296,11 +296,17 @@ int mysql_update(THD *thd, if (lock_tables(thd, table_list, table_count, 0)) DBUG_RETURN(1); - if (mysql_handle_derived(thd->lex, &mysql_derived_prepare) || - (thd->fill_derived_tables() && - mysql_handle_derived(thd->lex, &mysql_derived_filling))) + if (mysql_handle_derived(thd->lex, &mysql_derived_prepare)) DBUG_RETURN(1); + if (thd->fill_derived_tables() && + mysql_handle_derived(thd->lex, &mysql_derived_filling)) + { + mysql_handle_derived(thd->lex, &mysql_derived_cleanup); + DBUG_RETURN(1); + } + mysql_handle_derived(thd->lex, &mysql_derived_cleanup); + thd_proc_info(thd, "init"); table= table_list->table; @@ -1194,7 +1200,11 @@ int mysql_multi_update_prepare(THD *thd) if (thd->fill_derived_tables() && mysql_handle_derived(lex, &mysql_derived_filling)) + { + mysql_handle_derived(lex, &mysql_derived_cleanup); DBUG_RETURN(TRUE); + } + mysql_handle_derived(lex, &mysql_derived_cleanup); DBUG_RETURN (FALSE); }