MDEV-23094: Multiple calls to a Stored Procedure from another Stored Procedure crashes server
Added system-SELECT to IF/WHILE/REPET/FOR for correct subqueries connecting. Added control of system/usual selects for correct error detection.
This commit is contained in:
parent
571764c04f
commit
0f080dd60a
@ -1908,4 +1908,93 @@ KILL ( SELECT 1 ) + LASTVAL(s);
|
||||
ERROR 42000: KILL does not support subqueries or stored functions
|
||||
KILL LASTVAL(s);
|
||||
ERROR 42000: KILL does not support subqueries or stored functions
|
||||
#
|
||||
# MDEV-23094: Multiple calls to a Stored Procedure from another
|
||||
# Stored Procedure crashes server
|
||||
#
|
||||
create table t1 (id1 int primary key, data1 int);
|
||||
create table t2 (id2 int primary key, data2 int);
|
||||
create procedure p1(IN id int, IN dt int)
|
||||
begin
|
||||
if (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt))
|
||||
then
|
||||
select 1;
|
||||
end if;
|
||||
end //
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
drop procedure p1;
|
||||
create procedure p1(IN id int, IN dt int)
|
||||
begin
|
||||
case (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt))
|
||||
when 1 then
|
||||
select 1;
|
||||
else
|
||||
select 0;
|
||||
end case;
|
||||
end //
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
drop procedure p1;
|
||||
create procedure p1(IN id int, IN dt int)
|
||||
begin
|
||||
declare wcont int default 1;
|
||||
while (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt)) and wcont
|
||||
do
|
||||
select 1;
|
||||
set wcont=0;
|
||||
end while;
|
||||
end //
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
drop procedure p1;
|
||||
create procedure p1(IN id int, IN dt int)
|
||||
begin
|
||||
declare count int default 1;
|
||||
repeat
|
||||
select 1;
|
||||
set count=count+1;
|
||||
until (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt)) and
|
||||
count < 3
|
||||
end repeat;
|
||||
end //
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
drop procedure p1;
|
||||
create procedure p1(IN id int, IN dt int)
|
||||
begin
|
||||
for i in 1..(exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt))
|
||||
do
|
||||
select 1;
|
||||
end for;
|
||||
end //
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
drop procedure p1;
|
||||
drop table t1,t2;
|
||||
# End of 10.4 tests
|
||||
|
@ -1696,4 +1696,101 @@ KILL ( SELECT 1 ) + LASTVAL(s);
|
||||
--error ER_SUBQUERIES_NOT_SUPPORTED
|
||||
KILL LASTVAL(s);
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-23094: Multiple calls to a Stored Procedure from another
|
||||
--echo # Stored Procedure crashes server
|
||||
--echo #
|
||||
|
||||
create table t1 (id1 int primary key, data1 int);
|
||||
create table t2 (id2 int primary key, data2 int);
|
||||
|
||||
delimiter //;
|
||||
create procedure p1(IN id int, IN dt int)
|
||||
begin
|
||||
if (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt))
|
||||
then
|
||||
select 1;
|
||||
end if;
|
||||
end //
|
||||
delimiter ;//
|
||||
|
||||
call p1(1,2);
|
||||
call p1(1,2);
|
||||
|
||||
drop procedure p1;
|
||||
|
||||
delimiter //;
|
||||
create procedure p1(IN id int, IN dt int)
|
||||
begin
|
||||
case (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt))
|
||||
when 1 then
|
||||
select 1;
|
||||
else
|
||||
select 0;
|
||||
end case;
|
||||
end //
|
||||
delimiter ;//
|
||||
|
||||
call p1(1,2);
|
||||
call p1(1,2);
|
||||
|
||||
drop procedure p1;
|
||||
|
||||
delimiter //;
|
||||
create procedure p1(IN id int, IN dt int)
|
||||
begin
|
||||
declare wcont int default 1;
|
||||
while (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt)) and wcont
|
||||
do
|
||||
select 1;
|
||||
set wcont=0;
|
||||
end while;
|
||||
end //
|
||||
delimiter ;//
|
||||
|
||||
call p1(1,2);
|
||||
call p1(1,2);
|
||||
|
||||
drop procedure p1;
|
||||
|
||||
delimiter //;
|
||||
create procedure p1(IN id int, IN dt int)
|
||||
begin
|
||||
declare count int default 1;
|
||||
repeat
|
||||
select 1;
|
||||
set count=count+1;
|
||||
until (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt)) and
|
||||
count < 3
|
||||
end repeat;
|
||||
end //
|
||||
delimiter ;//
|
||||
|
||||
call p1(1,2);
|
||||
call p1(1,2);
|
||||
|
||||
drop procedure p1;
|
||||
|
||||
delimiter //;
|
||||
create procedure p1(IN id int, IN dt int)
|
||||
begin
|
||||
for i in 1..(exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt))
|
||||
do
|
||||
select 1;
|
||||
end for;
|
||||
end //
|
||||
delimiter ;//
|
||||
|
||||
call p1(1,2);
|
||||
call p1(1,2);
|
||||
|
||||
drop procedure p1;
|
||||
|
||||
drop table t1,t2;
|
||||
|
||||
--echo # End of 10.4 tests
|
||||
|
@ -643,3 +643,118 @@ END;
|
||||
#
|
||||
# End of 10.3 tests
|
||||
#
|
||||
#
|
||||
# MDEV-21998: Server crashes in st_select_lex::add_table_to_list
|
||||
# upon mix of KILL and sequences
|
||||
#
|
||||
KILL ( SELECT 1 ) + LASTVAL(s);
|
||||
ERROR 42000: KILL does not support subqueries or stored functions
|
||||
KILL LASTVAL(s);
|
||||
ERROR 42000: KILL does not support subqueries or stored functions
|
||||
#
|
||||
# MDEV-23094: Multiple calls to a Stored Procedure from another
|
||||
# Stored Procedure crashes server
|
||||
#
|
||||
create table t1 (id1 int primary key, data1 int);
|
||||
create table t2 (id2 int primary key, data2 int);
|
||||
create procedure p1(id int,dt int) as
|
||||
begin
|
||||
if (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt))
|
||||
then
|
||||
select 1;
|
||||
end if;
|
||||
end //
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
drop procedure p1;
|
||||
create procedure p1(id int, dt int) as
|
||||
begin
|
||||
case (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt))
|
||||
when 1 then
|
||||
select 1;
|
||||
else
|
||||
select 0;
|
||||
end case;
|
||||
end //
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
drop procedure p1;
|
||||
create procedure p1(id int, dt int) as
|
||||
begin
|
||||
declare wcont int default 1;
|
||||
begin
|
||||
while (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt)) and wcont
|
||||
loop
|
||||
select 1;
|
||||
set wcont=0;
|
||||
end loop;
|
||||
end;
|
||||
end //
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
drop procedure p1;
|
||||
create procedure p1(id int, dt int) as
|
||||
begin
|
||||
declare count int default 1;
|
||||
begin
|
||||
repeat
|
||||
select 1;
|
||||
set count=count+1;
|
||||
until (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt)) and
|
||||
count < 3
|
||||
end repeat;
|
||||
end;
|
||||
end //
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
drop procedure p1;
|
||||
create procedure p1(id int, dt int) as
|
||||
begin
|
||||
for i in 1..(exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt))
|
||||
loop
|
||||
select 1;
|
||||
end loop;
|
||||
end //
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
call p1(1,2);
|
||||
1
|
||||
1
|
||||
drop procedure p1;
|
||||
set sql_mode=ORACLE;
|
||||
create or replace procedure p1(id int, dt int) as
|
||||
begin
|
||||
while (1)
|
||||
loop
|
||||
exit when (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt));
|
||||
end loop;
|
||||
end;
|
||||
//
|
||||
call p1(1,2);
|
||||
call p1(1,2);
|
||||
drop procedure p1;
|
||||
drop table t1,t2;
|
||||
# End of 10.4 tests
|
||||
|
@ -459,3 +459,135 @@ DELIMITER ;//
|
||||
--echo #
|
||||
--echo # End of 10.3 tests
|
||||
--echo #
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-21998: Server crashes in st_select_lex::add_table_to_list
|
||||
--echo # upon mix of KILL and sequences
|
||||
--echo #
|
||||
|
||||
--error ER_SUBQUERIES_NOT_SUPPORTED
|
||||
KILL ( SELECT 1 ) + LASTVAL(s);
|
||||
--error ER_SUBQUERIES_NOT_SUPPORTED
|
||||
KILL LASTVAL(s);
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-23094: Multiple calls to a Stored Procedure from another
|
||||
--echo # Stored Procedure crashes server
|
||||
--echo #
|
||||
|
||||
create table t1 (id1 int primary key, data1 int);
|
||||
create table t2 (id2 int primary key, data2 int);
|
||||
|
||||
delimiter //;
|
||||
create procedure p1(id int,dt int) as
|
||||
begin
|
||||
if (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt))
|
||||
then
|
||||
select 1;
|
||||
end if;
|
||||
end //
|
||||
delimiter ;//
|
||||
|
||||
call p1(1,2);
|
||||
call p1(1,2);
|
||||
|
||||
drop procedure p1;
|
||||
|
||||
delimiter //;
|
||||
create procedure p1(id int, dt int) as
|
||||
begin
|
||||
case (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt))
|
||||
when 1 then
|
||||
select 1;
|
||||
else
|
||||
select 0;
|
||||
end case;
|
||||
end //
|
||||
delimiter ;//
|
||||
|
||||
call p1(1,2);
|
||||
call p1(1,2);
|
||||
|
||||
drop procedure p1;
|
||||
|
||||
delimiter //;
|
||||
create procedure p1(id int, dt int) as
|
||||
begin
|
||||
declare wcont int default 1;
|
||||
begin
|
||||
while (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt)) and wcont
|
||||
loop
|
||||
select 1;
|
||||
set wcont=0;
|
||||
end loop;
|
||||
end;
|
||||
end //
|
||||
delimiter ;//
|
||||
|
||||
call p1(1,2);
|
||||
call p1(1,2);
|
||||
|
||||
drop procedure p1;
|
||||
|
||||
delimiter //;
|
||||
create procedure p1(id int, dt int) as
|
||||
begin
|
||||
declare count int default 1;
|
||||
begin
|
||||
repeat
|
||||
select 1;
|
||||
set count=count+1;
|
||||
until (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt)) and
|
||||
count < 3
|
||||
end repeat;
|
||||
end;
|
||||
end //
|
||||
delimiter ;//
|
||||
|
||||
call p1(1,2);
|
||||
call p1(1,2);
|
||||
|
||||
drop procedure p1;
|
||||
|
||||
delimiter //;
|
||||
create procedure p1(id int, dt int) as
|
||||
begin
|
||||
for i in 1..(exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt))
|
||||
loop
|
||||
select 1;
|
||||
end loop;
|
||||
end //
|
||||
delimiter ;//
|
||||
|
||||
call p1(1,2);
|
||||
call p1(1,2);
|
||||
|
||||
drop procedure p1;
|
||||
|
||||
delimiter //;
|
||||
set sql_mode=ORACLE;
|
||||
create or replace procedure p1(id int, dt int) as
|
||||
begin
|
||||
while (1)
|
||||
loop
|
||||
exit when (exists(select * from t1 where id1 = id and data1 = dt) or
|
||||
not exists (select * from t2 where id2 = id and data2 = dt));
|
||||
end loop;
|
||||
end;
|
||||
//
|
||||
delimiter ;//
|
||||
|
||||
call p1(1,2);
|
||||
call p1(1,2);
|
||||
|
||||
drop procedure p1;
|
||||
|
||||
drop table t1,t2;
|
||||
|
||||
--echo # End of 10.4 tests
|
||||
|
@ -2428,6 +2428,7 @@ void st_select_lex::init_query()
|
||||
changed_elements= 0;
|
||||
first_natural_join_processing= 1;
|
||||
first_cond_optimization= 1;
|
||||
is_service_select= 0;
|
||||
parsing_place= NO_MATTER;
|
||||
save_parsing_place= NO_MATTER;
|
||||
exclude_from_table_unique_test= no_wrap_view_item= FALSE;
|
||||
@ -7614,7 +7615,7 @@ Item *LEX::create_item_ident_sp(THD *thd, Lex_ident_sys_st *name,
|
||||
return new (thd->mem_root) Item_func_sqlerrm(thd);
|
||||
}
|
||||
|
||||
if (!select_stack_head() &&
|
||||
if (fields_are_impossible() &&
|
||||
(current_select->parsing_place != FOR_LOOP_BOUND ||
|
||||
spcont->find_cursor(name, &unused_off, false) == NULL))
|
||||
{
|
||||
@ -8940,11 +8941,12 @@ void st_select_lex::add_statistics(SELECT_LEX_UNIT *unit)
|
||||
}
|
||||
|
||||
|
||||
bool LEX::main_select_push()
|
||||
bool LEX::main_select_push(bool service)
|
||||
{
|
||||
DBUG_ENTER("LEX::main_select_push");
|
||||
current_select_number= 1;
|
||||
builtin_select.select_number= 1;
|
||||
builtin_select.is_service_select= service;
|
||||
if (push_select(&builtin_select))
|
||||
DBUG_RETURN(TRUE);
|
||||
DBUG_RETURN(FALSE);
|
||||
|
@ -1249,6 +1249,8 @@ public:
|
||||
bool no_wrap_view_item;
|
||||
/* exclude this select from check of unique_table() */
|
||||
bool exclude_from_table_unique_test;
|
||||
/* the select is "service-select" and can not have tables*/
|
||||
bool is_service_select;
|
||||
/* index in the select list of the expression currently being fixed */
|
||||
int cur_pos_in_select_list;
|
||||
|
||||
@ -4413,7 +4415,7 @@ public:
|
||||
SELECT_LEX_UNIT *create_unit(SELECT_LEX*);
|
||||
SELECT_LEX *wrap_unit_into_derived(SELECT_LEX_UNIT *unit);
|
||||
SELECT_LEX *wrap_select_chain_into_derived(SELECT_LEX *sel);
|
||||
bool main_select_push();
|
||||
bool main_select_push(bool service= false);
|
||||
bool insert_select_hack(SELECT_LEX *sel);
|
||||
SELECT_LEX *create_priority_nest(SELECT_LEX *first_in_nest);
|
||||
|
||||
@ -4530,6 +4532,16 @@ public:
|
||||
Lex_field_type_st *type) const;
|
||||
|
||||
void mark_first_table_as_inserting();
|
||||
|
||||
bool fields_are_impossible()
|
||||
{
|
||||
// no select or it is last select with no tables (service select)
|
||||
return !select_stack_head() ||
|
||||
(select_stack_top == 1 &&
|
||||
select_stack[0]->is_service_select);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -8049,6 +8049,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
|
||||
(alias ? alias->str : table->table.str),
|
||||
table,
|
||||
this, select_number));
|
||||
DBUG_ASSERT(!is_service_select || (table_options & TL_OPTION_SEQUENCE));
|
||||
|
||||
if (unlikely(!table))
|
||||
DBUG_RETURN(0); // End of memory
|
||||
|
@ -1131,6 +1131,8 @@ JOIN::prepare(TABLE_LIST *tables_init,
|
||||
proc_param= proc_param_init;
|
||||
tables_list= tables_init;
|
||||
select_lex= select_lex_arg;
|
||||
DBUG_PRINT("info", ("select %p (%u) = JOIN %p",
|
||||
select_lex, select_lex->select_number, this));
|
||||
select_lex->join= this;
|
||||
join_list= &select_lex->top_join_list;
|
||||
union_part= unit_arg->is_unit_op();
|
||||
@ -4494,6 +4496,9 @@ int
|
||||
JOIN::destroy()
|
||||
{
|
||||
DBUG_ENTER("JOIN::destroy");
|
||||
|
||||
DBUG_PRINT("info", ("select %p (%u) <> JOIN %p",
|
||||
select_lex, select_lex->select_number, this));
|
||||
select_lex->join= 0;
|
||||
|
||||
cond_equal= 0;
|
||||
|
@ -2080,6 +2080,8 @@ bool st_select_lex::cleanup()
|
||||
bool error= FALSE;
|
||||
DBUG_ENTER("st_select_lex::cleanup()");
|
||||
|
||||
DBUG_PRINT("info", ("select: %p (%u) JOIN %p",
|
||||
this, select_number, join));
|
||||
cleanup_order(order_list.first);
|
||||
cleanup_order(group_list.first);
|
||||
cleanup_ftfuncs(this);
|
||||
|
@ -2809,8 +2809,6 @@ create:
|
||||
{
|
||||
Lex->create_info.default_table_charset= NULL;
|
||||
Lex->create_info.used_fields= 0;
|
||||
if (Lex->main_select_push())
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
opt_create_database_options
|
||||
{
|
||||
@ -2819,7 +2817,6 @@ create:
|
||||
$1 | $3)))
|
||||
MYSQL_YYABORT;
|
||||
lex->name= $4;
|
||||
Lex->pop_select(); //main select
|
||||
}
|
||||
| create_or_replace definer_opt opt_view_suid VIEW_SYM
|
||||
opt_if_not_exists table_ident
|
||||
@ -3653,10 +3650,13 @@ sp_cursor_stmt:
|
||||
{
|
||||
DBUG_ASSERT(thd->free_list == NULL);
|
||||
Lex->sphead->reset_lex(thd, $1);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
select
|
||||
{
|
||||
DBUG_ASSERT(Lex == $1);
|
||||
Lex->pop_select(); //main select
|
||||
if (unlikely($1->stmt_finalize(thd)) ||
|
||||
unlikely($1->sphead->restore_lex(thd)))
|
||||
MYSQL_YYABORT;
|
||||
@ -4154,6 +4154,11 @@ sp_proc_stmt_statement:
|
||||
Lex_input_stream *lip= YYLIP;
|
||||
|
||||
lex->sphead->reset_lex(thd);
|
||||
/*
|
||||
We should not push main select here, it will be done or not
|
||||
done by the statement, we just provide only a new LEX for the
|
||||
statement here as if it is start of parsing a new statement.
|
||||
*/
|
||||
lex->sphead->m_tmp_query= lip->get_tok_start();
|
||||
}
|
||||
statement
|
||||
@ -4172,11 +4177,16 @@ RETURN_ALLMODES_SYM:
|
||||
|
||||
sp_proc_stmt_return:
|
||||
RETURN_ALLMODES_SYM
|
||||
{ Lex->sphead->reset_lex(thd); }
|
||||
{
|
||||
Lex->sphead->reset_lex(thd);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
expr
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp= lex->sphead;
|
||||
Lex->pop_select(); //main select
|
||||
if (unlikely(sp->m_handler->add_instr_freturn(thd, sp, lex->spcont,
|
||||
$3, lex)) ||
|
||||
unlikely(sp->restore_lex(thd)))
|
||||
@ -4193,7 +4203,16 @@ sp_proc_stmt_return:
|
||||
;
|
||||
|
||||
reset_lex_expr:
|
||||
{ Lex->sphead->reset_lex(thd); } expr { $$= $2; }
|
||||
{
|
||||
Lex->sphead->reset_lex(thd);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
expr
|
||||
{
|
||||
Lex->pop_select(); //main select
|
||||
$$= $2;
|
||||
}
|
||||
;
|
||||
|
||||
sp_proc_stmt_exit_oracle:
|
||||
@ -4285,6 +4304,8 @@ assignment_source_expr:
|
||||
{
|
||||
DBUG_ASSERT(thd->free_list == NULL);
|
||||
Lex->sphead->reset_lex(thd, $1);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
expr
|
||||
{
|
||||
@ -4293,6 +4314,7 @@ assignment_source_expr:
|
||||
$$->sp_lex_in_use= true;
|
||||
$$->set_item_and_free_list($3, thd->free_list);
|
||||
thd->free_list= NULL;
|
||||
Lex->pop_select(); //min select
|
||||
if ($$->sphead->restore_lex(thd))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
@ -4302,6 +4324,8 @@ for_loop_bound_expr:
|
||||
assignment_source_lex
|
||||
{
|
||||
Lex->sphead->reset_lex(thd, $1);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
Lex->current_select->parsing_place= FOR_LOOP_BOUND;
|
||||
}
|
||||
expr
|
||||
@ -4310,6 +4334,7 @@ for_loop_bound_expr:
|
||||
$$= $1;
|
||||
$$->sp_lex_in_use= true;
|
||||
$$->set_item_and_free_list($3, NULL);
|
||||
Lex->pop_select(); //main select
|
||||
if (unlikely($$->sphead->restore_lex(thd)))
|
||||
MYSQL_YYABORT;
|
||||
Lex->current_select->parsing_place= NO_MATTER;
|
||||
@ -4424,7 +4449,11 @@ sp_fetch_list:
|
||||
;
|
||||
|
||||
sp_if:
|
||||
{ Lex->sphead->reset_lex(thd); }
|
||||
{
|
||||
Lex->sphead->reset_lex(thd);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
expr THEN_SYM
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
@ -4438,6 +4467,7 @@ sp_if:
|
||||
unlikely(sp->add_cont_backpatch(i)) ||
|
||||
unlikely(sp->add_instr(i)))
|
||||
MYSQL_YYABORT;
|
||||
Lex->pop_select(); //main select
|
||||
if (unlikely(sp->restore_lex(thd)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
@ -4538,12 +4568,17 @@ case_stmt_specification:
|
||||
;
|
||||
|
||||
case_stmt_body:
|
||||
{ Lex->sphead->reset_lex(thd); /* For expr $2 */ }
|
||||
{
|
||||
Lex->sphead->reset_lex(thd); /* For expr $2 */
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
expr
|
||||
{
|
||||
if (unlikely(Lex->case_stmt_action_expr($2)))
|
||||
MYSQL_YYABORT;
|
||||
|
||||
Lex->pop_select(); //main select
|
||||
if (Lex->sphead->restore_lex(thd))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
@ -4567,6 +4602,8 @@ simple_when_clause:
|
||||
WHEN_SYM
|
||||
{
|
||||
Lex->sphead->reset_lex(thd); /* For expr $3 */
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
expr
|
||||
{
|
||||
@ -4575,6 +4612,7 @@ simple_when_clause:
|
||||
LEX *lex= Lex;
|
||||
if (unlikely(lex->case_stmt_action_when($3, true)))
|
||||
MYSQL_YYABORT;
|
||||
Lex->pop_select(); //main select
|
||||
/* For expr $3 */
|
||||
if (unlikely(lex->sphead->restore_lex(thd)))
|
||||
MYSQL_YYABORT;
|
||||
@ -4591,12 +4629,15 @@ searched_when_clause:
|
||||
WHEN_SYM
|
||||
{
|
||||
Lex->sphead->reset_lex(thd); /* For expr $3 */
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
expr
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
if (unlikely(lex->case_stmt_action_when($3, false)))
|
||||
MYSQL_YYABORT;
|
||||
Lex->pop_select(); //main select
|
||||
/* For expr $3 */
|
||||
if (unlikely(lex->sphead->restore_lex(thd)))
|
||||
MYSQL_YYABORT;
|
||||
@ -4695,9 +4736,15 @@ opt_sp_for_loop_direction:
|
||||
;
|
||||
|
||||
sp_for_loop_index_and_bounds:
|
||||
ident sp_for_loop_bounds
|
||||
ident
|
||||
{
|
||||
if (unlikely(Lex->sp_for_loop_declarations(thd, &$$, &$1, $2)))
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
sp_for_loop_bounds
|
||||
{
|
||||
Lex->pop_select(); //main select
|
||||
if (unlikely(Lex->sp_for_loop_declarations(thd, &$$, &$1, $3)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
@ -4743,8 +4790,11 @@ while_body:
|
||||
LEX *lex= Lex;
|
||||
if (unlikely(lex->sp_while_loop_expression(thd, $1)))
|
||||
MYSQL_YYABORT;
|
||||
Lex->pop_select(); //main select
|
||||
if (lex->sphead->restore_lex(thd))
|
||||
MYSQL_YYABORT;
|
||||
if (lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
sp_proc_stmts1 END WHILE_SYM
|
||||
{
|
||||
@ -4755,7 +4805,11 @@ while_body:
|
||||
|
||||
repeat_body:
|
||||
sp_proc_stmts1 UNTIL_SYM
|
||||
{ Lex->sphead->reset_lex(thd); }
|
||||
{
|
||||
Lex->sphead->reset_lex(thd);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
expr END REPEAT_SYM
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
@ -4766,6 +4820,7 @@ repeat_body:
|
||||
if (unlikely(i == NULL) ||
|
||||
unlikely(lex->sphead->add_instr(i)))
|
||||
MYSQL_YYABORT;
|
||||
Lex->pop_select(); //main select
|
||||
if (lex->sphead->restore_lex(thd))
|
||||
MYSQL_YYABORT;
|
||||
/* We can shortcut the cont_backpatch here */
|
||||
@ -4794,6 +4849,8 @@ sp_labeled_control:
|
||||
if (unlikely(Lex->sp_push_loop_label(thd, &$1)))
|
||||
MYSQL_YYABORT;
|
||||
Lex->sphead->reset_lex(thd);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
while_body pop_sp_loop_label
|
||||
{ }
|
||||
@ -4845,6 +4902,8 @@ sp_unlabeled_control:
|
||||
if (unlikely(Lex->sp_push_loop_empty_label(thd)))
|
||||
MYSQL_YYABORT;
|
||||
Lex->sphead->reset_lex(thd);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
while_body
|
||||
{
|
||||
@ -7816,7 +7875,7 @@ alter:
|
||||
{
|
||||
Lex->create_info.default_table_charset= NULL;
|
||||
Lex->create_info.used_fields= 0;
|
||||
if (Lex->main_select_push())
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
create_database_options
|
||||
@ -13265,7 +13324,7 @@ do:
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->sql_command = SQLCOM_DO;
|
||||
if (lex->main_select_push())
|
||||
if (lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
mysql_init_select(lex);
|
||||
}
|
||||
@ -16453,7 +16512,7 @@ set:
|
||||
SET
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
if (lex->main_select_push())
|
||||
if (lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
lex->set_stmt_init();
|
||||
lex->var_list.empty();
|
||||
|
@ -2311,8 +2311,6 @@ create:
|
||||
{
|
||||
Lex->create_info.default_table_charset= NULL;
|
||||
Lex->create_info.used_fields= 0;
|
||||
if (Lex->main_select_push())
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
opt_create_database_options
|
||||
{
|
||||
@ -2321,7 +2319,6 @@ create:
|
||||
$1 | $3)))
|
||||
MYSQL_YYABORT;
|
||||
lex->name= $4;
|
||||
Lex->pop_select(); //main select
|
||||
}
|
||||
| create_or_replace definer_opt opt_view_suid VIEW_SYM
|
||||
opt_if_not_exists table_ident
|
||||
@ -3547,10 +3544,13 @@ sp_cursor_stmt:
|
||||
{
|
||||
DBUG_ASSERT(thd->free_list == NULL);
|
||||
Lex->sphead->reset_lex(thd, $1);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
select
|
||||
{
|
||||
DBUG_ASSERT(Lex == $1);
|
||||
Lex->pop_select(); //main select
|
||||
if (unlikely($1->stmt_finalize(thd)) ||
|
||||
unlikely($1->sphead->restore_lex(thd)))
|
||||
MYSQL_YYABORT;
|
||||
@ -4061,6 +4061,11 @@ sp_proc_stmt_statement:
|
||||
Lex_input_stream *lip= YYLIP;
|
||||
|
||||
lex->sphead->reset_lex(thd);
|
||||
/*
|
||||
We should not push main select here, it will be done or not
|
||||
done by the statement, we just provide only new LEX for the
|
||||
statement here as if it is start of parsing new statement.
|
||||
*/
|
||||
lex->sphead->m_tmp_query= lip->get_tok_start();
|
||||
}
|
||||
sp_statement
|
||||
@ -4079,11 +4084,16 @@ RETURN_ALLMODES_SYM:
|
||||
|
||||
sp_proc_stmt_return:
|
||||
RETURN_ALLMODES_SYM
|
||||
{ Lex->sphead->reset_lex(thd); }
|
||||
{
|
||||
Lex->sphead->reset_lex(thd);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
expr
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp= lex->sphead;
|
||||
Lex->pop_select(); //main select
|
||||
if (unlikely(sp->m_handler->add_instr_freturn(thd, sp, lex->spcont,
|
||||
$3, lex)) ||
|
||||
unlikely(sp->restore_lex(thd)))
|
||||
@ -4100,9 +4110,16 @@ sp_proc_stmt_return:
|
||||
;
|
||||
|
||||
reset_lex_expr:
|
||||
{ Lex->sphead->reset_lex(thd); }
|
||||
{
|
||||
Lex->sphead->reset_lex(thd);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
expr
|
||||
{ $$= $2; }
|
||||
{
|
||||
$$= $2;
|
||||
Lex->pop_select(); //main select
|
||||
}
|
||||
;
|
||||
|
||||
sp_proc_stmt_exit_oracle:
|
||||
@ -4201,6 +4218,8 @@ assignment_source_expr:
|
||||
{
|
||||
DBUG_ASSERT(thd->free_list == NULL);
|
||||
Lex->sphead->reset_lex(thd, $1);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
expr
|
||||
{
|
||||
@ -4209,6 +4228,7 @@ assignment_source_expr:
|
||||
$$->sp_lex_in_use= true;
|
||||
$$->set_item_and_free_list($3, thd->free_list);
|
||||
thd->free_list= NULL;
|
||||
Lex->pop_select(); //main select
|
||||
if ($$->sphead->restore_lex(thd))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
@ -4218,6 +4238,8 @@ for_loop_bound_expr:
|
||||
assignment_source_lex
|
||||
{
|
||||
Lex->sphead->reset_lex(thd, $1);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
Lex->current_select->parsing_place= FOR_LOOP_BOUND;
|
||||
}
|
||||
expr
|
||||
@ -4226,6 +4248,7 @@ for_loop_bound_expr:
|
||||
$$= $1;
|
||||
$$->sp_lex_in_use= true;
|
||||
$$->set_item_and_free_list($3, NULL);
|
||||
Lex->pop_select(); //main select
|
||||
if (unlikely($$->sphead->restore_lex(thd)))
|
||||
MYSQL_YYABORT;
|
||||
Lex->current_select->parsing_place= NO_MATTER;
|
||||
@ -4338,7 +4361,11 @@ sp_fetch_list:
|
||||
;
|
||||
|
||||
sp_if:
|
||||
{ Lex->sphead->reset_lex(thd); }
|
||||
{
|
||||
Lex->sphead->reset_lex(thd);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
expr THEN_SYM
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
@ -4352,6 +4379,7 @@ sp_if:
|
||||
unlikely(sp->add_cont_backpatch(i)) ||
|
||||
unlikely(sp->add_instr(i)))
|
||||
MYSQL_YYABORT;
|
||||
Lex->pop_select(); //main select
|
||||
if (unlikely(sp->restore_lex(thd)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
@ -4452,12 +4480,17 @@ case_stmt_specification:
|
||||
;
|
||||
|
||||
case_stmt_body:
|
||||
{ Lex->sphead->reset_lex(thd); /* For expr $2 */ }
|
||||
{
|
||||
Lex->sphead->reset_lex(thd); /* For expr $2 */
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
expr
|
||||
{
|
||||
if (unlikely(Lex->case_stmt_action_expr($2)))
|
||||
MYSQL_YYABORT;
|
||||
|
||||
Lex->pop_select(); //main select
|
||||
if (Lex->sphead->restore_lex(thd))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
@ -4481,6 +4514,8 @@ simple_when_clause:
|
||||
WHEN_SYM
|
||||
{
|
||||
Lex->sphead->reset_lex(thd); /* For expr $3 */
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
expr
|
||||
{
|
||||
@ -4489,6 +4524,7 @@ simple_when_clause:
|
||||
LEX *lex= Lex;
|
||||
if (unlikely(lex->case_stmt_action_when($3, true)))
|
||||
MYSQL_YYABORT;
|
||||
Lex->pop_select(); //main select
|
||||
/* For expr $3 */
|
||||
if (unlikely(lex->sphead->restore_lex(thd)))
|
||||
MYSQL_YYABORT;
|
||||
@ -4505,12 +4541,15 @@ searched_when_clause:
|
||||
WHEN_SYM
|
||||
{
|
||||
Lex->sphead->reset_lex(thd); /* For expr $3 */
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
expr
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
if (unlikely(lex->case_stmt_action_when($3, false)))
|
||||
MYSQL_YYABORT;
|
||||
Lex->pop_select(); //main select
|
||||
/* For expr $3 */
|
||||
if (unlikely(lex->sphead->restore_lex(thd)))
|
||||
MYSQL_YYABORT;
|
||||
@ -4699,9 +4738,15 @@ opt_sp_for_loop_direction:
|
||||
;
|
||||
|
||||
sp_for_loop_index_and_bounds:
|
||||
ident_directly_assignable sp_for_loop_bounds
|
||||
ident_directly_assignable
|
||||
{
|
||||
if (unlikely(Lex->sp_for_loop_declarations(thd, &$$, &$1, $2)))
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
sp_for_loop_bounds
|
||||
{
|
||||
Lex->pop_select(); //main select
|
||||
if (unlikely(Lex->sp_for_loop_declarations(thd, &$$, &$1, $3)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
@ -4747,8 +4792,11 @@ while_body:
|
||||
LEX *lex= Lex;
|
||||
if (unlikely(lex->sp_while_loop_expression(thd, $1)))
|
||||
MYSQL_YYABORT;
|
||||
Lex->pop_select(); //main select
|
||||
if (lex->sphead->restore_lex(thd))
|
||||
MYSQL_YYABORT;
|
||||
if (lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
sp_proc_stmts1 END LOOP_SYM
|
||||
{
|
||||
@ -4759,7 +4807,11 @@ while_body:
|
||||
|
||||
repeat_body:
|
||||
sp_proc_stmts1 UNTIL_SYM
|
||||
{ Lex->sphead->reset_lex(thd); }
|
||||
{
|
||||
Lex->sphead->reset_lex(thd);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
expr END REPEAT_SYM
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
@ -4770,6 +4822,7 @@ repeat_body:
|
||||
if (unlikely(i == NULL) ||
|
||||
unlikely(lex->sphead->add_instr(i)))
|
||||
MYSQL_YYABORT;
|
||||
Lex->pop_select(); //main select
|
||||
if (lex->sphead->restore_lex(thd))
|
||||
MYSQL_YYABORT;
|
||||
/* We can shortcut the cont_backpatch here */
|
||||
@ -4798,6 +4851,8 @@ sp_labeled_control:
|
||||
if (unlikely(Lex->sp_push_loop_label(thd, &$1)))
|
||||
MYSQL_YYABORT;
|
||||
Lex->sphead->reset_lex(thd);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
while_body pop_sp_loop_label
|
||||
{ }
|
||||
@ -4849,6 +4904,8 @@ sp_unlabeled_control:
|
||||
if (unlikely(Lex->sp_push_loop_empty_label(thd)))
|
||||
MYSQL_YYABORT;
|
||||
Lex->sphead->reset_lex(thd);
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
while_body
|
||||
{
|
||||
@ -7914,7 +7971,7 @@ alter:
|
||||
{
|
||||
Lex->create_info.default_table_charset= NULL;
|
||||
Lex->create_info.used_fields= 0;
|
||||
if (Lex->main_select_push())
|
||||
if (Lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
create_database_options
|
||||
@ -13372,7 +13429,7 @@ do:
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
lex->sql_command = SQLCOM_DO;
|
||||
if (lex->main_select_push())
|
||||
if (lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
mysql_init_select(lex);
|
||||
}
|
||||
@ -16619,7 +16676,7 @@ set:
|
||||
SET
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
if (lex->main_select_push())
|
||||
if (lex->main_select_push(true))
|
||||
MYSQL_YYABORT;
|
||||
lex->set_stmt_init();
|
||||
lex->var_list.empty();
|
||||
|
Loading…
x
Reference in New Issue
Block a user