diff options
author | Nirbhay Choubey <nirbhay@mariadb.com> | 2016-06-10 16:58:08 -0400 |
---|---|---|
committer | Nirbhay Choubey <nirbhay@mariadb.com> | 2016-06-10 18:39:43 -0400 |
commit | e2087c6e8da5d22cea2fb5a05408f48b1a3e5b35 (patch) | |
tree | 906c32bcd4e02edde054e08c4d5e020bbae27852 /sql/sql_insert.cc | |
parent | 7305be2f7e724e5e62961606794beab199d79045 (diff) | |
download | mariadb-git-e2087c6e8da5d22cea2fb5a05408f48b1a3e5b35.tar.gz |
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.
Diffstat (limited to 'sql/sql_insert.cc')
-rw-r--r-- | sql/sql_insert.cc | 39 |
1 files changed, 39 insertions, 0 deletions
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<Item> &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; |