From e2087c6e8da5d22cea2fb5a05408f48b1a3e5b35 Mon Sep 17 00:00:00 2001 From: Nirbhay Choubey Date: Fri, 10 Jun 2016 16:58:08 -0400 Subject: MDEV-5535: Cannot reopen temporary table Temporary table being created by outer statement should not be visible to inner statement. And if inner statement creates a table with same name. The whole statement should fail with ER_TABLE_EXISTS_ERROR. Implemented by temporarily de-linking the TABLE_SHARE being created by outer statement so that it remains hidden to the inner statement. --- sql/sql_insert.cc | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'sql/sql_insert.cc') diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 13ff5a74b0b..e3f26ccf377 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -4226,6 +4226,18 @@ select_create::prepare(List &values, SELECT_LEX_UNIT *u) /* abort() deletes table */ DBUG_RETURN(-1); + if (create_info->tmp_table()) + { + /* + When the temporary table was created & opened in create_table_impl(), + the table's TABLE_SHARE (and thus TABLE) object was also linked to THD + temporary tables lists. So, we must temporarily remove it from the + list to keep them inaccessible from inner statements. + e.g. CREATE TEMPORARY TABLE `t1` AS SELECT * FROM `t1`; + */ + saved_tmp_table_share= thd->save_tmp_table_share(create_table->table); + } + if (extra_lock) { DBUG_ASSERT(m_plock == NULL); @@ -4341,6 +4353,27 @@ bool select_create::send_eof() DBUG_RETURN(true); } + if (table->s->tmp_table) + { + /* + Now is good time to add the new table to THD temporary tables list. + But, before that we need to check if same table got created by the sub- + statement. + */ + if (thd->find_tmp_table_share(table->s->table_cache_key.str, + table->s->table_cache_key.length)) + { + my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table->alias.c_ptr()); + abort_result_set(); + DBUG_RETURN(true); + } + else + { + DBUG_ASSERT(saved_tmp_table_share); + thd->restore_tmp_table_share(saved_tmp_table_share); + } + } + /* Do an implicit commit at end of statement for non-temporary tables. This can fail, but we should unlock the table @@ -4466,6 +4499,12 @@ void select_create::abort_result_set() { bool tmp_table= table->s->tmp_table; + if (tmp_table) + { + DBUG_ASSERT(saved_tmp_table_share); + thd->restore_tmp_table_share(saved_tmp_table_share); + } + table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE); table->auto_increment_field_not_null= FALSE; -- cgit v1.2.1