Below is the list of changes that have just been committed into a local
5.0 repository of kent. When kent 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
1.1970 05/11/28 10:26:48 kent@stripped +6 -0
Merge kboortz@stripped:/home/bk/mysql-5.0
into mysql.com:/Users/kent/mysql/bk/mysql-5.0
sql/sql_class.h
1.276 05/11/28 10:26:42 kent@stripped +0 -0
Auto merged
sql/sp_head.cc
1.199 05/11/28 10:26:42 kent@stripped +0 -0
Auto merged
mysys/my_open.c
1.25 05/11/28 10:26:41 kent@stripped +0 -0
Auto merged
mysql-test/t/sp.test
1.166 05/11/28 10:26:41 kent@stripped +0 -0
Auto merged
mysql-test/r/sp.result
1.173 05/11/28 10:26:41 kent@stripped +0 -31
Auto merged
include/my_global.h
1.113 05/11/28 10:26:40 kent@stripped +0 -0
Auto merged
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: kent
# Host: c-534072d5.010-2112-6f72651.cust.bredbandsbolaget.se
# Root: /Users/kent/mysql/bk/mysql-5.0/RESYNC
--- 1.24/mysys/my_open.c 2005-11-22 01:02:33 +01:00
+++ 1.25/mysys/my_open.c 2005-11-28 10:26:41 +01:00
@@ -267,7 +267,7 @@
*/
switch (oflag & (_O_CREAT | _O_EXCL | _O_TRUNC)) {
case 0:
- case _O_EXCL: // ignore EXCL w/o CREAT
+ case _O_EXCL: /* ignore EXCL w/o CREAT */
filecreate= OPEN_EXISTING;
break;
@@ -281,7 +281,7 @@
break;
case _O_TRUNC:
- case _O_TRUNC | _O_EXCL: // ignore EXCL w/o CREAT
+ case _O_TRUNC | _O_EXCL: /* ignore EXCL w/o CREAT */
filecreate= TRUNCATE_EXISTING;
break;
@@ -290,7 +290,7 @@
break;
default:
- // this can't happen ... all cases are covered
+ /* this can't happen ... all cases are covered */
errno= EINVAL;
_doserrno= 0L;
return -1;
--- 1.275/sql/sql_class.h 2005-11-22 01:02:34 +01:00
+++ 1.276/sql/sql_class.h 2005-11-28 10:26:42 +01:00
@@ -530,6 +530,7 @@
ulong completion_type;
/* Determines which non-standard SQL behaviour should be enabled */
ulong sql_mode;
+ ulong max_sp_recursion_depth;
/* check of key presence in updatable view */
ulong updatable_views_with_limit;
ulong default_week_format;
@@ -1229,14 +1230,16 @@
free_root(&mem_root,MYF(MY_KEEP_PREALLOC));
#endif
}
-#ifdef USING_TRANSACTIONS
st_transactions()
{
+#ifdef USING_TRANSACTIONS
bzero((char*)this, sizeof(*this));
xid_state.xid.null();
init_sql_alloc(&mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
- }
+#else
+ xid_state.xa_state= XA_NOTR;
#endif
+ }
} transaction;
Field *dupp_field;
#ifndef __WIN__
@@ -2085,6 +2088,13 @@
class my_var : public Sql_alloc {
public:
LEX_STRING s;
+#ifndef DBUG_OFF
+ /*
+ Routine to which this Item_splocal belongs. Used for checking if correct
+ runtime context is used for variable handling.
+ */
+ sp_head *owner;
+#endif
bool local;
uint offset;
enum_field_types type;
--- 1.112/include/my_global.h 2005-11-22 01:02:31 +01:00
+++ 1.113/include/my_global.h 2005-11-28 10:26:40 +01:00
@@ -574,11 +574,7 @@
#define FN_LEN 256 /* Max file name len */
#define FN_HEADLEN 253 /* Max length of filepart of file name */
#define FN_EXTLEN 20 /* Max length of extension (part of FN_LEN) */
-#ifdef PATH_MAX
-#define FN_REFLEN PATH_MAX/* Max length of full path-name */
-#else
#define FN_REFLEN 512 /* Max length of full path-name */
-#endif
#define FN_EXTCHAR '.'
#define FN_HOMELIB '~' /* ~/ is used as abbrev for home dir */
#define FN_CURLIB '.' /* ./ is used as abbrev for current dir */
--- 1.172/mysql-test/r/sp.result 2005-11-22 01:02:32 +01:00
+++ 1.173/mysql-test/r/sp.result 2005-11-28 10:26:41 +01:00
@@ -988,6 +988,10 @@
select f5(1)|
f5(1)
1
+select f5(2)|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
+select f5(3)|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
create function f6() returns int
begin
declare n int;
@@ -1035,6 +1039,12 @@
ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
create function f1() returns int
return (select sum(data) from t1) + (select sum(data) from v1)|
+select f1()|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
+select * from v1|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
+select * from v2|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
drop function f1|
create function f1() returns int
return (select sum(data) from t1)|
@@ -1053,7 +1063,7 @@
select *, f0() from v0|
f0() f0()
100 100
-lock tables t1 read, t1 as t11 read, mysql.proc read|
+lock tables t1 read, t1 as t11 read|
select f3()|
f3()
1
@@ -1251,6 +1261,62 @@
drop procedure ip|
show procedure status like '%p%'|
Db Name Type Definer Modified Created Security_type Comment
+drop table if exists fib|
+create table fib ( f bigint unsigned not null )|
+drop procedure if exists fib|
+create procedure fib(n int unsigned)
+begin
+if n > 1 then
+begin
+declare x, y bigint unsigned;
+declare c cursor for select f from fib order by f desc limit 2;
+open c;
+fetch c into y;
+fetch c into x;
+close c;
+insert into fib values (x+y);
+call fib(n-1);
+end;
+end if;
+end|
+set @@max_sp_recursion_depth= 20|
+insert into fib values (0), (1)|
+call fib(3)|
+select * from fib order by f asc|
+f
+0
+1
+1
+2
+delete from fib|
+insert into fib values (0), (1)|
+call fib(20)|
+select * from fib order by f asc|
+f
+0
+1
+1
+2
+3
+5
+8
+13
+21
+34
+55
+89
+144
+233
+377
+610
+987
+1597
+2584
+4181
+6765
+drop table fib|
+drop procedure fib|
+set @@max_sp_recursion_depth= 0|
drop procedure if exists bar|
create procedure bar(x char(16), y int)
comment "111111111111" sql security invoker
@@ -1479,6 +1545,52 @@
@x2
2
drop procedure bug2260|
+drop procedure if exists bug2267_1|
+create procedure bug2267_1()
+begin
+show procedure status;
+end|
+drop procedure if exists bug2267_2|
+create procedure bug2267_2()
+begin
+show function status;
+end|
+drop procedure if exists bug2267_3|
+create procedure bug2267_3()
+begin
+show create procedure bug2267_1;
+end|
+drop procedure if exists bug2267_4|
+drop function if exists bug2267_4|
+create procedure bug2267_4()
+begin
+show create function bug2267_4;
+end|
+create function bug2267_4() returns int return 100|
+call bug2267_1()|
+Db Name Type Definer Modified Created Security_type Comment
+test bug2267_1 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+test bug2267_2 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+test bug2267_3 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+test bug2267_4 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+call bug2267_2()|
+Db Name Type Definer Modified Created Security_type Comment
+test bug2267_4 FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
+call bug2267_3()|
+Procedure sql_mode Create Procedure
+bug2267_1 CREATE PROCEDURE `bug2267_1`()
+begin
+show procedure status;
+end
+call bug2267_4()|
+Function sql_mode Create Function
+bug2267_4 CREATE FUNCTION `bug2267_4`() RETURNS int(11)
+return 100
+drop procedure bug2267_1|
+drop procedure bug2267_2|
+drop procedure bug2267_3|
+drop procedure bug2267_4|
+drop function bug2267_4|
drop procedure if exists bug2227|
create procedure bug2227(x int)
begin
@@ -1490,6 +1602,18 @@
1.3 x y 42 z
1.3 9 2.6 42 zzz
drop procedure bug2227|
+drop procedure if exists bug2614|
+create procedure bug2614()
+begin
+drop table if exists t3;
+create table t3 (id int default '0' not null);
+insert into t3 select 12;
+insert into t3 select * from t3;
+end|
+call bug2614()|
+call bug2614()|
+drop table t3|
+drop procedure bug2614|
drop function if exists bug2674|
create function bug2674() returns int
return @@sort_buffer_size|
@@ -3417,6 +3541,9 @@
tm1 CREATE TEMPORARY TABLE `tm1` (
`spv1` decimal(6,3) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop procedure bug12589_1|
+drop procedure bug12589_2|
+drop procedure bug12589_3|
drop table if exists t3|
drop procedure if exists bug7049_1|
drop procedure if exists bug7049_2|
@@ -3667,4 +3794,220 @@
a
0
drop procedure bug14845|
+drop procedure if exists bug13549_1|
+drop procedure if exists bug13549_2|
+CREATE PROCEDURE `bug13549_2`()
+begin
+call bug13549_1();
+end|
+CREATE PROCEDURE `bug13549_1`()
+begin
+declare done int default 0;
+set done= not done;
+end|
+CALL bug13549_2()|
+drop procedure bug13549_2|
+drop procedure bug13549_1|
+drop function if exists bug10100f|
+drop procedure if exists bug10100p|
+drop procedure if exists bug10100t|
+drop procedure if exists bug10100pt|
+drop procedure if exists bug10100pv|
+drop procedure if exists bug10100pd|
+drop procedure if exists bug10100pc|
+create function bug10100f(prm int) returns int
+begin
+if prm > 1 then
+return prm * bug10100f(prm - 1);
+end if;
+return 1;
+end|
+create procedure bug10100p(prm int, inout res int)
+begin
+set res = res * prm;
+if prm > 1 then
+call bug10100p(prm - 1, res);
+end if;
+end|
+create procedure bug10100t(prm int)
+begin
+declare res int;
+set res = 1;
+call bug10100p(prm, res);
+select res;
+end|
+create table t3 (a int)|
+insert into t3 values (0)|
+create view v1 as select a from t3;
+create procedure bug10100pt(level int, lim int)
+begin
+if level < lim then
+update t3 set a=level;
+FLUSH TABLES;
+call bug10100pt(level+1, lim);
+else
+select * from t3;
+end if;
+end|
+create procedure bug10100pv(level int, lim int)
+begin
+if level < lim then
+update v1 set a=level;
+FLUSH TABLES;
+call bug10100pv(level+1, lim);
+else
+select * from v1;
+end if;
+end|
+prepare stmt2 from "select * from t3;";
+create procedure bug10100pd(level int, lim int)
+begin
+if level < lim then
+select level;
+prepare stmt1 from "update t3 set a=a+2";
+execute stmt1;
+FLUSH TABLES;
+execute stmt1;
+FLUSH TABLES;
+execute stmt1;
+FLUSH TABLES;
+deallocate prepare stmt1;
+execute stmt2;
+select * from t3;
+call bug10100pd(level+1, lim);
+else
+execute stmt2;
+end if;
+end|
+create procedure bug10100pc(level int, lim int)
+begin
+declare lv int;
+declare c cursor for select a from t3;
+open c;
+if level < lim then
+select level;
+fetch c into lv;
+select lv;
+update t3 set a=level+lv;
+FLUSH TABLES;
+call bug10100pc(level+1, lim);
+else
+select * from t3;
+end if;
+close c;
+end|
+set @@max_sp_recursion_depth=4|
+select @@max_sp_recursion_depth|
+@@max_sp_recursion_depth
+4
+select bug10100f(3)|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
+select bug10100f(6)|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
+call bug10100t(5)|
+res
+120
+call bug10100pt(1,5)|
+a
+4
+call bug10100pv(1,5)|
+a
+4
+update t3 set a=1|
+call bug10100pd(1,5)|
+level
+1
+a
+7
+a
+7
+level
+2
+a
+13
+a
+13
+level
+3
+a
+19
+a
+19
+level
+4
+a
+25
+a
+25
+a
+25
+select * from t3|
+a
+25
+update t3 set a=1|
+call bug10100pc(1,5)|
+level
+1
+lv
+1
+level
+2
+lv
+2
+level
+3
+lv
+4
+level
+4
+lv
+7
+a
+11
+select * from t3|
+a
+11
+set @@max_sp_recursion_depth=0|
+select @@max_sp_recursion_depth|
+@@max_sp_recursion_depth
+0
+select bug10100f(5)|
+ERROR HY000: Recursive stored functions and triggers are not allowed.
+call bug10100t(5)|
+ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine bug10100p
+set @@max_sp_recursion_depth=255|
+set @var=1|
+call bug10100p(255, @var)|
+call bug10100pt(1,255)|
+call bug10100pv(1,255)|
+call bug10100pd(1,255)|
+call bug10100pc(1,255)|
+set @@max_sp_recursion_depth=0|
+deallocate prepare stmt2|
+drop function bug10100f|
+drop procedure bug10100p|
+drop procedure bug10100t|
+drop procedure bug10100pt|
+drop procedure bug10100pv|
+drop procedure bug10100pd|
+drop procedure bug10100pc|
+drop view v1|
+drop procedure if exists bug13729|
+drop table if exists t3|
+create table t3 (s1 int, primary key (s1))|
+insert into t3 values (1),(2)|
+create procedure bug13729()
+begin
+declare continue handler for sqlexception select 55;
+update t3 set s1 = 1;
+end|
+call bug13729()|
+55
+55
+select * from t3|
+s1
+1
+2
+drop procedure bug13729|
+drop table t3|
drop table t1,t2;
--- 1.165/mysql-test/t/sp.test 2005-11-22 01:02:33 +01:00
+++ 1.166/mysql-test/t/sp.test 2005-11-28 10:26:41 +01:00
@@ -1211,15 +1211,13 @@
end if;
end|
select f5(1)|
-# This should generate an error about insuficient number of tables locked
-# Now this crash server
---disable_parsing # until bug#11394 fix
---error 1100
+# Since currently recursive functions are disallowed ER_SP_NO_RECURSION
+# error will be returned, once we will allow them error about
+# insufficient number of locked tables will be returned instead.
+--error ER_SP_NO_RECURSION
select f5(2)|
-# But now it simply miserably fails because we are trying to use the same
-# lex on the next iteration :/ It should generate some error too...
+--error ER_SP_NO_RECURSION
select f5(3)|
---enable_parsing
# OTOH this should work
create function f6() returns int
@@ -1265,13 +1263,12 @@
# views and functions ?
create function f1() returns int
return (select sum(data) from t1) + (select sum(data) from v1)|
-# This queries will crash server because we can't use LEX in
-# reenterable fashion yet. Patch disabling recursion will heal this.
---disable_parsing
+--error ER_SP_NO_RECURSION
select f1()|
+--error ER_SP_NO_RECURSION
select * from v1|
+--error ER_SP_NO_RECURSION
select * from v2|
---enable_parsing
# Back to the normal cases
drop function f1|
create function f1() returns int
@@ -1289,9 +1286,7 @@
#
# Let us test how well prelocking works with explicit LOCK TABLES.
#
-# Nowdays we have to lock mysql.proc to be able to read SP definitions.
-# But Monty was going to fix this.
-lock tables t1 read, t1 as t11 read, mysql.proc read|
+lock tables t1 read, t1 as t11 read|
# These should work well
select f3()|
select id, f3() from t1 as t11|
@@ -1481,9 +1476,6 @@
# Fibonacci, for recursion test. (Yet Another Numerical series :)
#
-# This part of test is disabled until we implement support for
-# recursive stored procedures.
---disable_parsing
--disable_warnings
drop table if exists fib|
--enable_warnings
@@ -1512,6 +1504,9 @@
end if;
end|
+# Enable recursion
+set @@max_sp_recursion_depth= 20|
+
# Minimum test: recursion of 3 levels
insert into fib values (0), (1)|
@@ -1531,7 +1526,7 @@
select * from fib order by f asc|
drop table fib|
drop procedure fib|
---enable_parsing
+set @@max_sp_recursion_depth= 0|
#
# Comment & suid
@@ -1800,16 +1795,8 @@
drop procedure bug2260|
#
-# BUG#2267
+# BUG#2267 "Lost connect if stored procedure has SHOW FUNCTION STATUS"
#
-# NOTE: This test case will be fixed as soon as Monty
-# will allow to open mysql.proc table under LOCK TABLES
-# without mentioning in lock list.
-#
-# FIXME: Other solution would be to use preopened proc table
-# instead of opening it anew.
-#
---disable_parsing
--disable_warnings
drop procedure if exists bug2267_1|
--enable_warnings
@@ -1836,11 +1823,13 @@
--disable_warnings
drop procedure if exists bug2267_4|
+drop function if exists bug2267_4|
--enable_warnings
create procedure bug2267_4()
begin
- show create function fac;
+ show create function bug2267_4;
end|
+create function bug2267_4() returns int return 100|
--replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00'
call bug2267_1()|
@@ -1853,7 +1842,7 @@
drop procedure bug2267_2|
drop procedure bug2267_3|
drop procedure bug2267_4|
---enable_parsing
+drop function bug2267_4|
#
# BUG#2227
@@ -1873,23 +1862,16 @@
drop procedure bug2227|
#
-# BUG#2614
+# BUG#2614 "Stored procedure with INSERT ... SELECT that does not
+# contain any tables crashes server"
#
-# QQ The second insert doesn't work with temporary tables (it was an
-# QQ ordinary table before we changed the locking scheme). It results
-# QQ in an error: 1137: Can't reopen table: 't3'
-# QQ which is a known limit with temporary tables.
-# QQ For this reason we can't run this test any more (i.e., if we modify
-# QQ it, it's no longer a test case for the bug), but we keep it here
-# QQ anyway, for tracability.
---disable_parsing
--disable_warnings
drop procedure if exists bug2614|
--enable_warnings
create procedure bug2614()
begin
- drop temporary table if exists t3;
- create temporary table t3 (id int default '0' not null);
+ drop table if exists t3;
+ create table t3 (id int default '0' not null);
insert into t3 select 12;
insert into t3 select * from t3;
end|
@@ -1898,9 +1880,8 @@
call bug2614()|
--enable_warnings
call bug2614()|
-drop temporary table t3|
+drop table t3|
drop procedure bug2614|
---enable_parsing
#
# BUG#2674
@@ -4291,6 +4272,9 @@
# No warnings here
call bug12589_2()|
call bug12589_3()|
+drop procedure bug12589_1|
+drop procedure bug12589_2|
+drop procedure bug12589_3|
#
# BUG#7049: Stored procedure CALL errors are ignored
@@ -4593,6 +4577,210 @@
end|
call bug14845()|
drop procedure bug14845|
+
+#
+# BUG#13549 "Server crash with nested stored procedures".
+# Server should not crash when during execution of stored procedure
+# we have to parse trigger/function definition and this new trigger/
+# function has more local variables declared than invoking stored
+# procedure and last of these variables is used in argument of NOT
+# operator.
+#
+--disable_warnings
+drop procedure if exists bug13549_1|
+drop procedure if exists bug13549_2|
+--enable_warnings
+CREATE PROCEDURE `bug13549_2`()
+begin
+ call bug13549_1();
+end|
+CREATE PROCEDURE `bug13549_1`()
+begin
+ declare done int default 0;
+ set done= not done;
+end|
+CALL bug13549_2()|
+drop procedure bug13549_2|
+drop procedure bug13549_1|
+
+#
+# BUG#10100: function (and stored procedure?) recursivity problem
+#
+--disable_warnings
+drop function if exists bug10100f|
+drop procedure if exists bug10100p|
+drop procedure if exists bug10100t|
+drop procedure if exists bug10100pt|
+drop procedure if exists bug10100pv|
+drop procedure if exists bug10100pd|
+drop procedure if exists bug10100pc|
+--enable_warnings
+# routines with simple recursion
+create function bug10100f(prm int) returns int
+begin
+ if prm > 1 then
+ return prm * bug10100f(prm - 1);
+ end if;
+ return 1;
+end|
+create procedure bug10100p(prm int, inout res int)
+begin
+ set res = res * prm;
+ if prm > 1 then
+ call bug10100p(prm - 1, res);
+ end if;
+end|
+create procedure bug10100t(prm int)
+begin
+ declare res int;
+ set res = 1;
+ call bug10100p(prm, res);
+ select res;
+end|
+
+# a procedure which use tables and recursion
+create table t3 (a int)|
+insert into t3 values (0)|
+create view v1 as select a from t3;
+create procedure bug10100pt(level int, lim int)
+begin
+ if level < lim then
+ update t3 set a=level;
+ FLUSH TABLES;
+ call bug10100pt(level+1, lim);
+ else
+ select * from t3;
+ end if;
+end|
+# view & recursion
+create procedure bug10100pv(level int, lim int)
+begin
+ if level < lim then
+ update v1 set a=level;
+ FLUSH TABLES;
+ call bug10100pv(level+1, lim);
+ else
+ select * from v1;
+ end if;
+end|
+# dynamic sql & recursion
+prepare stmt2 from "select * from t3;";
+create procedure bug10100pd(level int, lim int)
+begin
+ if level < lim then
+ select level;
+ prepare stmt1 from "update t3 set a=a+2";
+ execute stmt1;
+ FLUSH TABLES;
+ execute stmt1;
+ FLUSH TABLES;
+ execute stmt1;
+ FLUSH TABLES;
+ deallocate prepare stmt1;
+ execute stmt2;
+ select * from t3;
+ call bug10100pd(level+1, lim);
+ else
+ execute stmt2;
+ end if;
+end|
+# cursor & recursion
+create procedure bug10100pc(level int, lim int)
+begin
+ declare lv int;
+ declare c cursor for select a from t3;
+ open c;
+ if level < lim then
+ select level;
+ fetch c into lv;
+ select lv;
+ update t3 set a=level+lv;
+ FLUSH TABLES;
+ call bug10100pc(level+1, lim);
+ else
+ select * from t3;
+ end if;
+ close c;
+end|
+
+set @@max_sp_recursion_depth=4|
+select @@max_sp_recursion_depth|
+-- error ER_SP_NO_RECURSION
+select bug10100f(3)|
+-- error ER_SP_NO_RECURSION
+select bug10100f(6)|
+call bug10100t(5)|
+call bug10100pt(1,5)|
+call bug10100pv(1,5)|
+update t3 set a=1|
+call bug10100pd(1,5)|
+select * from t3|
+update t3 set a=1|
+call bug10100pc(1,5)|
+select * from t3|
+set @@max_sp_recursion_depth=0|
+select @@max_sp_recursion_depth|
+-- error ER_SP_NO_RECURSION
+select bug10100f(5)|
+-- error ER_SP_RECURSION_LIMIT
+call bug10100t(5)|
+
+#end of the stack checking
+set @@max_sp_recursion_depth=255|
+set @var=1|
+#disable log because error about stack overrun contains numbers which
+#depend on a system
+-- disable_result_log
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100p(255, @var)|
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100pt(1,255)|
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100pv(1,255)|
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100pd(1,255)|
+-- error ER_STACK_OVERRUN_NEED_MORE
+call bug10100pc(1,255)|
+-- enable_result_log
+set @@max_sp_recursion_depth=0|
+
+deallocate prepare stmt2|
+
+drop function bug10100f|
+drop procedure bug10100p|
+drop procedure bug10100t|
+drop procedure bug10100pt|
+drop procedure bug10100pv|
+drop procedure bug10100pd|
+drop procedure bug10100pc|
+drop view v1|
+
+#
+# BUG#13729: Stored procedures: packet error after exception handled
+#
+--disable_warnings
+drop procedure if exists bug13729|
+drop table if exists t3|
+--enable_warnings
+
+create table t3 (s1 int, primary key (s1))|
+
+insert into t3 values (1),(2)|
+
+create procedure bug13729()
+begin
+ declare continue handler for sqlexception select 55;
+
+ update t3 set s1 = 1;
+end|
+
+call bug13729()|
+# Used to cause Packets out of order
+select * from t3|
+
+drop procedure bug13729|
+drop table t3|
+
#
# BUG#NNNN: New bug synopsis
--- 1.198/sql/sp_head.cc 2005-11-22 01:02:34 +01:00
+++ 1.199/sql/sp_head.cc 2005-11-28 10:26:42 +01:00
@@ -105,6 +105,8 @@
case SQLCOM_SHOW_TABLES:
case SQLCOM_SHOW_VARIABLES:
case SQLCOM_SHOW_WARNS:
+ case SQLCOM_SHOW_PROC_CODE:
+ case SQLCOM_SHOW_FUNC_CODE:
flags= sp_head::MULTI_RESULTS;
break;
/*
@@ -476,7 +478,8 @@
sp_head::sp_head()
:Query_arena(&main_mem_root, INITIALIZED_FOR_SP),
- m_flags(0), m_returns_cs(NULL)
+ m_flags(0), m_returns_cs(NULL), m_recursion_level(0), m_next_cached_sp(0),
+ m_first_instance(this), m_first_free_instance(this), m_last_cached_sp(this)
{
extern byte *
sp_table_key(const byte *ptr, uint *plen, my_bool first);
@@ -657,6 +660,7 @@
sp_head::~sp_head()
{
destroy();
+ delete m_next_cached_sp;
if (m_thd)
restore_thd_mem_root(m_thd);
}
@@ -883,6 +887,31 @@
/*
+ Return appropriate error about recursion limit reaching
+
+ SYNOPSIS
+ sp_head::recursion_level_error()
+
+ NOTE
+ For functions and triggers we return error about prohibited recursion.
+ For stored procedures we return about reaching recursion limit.
+*/
+
+void sp_head::recursion_level_error()
+{
+ if (m_type == TYPE_ENUM_PROCEDURE)
+ {
+ THD *thd= current_thd;
+ my_error(ER_SP_RECURSION_LIMIT, MYF(0),
+ thd->variables.max_sp_recursion_depth,
+ m_name);
+ }
+ else
+ my_error(ER_SP_NO_RECURSION, MYF(0));
+}
+
+
+/*
Execute the routine. The main instruction jump loop is there
Assume the parameters already set.
@@ -911,37 +940,31 @@
Item_change_list old_change_list;
String old_packet;
- /* init per-instruction memroot */
- init_alloc_root(&execute_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
-
-
/* Use some extra margin for possible SP recursion and functions */
- if (check_stack_overrun(thd, 4*STACK_MIN_SIZE, olddb))
+ if (check_stack_overrun(thd, 8 * STACK_MIN_SIZE, (char*)&old_packet))
{
DBUG_RETURN(-1);
}
- if (m_flags & IS_INVOKED)
- {
- /*
- We have to disable recursion for stored routines since in
- many cases LEX structure and many Item's can't be used in
- reentrant way now.
-
- TODO: We can circumvent this problem by using separate
- sp_head instances for each recursive invocation.
-
- NOTE: Theoretically arguments of procedure can be evaluated
- before its invocation so there should be no problem with
- recursion. But since we perform cleanup for CALL statement
- as for any other statement only after its execution, its LEX
- structure is not reusable for recursive calls. Thus we have
- to prohibit recursion for stored procedures too.
- */
- my_error(ER_SP_NO_RECURSION, MYF(0));
- DBUG_RETURN(-1);
- }
+ /* init per-instruction memroot */
+ init_alloc_root(&execute_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
+
+ DBUG_ASSERT(!(m_flags & IS_INVOKED));
m_flags|= IS_INVOKED;
+ m_first_instance->m_first_free_instance= m_next_cached_sp;
+ DBUG_PRINT("info", ("first free for 0x%lx ++: 0x%lx->0x%lx, level: %lu, flags %x",
+ (ulong)m_first_instance, this, m_next_cached_sp,
+ m_next_cached_sp->m_recursion_level,
+ m_next_cached_sp->m_flags));
+ /*
+ Check that if there are not any instances after this one then
+ pointer to the last instance points on this instance or if there are
+ some instances after this one then recursion level of next instance
+ greater then recursion level of current instance on 1
+ */
+ DBUG_ASSERT((m_next_cached_sp == 0 &&
+ m_first_instance->m_last_cached_sp == this) ||
+ (m_recursion_level + 1 == m_next_cached_sp->m_recursion_level));
dbchanged= FALSE;
if (m_db.length &&
@@ -1116,6 +1139,29 @@
ret= mysql_change_db(thd, olddb, 1);
}
m_flags&= ~IS_INVOKED;
+ DBUG_PRINT("info", ("first free for 0x%lx --: 0x%lx->0x%lx, level: %lu, flags %x",
+ (ulong)m_first_instance,
+ m_first_instance->m_first_free_instance, this,
+ m_recursion_level, m_flags));
+ /*
+ Check that we have one of following:
+
+ 1) there are not free instances which means that this instance is last
+ in the list of instances (pointer to the last instance point on it and
+ ther are not other instances after this one in the list)
+
+ 2) There are some free instances which mean that first free instance
+ should go just after this one and recursion level of that free instance
+ should be on 1 more then recursion leven of this instance.
+ */
+ DBUG_ASSERT((m_first_instance->m_first_free_instance == 0 &&
+ this == m_first_instance->m_last_cached_sp &&
+ m_next_cached_sp == 0) ||
+ (m_first_instance->m_first_free_instance != 0 &&
+ m_first_instance->m_first_free_instance == m_next_cached_sp &&
+ m_first_instance->m_first_free_instance->m_recursion_level ==
+ m_recursion_level + 1));
+ m_first_instance->m_first_free_instance= this;
DBUG_RETURN(ret);
}
@@ -1173,6 +1219,9 @@
// QQ Should have some error checking here? (types, etc...)
if (!(nctx= new sp_rcontext(octx, csize, hmax, cmax)))
goto end;
+#ifndef DBUG_OFF
+ nctx->owner= this;
+#endif
for (i= 0 ; i < argcount ; i++)
{
sp_pvar_t *pvar = m_pcont->find_pvar(i);
@@ -1317,6 +1366,9 @@
{ // Create a temporary old context
if (!(octx= new sp_rcontext(octx, csize, hmax, cmax)))
DBUG_RETURN(-1);
+#ifndef DBUG_OFF
+ octx->owner= 0;
+#endif
thd->spcont= octx;
/* set callers_arena to thd, for upper-level function to work */
@@ -1328,6 +1380,9 @@
thd->spcont= save_spcont;
DBUG_RETURN(-1);
}
+#ifndef DBUG_OFF
+ nctx->owner= this;
+#endif
if (csize > 0 || hmax > 0 || cmax > 0)
{
@@ -1740,7 +1795,7 @@
LINT_INIT(sql_mode_len);
if (check_show_routine_access(thd, this, &full_access))
- return 1;
+ DBUG_RETURN(1);
sql_mode_str=
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
@@ -1753,10 +1808,7 @@
max(buffer.length(), 1024)));
if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
Protocol::SEND_EOF))
- {
- res= 1;
- goto done;
- }
+ DBUG_RETURN(1);
protocol->prepare_for_resend();
protocol->store(m_name.str, m_name.length, system_charset_info);
protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
@@ -1765,7 +1817,6 @@
res= protocol->write();
send_eof(thd);
- done:
DBUG_RETURN(res);
}
@@ -1810,7 +1861,7 @@
LINT_INIT(sql_mode_len);
if (check_show_routine_access(thd, this, &full_access))
- return 1;
+ DBUG_RETURN(1);
sql_mode_str=
sys_var_thd_sql_mode::symbolic_mode_representation(thd,
@@ -1822,10 +1873,7 @@
max(buffer.length(),1024)));
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- {
- res= 1;
- goto done;
- }
+ DBUG_RETURN(1);
protocol->prepare_for_resend();
protocol->store(m_name.str, m_name.length, system_charset_info);
protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
@@ -1834,7 +1882,6 @@
res= protocol->write();
send_eof(thd);
- done:
DBUG_RETURN(res);
}
@@ -1894,6 +1941,50 @@
}
+#ifndef DBUG_OFF
+int
+sp_head::show_routine_code(THD *thd)
+{
+ Protocol *protocol= thd->protocol;
+ char buff[2048];
+ String buffer(buff, sizeof(buff), system_charset_info);
+ List<Item> field_list;
+ sp_instr *i;
+ bool full_access;
+ int res= 0;
+ uint ip;
+ DBUG_ENTER("sp_head::show_routine_code");
+ DBUG_PRINT("info", ("procedure: %s", m_name.str));
+
+ if (check_show_routine_access(thd, this, &full_access) || !full_access)
+ DBUG_RETURN(1);
+
+ field_list.push_back(new Item_uint("Pos", 9));
+ // 1024 is for not to confuse old clients
+ field_list.push_back(new Item_empty_string("Instruction",
+ max(buffer.length(), 1024)));
+ if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
+ Protocol::SEND_EOF))
+ DBUG_RETURN(1);
+
+ for (ip= 0; (i = get_instr(ip)) ; ip++)
+ {
+ protocol->prepare_for_resend();
+ protocol->store((longlong)ip);
+
+ buffer.set("", 0, system_charset_info);
+ i->print(&buffer);
+ protocol->store(buffer.ptr(), buffer.length(), system_charset_info);
+ if ((res= protocol->write()))
+ break;
+ }
+ send_eof(thd);
+
+ DBUG_RETURN(res);
+}
+#endif // ifndef DBUG_OFF
+
+
/*
Prepare LEX and thread for execution of instruction, if requested open
and lock LEX's tables, execute instruction's core function, perform
@@ -2052,14 +2143,43 @@
DBUG_RETURN(res);
}
+/*
+ Sufficient max length of printed destinations and frame offsets (all uints).
+*/
+#define SP_INSTR_UINT_MAXLEN 8
+
+#define SP_STMT_PRINT_MAXLEN 40
void
sp_instr_stmt::print(String *str)
{
- str->reserve(12);
- str->append(STRING_WITH_LEN("stmt "));
+ uint i, len;
+
+ /* stmt CMD "..." */
+ if (str->reserve(SP_STMT_PRINT_MAXLEN+SP_INSTR_UINT_MAXLEN+8))
+ return;
+ str->qs_append(STRING_WITH_LEN("stmt "));
str->qs_append((uint)m_lex_keeper.sql_command());
+ str->qs_append(STRING_WITH_LEN(" \""));
+ len= m_query.length;
+ /*
+ Print the query string (but not too much of it), just to indicate which
+ statement it is.
+ */
+ if (len > SP_STMT_PRINT_MAXLEN)
+ len= SP_STMT_PRINT_MAXLEN-3;
+ /* Copy the query string and replace '\n' with ' ' in the process */
+ for (i= 0 ; i < len ; i++)
+ {
+ if (m_query.str[i] == '\n')
+ str->qs_append(' ');
+ else
+ str->qs_append(m_query.str[i]);
+ }
+ if (m_query.length > SP_STMT_PRINT_MAXLEN)
+ str->qs_append(STRING_WITH_LEN("...")); /* Indicate truncated string */
+ str->qs_append('"');
}
-
+#undef SP_STMT_PRINT_MAXLEN
int
sp_instr_stmt::exec_core(THD *thd, uint *nextp)
@@ -2096,10 +2216,23 @@
void
sp_instr_set::print(String *str)
{
- str->reserve(12);
- str->append(STRING_WITH_LEN("set "));
+ /* set name@offset ... */
+ int rsrv = SP_INSTR_UINT_MAXLEN+6;
+ sp_pvar_t *var = m_ctx->find_pvar(m_offset);
+
+ /* 'var' should always be non-null, but just in case... */
+ if (var)
+ rsrv+= var->name.length;
+ if (str->reserve(rsrv))
+ return;
+ str->qs_append(STRING_WITH_LEN("set "));
+ if (var)
+ {
+ str->qs_append(var->name.str, var->name.length);
+ str->qs_append('@');
+ }
str->qs_append(m_offset);
- str->append(' ');
+ str->qs_append(' ');
m_value->print(str);
}
@@ -2132,7 +2265,7 @@
void
sp_instr_set_trigger_field::print(String *str)
{
- str->append(STRING_WITH_LEN("set "));
+ str->append(STRING_WITH_LEN("set_trigger_field "));
trigger_field->print(str);
str->append(STRING_WITH_LEN(":="));
value->print(str);
@@ -2156,8 +2289,10 @@
void
sp_instr_jump::print(String *str)
{
- str->reserve(12);
- str->append(STRING_WITH_LEN("jump "));
+ /* jump dest */
+ if (str->reserve(SP_INSTR_UINT_MAXLEN+5))
+ return;
+ str->qs_append(STRING_WITH_LEN("jump "));
str->qs_append(m_dest);
}
@@ -2238,10 +2373,12 @@
void
sp_instr_jump_if::print(String *str)
{
- str->reserve(12);
- str->append(STRING_WITH_LEN("jump_if "));
+ /* jump_if dest ... */
+ if (str->reserve(SP_INSTR_UINT_MAXLEN+8+32)) // Add some for the expr. too
+ return;
+ str->qs_append(STRING_WITH_LEN("jump_if "));
str->qs_append(m_dest);
- str->append(' ');
+ str->qs_append(' ');
m_expr->print(str);
}
@@ -2299,10 +2436,12 @@
void
sp_instr_jump_if_not::print(String *str)
{
- str->reserve(16);
- str->append(STRING_WITH_LEN("jump_if_not "));
+ /* jump_if_not dest ... */
+ if (str->reserve(SP_INSTR_UINT_MAXLEN+12+32)) // Add some for the expr. too
+ return;
+ str->qs_append(STRING_WITH_LEN("jump_if_not "));
str->qs_append(m_dest);
- str->append(' ');
+ str->qs_append(' ');
m_expr->print(str);
}
@@ -2357,10 +2496,12 @@
void
sp_instr_freturn::print(String *str)
{
- str->reserve(12);
- str->append(STRING_WITH_LEN("freturn "));
+ /* freturn type expr... */
+ if (str->reserve(UINT_MAX+8+32)) // Add some for the expr. too
+ return;
+ str->qs_append(STRING_WITH_LEN("freturn "));
str->qs_append((uint)m_type);
- str->append(' ');
+ str->qs_append(' ');
m_value->print(str);
}
@@ -2385,15 +2526,31 @@
void
sp_instr_hpush_jump::print(String *str)
{
- str->reserve(32);
- str->append(STRING_WITH_LEN("hpush_jump "));
+ /* hpush_jump dest fsize type */
+ if (str->reserve(SP_INSTR_UINT_MAXLEN*2 + 21))
+ return;
+ str->qs_append(STRING_WITH_LEN("hpush_jump "));
str->qs_append(m_dest);
- str->append(STRING_WITH_LEN(" t="));
- str->qs_append(m_type);
- str->append(STRING_WITH_LEN(" f="));
+ str->qs_append(' ');
str->qs_append(m_frame);
- str->append(STRING_WITH_LEN(" h="));
- str->qs_append(m_ip+1);
+ switch (m_type)
+ {
+ case SP_HANDLER_NONE:
+ str->qs_append(STRING_WITH_LEN(" NONE")); // This would be a bug
+ break;
+ case SP_HANDLER_EXIT:
+ str->qs_append(STRING_WITH_LEN(" EXIT"));
+ break;
+ case SP_HANDLER_CONTINUE:
+ str->qs_append(STRING_WITH_LEN(" CONTINUE"));
+ break;
+ case SP_HANDLER_UNDO:
+ str->qs_append(STRING_WITH_LEN(" UNDO"));
+ break;
+ default:
+ str->qs_append(STRING_WITH_LEN(" UNKNOWN:")); // This would be a bug as well
+ str->qs_append(m_type);
+ }
}
uint
@@ -2428,8 +2585,10 @@
void
sp_instr_hpop::print(String *str)
{
- str->reserve(12);
- str->append(STRING_WITH_LEN("hpop "));
+ /* hpop count */
+ if (str->reserve(SP_INSTR_UINT_MAXLEN+5))
+ return;
+ str->qs_append(STRING_WITH_LEN("hpop "));
str->qs_append(m_count);
}
@@ -2463,12 +2622,14 @@
void
sp_instr_hreturn::print(String *str)
{
- str->reserve(16);
- str->append(STRING_WITH_LEN("hreturn "));
+ /* hreturn framesize dest */
+ if (str->reserve(SP_INSTR_UINT_MAXLEN*2 + 9))
+ return;
+ str->qs_append(STRING_WITH_LEN("hreturn "));
str->qs_append(m_frame);
if (m_dest)
{
- str->append(' ');
+ str->qs_append(' ');
str->qs_append(m_dest);
}
}
@@ -2516,7 +2677,22 @@
void
sp_instr_cpush::print(String *str)
{
- str->append(STRING_WITH_LEN("cpush"));
+ LEX_STRING n;
+ my_bool found= m_ctx->find_cursor(m_cursor, &n);
+ /* cpush name@offset */
+ uint rsrv= SP_INSTR_UINT_MAXLEN+7;
+
+ if (found)
+ rsrv+= n.length;
+ if (str->reserve(rsrv))
+ return;
+ str->qs_append(STRING_WITH_LEN("cpush "));
+ if (found)
+ {
+ str->qs_append(n.str, n.length);
+ str->qs_append('@');
+ }
+ str->qs_append(m_cursor);
}
@@ -2537,8 +2713,10 @@
void
sp_instr_cpop::print(String *str)
{
- str->reserve(12);
- str->append(STRING_WITH_LEN("cpop "));
+ /* cpop count */
+ if (str->reserve(SP_INSTR_UINT_MAXLEN+5))
+ return;
+ str->qs_append(STRING_WITH_LEN("cpop "));
str->qs_append(m_count);
}
@@ -2612,8 +2790,21 @@
void
sp_instr_copen::print(String *str)
{
- str->reserve(12);
- str->append(STRING_WITH_LEN("copen "));
+ LEX_STRING n;
+ my_bool found= m_ctx->find_cursor(m_cursor, &n);
+ /* copen name@offset */
+ uint rsrv= SP_INSTR_UINT_MAXLEN+7;
+
+ if (found)
+ rsrv+= n.length;
+ if (str->reserve(rsrv))
+ return;
+ str->qs_append(STRING_WITH_LEN("copen "));
+ if (found)
+ {
+ str->qs_append(n.str, n.length);
+ str->qs_append('@');
+ }
str->qs_append(m_cursor);
}
@@ -2641,8 +2832,21 @@
void
sp_instr_cclose::print(String *str)
{
- str->reserve(12);
- str->append(STRING_WITH_LEN("cclose "));
+ LEX_STRING n;
+ my_bool found= m_ctx->find_cursor(m_cursor, &n);
+ /* cclose name@offset */
+ uint rsrv= SP_INSTR_UINT_MAXLEN+8;
+
+ if (found)
+ rsrv+= n.length;
+ if (str->reserve(rsrv))
+ return;
+ str->qs_append(STRING_WITH_LEN("cclose "));
+ if (found)
+ {
+ str->qs_append(n.str, n.length);
+ str->qs_append('@');
+ }
str->qs_append(m_cursor);
}
@@ -2671,14 +2875,29 @@
{
List_iterator_fast<struct sp_pvar> li(m_varlist);
sp_pvar_t *pv;
-
- str->reserve(12);
- str->append(STRING_WITH_LEN("cfetch "));
+ LEX_STRING n;
+ my_bool found= m_ctx->find_cursor(m_cursor, &n);
+ /* cfetch name@offset vars... */
+ uint rsrv= SP_INSTR_UINT_MAXLEN+8;
+
+ if (found)
+ rsrv+= n.length;
+ if (str->reserve(rsrv))
+ return;
+ str->qs_append(STRING_WITH_LEN("cfetch "));
+ if (found)
+ {
+ str->qs_append(n.str, n.length);
+ str->qs_append('@');
+ }
str->qs_append(m_cursor);
while ((pv= li++))
{
- str->reserve(8);
- str->append(' ');
+ if (str->reserve(pv->name.length+SP_INSTR_UINT_MAXLEN+2))
+ return;
+ str->qs_append(' ');
+ str->qs_append(pv->name.str, pv->name.length);
+ str->qs_append('@');
str->qs_append(pv->offset);
}
}
@@ -2702,8 +2921,10 @@
void
sp_instr_error::print(String *str)
{
- str->reserve(12);
- str->append(STRING_WITH_LEN("error "));
+ /* error code */
+ if (str->reserve(SP_INSTR_UINT_MAXLEN+6))
+ return;
+ str->qs_append(STRING_WITH_LEN("error "));
str->qs_append(m_errcode);
}
| Thread |
|---|
| • bk commit into 5.0 tree (kent:1.1970) | kent | 28 Nov |