Commit 151d75c2 authored by serg@serg.mylan's avatar serg@serg.mylan

merged

parents 419d82f8 83d692da
......@@ -3314,20 +3314,23 @@ static int handle_error(const char *query, struct st_query *q,
((q->expected_errno[i].type == ERR_SQLSTATE) &&
(strcmp(q->expected_errno[i].code.sqlstate, err_sqlstate) == 0)))
{
if (q->expected_errors == 1)
if (!disable_result_log)
{
/* Only log error if there is one possible error */
dynstr_append_mem(ds, "ERROR ", 6);
replace_dynstr_append(ds, err_sqlstate);
dynstr_append_mem(ds, ": ", 2);
replace_dynstr_append(ds, err_error);
dynstr_append_mem(ds,"\n",1);
if (q->expected_errors == 1)
{
/* Only log error if there is one possible error */
dynstr_append_mem(ds, "ERROR ", 6);
replace_dynstr_append(ds, err_sqlstate);
dynstr_append_mem(ds, ": ", 2);
replace_dynstr_append(ds, err_error);
dynstr_append_mem(ds,"\n",1);
}
/* Don't log error if we may not get an error */
else if (q->expected_errno[0].type == ERR_SQLSTATE ||
(q->expected_errno[0].type == ERR_ERRNO &&
q->expected_errno[0].code.errnum != 0))
dynstr_append(ds,"Got one of the listed errors\n");
}
/* Don't log error if we may not get an error */
else if (q->expected_errno[0].type == ERR_SQLSTATE ||
(q->expected_errno[0].type == ERR_ERRNO &&
q->expected_errno[0].code.errnum != 0))
dynstr_append(ds,"Got one of the listed errors\n");
/* OK */
DBUG_RETURN(0);
}
......@@ -3335,11 +3338,14 @@ static int handle_error(const char *query, struct st_query *q,
DBUG_PRINT("info",("i: %d expected_errors: %d", i, q->expected_errors));
dynstr_append_mem(ds, "ERROR ",6);
replace_dynstr_append(ds, err_sqlstate);
dynstr_append_mem(ds, ": ", 2);
replace_dynstr_append(ds, err_error);
dynstr_append_mem(ds, "\n", 1);
if (!disable_result_log)
{
dynstr_append_mem(ds, "ERROR ",6);
replace_dynstr_append(ds, err_sqlstate);
dynstr_append_mem(ds, ": ", 2);
replace_dynstr_append(ds, err_error);
dynstr_append_mem(ds, "\n", 1);
}
if (i)
{
......
......@@ -33,6 +33,8 @@ begin
execute stmt;
end|
prepare stmt from "call p1()"|
set @SAVE_SP_RECURSION_LEVELS=@@max_sp_recursion_depth|
set @@max_sp_recursion_depth=100|
execute stmt|
ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
execute stmt|
......@@ -40,11 +42,18 @@ ERROR HY000: The prepared statement contains a stored routine call that refers t
execute stmt|
ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
call p1()|
ERROR HY000: Recursive stored routines are not allowed.
ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
call p1()|
ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
call p1()|
ERROR HY000: The prepared statement contains a stored routine call that refers to that same statement. It's not allowed to execute a prepared statement in such a recursive manner
set @@max_sp_recursion_depth=@SAVE_SP_RECURSION_LEVELS|
call p1()|
ERROR HY000: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine p1
call p1()|
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 p1
call p1()|
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 p1
drop procedure p1|
create procedure p1()
begin
......
......@@ -708,7 +708,7 @@ return (i in (100, 200, bug11394(i-1), 400));
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 @@ return (select bug11394_1(i-1));
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 @@ call bug11394(i - 1,(select 1));
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
......
......@@ -3417,6 +3417,9 @@ Table Create Table
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 +3670,203 @@ call bug14845()|
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 table t3|
drop table t1,t2;
......@@ -703,8 +703,11 @@ create trigger t1_ai after insert on t1
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
......@@ -763,3 +766,17 @@ ERROR HY000: Table 't3' was not locked with LOCK TABLES
deallocate prepare stmt1;
drop procedure p1;
drop table t1, t2, t3;
create table t1 (a int);
drop procedure if exists p2;
CREATE PROCEDURE `p2`()
begin
insert into t1 values (1);
end//
create trigger trg before insert on t1 for each row
begin
declare done int default 0;
set done= not done;
end//
CALL p2();
drop procedure p2;
drop table t1;
......@@ -351,6 +351,14 @@ set global rpl_recovery_rank=100;
set global server_id=100;
set global slow_launch_time=100;
set sort_buffer_size=100;
set @@max_sp_recursion_depth=10;
select @@max_sp_recursion_depth;
@@max_sp_recursion_depth
10
set @@max_sp_recursion_depth=0;
select @@max_sp_recursion_depth;
@@max_sp_recursion_depth
0
set sql_auto_is_null=1;
select @@sql_auto_is_null;
@@sql_auto_is_null
......
......@@ -26,18 +26,29 @@ begin
execute stmt;
end|
prepare stmt from "call p1()"|
# 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_PS_NO_RECURSION
execute stmt|
--error ER_PS_NO_RECURSION
execute stmt|
--error ER_PS_NO_RECURSION
execute stmt|
--error ER_SP_NO_RECURSION
--error ER_PS_NO_RECURSION
call p1()|
--error ER_PS_NO_RECURSION
call p1()|
--error ER_SP_NO_RECURSION
--error ER_PS_NO_RECURSION
call p1()|
--error ER_SP_NO_RECURSION
set @@max_sp_recursion_depth=@SAVE_SP_RECURSION_LEVELS|
--error ER_SP_RECURSION_LIMIT
call p1()|
--error ER_SP_RECURSION_LIMIT
call p1()|
--error ER_SP_RECURSION_LIMIT
call p1()|
drop procedure p1|
#
# C. Create/drop a stored procedure in Dynamic SQL.
......
......@@ -1044,10 +1044,11 @@ begin
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 ;|
......
......@@ -4291,6 +4291,9 @@ call bug12589_1()|
# 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
......@@ -4594,6 +4597,185 @@ 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|
drop table t3|
#
# BUG#NNNN: New bug synopsis
#
......
......@@ -743,8 +743,12 @@ create trigger t1_ai after insert on t1
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;
......@@ -914,3 +918,31 @@ call p1();
deallocate prepare stmt1;
drop procedure p1;
drop table t1, t2, t3;
#
# 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.
#
create table t1 (a int);
--disable_warnings
drop procedure if exists p2;
--enable_warnings
DELIMITER //;
CREATE PROCEDURE `p2`()
begin
insert into t1 values (1);
end//
create trigger trg before insert on t1 for each row
begin
declare done int default 0;
set done= not done;
end//
DELIMITER ;//
CALL p2();
drop procedure p2;
drop table t1;
......@@ -237,6 +237,10 @@ set global rpl_recovery_rank=100;
set global server_id=100;
set global slow_launch_time=100;
set sort_buffer_size=100;
set @@max_sp_recursion_depth=10;
select @@max_sp_recursion_depth;
set @@max_sp_recursion_depth=0;
select @@max_sp_recursion_depth;
set sql_auto_is_null=1;
select @@sql_auto_is_null;
set @@sql_auto_is_null=0;
......
......@@ -894,6 +894,7 @@ bool Item_splocal::is_null()
Item *
Item_splocal::this_item()
{
DBUG_ASSERT(owner == thd->spcont->owner);
return thd->spcont->get_item(m_offset);
}
......@@ -901,12 +902,14 @@ Item_splocal::this_item()
Item **
Item_splocal::this_item_addr(THD *thd, Item **addr)
{
DBUG_ASSERT(owner == thd->spcont->owner);
return thd->spcont->get_item_addr(m_offset);
}
Item *
Item_splocal::this_const_item() const
{
DBUG_ASSERT(owner == thd->spcont->owner);
return thd->spcont->get_item(m_offset);
}
......@@ -914,7 +917,10 @@ Item::Type
Item_splocal::type() const
{
if (thd && thd->spcont)
{
DBUG_ASSERT(owner == thd->spcont->owner);
return thd->spcont->get_item(m_offset)->type();
}
return NULL_ITEM; // Anything but SUBSELECT_ITEM
}
......
......@@ -704,6 +704,8 @@ public:
};
class sp_head;
/*
A reference to local SP variable (incl. reference to SP parameter), used in
runtime.
......@@ -721,6 +723,13 @@ class Item_splocal : public Item
uint m_offset;
public:
#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
LEX_STRING m_name;
THD *thd;
......
......@@ -4690,10 +4690,16 @@ Item_func_sp::sp_result_field(void) const
{
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 @@ Item_func_sp::find_and_check_access(THD *thd, ulong want_access,
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;
......
......@@ -4545,6 +4545,7 @@ enum options_mysqld
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 @@ The minimum value for this variable is 4096.",
(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.",
......
......@@ -498,7 +498,7 @@ void Protocol::init(THD *thd_arg)
thd=thd_arg;
packet= &thd->packet;
convert= &thd->convert_buffer;
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
field_types= 0;
#endif
}
......@@ -551,7 +551,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
(void) my_net_write(&thd->net, buff,(uint) (pos-buff));
}
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
field_types= (enum_field_types*) thd->alloc(sizeof(field_types) *
list->elements);
uint count= 0;
......@@ -648,7 +648,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
item->send(&prot, &tmp); // Send default value
if (prot.write())
break; /* purecov: inspected */
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
field_types[count++]= field.type;
#endif
}
......@@ -732,14 +732,14 @@ bool Protocol::store(I_List<i_string>* str_list)
void Protocol_simple::prepare_for_resend()
{
packet->length(0);
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
field_pos= 0;
#endif
}
bool Protocol_simple::store_null()
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
field_pos++;
#endif
char buff[1];
......@@ -773,7 +773,7 @@ bool Protocol::store_string_aux(const char *from, uint length,
bool Protocol_simple::store(const char *from, uint length,
CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
field_types[field_pos] == MYSQL_TYPE_BIT ||
......@@ -790,7 +790,7 @@ bool Protocol_simple::store(const char *from, uint length,
CHARSET_INFO *fromcs)
{
CHARSET_INFO *tocs= this->thd->variables.character_set_results;
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
field_types[field_pos] == MYSQL_TYPE_BIT ||
......@@ -805,7 +805,7 @@ bool Protocol_simple::store(const char *from, uint length,
bool Protocol_simple::store_tiny(longlong from)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TINY);
field_pos++;
#endif
......@@ -817,7 +817,7 @@ bool Protocol_simple::store_tiny(longlong from)
bool Protocol_simple::store_short(longlong from)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_YEAR ||
field_types[field_pos] == MYSQL_TYPE_SHORT);
......@@ -831,7 +831,7 @@ bool Protocol_simple::store_short(longlong from)
bool Protocol_simple::store_long(longlong from)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_INT24 ||
field_types[field_pos] == MYSQL_TYPE_LONG);
......@@ -845,7 +845,7 @@ bool Protocol_simple::store_long(longlong from)
bool Protocol_simple::store_longlong(longlong from, bool unsigned_flag)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_LONGLONG);
field_pos++;
......@@ -860,7 +860,7 @@ bool Protocol_simple::store_longlong(longlong from, bool unsigned_flag)
bool Protocol_simple::store_decimal(const my_decimal *d)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
field_pos++;
......@@ -874,7 +874,7 @@ bool Protocol_simple::store_decimal(const my_decimal *d)
bool Protocol_simple::store(float from, uint32 decimals, String *buffer)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_FLOAT);
field_pos++;
......@@ -886,7 +886,7 @@ bool Protocol_simple::store(float from, uint32 decimals, String *buffer)
bool Protocol_simple::store(double from, uint32 decimals, String *buffer)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DOUBLE);
field_pos++;
......@@ -900,7 +900,7 @@ bool Protocol_simple::store(Field *field)
{
if (field->is_null())
return store_null();
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
field_pos++;
#endif
char buff[MAX_FIELD_WIDTH];
......@@ -921,7 +921,7 @@ bool Protocol_simple::store(Field *field)
bool Protocol_simple::store(TIME *tm)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DATETIME ||
field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
......@@ -944,7 +944,7 @@ bool Protocol_simple::store(TIME *tm)
bool Protocol_simple::store_date(TIME *tm)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_DATE);
field_pos++;
......@@ -963,7 +963,7 @@ bool Protocol_simple::store_date(TIME *tm)
bool Protocol_simple::store_time(TIME *tm)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_TIME);
field_pos++;
......@@ -1088,7 +1088,7 @@ bool Protocol_prep::store_longlong(longlong from, bool unsigned_flag)
bool Protocol_prep::store_decimal(const my_decimal *d)
{
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
DBUG_ASSERT(field_types == 0 ||
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
field_pos++;
......
......@@ -31,7 +31,7 @@ protected:
String *packet;
String *convert;
uint field_pos;
#ifndef DEBUG_OFF
#ifndef DBUG_OFF
enum enum_field_types *field_types;
#endif
uint field_count;
......
......@@ -261,6 +261,8 @@ sys_var_long_ptr sys_max_relay_log_size("max_relay_log_size",
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_var *sys_variables[]=
&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 @@ struct show_var_st init_vars[]= {
{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},
......
......@@ -5505,8 +5505,8 @@ ER_NO_DEFAULT_FOR_VIEW_FIELD
eng "Field of view '%-.64s.%-.64s' underlying table doesn't have a default value"
ger "Ein Feld der dem View '%-.64s.%-.64s' zugrundeliegenden Tabelle hat keinen Vorgabewert"
ER_SP_NO_RECURSION
eng "Recursive stored routines are not allowed."
ger "Rekursive gespeicherte Routinen sind nicht erlaubt"
eng "Recursive stored functions and triggers are not allowed."
ger "Rekursive gespeicherte Routinen und Triggers sind nicht erlaubt"
ER_TOO_BIG_SCALE 42000 S1009
eng "Too big scale %d specified for column '%-.64s'. Maximum is %d."
ger "Zu groer Skalierungsfaktor %d fr Feld '%-.64s' angegeben. Maximum ist %d"
......@@ -5598,3 +5598,5 @@ ER_TRG_NO_DEFINER
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"
This diff is collapsed.
......@@ -36,7 +36,8 @@ int
sp_drop_db_routines(THD *thd, char *db);
sp_head *
sp_find_procedure(THD *thd, sp_name *name, bool cache_only = 0);
sp_find_routine(THD *thd, int type, sp_name *name,
sp_cache **cp, bool cache_only);
int
sp_exists_routine(THD *thd, TABLE_LIST *procs, bool any, bool no_error);
......@@ -57,9 +58,6 @@ sp_show_create_procedure(THD *thd, sp_name *name);
int
sp_show_status_procedure(THD *thd, const char *wild);
sp_head *
sp_find_function(THD *thd, sp_name *name, bool cache_only = 0);
int
sp_create_function(THD *thd, sp_head *sp);
......
......@@ -478,7 +478,8 @@ sp_head::operator delete(void *ptr, size_t size)
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::create(THD *thd)
sp_head::~sp_head()
{
destroy();
delete m_next_cached_sp;
if (m_thd)
restore_thd_mem_root(m_thd);
}
......@@ -884,6 +886,31 @@ static bool subst_spvars(THD *thd, sp_instr *instr, LEX_STRING *query_str)
}
/*
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 @@ int sp_head::execute(THD *thd)
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 @@ int sp_head::execute(THD *thd)
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);
}
......@@ -1175,6 +1219,9 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
// 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);
......@@ -1319,6 +1366,9 @@ int sp_head::execute_procedure(THD *thd, List<Item> *args)
{ // 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 */
......@@ -1330,6 +1380,9 @@ int sp_head::execute_procedure(THD *thd, List<Item> *args)
thd->spcont= save_spcont;
DBUG_RETURN(-1);
}
#ifndef DBUG_OFF
nctx->owner= this;
#endif
if (csize > 0 || hmax > 0 || cmax > 0)
{
......
......@@ -143,6 +143,32 @@ public:
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
......@@ -266,6 +292,8 @@ public:
void optimize();
void opt_mark(uint ip);
void recursion_level_error();
inline sp_instr *
get_instr(uint i)
{
......
......@@ -66,6 +66,14 @@ class sp_rcontext : public Sql_alloc
*/
Query_arena *callers_arena;
#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
sp_rcontext(sp_rcontext *prev, uint fsize, uint hmax, uint cmax);
~sp_rcontext()
......
......@@ -1088,6 +1088,11 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
/* 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,
......
......@@ -410,7 +410,7 @@ protected:
/*
The following functions are only used when debugging
We don't protect these with ifndef DEBUG_OFF to not have to recompile
We don't protect these with ifndef DBUG_OFF to not have to recompile
everything if we want to add checks of the cache at some places.
*/
void wreck(uint line, const char *message);
......
......@@ -1495,7 +1495,13 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
my_var *mv= gl++;
if (mv->local)
(void)local_vars.push_back(new Item_splocal(mv->s, mv->offset));
{
Item_splocal *var;
(void)local_vars.push_back(var= new Item_splocal(mv->s, mv->offset));
#ifndef DEBUG_OFF
var->owner= mv->owner;
#endif
}
else
{
Item_func_set_user_var *var= new Item_func_set_user_var(mv->s, item);
......
......@@ -530,6 +530,7 @@ struct system_variables
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;
......@@ -2085,6 +2086,13 @@ public:
class my_var : public Sql_alloc {
public:
LEX_STRING s;
#ifndef DEBUG_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;
......
......@@ -3682,7 +3682,8 @@ end_with_restore_list:
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 @@ end_with_restore_list:
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 @@ end_with_restore_list:
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 @@ end_with_restore_list:
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)
{
......@@ -4560,9 +4566,11 @@ end_with_restore_list:
goto error;
}
if (lex->sql_command == SQLCOM_SHOW_PROC_CODE)
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);
if (!sp || !sp->show_routine_code(thd))
{
/* We don't distinguish between errors for now */
......
......@@ -816,6 +816,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
List_iterator_fast<LEX_STRING> it_definer(triggers->
definers_list);
LEX *old_lex= thd->lex, lex;
sp_rcontext *save_spcont= thd->spcont;
ulong save_sql_mode= thd->variables.sql_mode;
thd->lex= &lex;
......@@ -831,6 +832,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
thd->variables.sql_mode= (ulong)*trg_sql_mode;
lex_start(thd, (uchar*)trg_create_str->str, trg_create_str->length);
thd->spcont= 0;
if (yyparse((void *)thd) || thd->is_fatal_error)
{
/*
......@@ -911,6 +913,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
thd->db= save_db.str;
thd->db_length= save_db.length;
thd->lex= old_lex;
thd->spcont= save_spcont;
thd->variables.sql_mode= save_sql_mode;
DBUG_RETURN(0);
......@@ -919,6 +922,7 @@ err_with_lex_cleanup:
// QQ: anything else ?
lex_end(&lex);
thd->lex= old_lex;
thd->spcont= save_spcont;
thd->variables.sql_mode= save_sql_mode;
thd->db= save_db.str;
thd->db_length= save_db.length;
......
......@@ -2286,8 +2286,12 @@ sp_case:
ivar.str= (char *)"_tmp_";
ivar.length= 5;
Item *var= (Item*) new Item_splocal(ivar,
ctx->current_pvars()-1);
Item_splocal *var= new Item_splocal(ivar,
ctx->current_pvars()-1);
#ifndef DEBUG_OFF
if (var)
var->owner= sp;
#endif
Item *expr= new Item_func_eq(var, $2);
i= new sp_instr_jump_if_not(ip, ctx, expr, lex);
......@@ -5868,7 +5872,13 @@ select_var_ident:
YYABORT;
else
{
((select_dumpvar *)lex->result)->var_list.push_back( new my_var($1,1,t->offset,t->type));
my_var *var;
((select_dumpvar *)lex->result)->
var_list.push_back(var= new my_var($1,1,t->offset,t->type));
#ifndef DEBUG_OFF
if (var)
var->owner= lex->sphead;
#endif
}
}
;
......@@ -7171,6 +7181,10 @@ simple_ident:
Item_splocal *splocal;
splocal= new Item_splocal($1, spv->offset, lex->tok_start_prev -
lex->sphead->m_tmp_query);
#ifndef DEBUG_OFF
if (splocal)
splocal->owner= lex->sphead;
#endif
$$ = (Item*) splocal;
lex->variables_used= 1;
lex->safe_to_cache_query=0;
......
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