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); ...@@ -1908,4 +1908,93 @@ KILL ( SELECT 1 ) + LASTVAL(s);
ERROR 42000: KILL does not support subqueries or stored functions ERROR 42000: KILL does not support subqueries or stored functions
KILL LASTVAL(s); KILL LASTVAL(s);
ERROR 42000: KILL does not support subqueries or stored functions 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 # End of 10.4 tests
...@@ -1696,4 +1696,101 @@ KILL ( SELECT 1 ) + LASTVAL(s); ...@@ -1696,4 +1696,101 @@ KILL ( SELECT 1 ) + LASTVAL(s);
--error ER_SUBQUERIES_NOT_SUPPORTED --error ER_SUBQUERIES_NOT_SUPPORTED
KILL LASTVAL(s); 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 --echo # End of 10.4 tests
...@@ -643,3 +643,118 @@ END; ...@@ -643,3 +643,118 @@ END;
# #
# End of 10.3 tests # 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 ;// ...@@ -459,3 +459,135 @@ DELIMITER ;//
--echo # --echo #
--echo # End of 10.3 tests --echo # End of 10.3 tests
--echo # --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() ...@@ -2428,6 +2428,7 @@ void st_select_lex::init_query()
changed_elements= 0; changed_elements= 0;
first_natural_join_processing= 1; first_natural_join_processing= 1;
first_cond_optimization= 1; first_cond_optimization= 1;
is_service_select= 0;
parsing_place= NO_MATTER; parsing_place= NO_MATTER;
save_parsing_place= NO_MATTER; save_parsing_place= NO_MATTER;
exclude_from_table_unique_test= no_wrap_view_item= FALSE; 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, ...@@ -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); return new (thd->mem_root) Item_func_sqlerrm(thd);
} }
if (!select_stack_head() && if (fields_are_impossible() &&
(current_select->parsing_place != FOR_LOOP_BOUND || (current_select->parsing_place != FOR_LOOP_BOUND ||
spcont->find_cursor(name, &unused_off, false) == NULL)) spcont->find_cursor(name, &unused_off, false) == NULL))
{ {
...@@ -8940,11 +8941,12 @@ void st_select_lex::add_statistics(SELECT_LEX_UNIT *unit) ...@@ -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"); DBUG_ENTER("LEX::main_select_push");
current_select_number= 1; current_select_number= 1;
builtin_select.select_number= 1; builtin_select.select_number= 1;
builtin_select.is_service_select= service;
if (push_select(&builtin_select)) if (push_select(&builtin_select))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
......
...@@ -1249,6 +1249,8 @@ class st_select_lex: public st_select_lex_node ...@@ -1249,6 +1249,8 @@ class st_select_lex: public st_select_lex_node
bool no_wrap_view_item; bool no_wrap_view_item;
/* exclude this select from check of unique_table() */ /* exclude this select from check of unique_table() */
bool exclude_from_table_unique_test; 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 */ /* index in the select list of the expression currently being fixed */
int cur_pos_in_select_list; int cur_pos_in_select_list;
...@@ -4413,7 +4415,7 @@ struct LEX: public Query_tables_list ...@@ -4413,7 +4415,7 @@ struct LEX: public Query_tables_list
SELECT_LEX_UNIT *create_unit(SELECT_LEX*); SELECT_LEX_UNIT *create_unit(SELECT_LEX*);
SELECT_LEX *wrap_unit_into_derived(SELECT_LEX_UNIT *unit); SELECT_LEX *wrap_unit_into_derived(SELECT_LEX_UNIT *unit);
SELECT_LEX *wrap_select_chain_into_derived(SELECT_LEX *sel); 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); bool insert_select_hack(SELECT_LEX *sel);
SELECT_LEX *create_priority_nest(SELECT_LEX *first_in_nest); SELECT_LEX *create_priority_nest(SELECT_LEX *first_in_nest);
...@@ -4530,6 +4532,16 @@ struct LEX: public Query_tables_list ...@@ -4530,6 +4532,16 @@ struct LEX: public Query_tables_list
Lex_field_type_st *type) const; Lex_field_type_st *type) const;
void mark_first_table_as_inserting(); 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, ...@@ -8049,6 +8049,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
(alias ? alias->str : table->table.str), (alias ? alias->str : table->table.str),
table, table,
this, select_number)); this, select_number));
DBUG_ASSERT(!is_service_select || (table_options & TL_OPTION_SEQUENCE));
if (unlikely(!table)) if (unlikely(!table))
DBUG_RETURN(0); // End of memory DBUG_RETURN(0); // End of memory
......
...@@ -1131,6 +1131,8 @@ JOIN::prepare(TABLE_LIST *tables_init, ...@@ -1131,6 +1131,8 @@ JOIN::prepare(TABLE_LIST *tables_init,
proc_param= proc_param_init; proc_param= proc_param_init;
tables_list= tables_init; tables_list= tables_init;
select_lex= select_lex_arg; select_lex= select_lex_arg;
DBUG_PRINT("info", ("select %p (%u) = JOIN %p",
select_lex, select_lex->select_number, this));
select_lex->join= this; select_lex->join= this;
join_list= &select_lex->top_join_list; join_list= &select_lex->top_join_list;
union_part= unit_arg->is_unit_op(); union_part= unit_arg->is_unit_op();
...@@ -4494,6 +4496,9 @@ int ...@@ -4494,6 +4496,9 @@ int
JOIN::destroy() JOIN::destroy()
{ {
DBUG_ENTER("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; select_lex->join= 0;
cond_equal= 0; cond_equal= 0;
......
...@@ -2080,6 +2080,8 @@ bool st_select_lex::cleanup() ...@@ -2080,6 +2080,8 @@ bool st_select_lex::cleanup()
bool error= FALSE; bool error= FALSE;
DBUG_ENTER("st_select_lex::cleanup()"); 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(order_list.first);
cleanup_order(group_list.first); cleanup_order(group_list.first);
cleanup_ftfuncs(this); cleanup_ftfuncs(this);
......
...@@ -2809,8 +2809,6 @@ create: ...@@ -2809,8 +2809,6 @@ create:
{ {
Lex->create_info.default_table_charset= NULL; Lex->create_info.default_table_charset= NULL;
Lex->create_info.used_fields= 0; Lex->create_info.used_fields= 0;
if (Lex->main_select_push())
MYSQL_YYABORT;
} }
opt_create_database_options opt_create_database_options
{ {
...@@ -2819,7 +2817,6 @@ create: ...@@ -2819,7 +2817,6 @@ create:
$1 | $3))) $1 | $3)))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->name= $4; lex->name= $4;
Lex->pop_select(); //main select
} }
| create_or_replace definer_opt opt_view_suid VIEW_SYM | create_or_replace definer_opt opt_view_suid VIEW_SYM
opt_if_not_exists table_ident opt_if_not_exists table_ident
...@@ -3653,10 +3650,13 @@ sp_cursor_stmt: ...@@ -3653,10 +3650,13 @@ sp_cursor_stmt:
{ {
DBUG_ASSERT(thd->free_list == NULL); DBUG_ASSERT(thd->free_list == NULL);
Lex->sphead->reset_lex(thd, $1); Lex->sphead->reset_lex(thd, $1);
if (Lex->main_select_push(true))
MYSQL_YYABORT;
} }
select select
{ {
DBUG_ASSERT(Lex == $1); DBUG_ASSERT(Lex == $1);
Lex->pop_select(); //main select
if (unlikely($1->stmt_finalize(thd)) || if (unlikely($1->stmt_finalize(thd)) ||
unlikely($1->sphead->restore_lex(thd))) unlikely($1->sphead->restore_lex(thd)))
MYSQL_YYABORT; MYSQL_YYABORT;
...@@ -4154,6 +4154,11 @@ sp_proc_stmt_statement: ...@@ -4154,6 +4154,11 @@ sp_proc_stmt_statement:
Lex_input_stream *lip= YYLIP; Lex_input_stream *lip= YYLIP;
lex->sphead->reset_lex(thd); 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(); lex->sphead->m_tmp_query= lip->get_tok_start();
} }
statement statement
...@@ -4172,11 +4177,16 @@ RETURN_ALLMODES_SYM: ...@@ -4172,11 +4177,16 @@ RETURN_ALLMODES_SYM:
sp_proc_stmt_return: sp_proc_stmt_return:
RETURN_ALLMODES_SYM RETURN_ALLMODES_SYM
{ Lex->sphead->reset_lex(thd); } {
Lex->sphead->reset_lex(thd);
if (Lex->main_select_push(true))
MYSQL_YYABORT;
}
expr expr
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_head *sp= lex->sphead; sp_head *sp= lex->sphead;
Lex->pop_select(); //main select
if (unlikely(sp->m_handler->add_instr_freturn(thd, sp, lex->spcont, if (unlikely(sp->m_handler->add_instr_freturn(thd, sp, lex->spcont,
$3, lex)) || $3, lex)) ||
unlikely(sp->restore_lex(thd))) unlikely(sp->restore_lex(thd)))
...@@ -4193,7 +4203,16 @@ sp_proc_stmt_return: ...@@ -4193,7 +4203,16 @@ sp_proc_stmt_return:
; ;
reset_lex_expr: 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: sp_proc_stmt_exit_oracle:
...@@ -4285,6 +4304,8 @@ assignment_source_expr: ...@@ -4285,6 +4304,8 @@ assignment_source_expr:
{ {
DBUG_ASSERT(thd->free_list == NULL); DBUG_ASSERT(thd->free_list == NULL);
Lex->sphead->reset_lex(thd, $1); Lex->sphead->reset_lex(thd, $1);
if (Lex->main_select_push(true))
MYSQL_YYABORT;
} }
expr expr
{ {
...@@ -4293,6 +4314,7 @@ assignment_source_expr: ...@@ -4293,6 +4314,7 @@ assignment_source_expr:
$$->sp_lex_in_use= true; $$->sp_lex_in_use= true;
$$->set_item_and_free_list($3, thd->free_list); $$->set_item_and_free_list($3, thd->free_list);
thd->free_list= NULL; thd->free_list= NULL;
Lex->pop_select(); //min select
if ($$->sphead->restore_lex(thd)) if ($$->sphead->restore_lex(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
...@@ -4302,6 +4324,8 @@ for_loop_bound_expr: ...@@ -4302,6 +4324,8 @@ for_loop_bound_expr:
assignment_source_lex assignment_source_lex
{ {
Lex->sphead->reset_lex(thd, $1); Lex->sphead->reset_lex(thd, $1);
if (Lex->main_select_push(true))
MYSQL_YYABORT;
Lex->current_select->parsing_place= FOR_LOOP_BOUND; Lex->current_select->parsing_place= FOR_LOOP_BOUND;
} }
expr expr
...@@ -4310,6 +4334,7 @@ for_loop_bound_expr: ...@@ -4310,6 +4334,7 @@ for_loop_bound_expr:
$$= $1; $$= $1;
$$->sp_lex_in_use= true; $$->sp_lex_in_use= true;
$$->set_item_and_free_list($3, NULL); $$->set_item_and_free_list($3, NULL);
Lex->pop_select(); //main select
if (unlikely($$->sphead->restore_lex(thd))) if (unlikely($$->sphead->restore_lex(thd)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->current_select->parsing_place= NO_MATTER; Lex->current_select->parsing_place= NO_MATTER;
...@@ -4424,7 +4449,11 @@ sp_fetch_list: ...@@ -4424,7 +4449,11 @@ sp_fetch_list:
; ;
sp_if: sp_if:
{ Lex->sphead->reset_lex(thd); } {
Lex->sphead->reset_lex(thd);
if (Lex->main_select_push(true))
MYSQL_YYABORT;
}
expr THEN_SYM expr THEN_SYM
{ {
LEX *lex= Lex; LEX *lex= Lex;
...@@ -4438,6 +4467,7 @@ sp_if: ...@@ -4438,6 +4467,7 @@ sp_if:
unlikely(sp->add_cont_backpatch(i)) || unlikely(sp->add_cont_backpatch(i)) ||
unlikely(sp->add_instr(i))) unlikely(sp->add_instr(i)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->pop_select(); //main select
if (unlikely(sp->restore_lex(thd))) if (unlikely(sp->restore_lex(thd)))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
...@@ -4538,12 +4568,17 @@ case_stmt_specification: ...@@ -4538,12 +4568,17 @@ case_stmt_specification:
; ;
case_stmt_body: 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 expr
{ {
if (unlikely(Lex->case_stmt_action_expr($2))) if (unlikely(Lex->case_stmt_action_expr($2)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->pop_select(); //main select
if (Lex->sphead->restore_lex(thd)) if (Lex->sphead->restore_lex(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
...@@ -4567,6 +4602,8 @@ simple_when_clause: ...@@ -4567,6 +4602,8 @@ simple_when_clause:
WHEN_SYM WHEN_SYM
{ {
Lex->sphead->reset_lex(thd); /* For expr $3 */ Lex->sphead->reset_lex(thd); /* For expr $3 */
if (Lex->main_select_push(true))
MYSQL_YYABORT;
} }
expr expr
{ {
...@@ -4575,6 +4612,7 @@ simple_when_clause: ...@@ -4575,6 +4612,7 @@ simple_when_clause:
LEX *lex= Lex; LEX *lex= Lex;
if (unlikely(lex->case_stmt_action_when($3, true))) if (unlikely(lex->case_stmt_action_when($3, true)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->pop_select(); //main select
/* For expr $3 */ /* For expr $3 */
if (unlikely(lex->sphead->restore_lex(thd))) if (unlikely(lex->sphead->restore_lex(thd)))
MYSQL_YYABORT; MYSQL_YYABORT;
...@@ -4591,12 +4629,15 @@ searched_when_clause: ...@@ -4591,12 +4629,15 @@ searched_when_clause:
WHEN_SYM WHEN_SYM
{ {
Lex->sphead->reset_lex(thd); /* For expr $3 */ Lex->sphead->reset_lex(thd); /* For expr $3 */
if (Lex->main_select_push(true))
MYSQL_YYABORT;
} }
expr expr
{ {
LEX *lex= Lex; LEX *lex= Lex;
if (unlikely(lex->case_stmt_action_when($3, false))) if (unlikely(lex->case_stmt_action_when($3, false)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->pop_select(); //main select
/* For expr $3 */ /* For expr $3 */
if (unlikely(lex->sphead->restore_lex(thd))) if (unlikely(lex->sphead->restore_lex(thd)))
MYSQL_YYABORT; MYSQL_YYABORT;
...@@ -4695,9 +4736,15 @@ opt_sp_for_loop_direction: ...@@ -4695,9 +4736,15 @@ opt_sp_for_loop_direction:
; ;
sp_for_loop_index_and_bounds: 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; MYSQL_YYABORT;
} }
; ;
...@@ -4743,8 +4790,11 @@ while_body: ...@@ -4743,8 +4790,11 @@ while_body:
LEX *lex= Lex; LEX *lex= Lex;
if (unlikely(lex->sp_while_loop_expression(thd, $1))) if (unlikely(lex->sp_while_loop_expression(thd, $1)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->pop_select(); //main select
if (lex->sphead->restore_lex(thd)) if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
if (lex->main_select_push(true))
MYSQL_YYABORT;
} }
sp_proc_stmts1 END WHILE_SYM sp_proc_stmts1 END WHILE_SYM
{ {
...@@ -4755,7 +4805,11 @@ while_body: ...@@ -4755,7 +4805,11 @@ while_body:
repeat_body: repeat_body:
sp_proc_stmts1 UNTIL_SYM 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 expr END REPEAT_SYM
{ {
LEX *lex= Lex; LEX *lex= Lex;
...@@ -4766,6 +4820,7 @@ repeat_body: ...@@ -4766,6 +4820,7 @@ repeat_body:
if (unlikely(i == NULL) || if (unlikely(i == NULL) ||
unlikely(lex->sphead->add_instr(i))) unlikely(lex->sphead->add_instr(i)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->pop_select(); //main select
if (lex->sphead->restore_lex(thd)) if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
/* We can shortcut the cont_backpatch here */ /* We can shortcut the cont_backpatch here */
...@@ -4794,6 +4849,8 @@ sp_labeled_control: ...@@ -4794,6 +4849,8 @@ sp_labeled_control:
if (unlikely(Lex->sp_push_loop_label(thd, &$1))) if (unlikely(Lex->sp_push_loop_label(thd, &$1)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->sphead->reset_lex(thd); Lex->sphead->reset_lex(thd);
if (Lex->main_select_push(true))
MYSQL_YYABORT;
} }
while_body pop_sp_loop_label while_body pop_sp_loop_label
{ } { }
...@@ -4845,6 +4902,8 @@ sp_unlabeled_control: ...@@ -4845,6 +4902,8 @@ sp_unlabeled_control:
if (unlikely(Lex->sp_push_loop_empty_label(thd))) if (unlikely(Lex->sp_push_loop_empty_label(thd)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->sphead->reset_lex(thd); Lex->sphead->reset_lex(thd);
if (Lex->main_select_push(true))
MYSQL_YYABORT;
} }
while_body while_body
{ {
...@@ -7816,7 +7875,7 @@ alter: ...@@ -7816,7 +7875,7 @@ alter:
{ {
Lex->create_info.default_table_charset= NULL; Lex->create_info.default_table_charset= NULL;
Lex->create_info.used_fields= 0; Lex->create_info.used_fields= 0;
if (Lex->main_select_push()) if (Lex->main_select_push(true))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
create_database_options create_database_options
...@@ -13265,7 +13324,7 @@ do: ...@@ -13265,7 +13324,7 @@ do:
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->sql_command = SQLCOM_DO; lex->sql_command = SQLCOM_DO;
if (lex->main_select_push()) if (lex->main_select_push(true))
MYSQL_YYABORT; MYSQL_YYABORT;
mysql_init_select(lex); mysql_init_select(lex);
} }
...@@ -16453,7 +16512,7 @@ set: ...@@ -16453,7 +16512,7 @@ set:
SET SET
{ {
LEX *lex=Lex; LEX *lex=Lex;
if (lex->main_select_push()) if (lex->main_select_push(true))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->set_stmt_init(); lex->set_stmt_init();
lex->var_list.empty(); lex->var_list.empty();
......
...@@ -2311,8 +2311,6 @@ create: ...@@ -2311,8 +2311,6 @@ create:
{ {
Lex->create_info.default_table_charset= NULL; Lex->create_info.default_table_charset= NULL;
Lex->create_info.used_fields= 0; Lex->create_info.used_fields= 0;
if (Lex->main_select_push())
MYSQL_YYABORT;
} }
opt_create_database_options opt_create_database_options
{ {
...@@ -2321,7 +2319,6 @@ create: ...@@ -2321,7 +2319,6 @@ create:
$1 | $3))) $1 | $3)))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->name= $4; lex->name= $4;
Lex->pop_select(); //main select
} }
| create_or_replace definer_opt opt_view_suid VIEW_SYM | create_or_replace definer_opt opt_view_suid VIEW_SYM
opt_if_not_exists table_ident opt_if_not_exists table_ident
...@@ -3547,10 +3544,13 @@ sp_cursor_stmt: ...@@ -3547,10 +3544,13 @@ sp_cursor_stmt:
{ {
DBUG_ASSERT(thd->free_list == NULL); DBUG_ASSERT(thd->free_list == NULL);
Lex->sphead->reset_lex(thd, $1); Lex->sphead->reset_lex(thd, $1);
if (Lex->main_select_push(true))
MYSQL_YYABORT;
} }
select select
{ {
DBUG_ASSERT(Lex == $1); DBUG_ASSERT(Lex == $1);
Lex->pop_select(); //main select
if (unlikely($1->stmt_finalize(thd)) || if (unlikely($1->stmt_finalize(thd)) ||
unlikely($1->sphead->restore_lex(thd))) unlikely($1->sphead->restore_lex(thd)))
MYSQL_YYABORT; MYSQL_YYABORT;
...@@ -4061,6 +4061,11 @@ sp_proc_stmt_statement: ...@@ -4061,6 +4061,11 @@ sp_proc_stmt_statement:
Lex_input_stream *lip= YYLIP; Lex_input_stream *lip= YYLIP;
lex->sphead->reset_lex(thd); 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(); lex->sphead->m_tmp_query= lip->get_tok_start();
} }
sp_statement sp_statement
...@@ -4079,11 +4084,16 @@ RETURN_ALLMODES_SYM: ...@@ -4079,11 +4084,16 @@ RETURN_ALLMODES_SYM:
sp_proc_stmt_return: sp_proc_stmt_return:
RETURN_ALLMODES_SYM RETURN_ALLMODES_SYM
{ Lex->sphead->reset_lex(thd); } {
Lex->sphead->reset_lex(thd);
if (Lex->main_select_push(true))
MYSQL_YYABORT;
}
expr expr
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_head *sp= lex->sphead; sp_head *sp= lex->sphead;
Lex->pop_select(); //main select
if (unlikely(sp->m_handler->add_instr_freturn(thd, sp, lex->spcont, if (unlikely(sp->m_handler->add_instr_freturn(thd, sp, lex->spcont,
$3, lex)) || $3, lex)) ||
unlikely(sp->restore_lex(thd))) unlikely(sp->restore_lex(thd)))
...@@ -4100,9 +4110,16 @@ sp_proc_stmt_return: ...@@ -4100,9 +4110,16 @@ sp_proc_stmt_return:
; ;
reset_lex_expr: reset_lex_expr:
{ Lex->sphead->reset_lex(thd); } {
Lex->sphead->reset_lex(thd);
if (Lex->main_select_push(true))
MYSQL_YYABORT;
}
expr expr
{ $$= $2; } {
$$= $2;
Lex->pop_select(); //main select
}
; ;
sp_proc_stmt_exit_oracle: sp_proc_stmt_exit_oracle:
...@@ -4201,6 +4218,8 @@ assignment_source_expr: ...@@ -4201,6 +4218,8 @@ assignment_source_expr:
{ {
DBUG_ASSERT(thd->free_list == NULL); DBUG_ASSERT(thd->free_list == NULL);
Lex->sphead->reset_lex(thd, $1); Lex->sphead->reset_lex(thd, $1);
if (Lex->main_select_push(true))
MYSQL_YYABORT;
} }
expr expr
{ {
...@@ -4209,6 +4228,7 @@ assignment_source_expr: ...@@ -4209,6 +4228,7 @@ assignment_source_expr:
$$->sp_lex_in_use= true; $$->sp_lex_in_use= true;
$$->set_item_and_free_list($3, thd->free_list); $$->set_item_and_free_list($3, thd->free_list);
thd->free_list= NULL; thd->free_list= NULL;
Lex->pop_select(); //main select
if ($$->sphead->restore_lex(thd)) if ($$->sphead->restore_lex(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
...@@ -4218,6 +4238,8 @@ for_loop_bound_expr: ...@@ -4218,6 +4238,8 @@ for_loop_bound_expr:
assignment_source_lex assignment_source_lex
{ {
Lex->sphead->reset_lex(thd, $1); Lex->sphead->reset_lex(thd, $1);
if (Lex->main_select_push(true))
MYSQL_YYABORT;
Lex->current_select->parsing_place= FOR_LOOP_BOUND; Lex->current_select->parsing_place= FOR_LOOP_BOUND;
} }
expr expr
...@@ -4226,6 +4248,7 @@ for_loop_bound_expr: ...@@ -4226,6 +4248,7 @@ for_loop_bound_expr:
$$= $1; $$= $1;
$$->sp_lex_in_use= true; $$->sp_lex_in_use= true;
$$->set_item_and_free_list($3, NULL); $$->set_item_and_free_list($3, NULL);
Lex->pop_select(); //main select
if (unlikely($$->sphead->restore_lex(thd))) if (unlikely($$->sphead->restore_lex(thd)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->current_select->parsing_place= NO_MATTER; Lex->current_select->parsing_place= NO_MATTER;
...@@ -4338,7 +4361,11 @@ sp_fetch_list: ...@@ -4338,7 +4361,11 @@ sp_fetch_list:
; ;
sp_if: sp_if:
{ Lex->sphead->reset_lex(thd); } {
Lex->sphead->reset_lex(thd);
if (Lex->main_select_push(true))
MYSQL_YYABORT;
}
expr THEN_SYM expr THEN_SYM
{ {
LEX *lex= Lex; LEX *lex= Lex;
...@@ -4352,6 +4379,7 @@ sp_if: ...@@ -4352,6 +4379,7 @@ sp_if:
unlikely(sp->add_cont_backpatch(i)) || unlikely(sp->add_cont_backpatch(i)) ||
unlikely(sp->add_instr(i))) unlikely(sp->add_instr(i)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->pop_select(); //main select
if (unlikely(sp->restore_lex(thd))) if (unlikely(sp->restore_lex(thd)))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
...@@ -4452,12 +4480,17 @@ case_stmt_specification: ...@@ -4452,12 +4480,17 @@ case_stmt_specification:
; ;
case_stmt_body: 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 expr
{ {
if (unlikely(Lex->case_stmt_action_expr($2))) if (unlikely(Lex->case_stmt_action_expr($2)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->pop_select(); //main select
if (Lex->sphead->restore_lex(thd)) if (Lex->sphead->restore_lex(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
...@@ -4481,6 +4514,8 @@ simple_when_clause: ...@@ -4481,6 +4514,8 @@ simple_when_clause:
WHEN_SYM WHEN_SYM
{ {
Lex->sphead->reset_lex(thd); /* For expr $3 */ Lex->sphead->reset_lex(thd); /* For expr $3 */
if (Lex->main_select_push(true))
MYSQL_YYABORT;
} }
expr expr
{ {
...@@ -4489,6 +4524,7 @@ simple_when_clause: ...@@ -4489,6 +4524,7 @@ simple_when_clause:
LEX *lex= Lex; LEX *lex= Lex;
if (unlikely(lex->case_stmt_action_when($3, true))) if (unlikely(lex->case_stmt_action_when($3, true)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->pop_select(); //main select
/* For expr $3 */ /* For expr $3 */
if (unlikely(lex->sphead->restore_lex(thd))) if (unlikely(lex->sphead->restore_lex(thd)))
MYSQL_YYABORT; MYSQL_YYABORT;
...@@ -4505,12 +4541,15 @@ searched_when_clause: ...@@ -4505,12 +4541,15 @@ searched_when_clause:
WHEN_SYM WHEN_SYM
{ {
Lex->sphead->reset_lex(thd); /* For expr $3 */ Lex->sphead->reset_lex(thd); /* For expr $3 */
if (Lex->main_select_push(true))
MYSQL_YYABORT;
} }
expr expr
{ {
LEX *lex= Lex; LEX *lex= Lex;
if (unlikely(lex->case_stmt_action_when($3, false))) if (unlikely(lex->case_stmt_action_when($3, false)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->pop_select(); //main select
/* For expr $3 */ /* For expr $3 */
if (unlikely(lex->sphead->restore_lex(thd))) if (unlikely(lex->sphead->restore_lex(thd)))
MYSQL_YYABORT; MYSQL_YYABORT;
...@@ -4699,9 +4738,15 @@ opt_sp_for_loop_direction: ...@@ -4699,9 +4738,15 @@ opt_sp_for_loop_direction:
; ;
sp_for_loop_index_and_bounds: 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; MYSQL_YYABORT;
} }
; ;
...@@ -4747,8 +4792,11 @@ while_body: ...@@ -4747,8 +4792,11 @@ while_body:
LEX *lex= Lex; LEX *lex= Lex;
if (unlikely(lex->sp_while_loop_expression(thd, $1))) if (unlikely(lex->sp_while_loop_expression(thd, $1)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->pop_select(); //main select
if (lex->sphead->restore_lex(thd)) if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
if (lex->main_select_push(true))
MYSQL_YYABORT;
} }
sp_proc_stmts1 END LOOP_SYM sp_proc_stmts1 END LOOP_SYM
{ {
...@@ -4759,7 +4807,11 @@ while_body: ...@@ -4759,7 +4807,11 @@ while_body:
repeat_body: repeat_body:
sp_proc_stmts1 UNTIL_SYM 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 expr END REPEAT_SYM
{ {
LEX *lex= Lex; LEX *lex= Lex;
...@@ -4770,6 +4822,7 @@ repeat_body: ...@@ -4770,6 +4822,7 @@ repeat_body:
if (unlikely(i == NULL) || if (unlikely(i == NULL) ||
unlikely(lex->sphead->add_instr(i))) unlikely(lex->sphead->add_instr(i)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->pop_select(); //main select
if (lex->sphead->restore_lex(thd)) if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT; MYSQL_YYABORT;
/* We can shortcut the cont_backpatch here */ /* We can shortcut the cont_backpatch here */
...@@ -4798,6 +4851,8 @@ sp_labeled_control: ...@@ -4798,6 +4851,8 @@ sp_labeled_control:
if (unlikely(Lex->sp_push_loop_label(thd, &$1))) if (unlikely(Lex->sp_push_loop_label(thd, &$1)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->sphead->reset_lex(thd); Lex->sphead->reset_lex(thd);
if (Lex->main_select_push(true))
MYSQL_YYABORT;
} }
while_body pop_sp_loop_label while_body pop_sp_loop_label
{ } { }
...@@ -4849,6 +4904,8 @@ sp_unlabeled_control: ...@@ -4849,6 +4904,8 @@ sp_unlabeled_control:
if (unlikely(Lex->sp_push_loop_empty_label(thd))) if (unlikely(Lex->sp_push_loop_empty_label(thd)))
MYSQL_YYABORT; MYSQL_YYABORT;
Lex->sphead->reset_lex(thd); Lex->sphead->reset_lex(thd);
if (Lex->main_select_push(true))
MYSQL_YYABORT;
} }
while_body while_body
{ {
...@@ -7914,7 +7971,7 @@ alter: ...@@ -7914,7 +7971,7 @@ alter:
{ {
Lex->create_info.default_table_charset= NULL; Lex->create_info.default_table_charset= NULL;
Lex->create_info.used_fields= 0; Lex->create_info.used_fields= 0;
if (Lex->main_select_push()) if (Lex->main_select_push(true))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
create_database_options create_database_options
...@@ -13372,7 +13429,7 @@ do: ...@@ -13372,7 +13429,7 @@ do:
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->sql_command = SQLCOM_DO; lex->sql_command = SQLCOM_DO;
if (lex->main_select_push()) if (lex->main_select_push(true))
MYSQL_YYABORT; MYSQL_YYABORT;
mysql_init_select(lex); mysql_init_select(lex);
} }
...@@ -16619,7 +16676,7 @@ set: ...@@ -16619,7 +16676,7 @@ set:
SET SET
{ {
LEX *lex=Lex; LEX *lex=Lex;
if (lex->main_select_push()) if (lex->main_select_push(true))
MYSQL_YYABORT; MYSQL_YYABORT;
lex->set_stmt_init(); lex->set_stmt_init();
lex->var_list.empty(); 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