Commit 0f080dd6 authored by Oleksandr Byelkin's avatar Oleksandr Byelkin

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.
parent 571764c0
......@@ -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 @@ class st_select_lex: public st_select_lex_node
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 @@ struct LEX: public Query_tables_list
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 @@ struct LEX: public Query_tables_list
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();
......
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