mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +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.
This commit is contained in:
@ -1691,4 +1691,18 @@ ERROR 42000: Identifier name 'очень_очень_очень_очень_оче
|
|||||||
drop view имя_вью_кодировке_утф8_длиной_больше_чем_42;
|
drop view имя_вью_кодировке_утф8_длиной_больше_чем_42;
|
||||||
drop table имя_таблицы_в_кодировке_утф8_длиной_больше_чем_48;
|
drop table имя_таблицы_в_кодировке_утф8_длиной_больше_чем_48;
|
||||||
set names default;
|
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
|
End of 5.1 tests
|
||||||
|
@ -1303,4 +1303,29 @@ return 0;
|
|||||||
drop view имя_вью_кодировке_утф8_длиной_больше_чем_42;
|
drop view имя_вью_кодировке_утф8_длиной_больше_чем_42;
|
||||||
drop table имя_таблицы_в_кодировке_утф8_длиной_больше_чем_48;
|
drop table имя_таблицы_в_кодировке_утф8_длиной_больше_чем_48;
|
||||||
set names default;
|
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
|
--echo End of 5.1 tests
|
||||||
|
@ -3427,6 +3427,7 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
|||||||
int
|
int
|
||||||
select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||||
{
|
{
|
||||||
|
MYSQL_LOCK *extra_lock= NULL;
|
||||||
DBUG_ENTER("select_create::prepare");
|
DBUG_ENTER("select_create::prepare");
|
||||||
|
|
||||||
TABLEOP_HOOKS *hook_ptr= NULL;
|
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,
|
if (!(table= create_table_from_items(thd, create_info, create_table,
|
||||||
alter_info, &values,
|
alter_info, &values,
|
||||||
&thd->extra_lock, hook_ptr)))
|
&extra_lock, hook_ptr)))
|
||||||
DBUG_RETURN(-1); // abort() deletes table
|
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)
|
if (table->s->fields < values.elements)
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1);
|
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_NO_IGNORE_DUP_KEY);
|
||||||
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
|
table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
|
||||||
if (thd->extra_lock)
|
if (m_plock)
|
||||||
{
|
{
|
||||||
mysql_unlock_tables(thd, thd->extra_lock);
|
mysql_unlock_tables(thd, *m_plock);
|
||||||
thd->extra_lock=0;
|
m_plock= 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tmp;
|
return tmp;
|
||||||
@ -3675,10 +3688,10 @@ void select_create::abort()
|
|||||||
if (thd->current_stmt_binlog_row_based)
|
if (thd->current_stmt_binlog_row_based)
|
||||||
ha_rollback_stmt(thd);
|
ha_rollback_stmt(thd);
|
||||||
|
|
||||||
if (thd->extra_lock)
|
if (m_plock)
|
||||||
{
|
{
|
||||||
mysql_unlock_tables(thd, thd->extra_lock);
|
mysql_unlock_tables(thd, *m_plock);
|
||||||
thd->extra_lock=0;
|
m_plock= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (table)
|
if (table)
|
||||||
|
Reference in New Issue
Block a user