Commit ae079ec4 authored by davi@moksha.local's avatar davi@moksha.local

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.
parent 2a70d6fa
...@@ -1691,4 +1691,18 @@ ERROR 42000: Identifier name 'очень_очень_очень_очень_оче ...@@ -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; ...@@ -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, ...@@ -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) ...@@ -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() ...@@ -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() ...@@ -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)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment