mirror of
https://github.com/MariaDB/server.git
synced 2025-08-29 00:08:14 +03:00
Bug#30882 Dropping a temporary table inside a stored function may cause a server crash
If a stored function that contains a drop temporary table statement is invoked by a create temporary table of the same name may cause a server crash. The problem is that when dropping a table no check is done to ensure that table is not being used by some outer query (or outer statement), potentially leaving the outer query with a reference to a stale (freed) table. The solution is when dropping a temporary table, always check if the table is being used by some outer statement as a temporary table can be dropped inside stored procedures. The check is performed by looking at the TABLE::query_id value for temporary tables. To simplify this check and to solve a bug related to handling of temporary tables in prelocked mode, this patch changes the way in which this member is used to track the fact that table is used/unused. Now we ensure that TABLE::query_id is zero for unused temporary tables (which means that all temporary tables which were used by a statement should be marked as free for reuse after it's execution has been completed).
This commit is contained in:
@@ -566,3 +566,35 @@ reap;
|
||||
connection default;
|
||||
drop table t2;
|
||||
disconnect flush;
|
||||
|
||||
#
|
||||
# Bug#30882 Dropping a temporary table inside a stored function may cause a server crash
|
||||
#
|
||||
# Test HANDLER statements in conjunction with temporary tables. While the temporary table
|
||||
# is open by a HANDLER, no other statement can access it.
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t1;
|
||||
--enable_warnings
|
||||
create temporary table t1 (a int, b char(1), key a(a), key b(a,b));
|
||||
insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"),
|
||||
(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j");
|
||||
select a,b from t1;
|
||||
handler t1 open as a1;
|
||||
handler a1 read a first;
|
||||
handler a1 read a next;
|
||||
handler a1 read a next;
|
||||
--error ER_CANT_REOPEN_TABLE
|
||||
select a,b from t1;
|
||||
handler a1 read a prev;
|
||||
handler a1 read a prev;
|
||||
handler a1 read a=(6) where b="g";
|
||||
handler a1 close;
|
||||
select a,b from t1;
|
||||
handler t1 open as a2;
|
||||
handler a2 read a first;
|
||||
handler a2 read a last;
|
||||
handler a2 read a prev;
|
||||
handler a2 close;
|
||||
drop table t1;
|
||||
|
@@ -575,3 +575,65 @@ ERROR 42S02: Table 'test.t1' doesn't exist
|
||||
handler t1 close;
|
||||
handler t2 close;
|
||||
drop table t2;
|
||||
drop table if exists t1;
|
||||
create temporary table t1 (a int, b char(1), key a(a), key b(a,b));
|
||||
insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"),
|
||||
(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j");
|
||||
select a,b from t1;
|
||||
a b
|
||||
0 a
|
||||
1 b
|
||||
2 c
|
||||
3 d
|
||||
4 e
|
||||
5 f
|
||||
6 g
|
||||
7 h
|
||||
8 i
|
||||
9 j
|
||||
handler t1 open as a1;
|
||||
handler a1 read a first;
|
||||
a b
|
||||
0 a
|
||||
handler a1 read a next;
|
||||
a b
|
||||
1 b
|
||||
handler a1 read a next;
|
||||
a b
|
||||
2 c
|
||||
select a,b from t1;
|
||||
ERROR HY000: Can't reopen table: 'a1'
|
||||
handler a1 read a prev;
|
||||
a b
|
||||
1 b
|
||||
handler a1 read a prev;
|
||||
a b
|
||||
0 a
|
||||
handler a1 read a=(6) where b="g";
|
||||
a b
|
||||
6 g
|
||||
handler a1 close;
|
||||
select a,b from t1;
|
||||
a b
|
||||
0 a
|
||||
1 b
|
||||
2 c
|
||||
3 d
|
||||
4 e
|
||||
5 f
|
||||
6 g
|
||||
7 h
|
||||
8 i
|
||||
9 j
|
||||
handler t1 open as a2;
|
||||
handler a2 read a first;
|
||||
a b
|
||||
0 a
|
||||
handler a2 read a last;
|
||||
a b
|
||||
9 j
|
||||
handler a2 read a prev;
|
||||
a b
|
||||
8 i
|
||||
handler a2 close;
|
||||
drop table t1;
|
||||
|
@@ -575,3 +575,65 @@ ERROR 42S02: Table 'test.t1' doesn't exist
|
||||
handler t1 close;
|
||||
handler t2 close;
|
||||
drop table t2;
|
||||
drop table if exists t1;
|
||||
create temporary table t1 (a int, b char(1), key a(a), key b(a,b));
|
||||
insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"),
|
||||
(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j");
|
||||
select a,b from t1;
|
||||
a b
|
||||
0 a
|
||||
1 b
|
||||
2 c
|
||||
3 d
|
||||
4 e
|
||||
5 f
|
||||
6 g
|
||||
7 h
|
||||
8 i
|
||||
9 j
|
||||
handler t1 open as a1;
|
||||
handler a1 read a first;
|
||||
a b
|
||||
0 a
|
||||
handler a1 read a next;
|
||||
a b
|
||||
1 b
|
||||
handler a1 read a next;
|
||||
a b
|
||||
2 c
|
||||
select a,b from t1;
|
||||
ERROR HY000: Can't reopen table: 'a1'
|
||||
handler a1 read a prev;
|
||||
a b
|
||||
1 b
|
||||
handler a1 read a prev;
|
||||
a b
|
||||
0 a
|
||||
handler a1 read a=(6) where b="g";
|
||||
a b
|
||||
6 g
|
||||
handler a1 close;
|
||||
select a,b from t1;
|
||||
a b
|
||||
0 a
|
||||
1 b
|
||||
2 c
|
||||
3 d
|
||||
4 e
|
||||
5 f
|
||||
6 g
|
||||
7 h
|
||||
8 i
|
||||
9 j
|
||||
handler t1 open as a2;
|
||||
handler a2 read a first;
|
||||
a b
|
||||
0 a
|
||||
handler a2 read a last;
|
||||
a b
|
||||
9 j
|
||||
handler a2 read a prev;
|
||||
a b
|
||||
8 i
|
||||
handler a2 close;
|
||||
drop table t1;
|
||||
|
@@ -1428,7 +1428,6 @@ create function bug20701() returns varchar(25) binary return "test";
|
||||
ERROR 42000: This version of MySQL doesn't yet support 'return value collation'
|
||||
create function bug20701() returns varchar(25) return "test";
|
||||
drop function bug20701;
|
||||
End of 5.1 tests
|
||||
create procedure proc_26503_error_1()
|
||||
begin
|
||||
retry:
|
||||
@@ -1530,6 +1529,53 @@ return 1;
|
||||
end|
|
||||
ERROR HY000: Not allowed to set autocommit from a stored function or trigger
|
||||
create trigger t1
|
||||
before insert on t2 for each row set password = password('foo');
|
||||
delimiter ;|
|
||||
before insert on t2 for each row set password = password('foo');|
|
||||
ERROR HY000: Not allowed to set autocommit from a stored function or trigger
|
||||
drop function if exists f1;
|
||||
drop function if exists f2;
|
||||
drop table if exists t1, t2;
|
||||
create function f1() returns int
|
||||
begin
|
||||
drop temporary table t1;
|
||||
return 1;
|
||||
end|
|
||||
create temporary table t1 as select f1();
|
||||
ERROR HY000: Can't reopen table: 't1'
|
||||
create function f2() returns int
|
||||
begin
|
||||
create temporary table t2 as select f1();
|
||||
return 1;
|
||||
end|
|
||||
create temporary table t1 as select f2();
|
||||
ERROR HY000: Can't reopen table: 't1'
|
||||
drop function f1;
|
||||
drop function f2;
|
||||
create function f1() returns int
|
||||
begin
|
||||
drop temporary table t2,t1;
|
||||
return 1;
|
||||
end|
|
||||
create function f2() returns int
|
||||
begin
|
||||
create temporary table t2 as select f1();
|
||||
return 1;
|
||||
end|
|
||||
create temporary table t1 as select f2();
|
||||
ERROR HY000: Can't reopen table: 't2'
|
||||
drop function f1;
|
||||
drop function f2;
|
||||
create temporary table t2(a int);
|
||||
select * from t2;
|
||||
a
|
||||
create function f2() returns int
|
||||
begin
|
||||
drop temporary table t2;
|
||||
return 1;
|
||||
end|
|
||||
select f2();
|
||||
f2()
|
||||
1
|
||||
drop function f2;
|
||||
drop table t2;
|
||||
ERROR 42S02: Unknown table 't2'
|
||||
End of 5.1 tests
|
||||
|
@@ -2078,10 +2078,6 @@ create function bug20701() returns varchar(25) binary return "test";
|
||||
create function bug20701() returns varchar(25) return "test";
|
||||
drop function bug20701;
|
||||
|
||||
|
||||
--echo End of 5.1 tests
|
||||
|
||||
|
||||
#
|
||||
# Bug#26503 (Illegal SQL exception handler code causes the server to crash)
|
||||
#
|
||||
@@ -2237,10 +2233,78 @@ end|
|
||||
|
||||
--error ER_SP_CANT_SET_AUTOCOMMIT
|
||||
create trigger t1
|
||||
before insert on t2 for each row set password = password('foo');
|
||||
before insert on t2 for each row set password = password('foo');|
|
||||
|
||||
delimiter ;|
|
||||
|
||||
#
|
||||
# Bug#30882 Dropping a temporary table inside a stored function may cause a server crash
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
drop function if exists f1;
|
||||
drop function if exists f2;
|
||||
drop table if exists t1, t2;
|
||||
--enable_warnings
|
||||
|
||||
delimiter |;
|
||||
create function f1() returns int
|
||||
begin
|
||||
drop temporary table t1;
|
||||
return 1;
|
||||
end|
|
||||
delimiter ;|
|
||||
--error ER_CANT_REOPEN_TABLE
|
||||
create temporary table t1 as select f1();
|
||||
|
||||
delimiter |;
|
||||
create function f2() returns int
|
||||
begin
|
||||
create temporary table t2 as select f1();
|
||||
return 1;
|
||||
end|
|
||||
delimiter ;|
|
||||
--error ER_CANT_REOPEN_TABLE
|
||||
create temporary table t1 as select f2();
|
||||
|
||||
drop function f1;
|
||||
drop function f2;
|
||||
|
||||
delimiter |;
|
||||
create function f1() returns int
|
||||
begin
|
||||
drop temporary table t2,t1;
|
||||
return 1;
|
||||
end|
|
||||
create function f2() returns int
|
||||
begin
|
||||
create temporary table t2 as select f1();
|
||||
return 1;
|
||||
end|
|
||||
delimiter ;|
|
||||
--error ER_CANT_REOPEN_TABLE
|
||||
create temporary table t1 as select f2();
|
||||
|
||||
drop function f1;
|
||||
drop function f2;
|
||||
|
||||
create temporary table t2(a int);
|
||||
select * from t2;
|
||||
delimiter |;
|
||||
create function f2() returns int
|
||||
begin
|
||||
drop temporary table t2;
|
||||
return 1;
|
||||
end|
|
||||
delimiter ;|
|
||||
select f2();
|
||||
|
||||
drop function f2;
|
||||
--error ER_BAD_TABLE_ERROR
|
||||
drop table t2;
|
||||
|
||||
--echo End of 5.1 tests
|
||||
|
||||
#
|
||||
# BUG#NNNN: New bug synopsis
|
||||
#
|
||||
|
Reference in New Issue
Block a user