Below is the list of changes that have just been committed into a local
5.0 repository of bell. When bell 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.1994 05/11/23 01:28:32 bell@stripped +15 -0
Merge sanja.is.com.ua:/home/bell/mysql/bk/work-bug7-5.0
into sanja.is.com.ua:/home/bell/mysql/bk/work-merge-5.0
sql/share/errmsg.txt
1.58 05/11/23 01:28:29 bell@stripped +2 -2
merge
mysql-test/r/sp.result
1.173 05/11/23 01:28:29 bell@stripped +0 -0
merge
sql/sql_parse.cc
1.517 05/11/23 01:12:36 bell@stripped +0 -0
Auto merged
sql/sql_class.h
1.277 05/11/23 01:12:35 bell@stripped +0 -0
Auto merged
sql/sql_base.cc
1.321 05/11/23 01:12:35 bell@stripped +0 -0
Auto merged
sql/sp_head.h
1.77 05/11/23 01:12:35 bell@stripped +0 -0
Auto merged
sql/sp_head.cc
1.202 05/11/23 01:12:35 bell@stripped +0 -0
Auto merged
sql/set_var.cc
1.145 05/11/23 01:12:35 bell@stripped +0 -0
Auto merged
sql/mysqld.cc
1.519 05/11/23 01:12:34 bell@stripped +0 -0
Auto merged
sql/item_func.cc
1.270 05/11/23 01:12:34 bell@stripped +0 -0
Auto merged
mysql-test/t/trigger.test
1.30 05/11/23 01:12:33 bell@stripped +0 -0
Auto merged
mysql-test/t/sp.test
1.166 05/11/23 01:12:33 bell@stripped +0 -0
Auto merged
mysql-test/t/sp-error.test
1.97 05/11/23 01:12:33 bell@stripped +0 -0
Auto merged
mysql-test/r/trigger.result
1.24 05/11/23 01:12:33 bell@stripped +0 -0
Auto merged
mysql-test/r/sp-error.result
1.93 05/11/23 01:12:33 bell@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: bell
# Host: sanja.is.com.ua
# Root: /home/bell/mysql/bk/work-merge-5.0/RESYNC
--- 1.269/sql/item_func.cc 2005-11-21 21:15:41 +02:00
+++ 1.270/sql/item_func.cc 2005-11-23 01:12:34 +02:00
@@ -4690,10 +4690,16 @@
{
Field *field;
DBUG_ENTER("Item_func_sp::sp_result_field");
+ DBUG_PRINT("info", ("sp: %s, flags: %x, level: %lu",
+ (m_sp ? "YES" : "NO"),
+ (m_sp ? m_sp->m_flags : (uint)0),
+ (m_sp ? m_sp->m_recursion_level : (ulong)0)));
if (!m_sp)
{
- if (!(m_sp= sp_find_function(current_thd, m_name, TRUE)))
+ THD *thd= current_thd;
+ if (!(m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name,
+ &thd->sp_func_cache, TRUE)))
{
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
DBUG_RETURN(0);
@@ -4919,7 +4925,8 @@
bool res= TRUE;
*save= 0; // Safety if error
- if (! m_sp && ! (m_sp= sp_find_function(thd, m_name, TRUE)))
+ if (! m_sp && ! (m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name,
+ &thd->sp_func_cache, TRUE)))
{
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
goto error;
--- 1.518/sql/mysqld.cc 2005-11-21 21:15:41 +02:00
+++ 1.519/sql/mysqld.cc 2005-11-23 01:12:34 +02:00
@@ -4545,6 +4545,7 @@
OPT_OPTIMIZER_PRUNE_LEVEL,
OPT_UPDATABLE_VIEWS_WITH_LIMIT,
OPT_SP_AUTOMATIC_PRIVILEGES,
+ OPT_MAX_SP_RECURSION_DEPTH,
OPT_AUTO_INCREMENT, OPT_AUTO_INCREMENT_OFFSET,
OPT_ENABLE_LARGE_PAGES,
OPT_TIMED_MUTEXES,
@@ -5760,6 +5761,11 @@
(gptr*) &global_system_variables.read_buff_size,
(gptr*) &max_system_variables.read_buff_size,0, GET_ULONG, REQUIRED_ARG,
128*1024L, IO_SIZE*2+MALLOC_OVERHEAD, ~0L, MALLOC_OVERHEAD, IO_SIZE, 0},
+ {"max_sp_recursion_depth", OPT_MAX_SP_RECURSION_DEPTH,
+ "Maximum stored procedure recursion depth. (discussed with docs).",
+ (gptr*) &global_system_variables.max_sp_recursion_depth,
+ (gptr*) &max_system_variables.max_sp_recursion_depth, 0, GET_ULONG,
+ OPT_ARG, 0, 0, 255, 0, 1, 0 },
#ifdef HAVE_REPLICATION
{"relay_log_purge", OPT_RELAY_LOG_PURGE,
"0 = do not purge relay logs. 1 = purge them as soon as they are no more needed.",
--- 1.320/sql/sql_base.cc 2005-11-21 21:14:32 +02:00
+++ 1.321/sql/sql_base.cc 2005-11-23 01:12:35 +02:00
@@ -1088,6 +1088,11 @@
/* find a unused table in the open table cache */
if (refresh)
*refresh=0;
+
+ /* an open table operation needs a lot of the stack space */
+ if (check_stack_overrun(thd, 8 * STACK_MIN_SIZE, (char *)&alias))
+ return 0;
+
if (thd->killed)
DBUG_RETURN(0);
key_length= (uint) (strmov(strmov(key, table_list->db)+1,
--- 1.276/sql/sql_class.h 2005-11-23 00:51:48 +02:00
+++ 1.277/sql/sql_class.h 2005-11-23 01:12:35 +02: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;
--- 1.516/sql/sql_parse.cc 2005-11-22 14:13:20 +02:00
+++ 1.517/sql/sql_parse.cc 2005-11-23 01:12:36 +02:00
@@ -3682,7 +3682,8 @@
if (check_access(thd,INSERT_ACL,"mysql",0,1,0,0))
break;
#ifdef HAVE_DLOPEN
- if (sp_find_function(thd, lex->spname))
+ if (sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
+ &thd->sp_func_cache, FALSE))
{
my_error(ER_UDF_EXISTS, MYF(0), lex->spname->m_name.str);
goto error;
@@ -4216,7 +4217,8 @@
By this moment all needed SPs should be in cache so no need to look
into DB.
*/
- if (!(sp= sp_find_procedure(thd, lex->spname, TRUE)))
+ if (!(sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
+ &thd->sp_proc_cache, TRUE)))
{
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PROCEDURE",
lex->spname->m_qname.str);
@@ -4340,9 +4342,11 @@
memcpy(&chistics, &lex->sp_chistics, sizeof(chistics));
if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
- sp= sp_find_procedure(thd, lex->spname);
+ sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
+ &thd->sp_proc_cache, FALSE);
else
- sp= sp_find_function(thd, lex->spname);
+ sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
+ &thd->sp_func_cache, FALSE);
mysql_reset_errors(thd, 0);
if (! sp)
{
@@ -4418,9 +4422,11 @@
char *db, *name;
if (lex->sql_command == SQLCOM_DROP_PROCEDURE)
- sp= sp_find_procedure(thd, lex->spname);
+ sp= sp_find_routine(thd, TYPE_ENUM_PROCEDURE, lex->spname,
+ &thd->sp_proc_cache, FALSE);
else
- sp= sp_find_function(thd, lex->spname);
+ sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
+ &thd->sp_func_cache, FALSE);
mysql_reset_errors(thd, 0);
if (sp)
{
--- 1.57/sql/share/errmsg.txt 2005-11-20 20:47:01 +02:00
+++ 1.58/sql/share/errmsg.txt 2005-11-23 01:28:29 +02:00
@@ -5361,7 +5361,7 @@
ER_NO_DEFAULT_FOR_VIEW_FIELD
eng "Field of view '%-.64s.%-.64s' underlying table doesn't have a default value"
ER_SP_NO_RECURSION
- eng "Recursive stored routines are not allowed."
+ eng "Recursive stored functions and triggers are not allowed."
ER_TOO_BIG_SCALE 42000 S1009
eng "Too big scale %d specified for column '%-.64s'. Maximum is %d."
ER_TOO_BIG_PRECISION 42000 S1009
@@ -5425,3 +5425,5 @@
eng "No definer attribute for trigger '%-.64s'.'%-.64s'. The trigger will be activated
under the authorization of the invoker, which may have insufficient privileges. Please
recreate the trigger."
ER_OLD_FILE_FORMAT
eng "'%-.64s' has an old format, you should re-create the '%s' object(s)"
+ER_SP_RECURSION_LIMIT
+ eng "Recursive limit %d (as set by the max_sp_recursion_depth variable) was
exceeded for routine %.64s"
--- 1.23/mysql-test/r/trigger.result 2005-11-23 00:58:09 +02:00
+++ 1.24/mysql-test/r/trigger.result 2005-11-23 01:12:33 +02:00
@@ -703,8 +703,11 @@
for each row insert into t2 values (new.f1+1);
create trigger t2_ai after insert on t2
for each row insert into t1 values (new.f2+1);
+set @SAVE_SP_RECURSION_LEVELS=@@max_sp_recursion_depth;
+set @@max_sp_recursion_depth=100;
insert into t1 values (1);
ERROR HY000: Can't update table 't1' in stored function/trigger because it is already
used by statement which invoked this stored function/trigger.
+set @@max_sp_recursion_depth=@SAVE_SP_RECURSION_LEVELS;
select * from t1;
f1
1
--- 1.29/mysql-test/t/trigger.test 2005-11-23 00:58:09 +02:00
+++ 1.30/mysql-test/t/trigger.test 2005-11-23 01:12:33 +02:00
@@ -743,8 +743,12 @@
for each row insert into t2 values (new.f1+1);
create trigger t2_ai after insert on t2
for each row insert into t1 values (new.f2+1);
+# Allow SP resursion to be show that it has not influence here
+set @SAVE_SP_RECURSION_LEVELS=@@max_sp_recursion_depth;
+set @@max_sp_recursion_depth=100;
--error ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
insert into t1 values (1);
+set @@max_sp_recursion_depth=@SAVE_SP_RECURSION_LEVELS;
select * from t1;
select * from t2;
drop trigger t1_ai;
--- 1.144/sql/set_var.cc 2005-11-17 16:06:38 +02:00
+++ 1.145/sql/set_var.cc 2005-11-23 01:12:35 +02:00
@@ -261,6 +261,8 @@
fix_max_relay_log_size);
sys_var_thd_ulong sys_max_sort_length("max_sort_length",
&SV::max_sort_length);
+sys_var_thd_ulong sys_max_sp_recursion_depth("max_sp_recursion_depth",
+ &SV::max_sp_recursion_depth);
sys_var_max_user_conn sys_max_user_connections("max_user_connections");
sys_var_thd_ulong sys_max_tmp_tables("max_tmp_tables",
&SV::max_tmp_tables);
@@ -631,6 +633,7 @@
&sys_max_relay_log_size,
&sys_max_seeks_for_key,
&sys_max_sort_length,
+ &sys_max_sp_recursion_depth,
&sys_max_tmp_tables,
&sys_max_user_connections,
&sys_max_write_lock_count,
@@ -896,6 +899,8 @@
{sys_max_relay_log_size.name, (char*) &sys_max_relay_log_size, SHOW_SYS},
{sys_max_seeks_for_key.name, (char*) &sys_max_seeks_for_key, SHOW_SYS},
{sys_max_sort_length.name, (char*) &sys_max_sort_length, SHOW_SYS},
+ {sys_max_sp_recursion_depth.name,
+ (char*) &sys_max_sp_recursion_depth, SHOW_SYS},
{sys_max_tmp_tables.name, (char*) &sys_max_tmp_tables, SHOW_SYS},
{sys_max_user_connections.name,(char*) &sys_max_user_connections, SHOW_SYS},
{sys_max_write_lock_count.name, (char*) &sys_max_write_lock_count,SHOW_SYS},
--- 1.92/mysql-test/r/sp-error.result 2005-11-19 00:21:53 +02:00
+++ 1.93/mysql-test/r/sp-error.result 2005-11-23 01:12:33 +02:00
@@ -708,7 +708,7 @@
end if;
end|
select bug11394(2)|
-ERROR HY000: Recursive stored routines are not allowed.
+ERROR HY000: Recursive stored functions and triggers are not allowed.
drop function bug11394|
create function bug11394_1(i int) returns int
begin
@@ -719,7 +719,7 @@
end if;
end|
select bug11394_1(2)|
-ERROR HY000: Recursive stored routines are not allowed.
+ERROR HY000: Recursive stored functions and triggers are not allowed.
drop function bug11394_1|
create function bug11394_2(i int) returns int return i|
select bug11394_2(bug11394_2(10))|
@@ -733,7 +733,10 @@
end if;
end|
call bug11394(2, 1)|
-ERROR HY000: Recursive stored routines are not allowed.
+ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was
exceeded for routine bug11394
+set @@max_sp_recursion_depth=10|
+call bug11394(2, 1)|
+set @@max_sp_recursion_depth=default|
drop procedure bug11394|
CREATE PROCEDURE BUG_12490() HELP CONTENTS;
ERROR 0A000: HELP is not allowed in stored procedures
--- 1.172/mysql-test/r/sp.result 2005-11-23 00:58:09 +02:00
+++ 1.173/mysql-test/r/sp.result 2005-11-23 01:28:29 +02:00
@@ -3617,6 +3617,191 @@
drop table t3, t4|
drop procedure bug14210|
set @@session.max_heap_table_size=default|
+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 table t3|
drop function if exists bug14723|
drop procedure if exists bug14723|
/*!50003 create function bug14723()
--- 1.96/mysql-test/t/sp-error.test 2005-11-19 00:21:54 +02:00
+++ 1.97/mysql-test/t/sp-error.test 2005-11-23 01:12:33 +02:00
@@ -1044,10 +1044,11 @@
call bug11394(i - 1,(select 1));
end if;
end|
-# Again if we allow recursion for stored procedures (without
-# additional efforts) the following statement will crash the server.
---error 1424
+--error ER_SP_RECURSION_LIMIT
call bug11394(2, 1)|
+set @@max_sp_recursion_depth=10|
+call bug11394(2, 1)|
+set @@max_sp_recursion_depth=default|
drop procedure bug11394|
delimiter ;|
--- 1.165/mysql-test/t/sp.test 2005-11-23 00:58:09 +02:00
+++ 1.166/mysql-test/t/sp.test 2005-11-23 01:12:33 +02:00
@@ -4623,6 +4623,160 @@
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|
+drop table t3|
+
+
+#
# BUG#NNNN: New bug synopsis
#
#--disable_warnings
--- 1.201/sql/sp_head.cc 2005-11-23 00:51:48 +02:00
+++ 1.202/sql/sp_head.cc 2005-11-23 01:12:35 +02:00
@@ -478,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);
@@ -659,6 +660,7 @@
sp_head::~sp_head()
{
destroy();
+ delete m_next_cached_sp;
if (m_thd)
restore_thd_mem_root(m_thd);
}
@@ -885,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.
@@ -913,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 &&
@@ -1118,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);
}
--- 1.76/sql/sp_head.h 2005-11-22 14:13:19 +02:00
+++ 1.77/sql/sp_head.h 2005-11-23 01:12:35 +02:00
@@ -143,6 +143,32 @@
LEX_STRING m_definer_host;
longlong m_created;
longlong m_modified;
+ /* Recursion level of the current SP instance. The levels are numbered from 0 */
+ ulong m_recursion_level;
+ /*
+ A list of diferent recursion level instances for the same procedure.
+ For every recursion level we have a sp_head instance. This instances
+ connected in the list. The list ordered by increasing recursion level
+ (m_recursion_level).
+ */
+ sp_head *m_next_cached_sp;
+ /*
+ Pointer to the first element of the above list
+ */
+ sp_head *m_first_instance;
+ /*
+ Pointer to the first free (non-INVOKED) routine in the list of
+ cached instances for this SP. This pointer is set only for the first
+ SP in the list of instences (see above m_first_cached_sp pointer).
+ The pointer equal to 0 if we have no free instances.
+ For non-first instance value of this pointer meanless (point to itself);
+ */
+ sp_head *m_first_free_instance;
+ /*
+ Pointer to the last element in the list of instances of the SP.
+ For non-first instance value of this pointer meanless (point to itself);
+ */
+ sp_head *m_last_cached_sp;
/*
Set containing names of stored routines used by this routine.
Note that unlike elements of similar set for statement elements of this
@@ -265,6 +291,8 @@
void optimize();
void opt_mark(uint ip);
+
+ void recursion_level_error();
inline sp_instr *
get_instr(uint i)
| Thread |
|---|
| • bk commit into 5.0 tree (bell:1.1994) | sanja | 23 Nov |