summaryrefslogtreecommitdiff
path: root/sql/sql_insert.cc
diff options
context:
space:
mode:
authorNirbhay Choubey <nirbhay@mariadb.com>2016-06-10 16:58:08 -0400
committerNirbhay Choubey <nirbhay@mariadb.com>2016-06-10 18:39:43 -0400
commite2087c6e8da5d22cea2fb5a05408f48b1a3e5b35 (patch)
tree906c32bcd4e02edde054e08c4d5e020bbae27852 /sql/sql_insert.cc
parent7305be2f7e724e5e62961606794beab199d79045 (diff)
downloadmariadb-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.cc39
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;