Commit c81b848d authored by pem@mysql.comhem.se's avatar pem@mysql.comhem.se

Major rehacking and cleanup of sp_pcontext.

This finishes (almost) WL#2002: Implement stored procedure GOTO.
Only the syntax issue for free labels remains ("label L;" vs "L:").
parent 6b5a6cdf
......@@ -373,4 +373,5 @@
#define ER_WARN_VIEW_WITHOUT_KEY 1354
#define ER_VIEW_INVALID 1355
#define ER_SP_NO_DROP_SP 1356
#define ER_SP_GOTO_IN_HNDLR 1357
#define ER_ERROR_MESSAGES 357
......@@ -68,6 +68,42 @@ goto foo;
end|
ERROR 42000: GOTO with no matching label: foo
create procedure foo()
begin
begin
label foo;
end;
goto foo;
end|
ERROR 42000: GOTO with no matching label: foo
create procedure foo()
begin
goto foo;
begin
label foo;
end;
end|
ERROR 42000: GOTO with no matching label: foo
create procedure foo()
begin
begin
goto foo;
end;
begin
label foo;
end;
end|
ERROR 42000: GOTO with no matching label: foo
create procedure foo()
begin
begin
label foo;
end;
begin
goto foo;
end;
end|
ERROR 42000: GOTO with no matching label: foo
create procedure foo()
foo: loop
foo: loop
set @x=2;
......@@ -288,6 +324,16 @@ declare continue handler for sqlstate '42S99' set x = 1;
declare c cursor for select * from t1;
end|
ERROR 42000: Cursor declaration after handler declaration
create procedure p()
begin
declare continue handler for sqlexception
begin
goto L1;
end;
select field from t1;
label L1;
end|
ERROR HY000: GOTO is not allowed in a stored procedure handler
create procedure bug1965()
begin
declare c cursor for select val from t1 order by valname;
......
reset master;
use test;
drop table if exists t1;
drop table if exists t2;
......@@ -398,7 +397,7 @@ id data
i 3
delete from t1|
drop procedure i|
create procedure j()
create procedure goto1()
begin
declare y int;
label a;
......@@ -411,7 +410,7 @@ insert into t1 values ("j", y);
goto a;
label b;
end|
call j()|
call goto1()|
id data
id data
j 0
......@@ -422,8 +421,8 @@ id data
j 0
j 1
j 2
drop procedure j|
create procedure k(a int)
drop procedure goto1|
create procedure goto2(a int)
begin
declare x int default 0;
declare continue handler for sqlstate '42S98' set x = 1;
......@@ -446,7 +445,7 @@ end;
end while b;
select * from t1;
end|
call k(0)|
call goto2(0)|
id data
j 0
j 1
......@@ -455,7 +454,7 @@ id data
j 0
j 1
j 2
call k(1)|
call goto2(1)|
id data
j 0
j 1
......@@ -464,7 +463,7 @@ id data
j 0
j 1
j 2
call k(2)|
call goto2(2)|
id data
j 0
j 1
......@@ -477,8 +476,60 @@ id data
j 0
j 1
j 2
drop procedure k|
drop procedure goto2|
delete from t1|
create procedure goto3()
begin
label L1;
begin
end;
goto L1;
end|
drop procedure goto3|
create procedure goto4()
begin
begin
label lab1;
begin
goto lab1;
end;
end;
end|
drop procedure goto4|
create procedure goto5()
begin
begin
begin
goto lab1;
end;
label lab1;
end;
end|
drop procedure goto5|
create procedure goto6()
begin
label L1;
goto L5;
begin
label L2;
goto L1;
goto L5;
begin
label L3;
goto L1;
goto L2;
goto L3;
goto L4;
goto L5;
end;
goto L2;
goto L4;
label L4;
end;
label L5;
goto L1;
end|
drop procedure goto6|
insert into t1 values ("foo", 3), ("bar", 19)|
insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)|
create procedure sel1()
......@@ -1536,11 +1587,8 @@ show errors;
show columns from t1;
show grants for 'root'@'localhost';
show keys from t1;
show master status;
show open tables like 'foo';
show privileges;
show slave hosts;
show slave status;
show status like 'foo';
show tables like 'foo';
show variables like 'foo';
......@@ -1567,8 +1615,6 @@ data int(11) 0
Grants for root@localhost
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 22451
Database Table In_use Name_locked
Privilege Context Comment
Alter Tables To alter the table
......@@ -1594,8 +1640,6 @@ Shutdown Server Admin To shut down the server
Super Server Admin To use KILL thread, SET GLOBAL, CHANGE MASTER, etc.
Update Tables To update existing rows
Usage Server Admin No privileges - allow connect only
Server_id Host Port Rpl_recovery_rank Master_id
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
Variable_name Value
Tables_in_test (foo) table_type
Variable_name Value
......@@ -1621,8 +1665,6 @@ data int(11) 0
Grants for root@localhost
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
File Position Binlog_Do_DB Binlog_Ignore_DB
master-bin.000001 22451
Database Table In_use Name_locked
Privilege Context Comment
Alter Tables To alter the table
......@@ -1648,8 +1690,6 @@ Shutdown Server Admin To shut down the server
Super Server Admin To use KILL thread, SET GLOBAL, CHANGE MASTER, etc.
Update Tables To update existing rows
Usage Server Admin No privileges - allow connect only
Server_id Host Port Rpl_recovery_rank Master_id
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
Variable_name Value
Tables_in_test (foo) table_type
Variable_name Value
......
......@@ -103,6 +103,42 @@ create procedure foo()
begin
goto foo;
end|
--error 1307
create procedure foo()
begin
begin
label foo;
end;
goto foo;
end|
--error 1307
create procedure foo()
begin
goto foo;
begin
label foo;
end;
end|
--error 1307
create procedure foo()
begin
begin
goto foo;
end;
begin
label foo;
end;
end|
--error 1307
create procedure foo()
begin
begin
label foo;
end;
begin
goto foo;
end;
end|
# Redefining label
--error 1308
......@@ -380,6 +416,18 @@ begin
declare c cursor for select * from t1;
end|
--error 1357
create procedure p()
begin
declare continue handler for sqlexception
begin
goto L1;
end;
select field from t1;
label L1;
end|
#
# BUG#1965
#
......
#
# Basic stored PROCEDURE tests
#
#
# Let us reset binary logs in order to make show master status
# in test for bug 4902 repeatable.
reset master;
# Please keep this file free of --error cases and other
# things that will not run in a single debugged mysqld
# process (e.g. master-slave things).
use test;
......@@ -470,10 +468,10 @@ drop procedure i|
# The non-standard GOTO, for compatibility
#
# QQQ The "label" syntax is temporary.
# QQQ This is no nearly enough, more tests are needed
# QQQ The "label" syntax is temporary, it will (hopefully)
# change to the more common "L:" syntax soon.
#
create procedure j()
create procedure goto1()
begin
declare y int;
......@@ -488,12 +486,11 @@ label a;
label b;
end|
call j()|
drop procedure j|
call goto1()|
drop procedure goto1|
# With dummy handlers, just to test restore of contexts with jumps
create procedure k(a int)
create procedure goto2(a int)
begin
declare x int default 0;
declare continue handler for sqlstate '42S98' set x = 1;
......@@ -520,13 +517,70 @@ b:
select * from t1;
end|
call k(0)|
call k(1)|
call k(2)|
call goto2(0)|
call goto2(1)|
call goto2(2)|
drop procedure k|
drop procedure goto2|
delete from t1|
# Check label visibility for some more cases. We don't call these.
create procedure goto3()
begin
label L1;
begin
end;
goto L1;
end|
drop procedure goto3|
create procedure goto4()
begin
begin
label lab1;
begin
goto lab1;
end;
end;
end|
drop procedure goto4|
create procedure goto5()
begin
begin
begin
goto lab1;
end;
label lab1;
end;
end|
drop procedure goto5|
create procedure goto6()
begin
label L1;
goto L5;
begin
label L2;
goto L1;
goto L5;
begin
label L3;
goto L1;
goto L2;
goto L3;
goto L4;
goto L5;
end;
goto L2;
goto L4;
label L4;
end;
label L5;
goto L1;
end|
drop procedure goto6|
# SELECT with one of more result set sent back to the clinet
insert into t1 values ("foo", 3), ("bar", 19)|
insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)|
......@@ -1761,11 +1815,8 @@ begin
show columns from t1;
show grants for 'root'@'localhost';
show keys from t1;
show master status;
show open tables like 'foo';
show privileges;
show slave hosts;
show slave status;
show status like 'foo';
show tables like 'foo';
show variables like 'foo';
......@@ -1773,6 +1824,9 @@ begin
end|
#show binlog events;
#show storage engines;
#show master status;
#show slave hosts;
#show slave status;
call bug4902()|
call bug4902()|
......
......@@ -369,3 +369,4 @@ character-set=latin2
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -363,3 +363,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -371,3 +371,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -360,3 +360,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -365,3 +365,4 @@ character-set=latin7
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -360,3 +360,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -372,3 +372,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -360,3 +360,4 @@ character-set=greek
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -362,3 +362,4 @@ character-set=latin2
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -360,3 +360,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -362,3 +362,4 @@ character-set=ujis
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -360,3 +360,4 @@ character-set=euckr
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -362,3 +362,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -362,3 +362,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -364,3 +364,4 @@ character-set=latin2
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -361,3 +361,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -364,3 +364,4 @@ character-set=latin2
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -362,3 +362,4 @@ character-set=koi8r
" view ()"
"View '%-.64s.%-.64s' "
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -366,3 +366,4 @@ character-set=cp1250
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -368,3 +368,4 @@ character-set=latin2
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -362,3 +362,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -360,3 +360,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -365,3 +365,4 @@ character-set=koi8u
"View, , ͦ æ(), Ҧ "
"View '%-.64s.%-.64s' Ŧަ æ æ"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
......@@ -257,7 +257,7 @@ sp_head::operator delete(void *ptr, size_t size)
sp_head::sp_head()
:Item_arena((bool)FALSE), m_returns_cs(NULL), m_has_return(FALSE),
m_simple_case(FALSE), m_multi_results(FALSE)
m_simple_case(FALSE), m_multi_results(FALSE), m_in_handler(FALSE)
{
DBUG_ENTER("sp_head::sp_head");
......@@ -272,7 +272,7 @@ sp_head::init(LEX *lex)
{
DBUG_ENTER("sp_head::init");
lex->spcont= m_pcont= new sp_pcontext();
lex->spcont= m_pcont= new sp_pcontext(NULL);
my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8);
m_param_begin= m_param_end= m_returns_begin= m_returns_end= m_body_begin= 0;
m_qname.str= m_db.str= m_name.str= m_params.str= m_retstr.str=
......@@ -514,10 +514,10 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
{
DBUG_ENTER("sp_head::execute_function");
DBUG_PRINT("info", ("function %s", m_name.str));
uint csize = m_pcont->max_framesize();
uint params = m_pcont->params();
uint hmax = m_pcont->handlers();
uint cmax = m_pcont->cursors();
uint csize = m_pcont->max_pvars();
uint params = m_pcont->current_pvars();
uint hmax = m_pcont->max_handlers();
uint cmax = m_pcont->max_cursors();
sp_rcontext *octx = thd->spcont;
sp_rcontext *nctx = NULL;
uint i;
......@@ -594,10 +594,10 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
DBUG_ENTER("sp_head::execute_procedure");
DBUG_PRINT("info", ("procedure %s", m_name.str));
int ret= 0;
uint csize = m_pcont->max_framesize();
uint params = m_pcont->params();
uint hmax = m_pcont->handlers();
uint cmax = m_pcont->cursors();
uint csize = m_pcont->max_pvars();
uint params = m_pcont->current_pvars();
uint hmax = m_pcont->max_handlers();
uint cmax = m_pcont->max_cursors();
sp_rcontext *octx = thd->spcont;
sp_rcontext *nctx = NULL;
my_bool tmp_octx = FALSE; // True if we have allocated a temporary octx
......@@ -851,12 +851,18 @@ sp_head::backpatch(sp_label_t *lab)
(bp->lab->type == SP_LAB_REF &&
my_strcasecmp(system_charset_info, bp->lab->name, lab->name) == 0))
{
sp_scope_t sdiff;
if (bp->lab->type != SP_LAB_REF)
bp->instr->backpatch(dest, lab->ctx);
else
{
sp_label_t *dstlab= bp->lab->ctx->find_label(lab->name);
if (bp->lab->type == SP_LAB_REF)
if (dstlab)
{
bp->lab= lab;
m_pcont->diff_scopes(0, &sdiff);
bp->instr->backpatch(dest, sdiff.hndlrs, sdiff.curs);
bp->instr->backpatch(dest, dstlab->ctx);
}
}
}
}
}
......@@ -1236,7 +1242,7 @@ sp_instr_jump::print(String *str)
uint
sp_instr_jump::opt_mark(sp_head *sp)
{
m_dest= opt_shortcut_jump(sp);
m_dest= opt_shortcut_jump(sp, this);
if (m_dest != m_ip+1) /* Jumping to following instruction? */
marked= 1;
m_optdest= sp->get_instr(m_dest);
......@@ -1244,15 +1250,18 @@ sp_instr_jump::opt_mark(sp_head *sp)
}
uint
sp_instr_jump::opt_shortcut_jump(sp_head *sp)
sp_instr_jump::opt_shortcut_jump(sp_head *sp, sp_instr *start)
{
uint dest= m_dest;
sp_instr *i;
while ((i= sp->get_instr(dest)))
{
uint ndest= i->opt_shortcut_jump(sp);
uint ndest;
if (start == i)
break;
ndest= i->opt_shortcut_jump(sp, start);
if (ndest == dest)
break;
dest= ndest;
......@@ -1320,7 +1329,7 @@ sp_instr_jump_if::opt_mark(sp_head *sp)
marked= 1;
if ((i= sp->get_instr(m_dest)))
{
m_dest= i->opt_shortcut_jump(sp);
m_dest= i->opt_shortcut_jump(sp, this);
m_optdest= sp->get_instr(m_dest);
}
sp->opt_mark(m_dest);
......@@ -1377,7 +1386,7 @@ sp_instr_jump_if_not::opt_mark(sp_head *sp)
marked= 1;
if ((i= sp->get_instr(m_dest)))
{
m_dest= i->opt_shortcut_jump(sp);
m_dest= i->opt_shortcut_jump(sp, this);
m_optdest= sp->get_instr(m_dest);
}
sp->opt_mark(m_dest);
......@@ -1460,7 +1469,7 @@ sp_instr_hpush_jump::opt_mark(sp_head *sp)
marked= 1;
if ((i= sp->get_instr(m_dest)))
{
m_dest= i->opt_shortcut_jump(sp);
m_dest= i->opt_shortcut_jump(sp, this);
m_optdest= sp->get_instr(m_dest);
}
sp->opt_mark(m_dest);
......@@ -1487,6 +1496,13 @@ sp_instr_hpop::print(String *str)
str->qs_append(m_count);
}
void
sp_instr_hpop::backpatch(uint dest, sp_pcontext *dst_ctx)
{
m_count= m_ctx->diff_handlers(dst_ctx);
}
//
// sp_instr_hreturn
//
......@@ -1551,6 +1567,12 @@ sp_instr_cpop::print(String *str)
str->qs_append(m_count);
}
void
sp_instr_cpop::backpatch(uint dest, sp_pcontext *dst_ctx)
{
m_count= m_ctx->diff_cursors(dst_ctx);
}
//
// sp_instr_copen
//
......
......@@ -86,6 +86,7 @@ public:
my_bool m_has_return; // For FUNCTIONs only
my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise
my_bool m_multi_results; // TRUE if a procedure with SELECT(s)
my_bool m_in_handler; // TRUE if parser in a handler body
uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value
st_sp_chistics *m_chistics;
ulong m_sql_mode; // For SHOW CREATE
......@@ -262,10 +263,11 @@ public:
uint marked;
Item *free_list; // My Items
uint m_ip; // My index
sp_pcontext *m_ctx; // My parse context
// Should give each a name or type code for debugging purposes?
sp_instr(uint ip)
:Sql_alloc(), marked(0), free_list(0), m_ip(ip)
sp_instr(uint ip, sp_pcontext *ctx)
:Sql_alloc(), marked(0), free_list(0), m_ip(ip), m_ctx(ctx)
{}
virtual ~sp_instr()
......@@ -279,7 +281,7 @@ public:
virtual void print(String *str) = 0;
virtual void backpatch(uint dest, uint hpop, uint cpop)
virtual void backpatch(uint dest, sp_pcontext *dst_ctx)
{}
virtual uint opt_mark(sp_head *sp)
......@@ -288,7 +290,7 @@ public:
return m_ip+1;
}
virtual uint opt_shortcut_jump(sp_head *sp)
virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
{
return m_ip;
}
......@@ -311,8 +313,8 @@ class sp_instr_stmt : public sp_instr
public:
sp_instr_stmt(uint ip)
: sp_instr(ip), m_lex(NULL)
sp_instr_stmt(uint ip, sp_pcontext *ctx)
: sp_instr(ip, ctx), m_lex(NULL)
{}
virtual ~sp_instr_stmt();
......@@ -353,8 +355,10 @@ public:
TABLE_LIST *tables;
sp_instr_set(uint ip, uint offset, Item *val, enum enum_field_types type)
: sp_instr(ip), tables(NULL), m_offset(offset), m_value(val), m_type(type)
sp_instr_set(uint ip, sp_pcontext *ctx,
uint offset, Item *val, enum enum_field_types type)
: sp_instr(ip, ctx),
tables(NULL), m_offset(offset), m_value(val), m_type(type)
{}
virtual ~sp_instr_set()
......@@ -382,12 +386,12 @@ public:
uint m_dest; // Where we will go
sp_instr_jump(uint ip)
: sp_instr(ip), m_dest(0), m_optdest(0)
sp_instr_jump(uint ip, sp_pcontext *ctx)
: sp_instr(ip, ctx), m_dest(0), m_optdest(0)
{}
sp_instr_jump(uint ip, uint dest)
: sp_instr(ip), m_dest(dest), m_optdest(0)
sp_instr_jump(uint ip, sp_pcontext *ctx, uint dest)
: sp_instr(ip, ctx), m_dest(dest), m_optdest(0)
{}
virtual ~sp_instr_jump()
......@@ -399,11 +403,11 @@ public:
virtual uint opt_mark(sp_head *sp);
virtual uint opt_shortcut_jump(sp_head *sp);
virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start);
virtual void opt_move(uint dst, List<sp_instr> *ibp);
virtual void backpatch(uint dest, uint hpop, uint cpop)
virtual void backpatch(uint dest, sp_pcontext *dst_ctx)
{
if (m_dest == 0) // Don't reset
m_dest= dest;
......@@ -425,12 +429,12 @@ public:
TABLE_LIST *tables;
sp_instr_jump_if(uint ip, Item *i)
: sp_instr_jump(ip), tables(NULL), m_expr(i)
sp_instr_jump_if(uint ip, sp_pcontext *ctx, Item *i)
: sp_instr_jump(ip, ctx), tables(NULL), m_expr(i)
{}
sp_instr_jump_if(uint ip, Item *i, uint dest)
: sp_instr_jump(ip, dest), tables(NULL), m_expr(i)
sp_instr_jump_if(uint ip, sp_pcontext *ctx, Item *i, uint dest)
: sp_instr_jump(ip, ctx, dest), tables(NULL), m_expr(i)
{}
virtual ~sp_instr_jump_if()
......@@ -442,7 +446,7 @@ public:
virtual uint opt_mark(sp_head *sp);
virtual uint opt_shortcut_jump(sp_head *sp)
virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
{
return m_ip;
}
......@@ -463,12 +467,12 @@ public:
TABLE_LIST *tables;
sp_instr_jump_if_not(uint ip, Item *i)
: sp_instr_jump(ip), tables(NULL), m_expr(i)
sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i)
: sp_instr_jump(ip, ctx), tables(NULL), m_expr(i)
{}
sp_instr_jump_if_not(uint ip, Item *i, uint dest)
: sp_instr_jump(ip, dest), tables(NULL), m_expr(i)
sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i, uint dest)
: sp_instr_jump(ip, ctx, dest), tables(NULL), m_expr(i)
{}
virtual ~sp_instr_jump_if_not()
......@@ -480,7 +484,7 @@ public:
virtual uint opt_mark(sp_head *sp);
virtual uint opt_shortcut_jump(sp_head *sp)
virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
{
return m_ip;
}
......@@ -501,8 +505,9 @@ public:
TABLE_LIST *tables;
sp_instr_freturn(uint ip, Item *val, enum enum_field_types type)
: sp_instr(ip), tables(NULL), m_value(val), m_type(type)
sp_instr_freturn(uint ip, sp_pcontext *ctx,
Item *val, enum enum_field_types type)
: sp_instr(ip, ctx), tables(NULL), m_value(val), m_type(type)
{}
virtual ~sp_instr_freturn()
......@@ -533,8 +538,8 @@ class sp_instr_hpush_jump : public sp_instr_jump
public:
sp_instr_hpush_jump(uint ip, int htype, uint fp)
: sp_instr_jump(ip), m_type(htype), m_frame(fp)
sp_instr_hpush_jump(uint ip, sp_pcontext *ctx, int htype, uint fp)
: sp_instr_jump(ip, ctx), m_type(htype), m_frame(fp)
{
m_handler= ip+1;
m_cond.empty();
......@@ -551,7 +556,7 @@ public:
virtual uint opt_mark(sp_head *sp);
virtual uint opt_shortcut_jump(sp_head *sp)
virtual uint opt_shortcut_jump(sp_head *sp, sp_instr *start)
{
return m_ip;
}
......@@ -578,8 +583,8 @@ class sp_instr_hpop : public sp_instr
public:
sp_instr_hpop(uint ip, uint count)
: sp_instr(ip), m_count(count)
sp_instr_hpop(uint ip, sp_pcontext *ctx, uint count)
: sp_instr(ip, ctx), m_count(count)
{}
virtual ~sp_instr_hpop()
......@@ -589,13 +594,7 @@ public:
virtual void print(String *str);
virtual void backpatch(uint dest, uint hpop, uint cpop)
{
if (hpop > m_count)
m_count= 0;
else
m_count-= hpop;
}
virtual void backpatch(uint dest, sp_pcontext *dst_ctx);
virtual uint opt_mark(sp_head *sp)
{
......@@ -618,8 +617,8 @@ class sp_instr_hreturn : public sp_instr
public:
sp_instr_hreturn(uint ip, uint fp)
: sp_instr(ip), m_frame(fp)
sp_instr_hreturn(uint ip, sp_pcontext *ctx, uint fp)
: sp_instr(ip, ctx), m_frame(fp)
{}
virtual ~sp_instr_hreturn()
......@@ -649,8 +648,8 @@ class sp_instr_cpush : public sp_instr
public:
sp_instr_cpush(uint ip, LEX *lex)
: sp_instr(ip), m_lex(lex)
sp_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex)
: sp_instr(ip, ctx), m_lex(lex)
{}
virtual ~sp_instr_cpush();
......@@ -673,8 +672,8 @@ class sp_instr_cpop : public sp_instr
public:
sp_instr_cpop(uint ip, uint count)
: sp_instr(ip), m_count(count)
sp_instr_cpop(uint ip, sp_pcontext *ctx, uint count)
: sp_instr(ip, ctx), m_count(count)
{}
virtual ~sp_instr_cpop()
......@@ -684,13 +683,7 @@ public:
virtual void print(String *str);
virtual void backpatch(uint dest, uint hpop, uint cpop)
{
if (cpop > m_count)
m_count= 0;
else
m_count-= cpop;
}
virtual void backpatch(uint dest, sp_pcontext *dst_ctx);
virtual uint opt_mark(sp_head *sp)
{
......@@ -713,8 +706,8 @@ class sp_instr_copen : public sp_instr_stmt
public:
sp_instr_copen(uint ip, uint c)
: sp_instr_stmt(ip), m_cursor(c)
sp_instr_copen(uint ip, sp_pcontext *ctx, uint c)
: sp_instr_stmt(ip, ctx), m_cursor(c)
{}
virtual ~sp_instr_copen()
......@@ -738,8 +731,8 @@ class sp_instr_cclose : public sp_instr
public:
sp_instr_cclose(uint ip, uint c)
: sp_instr(ip), m_cursor(c)
sp_instr_cclose(uint ip, sp_pcontext *ctx, uint c)
: sp_instr(ip, ctx), m_cursor(c)
{}
virtual ~sp_instr_cclose()
......@@ -763,8 +756,8 @@ class sp_instr_cfetch : public sp_instr
public:
sp_instr_cfetch(uint ip, uint c)
: sp_instr(ip), m_cursor(c)
sp_instr_cfetch(uint ip, sp_pcontext *ctx, uint c)
: sp_instr(ip, ctx), m_cursor(c)
{
m_varlist.empty();
}
......@@ -796,8 +789,8 @@ class sp_instr_error : public sp_instr
public:
sp_instr_error(uint ip, int errcode)
: sp_instr(ip), m_errcode(errcode)
sp_instr_error(uint ip, sp_pcontext *ctx, int errcode)
: sp_instr(ip, ctx), m_errcode(errcode)
{}
virtual ~sp_instr_error()
......
......@@ -26,79 +26,98 @@
#include "sp_pcontext.h"
#include "sp_head.h"
sp_pcontext::sp_pcontext()
: Sql_alloc(), m_params(0), m_framesize(0), m_handlers(0), m_cursmax(0),
m_hndlrlev(0)
sp_pcontext::sp_pcontext(sp_pcontext *prev)
: Sql_alloc(), m_psubsize(0), m_csubsize(0), m_hsubsize(0),
m_parent(prev), m_handlers(0)
{
VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8));
VOID(my_init_dynamic_array(&m_cond, sizeof(sp_cond_type_t *), 16, 8));
VOID(my_init_dynamic_array(&m_cursor, sizeof(LEX_STRING), 16, 8));
VOID(my_init_dynamic_array(&m_scopes, sizeof(sp_scope_t), 16, 8));
VOID(my_init_dynamic_array(&m_glabel, sizeof(sp_label_t *), 16, 8));
m_label.empty();
m_children.empty();
if (!prev)
m_poffset= m_coffset= 0;
else
{
m_poffset= prev->current_pvars();
m_coffset= prev->current_cursors();
}
}
void
sp_pcontext::destroy()
{
List_iterator_fast<sp_pcontext> li(m_children);
sp_pcontext *child;
while ((child= li++))
child->destroy();
m_children.empty();
m_label.empty();
delete_dynamic(&m_pvar);
delete_dynamic(&m_cond);
delete_dynamic(&m_cursor);
delete_dynamic(&m_scopes);
delete_dynamic(&m_glabel);
m_label.empty();
}
void
sp_pcontext::push_scope()
sp_pcontext *
sp_pcontext::push_context()
{
sp_scope_t s;
s.vars= m_pvar.elements;
s.conds= m_cond.elements;
s.hndlrs= m_hndlrlev;
s.curs= m_cursor.elements;
s.glab= m_glabel.elements;
insert_dynamic(&m_scopes, (gptr)&s);
sp_pcontext *child= new sp_pcontext(this);
if (child)
m_children.push_back(child);
return child;
}
void
sp_pcontext::pop_scope(sp_scope_t *sp)
sp_pcontext *
sp_pcontext::pop_context()
{
byte *p= pop_dynamic(&m_scopes);
if (sp && p)
memcpy(sp, p, sizeof(sp_scope_t));
uint submax= max_pvars();
if (submax > m_parent->m_psubsize)
m_parent->m_psubsize= submax;
submax= max_handlers();
if (submax > m_parent->m_hsubsize)
m_parent->m_hsubsize= submax;
submax= max_cursors();
if (submax > m_parent->m_csubsize)
m_parent->m_csubsize= submax;
return m_parent;
}
void
sp_pcontext::diff_scopes(uint sold, sp_scope_t *diffs)
uint
sp_pcontext::diff_handlers(sp_pcontext *ctx)
{
uint snew= m_scopes.elements;
sp_scope_t scope;
uint n= 0;
sp_pcontext *pctx= this;
diffs->vars= diffs->conds= diffs->hndlrs= diffs->curs= diffs->glab= 0;
while (snew-- > sold)
while (pctx && pctx != ctx)
{
get_dynamic(&m_scopes, (gptr)&scope, snew);
diffs->vars+= scope.vars;
diffs->conds+= scope.conds;
diffs->hndlrs+= scope.hndlrs;
diffs->curs+= scope.curs;
diffs->glab+= scope.glab;
n+= pctx->max_handlers();
pctx= pctx->parent_context();
}
if (sold)
if (pctx)
return n;
return 0; // Didn't find ctx
}
uint
sp_pcontext::diff_cursors(sp_pcontext *ctx)
{
uint n= 0;
sp_pcontext *pctx= this;
while (pctx && pctx != ctx)
{
get_dynamic(&m_scopes, (gptr)&scope, sold-1);
diffs->vars-= scope.vars;
diffs->conds-= scope.conds;
diffs->hndlrs-= scope.hndlrs;
diffs->curs-= scope.curs;
diffs->glab-= scope.glab;
n+= pctx->max_cursors();
pctx= pctx->parent_context();
}
if (pctx)
return n;
return 0; // Didn't find ctx
}
/* This does a linear search (from newer to older variables, in case
** we have shadowed names).
** It's possible to have a more efficient allocation and search method,
......@@ -109,20 +128,9 @@ sp_pcontext::diff_scopes(uint sold, sp_scope_t *diffs)
sp_pvar_t *
sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped)
{
uint i = m_pvar.elements;
uint limit;
uint i= m_pvar.elements;
if (! scoped || m_scopes.elements == 0)
limit= 0;
else
{
sp_scope_t s;
get_dynamic(&m_scopes, (gptr)&s, m_scopes.elements-1);
limit= s.vars;
}
while (i-- > limit)
while (i--)
{
sp_pvar_t *p;
......@@ -134,6 +142,8 @@ sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped)
return p;
}
}
if (!scoped && m_parent)
return m_parent->find_pvar(name, scoped);
return NULL;
}
......@@ -145,13 +155,13 @@ sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type,
if (p)
{
if (m_pvar.elements == m_framesize)
m_framesize += 1;
if (m_pvar.elements == m_psubsize)
m_psubsize+= 1;
p->name.str= name->str;
p->name.length= name->length;
p->type= type;
p->mode= mode;
p->offset= m_pvar.elements;
p->offset= current_pvars();
p->isset= (mode == sp_param_out ? FALSE : TRUE);
p->dflt= NULL;
insert_dynamic(&m_pvar, (gptr)&p);
......@@ -168,7 +178,7 @@ sp_pcontext::push_label(char *name, uint ip)
lab->name= name;
lab->ip= ip;
lab->type= SP_LAB_GOTO;
lab->scopes= 0;
lab->ctx= this;
m_label.push_front(lab);
}
return lab;
......@@ -184,6 +194,8 @@ sp_pcontext::find_label(char *name)
if (my_strcasecmp(system_charset_info, name, lab->name) == 0)
return lab;
if (m_parent)
return m_parent->find_label(name);
return NULL;
}
......@@ -207,20 +219,9 @@ sp_pcontext::push_cond(LEX_STRING *name, sp_cond_type_t *val)
sp_cond_type_t *
sp_pcontext::find_cond(LEX_STRING *name, my_bool scoped)
{
uint i = m_cond.elements;
uint limit;
if (! scoped || m_scopes.elements == 0)
limit= 0;
else
{
sp_scope_t s;
get_dynamic(&m_scopes, (gptr)&s, m_scopes.elements-1);
limit= s.conds;
}
uint i= m_cond.elements;
while (i-- > limit)
while (i--)
{
sp_cond_t *p;
......@@ -232,6 +233,8 @@ sp_pcontext::find_cond(LEX_STRING *name, my_bool scoped)
return p->val;
}
}
if (!scoped && m_parent)
return m_parent->find_cond(name, scoped);
return NULL;
}
......@@ -240,11 +243,11 @@ sp_pcontext::push_cursor(LEX_STRING *name)
{
LEX_STRING n;
if (m_cursor.elements == m_csubsize)
m_csubsize+= 1;
n.str= name->str;
n.length= name->length;
insert_dynamic(&m_cursor, (gptr)&n);
if (m_cursor.elements > m_cursmax)
m_cursmax= m_cursor.elements;
}
/*
......@@ -253,20 +256,9 @@ sp_pcontext::push_cursor(LEX_STRING *name)
my_bool
sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped)
{
uint i = m_cursor.elements;
uint limit;
uint i= m_cursor.elements;
if (! scoped || m_scopes.elements == 0)
limit= 0;
else
{
sp_scope_t s;
get_dynamic(&m_scopes, (gptr)&s, m_scopes.elements-1);
limit= s.curs;
}
while (i-- > limit)
while (i--)
{
LEX_STRING n;
......@@ -279,43 +271,7 @@ sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped)
return TRUE;
}
}
if (!scoped && m_parent)
return m_parent->find_cursor(name, poff, scoped);
return FALSE;
}
sp_label_t *
sp_pcontext::push_glabel(char *name, uint ip)
{
sp_label_t *lab = (sp_label_t *)sql_alloc(sizeof(sp_label_t));
if (lab)
{
lab->name= name;
lab->ip= ip;
lab->type= SP_LAB_GOTO;
lab->scopes= 0;
insert_dynamic(&m_glabel, (gptr)&lab);
}
return lab;
}
sp_label_t *
sp_pcontext::find_glabel(char *name)
{
uint i= m_glabel.elements;
while (i--)
{
sp_label_t *lab;
get_dynamic(&m_glabel, (gptr)&lab, i);
if (my_strcasecmp(system_charset_info, name, lab->name) == 0)
return lab;
}
return NULL;
}
void
sp_pcontext::pop_glabel(uint count)
{
(void)pop_dynamic(&m_glabel);
}
......@@ -50,7 +50,7 @@ typedef struct sp_label
char *name;
uint ip; // Instruction index
int type; // begin/iter or ref/free
uint scopes; // No. of scopes at label
struct sp_pcontext *ctx; // The label's context
} sp_label_t;
typedef struct sp_cond_type
......@@ -66,11 +66,6 @@ typedef struct sp_cond
sp_cond_type_t *val;
} sp_cond_t;
typedef struct sp_scope
{
uint vars, conds, hndlrs, curs, glab;
} sp_scope_t;
class sp_pcontext : public Sql_alloc
{
sp_pcontext(const sp_pcontext &); /* Prevent use of these */
......@@ -78,28 +73,30 @@ class sp_pcontext : public Sql_alloc
public:
sp_pcontext();
sp_pcontext(sp_pcontext *prev);
// Free memory
void
destroy();
// For error checking of duplicate things
void
push_scope();
sp_pcontext *
push_context();
void
pop_scope(sp_scope_t *sp = 0);
// Returns the previous context, not the one we pop
sp_pcontext *
pop_context();
uint
scopes()
sp_pcontext *
parent_context()
{
return m_scopes.elements;
return m_parent;
}
// Sets '*diffs' to the differences between current scope index snew and sold
void
diff_scopes(uint sold, sp_scope_t *diffs);
uint
diff_handlers(sp_pcontext *ctx);
uint
diff_cursors(sp_pcontext *ctx);
//
......@@ -107,28 +104,27 @@ class sp_pcontext : public Sql_alloc
//
inline uint
max_framesize()
max_pvars()
{
return m_framesize;
return m_psubsize + m_pvar.elements;
}
inline uint
current_framesize()
current_pvars()
{
return m_pvar.elements;
return m_poffset + m_pvar.elements;
}
inline uint
params()
context_pvars()
{
return m_params;
return m_pvar.elements;
}
// Set the number of parameters to the current esize
inline void
set_params()
inline uint
pvar_context2index(uint i)
{
m_params= m_pvar.elements;
return m_poffset + i;
}
inline void
......@@ -199,7 +195,11 @@ class sp_pcontext : public Sql_alloc
inline sp_label_t *
last_label()
{
return m_label.head();
sp_label_t *lab= m_label.head();
if (!lab && m_parent)
lab= m_parent->last_label();
return lab;
}
inline sp_label_t *
......@@ -236,21 +236,15 @@ class sp_pcontext : public Sql_alloc
}
inline uint
handlers()
{
return m_handlers;
}
inline void
push_handlers(uint count)
max_handlers()
{
m_hndlrlev+= count;
return m_hsubsize + m_handlers;
}
inline void
pop_handlers(uint count)
push_handlers(uint n)
{
m_hndlrlev-= count;
m_handlers+= n;
}
//
......@@ -263,48 +257,41 @@ class sp_pcontext : public Sql_alloc
my_bool
find_cursor(LEX_STRING *name, uint *poff, my_bool scoped=0);
inline void
pop_cursor(uint num)
inline uint
max_cursors()
{
while (num--)
pop_dynamic(&m_cursor);
return m_csubsize + m_cursor.elements;
}
inline uint
cursors()
current_cursors()
{
return m_cursmax;
return m_coffset + m_cursor.elements;
}
//
// GOTO labels
//
protected:
sp_label_t *
push_glabel(char *name, uint ip);
sp_label_t *
find_glabel(char *name);
void
pop_glabel(uint count);
// The maximum sub context's framesizes
uint m_psubsize;
uint m_csubsize;
uint m_hsubsize;
private:
uint m_params; // The number of parameters
uint m_framesize; // The maximum framesize
uint m_handlers; // The total number of handlers
uint m_cursmax; // The maximum number of cursors
uint m_hndlrlev; // Current number of active handlers
sp_pcontext *m_parent; // Parent context
uint m_poffset; // Variable offset for this context
uint m_coffset; // Cursor offset for this context
uint m_handlers; // No. of handlers in this context
DYNAMIC_ARRAY m_pvar; // Parameters/variables
DYNAMIC_ARRAY m_cond; // Conditions
DYNAMIC_ARRAY m_cursor; // Cursors
DYNAMIC_ARRAY m_scopes; // For error checking
DYNAMIC_ARRAY m_glabel; // Goto labels
List<sp_label_t> m_label; // The label list
List<sp_pcontext> m_children; // Children contexts, used for destruction
}; // class sp_pcontext : public Sql_alloc
......
......@@ -1169,7 +1169,6 @@ create:
LEX *lex= Lex;
lex->sphead->m_param_end= lex->tok_start;
lex->spcont->set_params();
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
}
sp_c_chistics
......@@ -1258,7 +1257,6 @@ create_function_tail:
{
LEX *lex= Lex;
lex->spcont->set_params();
lex->sphead->m_param_end= lex->tok_start;
}
RETURNS_SYM
......@@ -1470,25 +1468,28 @@ sp_decl:
DECLARE_SYM sp_decl_idents type sp_opt_default
{
LEX *lex= Lex;
uint max= lex->spcont->current_framesize();
sp_pcontext *ctx= lex->spcont;
uint max= ctx->context_pvars();
enum enum_field_types type= (enum enum_field_types)$3;
Item *it= $4;
for (uint i = max-$2 ; i < max ; i++)
{
lex->spcont->set_type(i, type);
ctx->set_type(i, type);
if (! it)
lex->spcont->set_isset(i, FALSE);
ctx->set_isset(i, FALSE);
else
{
sp_instr_set *in= new sp_instr_set(lex->sphead->instructions(),
i, it, type);
ctx,
ctx->pvar_context2index(i),
it, type);
in->tables= lex->query_tables;
lex->query_tables= 0;
lex->sphead->add_instr(in);
lex->spcont->set_isset(i, TRUE);
lex->spcont->set_default(i, it);
ctx->set_isset(i, TRUE);
ctx->set_default(i, it);
}
}
$$.vars= $2;
......@@ -1514,30 +1515,33 @@ sp_decl:
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
sp_instr_hpush_jump *i=
new sp_instr_hpush_jump(sp->instructions(), $2,
ctx->current_framesize());
new sp_instr_hpush_jump(sp->instructions(), ctx, $2,
ctx->current_pvars());
sp->add_instr(i);
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
ctx->add_handler();
sp->m_in_handler= TRUE;
}
sp_hcond_list sp_proc_stmt
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
sp_label_t *hlab= lex->spcont->pop_label(); /* After this hdlr */
if ($2 == SP_HANDLER_CONTINUE)
sp->add_instr(new sp_instr_hreturn(sp->instructions(),
lex->spcont->current_framesize()));
sp->add_instr(new sp_instr_hreturn(sp->instructions(), ctx,
ctx->current_pvars()));
else
{ /* EXIT or UNDO handler, just jump to the end of the block */
sp_instr_jump *i= new sp_instr_jump(sp->instructions());
sp_instr_jump *i= new sp_instr_jump(sp->instructions(), ctx);
sp->add_instr(i);
sp->push_backpatch(i, lex->spcont->last_label()); /* Block end */
}
lex->sphead->backpatch(hlab);
sp->m_in_handler= FALSE;
$$.vars= $$.conds= $$.curs= 0;
$$.hndlrs= $6;
}
......@@ -1545,19 +1549,19 @@ sp_decl:
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *spc= lex->spcont;
sp_pcontext *ctx= lex->spcont;
uint offp;
sp_instr_cpush *i;
if (spc->find_cursor(&$2, &offp, TRUE))
if (ctx->find_cursor(&$2, &offp, TRUE))
{
net_printf(YYTHD, ER_SP_DUP_CURS, $2.str);
delete $5;
YYABORT;
}
i= new sp_instr_cpush(sp->instructions(), $5);
i= new sp_instr_cpush(sp->instructions(), ctx, $5);
sp->add_instr(i);
lex->spcont->push_cursor(&$2);
ctx->push_cursor(&$2);
$$.vars= $$.conds= $$.hndlrs= 0;
$$.curs= 1;
}
......@@ -1748,7 +1752,8 @@ sp_proc_stmt:
}
else
{
sp_instr_stmt *i=new sp_instr_stmt(lex->sphead->instructions());
sp_instr_stmt *i=new sp_instr_stmt(lex->sphead->instructions(),
lex->spcont);
i->set_lex(lex);
lex->sphead->add_instr(i);
......@@ -1776,6 +1781,7 @@ sp_proc_stmt:
YYABORT;
}
i= new sp_instr_freturn(lex->sphead->instructions(),
lex->spcont,
$2, lex->sphead->m_returns);
lex->sphead->add_instr(i);
lex->sphead->m_has_return= TRUE;
......@@ -1794,8 +1800,9 @@ sp_proc_stmt:
at the same frame level, so we then know that it's the
top-most variable in the frame. */
LEX *lex= Lex;
uint offset= lex->spcont->current_framesize();
uint offset= lex->spcont->current_pvars();
sp_instr_set *i = new sp_instr_set(lex->sphead->instructions(),
lex->spcont,
offset, $2, MYSQL_TYPE_STRING);
LEX_STRING dummy;
......@@ -1839,19 +1846,17 @@ sp_proc_stmt:
else
{
uint ip= sp->instructions();
sp_scope_t sdiff;
sp_instr_jump *i;
sp_instr_hpop *ih;
sp_instr_cpop *ic;
ctx->diff_scopes(0, &sdiff);
ih= new sp_instr_hpop(ip++, sdiff.hndlrs);
ih= new sp_instr_hpop(ip++, ctx, 0);
sp->push_backpatch(ih, lab);
sp->add_instr(ih);
ic= new sp_instr_cpop(ip++, sdiff.curs);
ic= new sp_instr_cpop(ip++, ctx, 0);
sp->push_backpatch(ic, lab);
sp->add_instr(ic);
i= new sp_instr_jump(ip);
i= new sp_instr_jump(ip, ctx);
sp->push_backpatch(i, lab); /* Jumping forward */
sp->add_instr(i);
}
......@@ -1872,14 +1877,15 @@ sp_proc_stmt:
{
sp_instr_jump *i;
uint ip= sp->instructions();
sp_scope_t sdiff;
ctx->diff_scopes(lab->scopes, &sdiff);
if (sdiff.hndlrs)
sp->add_instr(new sp_instr_hpop(ip++, sdiff.hndlrs));
if (sdiff.curs)
sp->add_instr(new sp_instr_cpop(ip++, sdiff.curs));
i= new sp_instr_jump(ip, lab->ip); /* Jump back */
uint n;
n= ctx->diff_handlers(lab->ctx);
if (n)
sp->add_instr(new sp_instr_hpop(ip++, ctx, n));
n= ctx->diff_cursors(lab->ctx);
if (n)
sp->add_instr(new sp_instr_cpop(ip++, ctx, n));
i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
sp->add_instr(i);
}
}
......@@ -1890,8 +1896,6 @@ sp_proc_stmt:
sp_pcontext *ctx= lex->spcont;
sp_label_t *lab= ctx->find_label($2.str);
if (! lab)
lab= ctx->find_glabel($2.str);
if (lab)
{
net_printf(YYTHD, ER_SP_LABEL_REDEFINE, $2.str);
......@@ -1899,9 +1903,9 @@ sp_proc_stmt:
}
else
{
lab= ctx->push_glabel($2.str, sp->instructions());
lab= ctx->push_label($2.str, sp->instructions());
lab->type= SP_LAB_GOTO;
lab->scopes= ctx->scopes();
lab->ctx= ctx;
sp->backpatch(lab);
}
}
......@@ -1911,48 +1915,52 @@ sp_proc_stmt:
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
uint ip= lex->sphead->instructions();
sp_label_t *lab= ctx->find_label($2.str);
sp_scope_t sdiff;
sp_label_t *lab;
sp_instr_jump *i;
sp_instr_hpop *ih;
sp_instr_cpop *ic;
if (! lab)
lab= ctx->find_glabel($2.str);
if (sp->m_in_handler)
{
send_error(lex->thd, ER_SP_GOTO_IN_HNDLR);
YYABORT;
}
lab= ctx->find_label($2.str);
if (! lab)
{
lab= (sp_label_t *)YYTHD->alloc(sizeof(sp_label_t));
lab->name= $2.str;
lab->ip= 0;
lab->type= SP_LAB_REF;
lab->scopes= 0;
lab->ctx= ctx;
ctx->diff_scopes(0, &sdiff);
ih= new sp_instr_hpop(ip++, sdiff.hndlrs);
ih= new sp_instr_hpop(ip++, ctx, 0);
sp->push_backpatch(ih, lab);
sp->add_instr(ih);
ic= new sp_instr_cpop(ip++, sdiff.curs);
ic= new sp_instr_cpop(ip++, ctx, 0);
sp->add_instr(ic);
sp->push_backpatch(ic, lab);
i= new sp_instr_jump(ip);
i= new sp_instr_jump(ip, ctx);
sp->push_backpatch(i, lab); /* Jumping forward */
sp->add_instr(i);
}
else
{
ctx->diff_scopes(lab->scopes, &sdiff);
if (sdiff.hndlrs)
uint n;
n= ctx->diff_handlers(lab->ctx);
if (n)
{
ih= new sp_instr_hpop(ip++, sdiff.hndlrs);
ih= new sp_instr_hpop(ip++, ctx, n);
sp->add_instr(ih);
}
if (sdiff.curs)
n= ctx->diff_cursors(lab->ctx);
if (n)
{
ic= new sp_instr_cpop(ip++, sdiff.curs);
ic= new sp_instr_cpop(ip++, ctx, n);
sp->add_instr(ic);
}
i= new sp_instr_jump(ip, lab->ip); /* Jump back */
i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */
sp->add_instr(i);
}
}
......@@ -1968,7 +1976,7 @@ sp_proc_stmt:
net_printf(YYTHD, ER_SP_CURSOR_MISMATCH, $2.str);
YYABORT;
}
i= new sp_instr_copen(sp->instructions(), offset);
i= new sp_instr_copen(sp->instructions(), lex->spcont, offset);
sp->add_instr(i);
}
| FETCH_SYM ident INTO
......@@ -1983,7 +1991,7 @@ sp_proc_stmt:
net_printf(YYTHD, ER_SP_CURSOR_MISMATCH, $2.str);
YYABORT;
}
i= new sp_instr_cfetch(sp->instructions(), offset);
i= new sp_instr_cfetch(sp->instructions(), lex->spcont, offset);
sp->add_instr(i);
}
sp_fetch_list
......@@ -2000,7 +2008,7 @@ sp_proc_stmt:
net_printf(YYTHD, ER_SP_CURSOR_MISMATCH, $2.str);
YYABORT;
}
i= new sp_instr_cclose(sp->instructions(), offset);
i= new sp_instr_cclose(sp->instructions(), lex->spcont, offset);
sp->add_instr(i);
}
;
......@@ -2056,7 +2064,7 @@ sp_if:
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
uint ip= sp->instructions();
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, $1);
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, ctx, $1);
i->tables= lex->query_tables;
lex->query_tables= 0;
......@@ -2068,7 +2076,7 @@ sp_if:
sp_head *sp= Lex->sphead;
sp_pcontext *ctx= Lex->spcont;
uint ip= sp->instructions();
sp_instr_jump *i = new sp_instr_jump(ip);
sp_instr_jump *i = new sp_instr_jump(ip, ctx);
sp->add_instr(i);
sp->backpatch(ctx->pop_label());
......@@ -2098,7 +2106,7 @@ sp_case:
sp_instr_jump_if_not *i;
if (! sp->m_simple_case)
i= new sp_instr_jump_if_not(ip, $1);
i= new sp_instr_jump_if_not(ip, ctx, $1);
else
{ /* Simple case: <caseval> = <whenval> */
LEX_STRING ivar;
......@@ -2106,10 +2114,10 @@ sp_case:
ivar.str= (char *)"_tmp_";
ivar.length= 5;
Item *var= (Item*) new Item_splocal(ivar,
ctx->current_framesize()-1);
ctx->current_pvars()-1);
Item *expr= new Item_func_eq(var, $1);
i= new sp_instr_jump_if_not(ip, expr);
i= new sp_instr_jump_if_not(ip, ctx, expr);
lex->variables_used= 1;
}
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
......@@ -2122,7 +2130,7 @@ sp_case:
sp_head *sp= Lex->sphead;
sp_pcontext *ctx= Lex->spcont;
uint ip= sp->instructions();
sp_instr_jump *i = new sp_instr_jump(ip);
sp_instr_jump *i = new sp_instr_jump(ip, ctx);
sp->add_instr(i);
sp->backpatch(ctx->pop_label());
......@@ -2141,7 +2149,8 @@ sp_whens:
{
sp_head *sp= Lex->sphead;
uint ip= sp->instructions();
sp_instr_error *i= new sp_instr_error(ip, ER_SP_CASE_NOT_FOUND);
sp_instr_error *i= new sp_instr_error(ip, Lex->spcont,
ER_SP_CASE_NOT_FOUND);
sp->add_instr(i);
}
......@@ -2166,7 +2175,6 @@ sp_labeled_control:
lab= lex->spcont->push_label($1.str,
lex->sphead->instructions());
lab->type= SP_LAB_ITER;
lab->scopes= ctx->scopes();
}
}
sp_unlabeled_control sp_opt_label
......@@ -2204,32 +2212,24 @@ sp_unlabeled_control:
sp_label_t *lab= lex->spcont->last_label();
lab->type= SP_LAB_BEGIN;
/* Scope duplicate checking */
lex->spcont->push_scope();
lex->spcont= lex->spcont->push_context();
}
sp_decls
{
Lex->spcont->push_handlers($3.hndlrs);
}
sp_proc_stmts
END
{
LEX *lex= Lex;
sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont;
sp_scope_t scope;
sp->backpatch(ctx->last_label()); /* We always have a label */
ctx->pop_pvar($3.vars);
ctx->pop_cond($3.conds);
ctx->pop_handlers($3.hndlrs);
ctx->pop_cursor($3.curs);
if ($3.hndlrs)
sp->add_instr(new sp_instr_hpop(sp->instructions(), $3.hndlrs));
sp->add_instr(new sp_instr_hpop(sp->instructions(), ctx,
$3.hndlrs));
if ($3.curs)
sp->add_instr(new sp_instr_cpop(sp->instructions(), $3.curs));
ctx->pop_scope(&scope);
ctx->pop_glabel(scope.glab);
sp->add_instr(new sp_instr_cpop(sp->instructions(), ctx,
$3.curs));
lex->spcont= ctx->pop_context();
}
| LOOP_SYM
sp_proc_stmts END LOOP_SYM
......@@ -2237,7 +2237,7 @@ sp_unlabeled_control:
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
sp_instr_jump *i = new sp_instr_jump(ip, lab->ip);
sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip);
lex->sphead->add_instr(i);
}
......@@ -2246,7 +2246,8 @@ sp_unlabeled_control:
LEX *lex= Lex;
sp_head *sp= lex->sphead;
uint ip= sp->instructions();
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, $2);
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont,
$2);
/* Jumping forward */
sp->push_backpatch(i, lex->spcont->last_label());
......@@ -2259,7 +2260,7 @@ sp_unlabeled_control:
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
sp_instr_jump *i = new sp_instr_jump(ip, lab->ip);
sp_instr_jump *i = new sp_instr_jump(ip, lex->spcont, lab->ip);
lex->sphead->add_instr(i);
}
......@@ -2268,7 +2269,8 @@ sp_unlabeled_control:
LEX *lex= Lex;
uint ip= lex->sphead->instructions();
sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, $4, lab->ip);
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, lex->spcont,
$4, lab->ip);
i->tables= lex->query_tables;
lex->query_tables= 0;
......@@ -6786,11 +6788,12 @@ option_value:
}
else
{ /* An SP local variable */
sp_pcontext *ctx= lex->spcont;
sp_pvar_t *spv;
sp_instr_set *i;
Item *it;
spv= lex->spcont->find_pvar(&$1.base_name);
spv= ctx->find_pvar(&$1.base_name);
if ($3)
it= $3;
......@@ -6798,7 +6801,7 @@ option_value:
it= spv->dflt;
else
it= new Item_null();
i= new sp_instr_set(lex->sphead->instructions(),
i= new sp_instr_set(lex->sphead->instructions(), ctx,
spv->offset, it, spv->type);
i->tables= lex->query_tables;
lex->query_tables= 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment