Merge malff@bk-internal.mysql.com:/home/bk/mysql-5.0-runtime
into weblab.(none):/home/marcsql/TREE/mysql-5.0-26503
This commit is contained in:
commit
cfcd27b3db
@ -1400,3 +1400,55 @@ drop table table_25345_b;
|
||||
drop procedure proc_25345;
|
||||
drop function func_25345;
|
||||
drop function func_25345_b;
|
||||
create procedure proc_26503_error_1()
|
||||
begin
|
||||
retry:
|
||||
repeat
|
||||
begin
|
||||
declare continue handler for sqlexception
|
||||
begin
|
||||
iterate retry;
|
||||
end
|
||||
select "do something";
|
||||
end
|
||||
until true end repeat retry;
|
||||
end//
|
||||
ERROR 42000: ITERATE with no matching label: retry
|
||||
create procedure proc_26503_error_2()
|
||||
begin
|
||||
retry:
|
||||
repeat
|
||||
begin
|
||||
declare continue handler for sqlexception
|
||||
iterate retry;
|
||||
select "do something";
|
||||
end
|
||||
until true end repeat retry;
|
||||
end//
|
||||
ERROR 42000: ITERATE with no matching label: retry
|
||||
create procedure proc_26503_error_3()
|
||||
begin
|
||||
retry:
|
||||
repeat
|
||||
begin
|
||||
declare continue handler for sqlexception
|
||||
begin
|
||||
leave retry;
|
||||
end
|
||||
select "do something";
|
||||
end
|
||||
until true end repeat retry;
|
||||
end//
|
||||
ERROR 42000: LEAVE with no matching label: retry
|
||||
create procedure proc_26503_error_4()
|
||||
begin
|
||||
retry:
|
||||
repeat
|
||||
begin
|
||||
declare continue handler for sqlexception
|
||||
leave retry;
|
||||
select "do something";
|
||||
end
|
||||
until true end repeat retry;
|
||||
end//
|
||||
ERROR 42000: LEAVE with no matching label: retry
|
||||
|
@ -5805,4 +5805,169 @@ func_8407_b()
|
||||
1500
|
||||
drop function func_8407_a|
|
||||
drop function func_8407_b|
|
||||
drop table if exists table_26503|
|
||||
drop procedure if exists proc_26503_ok_1|
|
||||
drop procedure if exists proc_26503_ok_2|
|
||||
drop procedure if exists proc_26503_ok_3|
|
||||
drop procedure if exists proc_26503_ok_4|
|
||||
create table table_26503(a int unique)|
|
||||
create procedure proc_26503_ok_1(v int)
|
||||
begin
|
||||
declare i int default 5;
|
||||
declare continue handler for sqlexception
|
||||
begin
|
||||
select 'caught something';
|
||||
retry:
|
||||
while i > 0 do
|
||||
begin
|
||||
set i = i - 1;
|
||||
select 'looping', i;
|
||||
iterate retry;
|
||||
select 'dead code';
|
||||
end;
|
||||
end while retry;
|
||||
select 'leaving handler';
|
||||
end;
|
||||
select 'do something';
|
||||
insert into table_26503 values (v);
|
||||
select 'do something again';
|
||||
insert into table_26503 values (v);
|
||||
end|
|
||||
create procedure proc_26503_ok_2(v int)
|
||||
begin
|
||||
declare i int default 5;
|
||||
declare continue handler for sqlexception
|
||||
begin
|
||||
select 'caught something';
|
||||
retry:
|
||||
while i > 0 do
|
||||
begin
|
||||
set i = i - 1;
|
||||
select 'looping', i;
|
||||
leave retry;
|
||||
select 'dead code';
|
||||
end;
|
||||
end while;
|
||||
select 'leaving handler';
|
||||
end;
|
||||
select 'do something';
|
||||
insert into table_26503 values (v);
|
||||
select 'do something again';
|
||||
insert into table_26503 values (v);
|
||||
end|
|
||||
create procedure proc_26503_ok_3(v int)
|
||||
begin
|
||||
declare i int default 5;
|
||||
retry:
|
||||
begin
|
||||
declare continue handler for sqlexception
|
||||
begin
|
||||
select 'caught something';
|
||||
retry:
|
||||
while i > 0 do
|
||||
begin
|
||||
set i = i - 1;
|
||||
select 'looping', i;
|
||||
iterate retry;
|
||||
select 'dead code';
|
||||
end;
|
||||
end while retry;
|
||||
select 'leaving handler';
|
||||
end;
|
||||
select 'do something';
|
||||
insert into table_26503 values (v);
|
||||
select 'do something again';
|
||||
insert into table_26503 values (v);
|
||||
end;
|
||||
end|
|
||||
create procedure proc_26503_ok_4(v int)
|
||||
begin
|
||||
declare i int default 5;
|
||||
retry:
|
||||
begin
|
||||
declare continue handler for sqlexception
|
||||
begin
|
||||
select 'caught something';
|
||||
retry:
|
||||
while i > 0 do
|
||||
begin
|
||||
set i = i - 1;
|
||||
select 'looping', i;
|
||||
leave retry;
|
||||
select 'dead code';
|
||||
end;
|
||||
end while;
|
||||
select 'leaving handler';
|
||||
end;
|
||||
select 'do something';
|
||||
insert into table_26503 values (v);
|
||||
select 'do something again';
|
||||
insert into table_26503 values (v);
|
||||
end;
|
||||
end|
|
||||
call proc_26503_ok_1(1)|
|
||||
do something
|
||||
do something
|
||||
do something again
|
||||
do something again
|
||||
caught something
|
||||
caught something
|
||||
looping i
|
||||
looping 4
|
||||
looping i
|
||||
looping 3
|
||||
looping i
|
||||
looping 2
|
||||
looping i
|
||||
looping 1
|
||||
looping i
|
||||
looping 0
|
||||
leaving handler
|
||||
leaving handler
|
||||
call proc_26503_ok_2(2)|
|
||||
do something
|
||||
do something
|
||||
do something again
|
||||
do something again
|
||||
caught something
|
||||
caught something
|
||||
looping i
|
||||
looping 4
|
||||
leaving handler
|
||||
leaving handler
|
||||
call proc_26503_ok_3(3)|
|
||||
do something
|
||||
do something
|
||||
do something again
|
||||
do something again
|
||||
caught something
|
||||
caught something
|
||||
looping i
|
||||
looping 4
|
||||
looping i
|
||||
looping 3
|
||||
looping i
|
||||
looping 2
|
||||
looping i
|
||||
looping 1
|
||||
looping i
|
||||
looping 0
|
||||
leaving handler
|
||||
leaving handler
|
||||
call proc_26503_ok_4(4)|
|
||||
do something
|
||||
do something
|
||||
do something again
|
||||
do something again
|
||||
caught something
|
||||
caught something
|
||||
looping i
|
||||
looping 4
|
||||
leaving handler
|
||||
leaving handler
|
||||
drop table table_26503|
|
||||
drop procedure proc_26503_ok_1|
|
||||
drop procedure proc_26503_ok_2|
|
||||
drop procedure proc_26503_ok_3|
|
||||
drop procedure proc_26503_ok_4|
|
||||
drop table t1,t2;
|
||||
|
@ -2021,6 +2021,74 @@ drop procedure proc_25345;
|
||||
drop function func_25345;
|
||||
drop function func_25345_b;
|
||||
|
||||
#
|
||||
# Bug#26503 (Illegal SQL exception handler code causes the server to crash)
|
||||
#
|
||||
|
||||
delimiter //;
|
||||
|
||||
--error ER_SP_LILABEL_MISMATCH
|
||||
create procedure proc_26503_error_1()
|
||||
begin
|
||||
retry:
|
||||
repeat
|
||||
begin
|
||||
declare continue handler for sqlexception
|
||||
begin
|
||||
iterate retry;
|
||||
end
|
||||
|
||||
select "do something";
|
||||
end
|
||||
until true end repeat retry;
|
||||
end//
|
||||
|
||||
--error ER_SP_LILABEL_MISMATCH
|
||||
create procedure proc_26503_error_2()
|
||||
begin
|
||||
retry:
|
||||
repeat
|
||||
begin
|
||||
declare continue handler for sqlexception
|
||||
iterate retry;
|
||||
|
||||
select "do something";
|
||||
end
|
||||
until true end repeat retry;
|
||||
end//
|
||||
|
||||
--error ER_SP_LILABEL_MISMATCH
|
||||
create procedure proc_26503_error_3()
|
||||
begin
|
||||
retry:
|
||||
repeat
|
||||
begin
|
||||
declare continue handler for sqlexception
|
||||
begin
|
||||
leave retry;
|
||||
end
|
||||
|
||||
select "do something";
|
||||
end
|
||||
until true end repeat retry;
|
||||
end//
|
||||
|
||||
--error ER_SP_LILABEL_MISMATCH
|
||||
create procedure proc_26503_error_4()
|
||||
begin
|
||||
retry:
|
||||
repeat
|
||||
begin
|
||||
declare continue handler for sqlexception
|
||||
leave retry;
|
||||
|
||||
select "do something";
|
||||
end
|
||||
until true end repeat retry;
|
||||
end//
|
||||
|
||||
delimiter ;//
|
||||
|
||||
#
|
||||
# BUG#NNNN: New bug synopsis
|
||||
#
|
||||
|
@ -6800,6 +6800,141 @@ select func_8407_b()|
|
||||
drop function func_8407_a|
|
||||
drop function func_8407_b|
|
||||
|
||||
#
|
||||
# Bug#26503 (Illegal SQL exception handler code causes the server to crash)
|
||||
#
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists table_26503|
|
||||
drop procedure if exists proc_26503_ok_1|
|
||||
drop procedure if exists proc_26503_ok_2|
|
||||
drop procedure if exists proc_26503_ok_3|
|
||||
drop procedure if exists proc_26503_ok_4|
|
||||
--enable_warnings
|
||||
|
||||
create table table_26503(a int unique)|
|
||||
|
||||
create procedure proc_26503_ok_1(v int)
|
||||
begin
|
||||
declare i int default 5;
|
||||
|
||||
declare continue handler for sqlexception
|
||||
begin
|
||||
select 'caught something';
|
||||
retry:
|
||||
while i > 0 do
|
||||
begin
|
||||
set i = i - 1;
|
||||
select 'looping', i;
|
||||
iterate retry;
|
||||
select 'dead code';
|
||||
end;
|
||||
end while retry;
|
||||
select 'leaving handler';
|
||||
end;
|
||||
|
||||
select 'do something';
|
||||
insert into table_26503 values (v);
|
||||
select 'do something again';
|
||||
insert into table_26503 values (v);
|
||||
end|
|
||||
|
||||
create procedure proc_26503_ok_2(v int)
|
||||
begin
|
||||
declare i int default 5;
|
||||
|
||||
declare continue handler for sqlexception
|
||||
begin
|
||||
select 'caught something';
|
||||
retry:
|
||||
while i > 0 do
|
||||
begin
|
||||
set i = i - 1;
|
||||
select 'looping', i;
|
||||
leave retry;
|
||||
select 'dead code';
|
||||
end;
|
||||
end while;
|
||||
select 'leaving handler';
|
||||
end;
|
||||
|
||||
select 'do something';
|
||||
insert into table_26503 values (v);
|
||||
select 'do something again';
|
||||
insert into table_26503 values (v);
|
||||
end|
|
||||
|
||||
## The outer retry label should not prevent using the inner label.
|
||||
|
||||
create procedure proc_26503_ok_3(v int)
|
||||
begin
|
||||
declare i int default 5;
|
||||
|
||||
retry:
|
||||
begin
|
||||
declare continue handler for sqlexception
|
||||
begin
|
||||
select 'caught something';
|
||||
retry:
|
||||
while i > 0 do
|
||||
begin
|
||||
set i = i - 1;
|
||||
select 'looping', i;
|
||||
iterate retry;
|
||||
select 'dead code';
|
||||
end;
|
||||
end while retry;
|
||||
select 'leaving handler';
|
||||
end;
|
||||
|
||||
select 'do something';
|
||||
insert into table_26503 values (v);
|
||||
select 'do something again';
|
||||
insert into table_26503 values (v);
|
||||
end;
|
||||
end|
|
||||
|
||||
## The outer retry label should not prevent using the inner label.
|
||||
|
||||
create procedure proc_26503_ok_4(v int)
|
||||
begin
|
||||
declare i int default 5;
|
||||
|
||||
retry:
|
||||
begin
|
||||
declare continue handler for sqlexception
|
||||
begin
|
||||
select 'caught something';
|
||||
retry:
|
||||
while i > 0 do
|
||||
begin
|
||||
set i = i - 1;
|
||||
select 'looping', i;
|
||||
leave retry;
|
||||
select 'dead code';
|
||||
end;
|
||||
end while;
|
||||
select 'leaving handler';
|
||||
end;
|
||||
|
||||
select 'do something';
|
||||
insert into table_26503 values (v);
|
||||
select 'do something again';
|
||||
insert into table_26503 values (v);
|
||||
end;
|
||||
end|
|
||||
|
||||
call proc_26503_ok_1(1)|
|
||||
call proc_26503_ok_2(2)|
|
||||
call proc_26503_ok_3(3)|
|
||||
call proc_26503_ok_4(4)|
|
||||
|
||||
drop table table_26503|
|
||||
drop procedure proc_26503_ok_1|
|
||||
drop procedure proc_26503_ok_2|
|
||||
drop procedure proc_26503_ok_3|
|
||||
drop procedure proc_26503_ok_4|
|
||||
|
||||
#
|
||||
# NOTE: The delimiter is `|`, and not `;`. It is changed to `;`
|
||||
# at the end of the file!
|
||||
|
@ -470,7 +470,7 @@ sp_head::init(LEX *lex)
|
||||
{
|
||||
DBUG_ENTER("sp_head::init");
|
||||
|
||||
lex->spcont= m_pcont= new sp_pcontext(NULL);
|
||||
lex->spcont= m_pcont= new sp_pcontext();
|
||||
|
||||
/*
|
||||
Altough trg_table_fields list is used only in triggers we init for all
|
||||
|
@ -107,8 +107,6 @@ public:
|
||||
/* Possible values of m_flags */
|
||||
enum {
|
||||
HAS_RETURN= 1, // For FUNCTIONs only: is set if has RETURN
|
||||
IN_SIMPLE_CASE= 2, // Is set if parsing a simple CASE
|
||||
IN_HANDLER= 4, // Is set if the parser is in a handler body
|
||||
MULTI_RESULTS= 8, // Is set if a procedure with SELECT(s)
|
||||
CONTAINS_DYNAMIC_SQL= 16, // Is set if a procedure with PREPARE/EXECUTE
|
||||
IS_INVOKED= 32, // Is set if this sp_head is being used
|
||||
|
@ -25,6 +25,11 @@
|
||||
#include "sp_pcontext.h"
|
||||
#include "sp_head.h"
|
||||
|
||||
/* Initial size for the dynamic arrays in sp_pcontext */
|
||||
#define PCONTEXT_ARRAY_INIT_ALLOC 16
|
||||
/* Increment size for the dynamic arrays in sp_pcontext */
|
||||
#define PCONTEXT_ARRAY_INCREMENT_ALLOC 8
|
||||
|
||||
/*
|
||||
Sanity check for SQLSTATEs. Will not check if it's really an existing
|
||||
state (there are just too many), but will check length and bad characters.
|
||||
@ -49,28 +54,61 @@ sp_cond_check(LEX_STRING *sqlstate)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
sp_pcontext::sp_pcontext(sp_pcontext *prev)
|
||||
:Sql_alloc(), m_max_var_index(0), m_max_cursor_index(0), m_max_handler_index(0),
|
||||
m_context_handlers(0), m_parent(prev), m_pboundary(0)
|
||||
sp_pcontext::sp_pcontext()
|
||||
: Sql_alloc(),
|
||||
m_max_var_index(0), m_max_cursor_index(0), m_max_handler_index(0),
|
||||
m_context_handlers(0), m_parent(NULL), m_pboundary(0),
|
||||
m_label_scope(LABEL_DEFAULT_SCOPE)
|
||||
{
|
||||
VOID(my_init_dynamic_array(&m_vars, sizeof(sp_variable_t *), 16, 8));
|
||||
VOID(my_init_dynamic_array(&m_case_expr_id_lst, sizeof(int), 16, 8));
|
||||
VOID(my_init_dynamic_array(&m_conds, sizeof(sp_cond_type_t *), 16, 8));
|
||||
VOID(my_init_dynamic_array(&m_cursors, sizeof(LEX_STRING), 16, 8));
|
||||
VOID(my_init_dynamic_array(&m_handlers, sizeof(sp_cond_type_t *), 16, 8));
|
||||
VOID(my_init_dynamic_array(&m_vars, sizeof(sp_variable_t *),
|
||||
PCONTEXT_ARRAY_INIT_ALLOC,
|
||||
PCONTEXT_ARRAY_INCREMENT_ALLOC));
|
||||
VOID(my_init_dynamic_array(&m_case_expr_id_lst, sizeof(int),
|
||||
PCONTEXT_ARRAY_INIT_ALLOC,
|
||||
PCONTEXT_ARRAY_INCREMENT_ALLOC));
|
||||
VOID(my_init_dynamic_array(&m_conds, sizeof(sp_cond_type_t *),
|
||||
PCONTEXT_ARRAY_INIT_ALLOC,
|
||||
PCONTEXT_ARRAY_INCREMENT_ALLOC));
|
||||
VOID(my_init_dynamic_array(&m_cursors, sizeof(LEX_STRING),
|
||||
PCONTEXT_ARRAY_INIT_ALLOC,
|
||||
PCONTEXT_ARRAY_INCREMENT_ALLOC));
|
||||
VOID(my_init_dynamic_array(&m_handlers, sizeof(sp_cond_type_t *),
|
||||
PCONTEXT_ARRAY_INIT_ALLOC,
|
||||
PCONTEXT_ARRAY_INCREMENT_ALLOC));
|
||||
m_label.empty();
|
||||
m_children.empty();
|
||||
if (!prev)
|
||||
{
|
||||
m_var_offset= m_cursor_offset= 0;
|
||||
m_num_case_exprs= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_var_offset= prev->m_var_offset + prev->m_max_var_index;
|
||||
m_cursor_offset= prev->current_cursor_count();
|
||||
m_num_case_exprs= prev->get_num_case_exprs();
|
||||
}
|
||||
|
||||
m_var_offset= m_cursor_offset= 0;
|
||||
m_num_case_exprs= 0;
|
||||
}
|
||||
|
||||
sp_pcontext::sp_pcontext(sp_pcontext *prev, label_scope_type label_scope)
|
||||
: Sql_alloc(),
|
||||
m_max_var_index(0), m_max_cursor_index(0), m_max_handler_index(0),
|
||||
m_context_handlers(0), m_parent(prev), m_pboundary(0),
|
||||
m_label_scope(label_scope)
|
||||
{
|
||||
VOID(my_init_dynamic_array(&m_vars, sizeof(sp_variable_t *),
|
||||
PCONTEXT_ARRAY_INIT_ALLOC,
|
||||
PCONTEXT_ARRAY_INCREMENT_ALLOC));
|
||||
VOID(my_init_dynamic_array(&m_case_expr_id_lst, sizeof(int),
|
||||
PCONTEXT_ARRAY_INIT_ALLOC,
|
||||
PCONTEXT_ARRAY_INCREMENT_ALLOC));
|
||||
VOID(my_init_dynamic_array(&m_conds, sizeof(sp_cond_type_t *),
|
||||
PCONTEXT_ARRAY_INIT_ALLOC,
|
||||
PCONTEXT_ARRAY_INCREMENT_ALLOC));
|
||||
VOID(my_init_dynamic_array(&m_cursors, sizeof(LEX_STRING),
|
||||
PCONTEXT_ARRAY_INIT_ALLOC,
|
||||
PCONTEXT_ARRAY_INCREMENT_ALLOC));
|
||||
VOID(my_init_dynamic_array(&m_handlers, sizeof(sp_cond_type_t *),
|
||||
PCONTEXT_ARRAY_INIT_ALLOC,
|
||||
PCONTEXT_ARRAY_INCREMENT_ALLOC));
|
||||
m_label.empty();
|
||||
m_children.empty();
|
||||
|
||||
m_var_offset= prev->m_var_offset + prev->m_max_var_index;
|
||||
m_cursor_offset= prev->current_cursor_count();
|
||||
m_num_case_exprs= prev->get_num_case_exprs();
|
||||
}
|
||||
|
||||
void
|
||||
@ -92,9 +130,9 @@ sp_pcontext::destroy()
|
||||
}
|
||||
|
||||
sp_pcontext *
|
||||
sp_pcontext::push_context()
|
||||
sp_pcontext::push_context(label_scope_type label_scope)
|
||||
{
|
||||
sp_pcontext *child= new sp_pcontext(this);
|
||||
sp_pcontext *child= new sp_pcontext(this, label_scope);
|
||||
|
||||
if (child)
|
||||
m_children.push_back(child);
|
||||
@ -257,7 +295,15 @@ sp_pcontext::find_label(char *name)
|
||||
if (my_strcasecmp(system_charset_info, name, lab->name) == 0)
|
||||
return lab;
|
||||
|
||||
if (m_parent)
|
||||
/*
|
||||
Note about exception handlers.
|
||||
See SQL:2003 SQL/PSM (ISO/IEC 9075-4:2003),
|
||||
section 13.1 <compound statement>,
|
||||
syntax rule 4.
|
||||
In short, a DECLARE HANDLER block can not refer
|
||||
to labels from the parent context, as they are out of scope.
|
||||
*/
|
||||
if (m_parent && (m_label_scope == LABEL_DEFAULT_SCOPE))
|
||||
return m_parent->find_label(name);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -88,16 +88,33 @@ typedef struct sp_cond
|
||||
sp_cond_type_t *val;
|
||||
} sp_cond_t;
|
||||
|
||||
/**
|
||||
The scope of a label in Stored Procedures,
|
||||
for name resolution of labels in a parsing context.
|
||||
*/
|
||||
enum label_scope_type
|
||||
{
|
||||
/**
|
||||
The labels declared in a parent context are in scope.
|
||||
*/
|
||||
LABEL_DEFAULT_SCOPE,
|
||||
/**
|
||||
The labels declared in a parent context are not in scope.
|
||||
*/
|
||||
LABEL_HANDLER_SCOPE
|
||||
};
|
||||
|
||||
/*
|
||||
The parse-time context, used to keep track on declared variables/parameters,
|
||||
/**
|
||||
The parse-time context, used to keep track of declared variables/parameters,
|
||||
conditions, handlers, cursors and labels, during parsing.
|
||||
sp_contexts are organized as a tree, with one object for each begin-end
|
||||
block, plus a root-context for the parameters.
|
||||
block, one object for each exception handler,
|
||||
plus a root-context for the parameters.
|
||||
This is used during parsing for looking up defined names (e.g. declared
|
||||
variables and visible labels), for error checking, and to calculate offsets
|
||||
to be used at runtime. (During execution variable values, active handlers
|
||||
and cursors, etc, are referred to by an index in a stack.)
|
||||
Parsing contexts for exception handlers limit the visibility of labels.
|
||||
The pcontext tree is also kept during execution and is used for error
|
||||
checking (e.g. correct number of parameters), and in the future, used by
|
||||
the debugger.
|
||||
@ -105,21 +122,30 @@ typedef struct sp_cond
|
||||
|
||||
class sp_pcontext : public Sql_alloc
|
||||
{
|
||||
sp_pcontext(const sp_pcontext &); /* Prevent use of these */
|
||||
void operator=(sp_pcontext &);
|
||||
public:
|
||||
|
||||
public:
|
||||
|
||||
sp_pcontext(sp_pcontext *prev);
|
||||
/**
|
||||
Constructor.
|
||||
Builds a parsing context root node.
|
||||
*/
|
||||
sp_pcontext();
|
||||
|
||||
// Free memory
|
||||
void
|
||||
destroy();
|
||||
|
||||
/**
|
||||
Create and push a new context in the tree.
|
||||
@param label_scope label scope for the new parsing context
|
||||
@return the node created
|
||||
*/
|
||||
sp_pcontext *
|
||||
push_context();
|
||||
push_context(label_scope_type label_scope);
|
||||
|
||||
// Returns the previous context, not the one we pop
|
||||
/**
|
||||
Pop a node from the parsing context tree.
|
||||
@return the parent node
|
||||
*/
|
||||
sp_pcontext *
|
||||
pop_context();
|
||||
|
||||
@ -363,6 +389,13 @@ class sp_pcontext : public Sql_alloc
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
Constructor for a tree node.
|
||||
@param prev the parent parsing context
|
||||
@param label_scope label_scope for this parsing context
|
||||
*/
|
||||
sp_pcontext(sp_pcontext *prev, label_scope_type label_scope);
|
||||
|
||||
/*
|
||||
m_max_var_index -- number of variables (including all types of arguments)
|
||||
in this context including all children contexts.
|
||||
@ -416,6 +449,14 @@ private:
|
||||
|
||||
List<sp_pcontext> m_children; // Children contexts, used for destruction
|
||||
|
||||
/**
|
||||
Scope of labels for this parsing context.
|
||||
*/
|
||||
label_scope_type m_label_scope;
|
||||
|
||||
private:
|
||||
sp_pcontext(const sp_pcontext &); /* Prevent use of these */
|
||||
void operator=(sp_pcontext &);
|
||||
}; // class sp_pcontext : public Sql_alloc
|
||||
|
||||
|
||||
|
@ -2006,6 +2006,9 @@ sp_decl:
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp= lex->sphead;
|
||||
|
||||
lex->spcont= lex->spcont->push_context(LABEL_HANDLER_SCOPE);
|
||||
|
||||
sp_pcontext *ctx= lex->spcont;
|
||||
sp_instr_hpush_jump *i=
|
||||
new sp_instr_hpush_jump(sp->instructions(), ctx, $2,
|
||||
@ -2013,7 +2016,6 @@ sp_decl:
|
||||
|
||||
sp->add_instr(i);
|
||||
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
|
||||
sp->m_flags|= sp_head::IN_HANDLER;
|
||||
}
|
||||
sp_hcond_list sp_proc_stmt
|
||||
{
|
||||
@ -2037,10 +2039,12 @@ sp_decl:
|
||||
sp->push_backpatch(i, lex->spcont->last_label()); /* Block end */
|
||||
}
|
||||
lex->sphead->backpatch(hlab);
|
||||
sp->m_flags&= ~sp_head::IN_HANDLER;
|
||||
|
||||
lex->spcont= ctx->pop_context();
|
||||
|
||||
$$.vars= $$.conds= $$.curs= 0;
|
||||
$$.hndlrs= $6;
|
||||
ctx->add_handlers($6);
|
||||
lex->spcont->add_handlers($6);
|
||||
}
|
||||
| DECLARE_SYM ident CURSOR_SYM FOR_SYM sp_cursor_stmt
|
||||
{
|
||||
@ -2103,11 +2107,18 @@ sp_handler_type:
|
||||
;
|
||||
|
||||
sp_hcond_list:
|
||||
sp_hcond_element
|
||||
{ $$= 1; }
|
||||
| sp_hcond_list ',' sp_hcond_element
|
||||
{ $$+= 1; }
|
||||
;
|
||||
|
||||
sp_hcond_element:
|
||||
sp_hcond
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp= lex->sphead;
|
||||
sp_pcontext *ctx= lex->spcont;
|
||||
sp_pcontext *ctx= lex->spcont->parent_context();
|
||||
|
||||
if (ctx->find_handler($1))
|
||||
{
|
||||
@ -2121,28 +2132,6 @@ sp_hcond_list:
|
||||
|
||||
i->add_condition($1);
|
||||
ctx->push_handler($1);
|
||||
$$= 1;
|
||||
}
|
||||
}
|
||||
| sp_hcond_list ',' sp_hcond
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp= lex->sphead;
|
||||
sp_pcontext *ctx= lex->spcont;
|
||||
|
||||
if (ctx->find_handler($3))
|
||||
{
|
||||
my_message(ER_SP_DUP_HANDLER, ER(ER_SP_DUP_HANDLER), MYF(0));
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
sp_instr_hpush_jump *i=
|
||||
(sp_instr_hpush_jump *)sp->last_instruction();
|
||||
|
||||
i->add_condition($3);
|
||||
ctx->push_handler($3);
|
||||
$$= $1 + 1;
|
||||
}
|
||||
}
|
||||
;
|
||||
@ -2687,7 +2676,7 @@ sp_unlabeled_control:
|
||||
sp_label_t *lab= lex->spcont->last_label();
|
||||
|
||||
lab->type= SP_LAB_BEGIN;
|
||||
lex->spcont= lex->spcont->push_context();
|
||||
lex->spcont= lex->spcont->push_context(LABEL_DEFAULT_SCOPE);
|
||||
}
|
||||
sp_decls
|
||||
sp_proc_stmts
|
||||
|
Loading…
x
Reference in New Issue
Block a user