1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Bug#21136 CREATE TABLE SELECT within CREATE TABLE SELECT causes server crash

When CREATE TEMPORARY TABLE .. SELECT is invoked from a stored function
which in turn is called from CREATE TABLE SELECT causes a memory leak
because the inner create temporary table overrides the outter extra_lock
reference when locking the table.

The solution is to simply not overrride the extra_lock by only using the
extra_lock for a non-temporary table lock.


mysql-test/r/create.result:
  Add test case result for Bug#21136
mysql-test/t/create.test:
  Add test case for Bug#21136
sql/sql_insert.cc:
  For temporary tables, store the lock data within the select_create class
  since tmp tables contents are not replicated. For "real" tables, store
  the lock data in the thread extra_lock pointer.
This commit is contained in:
unknown
2007-09-28 18:25:47 -03:00
parent a73a57554a
commit 6e668b4f5b
3 changed files with 59 additions and 7 deletions

View File

@@ -3427,6 +3427,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
int
select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
{
MYSQL_LOCK *extra_lock= NULL;
DBUG_ENTER("select_create::prepare");
TABLEOP_HOOKS *hook_ptr= NULL;
@@ -3496,9 +3497,21 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
if (!(table= create_table_from_items(thd, create_info, create_table,
alter_info, &values,
&thd->extra_lock, hook_ptr)))
&extra_lock, hook_ptr)))
DBUG_RETURN(-1); // abort() deletes table
if (extra_lock)
{
DBUG_ASSERT(m_plock == NULL);
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
m_plock= &m_lock;
else
m_plock= &thd->extra_lock;
*m_plock= extra_lock;
}
if (table->s->fields < values.elements)
{
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1);
@@ -3637,10 +3650,10 @@ bool select_create::send_eof()
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
if (thd->extra_lock)
if (m_plock)
{
mysql_unlock_tables(thd, thd->extra_lock);
thd->extra_lock=0;
mysql_unlock_tables(thd, *m_plock);
m_plock= 0;
}
}
return tmp;
@@ -3675,10 +3688,10 @@ void select_create::abort()
if (thd->current_stmt_binlog_row_based)
ha_rollback_stmt(thd);
if (thd->extra_lock)
if (m_plock)
{
mysql_unlock_tables(thd, thd->extra_lock);
thd->extra_lock=0;
mysql_unlock_tables(thd, *m_plock);
m_plock= 0;
}
if (table)