Below is the list of changes that have just been committed into a local
5.1 repository of davi. When davi does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-09-11 01:29:33-03:00, davi@stripped +3 -0
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 reference if the
table being created/locked is a temporary table.
mysql-test/r/create.result@stripped, 2007-09-11 01:29:28-03:00, davi@stripped +14 -0
Add test case result for Bug#21136
mysql-test/t/create.test@stripped, 2007-09-11 01:29:29-03:00, davi@stripped +25 -0
Add test case for Bug#21136
sql/sql_insert.cc@stripped, 2007-09-11 01:29:29-03:00, davi@stripped +14 -6
Only update the extra_lock reference when the table being created is not
temporary. Altought locking is not necessary for temporary tables, it's
valid in this context because it implicitly starts a transaction (making
rollback possible even after a "create table if exists").
diff -Nrup a/mysql-test/r/create.result b/mysql-test/r/create.result
--- a/mysql-test/r/create.result 2007-07-25 21:28:07 -03:00
+++ b/mysql-test/r/create.result 2007-09-11 01:29:28 -03:00
@@ -1699,4 +1699,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
diff -Nrup a/mysql-test/t/create.test b/mysql-test/t/create.test
--- a/mysql-test/t/create.test 2007-07-25 21:23:29 -03:00
+++ b/mysql-test/t/create.test 2007-09-11 01:29:29 -03:00
@@ -1300,4 +1300,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
diff -Nrup a/sql/sql_insert.cc b/sql/sql_insert.cc
--- a/sql/sql_insert.cc 2007-09-10 06:42:13 -03:00
+++ b/sql/sql_insert.cc 2007-09-11 01:29:29 -03:00
@@ -3265,7 +3265,7 @@ static TABLE *create_table_from_items(TH
TABLE_LIST *create_table,
Alter_info *alter_info,
List<Item> *items,
- MYSQL_LOCK **lock,
+ MYSQL_LOCK **extra_lock,
TABLEOP_HOOKS *hooks)
{
TABLE tmp_table; // Used during 'Create_field()'
@@ -3277,6 +3277,7 @@ static TABLE *create_table_from_items(TH
Item *item;
Field *tmp_field;
bool not_used;
+ MYSQL_LOCK *lock;
DBUG_ENTER("create_table_from_items");
DBUG_EXECUTE_IF("sleep_create_select_before_check_if_exists", my_sleep(6000000););
@@ -3406,20 +3407,27 @@ static TABLE *create_table_from_items(TH
table->reginfo.lock_type=TL_WRITE;
hooks->prelock(&table, 1); // Call prelock hooks
- if (! ((*lock)= mysql_lock_tables(thd, &table, 1,
- MYSQL_LOCK_IGNORE_FLUSH, ¬_used)) ||
+ if (! (lock= mysql_lock_tables(thd, &table, 1,
+ MYSQL_LOCK_IGNORE_FLUSH, ¬_used)) ||
hooks->postlock(&table, 1))
{
- if (*lock)
+ if (lock)
{
- mysql_unlock_tables(thd, *lock);
- *lock= 0;
+ mysql_unlock_tables(thd, lock);
+ if (! (create_info->options & HA_LEX_CREATE_TMP_TABLE))
+ *extra_lock= 0;
}
if (!create_info->table_existed)
drop_open_table(thd, table, create_table->db, create_table->table_name);
DBUG_RETURN(0);
}
+
+ if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
+ mysql_unlock_tables(thd, lock);
+ else
+ *extra_lock= lock;
+
DBUG_RETURN(table);
}