mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 04:22:27 +01: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:
parent
a73a57554a
commit
6e668b4f5b
3 changed files with 59 additions and 7 deletions
|
@ -1691,4 +1691,18 @@ ERROR 42000: Identifier name 'очень_очень_очень_очень_оче
|
|||
drop view имя_вью_кодировке_утф8_длиной_больше_чем_42;
|
||||
drop table имя_таблицы_в_кодировке_утф8_длиной_больше_чем_48;
|
||||
set names default;
|
||||
drop table if exists t1,t2,t3;
|
||||
drop function if exists f1;
|
||||
create function f1() returns int
|
||||
begin
|
||||
declare res int;
|
||||
create temporary table t3 select 1 i;
|
||||
set res:= (select count(*) from t1);
|
||||
drop temporary table t3;
|
||||
return res;
|
||||
end|
|
||||
create table t1 as select 1;
|
||||
create table t2 as select f1() from t1;
|
||||
drop table t1,t2;
|
||||
drop function f1;
|
||||
End of 5.1 tests
|
||||
|
|
|
@ -1303,4 +1303,29 @@ return 0;
|
|||
drop view имя_вью_кодировке_утф8_длиной_больше_чем_42;
|
||||
drop table имя_таблицы_в_кодировке_утф8_длиной_больше_чем_48;
|
||||
set names default;
|
||||
|
||||
#
|
||||
# Bug#21136 CREATE TABLE SELECT within CREATE TABLE SELECT causes server crash
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t1,t2,t3;
|
||||
drop function if exists f1;
|
||||
--enable_warnings
|
||||
|
||||
--delimiter |
|
||||
create function f1() returns int
|
||||
begin
|
||||
declare res int;
|
||||
create temporary table t3 select 1 i;
|
||||
set res:= (select count(*) from t1);
|
||||
drop temporary table t3;
|
||||
return res;
|
||||
end|
|
||||
--delimiter ;
|
||||
create table t1 as select 1;
|
||||
create table t2 as select f1() from t1;
|
||||
drop table t1,t2;
|
||||
drop function f1;
|
||||
|
||||
--echo End of 5.1 tests
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue