Commit 071651ef authored by unknown's avatar unknown

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:").


include/mysqld_error.h:
  New error code for GOTO in SP handler.
mysql-test/r/sp-error.result:
  New error test cases for GOTO.
mysql-test/r/sp.result:
  New test cases for GOTO.
  Also removed some things that made it impossible to run the test in
  an external (debugged) mysqld.
mysql-test/t/sp-error.test:
  New error test cases for GOTO.
mysql-test/t/sp.test:
  New test cases for GOTO.
  Also removed some things that made it impossible to run the test in
  an external (debugged) mysqld.
sql/share/czech/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/danish/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/dutch/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/english/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/estonian/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/french/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/german/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/greek/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/hungarian/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/italian/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/japanese/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/korean/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/norwegian-ny/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/norwegian/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/polish/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/portuguese/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/romanian/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/russian/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/serbian/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/slovak/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/spanish/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/swedish/errmsg.txt:
  New error message for GOTO in SP handler.
sql/share/ukrainian/errmsg.txt:
  New error message for GOTO in SP handler.
sql/sp_head.cc:
  Code cleanup (renaming of pcontext methods), support goto, and fixed bug
  in jump shortcutting in the optimizer (detect infinite loops).
sql/sp_head.h:
  Code cleanup (renaming of pcontext methods), support goto, and fixed bug
  in jump shortcutting in the optimizer (detect infinite loops).
sql/sp_pcontext.cc:
  Major rehack and cleanup:
  - We now push and pop a chain of contexts during parsing (instead of having
    a single one).
  - Makes error detection for GOTO easier and enables some optmizations and
    debugger support.
  - Makes it a little trickier to keep track on variable and cursor indexes instead.
  - Renamed things to get a more consistent naming scheme too.
sql/sp_pcontext.h:
  Major rehack and cleanup:
  - We now push and pop a chain of contexts during parsing (instead of having
    a single one).
  - Makes error detection for GOTO easier and enables some optmizations and
    debugger support.
  - Makes it a little trickier to keep track on variable and cursor indexes instead.
  - Renamed things to get a more consistent naming scheme too.
sql/sql_yacc.yy:
  Changes to reflect the rework and renamings in sp_pcontext, and fixed
  some GOTO error checking.
parent ac06195c
...@@ -373,4 +373,5 @@ ...@@ -373,4 +373,5 @@
#define ER_WARN_VIEW_WITHOUT_KEY 1354 #define ER_WARN_VIEW_WITHOUT_KEY 1354
#define ER_VIEW_INVALID 1355 #define ER_VIEW_INVALID 1355
#define ER_SP_NO_DROP_SP 1356 #define ER_SP_NO_DROP_SP 1356
#define ER_SP_GOTO_IN_HNDLR 1357
#define ER_ERROR_MESSAGES 357 #define ER_ERROR_MESSAGES 357
...@@ -68,6 +68,42 @@ goto foo; ...@@ -68,6 +68,42 @@ goto foo;
end| end|
ERROR 42000: GOTO with no matching label: foo ERROR 42000: GOTO with no matching label: foo
create procedure 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
foo: loop foo: loop
set @x=2; set @x=2;
...@@ -288,6 +324,16 @@ declare continue handler for sqlstate '42S99' set x = 1; ...@@ -288,6 +324,16 @@ declare continue handler for sqlstate '42S99' set x = 1;
declare c cursor for select * from t1; declare c cursor for select * from t1;
end| end|
ERROR 42000: Cursor declaration after handler declaration 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() create procedure bug1965()
begin begin
declare c cursor for select val from t1 order by valname; declare c cursor for select val from t1 order by valname;
......
reset master;
use test; use test;
drop table if exists t1; drop table if exists t1;
drop table if exists t2; drop table if exists t2;
...@@ -398,7 +397,7 @@ id data ...@@ -398,7 +397,7 @@ id data
i 3 i 3
delete from t1| delete from t1|
drop procedure i| drop procedure i|
create procedure j() create procedure goto1()
begin begin
declare y int; declare y int;
label a; label a;
...@@ -411,7 +410,7 @@ insert into t1 values ("j", y); ...@@ -411,7 +410,7 @@ insert into t1 values ("j", y);
goto a; goto a;
label b; label b;
end| end|
call j()| call goto1()|
id data id data
id data id data
j 0 j 0
...@@ -422,8 +421,8 @@ id data ...@@ -422,8 +421,8 @@ id data
j 0 j 0
j 1 j 1
j 2 j 2
drop procedure j| drop procedure goto1|
create procedure k(a int) create procedure goto2(a int)
begin begin
declare x int default 0; declare x int default 0;
declare continue handler for sqlstate '42S98' set x = 1; declare continue handler for sqlstate '42S98' set x = 1;
...@@ -446,7 +445,7 @@ end; ...@@ -446,7 +445,7 @@ end;
end while b; end while b;
select * from t1; select * from t1;
end| end|
call k(0)| call goto2(0)|
id data id data
j 0 j 0
j 1 j 1
...@@ -455,7 +454,7 @@ id data ...@@ -455,7 +454,7 @@ id data
j 0 j 0
j 1 j 1
j 2 j 2
call k(1)| call goto2(1)|
id data id data
j 0 j 0
j 1 j 1
...@@ -464,7 +463,7 @@ id data ...@@ -464,7 +463,7 @@ id data
j 0 j 0
j 1 j 1
j 2 j 2
call k(2)| call goto2(2)|
id data id data
j 0 j 0
j 1 j 1
...@@ -477,8 +476,60 @@ id data ...@@ -477,8 +476,60 @@ id data
j 0 j 0
j 1 j 1
j 2 j 2
drop procedure k| drop procedure goto2|
delete from t1| 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 t1 values ("foo", 3), ("bar", 19)|
insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)| insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)|
create procedure sel1() create procedure sel1()
...@@ -1536,11 +1587,8 @@ show errors; ...@@ -1536,11 +1587,8 @@ show errors;
show columns from t1; show columns from t1;
show grants for 'root'@'localhost'; show grants for 'root'@'localhost';
show keys from t1; show keys from t1;
show master status;
show open tables like 'foo'; show open tables like 'foo';
show privileges; show privileges;
show slave hosts;
show slave status;
show status like 'foo'; show status like 'foo';
show tables like 'foo'; show tables like 'foo';
show variables like 'foo'; show variables like 'foo';
...@@ -1567,8 +1615,6 @@ data int(11) 0 ...@@ -1567,8 +1615,6 @@ data int(11) 0
Grants for root@localhost Grants for root@localhost
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION 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 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 Database Table In_use Name_locked
Privilege Context Comment Privilege Context Comment
Alter Tables To alter the table Alter Tables To alter the table
...@@ -1594,8 +1640,6 @@ Shutdown Server Admin To shut down the server ...@@ -1594,8 +1640,6 @@ Shutdown Server Admin To shut down the server
Super Server Admin To use KILL thread, SET GLOBAL, CHANGE MASTER, etc. Super Server Admin To use KILL thread, SET GLOBAL, CHANGE MASTER, etc.
Update Tables To update existing rows Update Tables To update existing rows
Usage Server Admin No privileges - allow connect only 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 Variable_name Value
Tables_in_test (foo) table_type Tables_in_test (foo) table_type
Variable_name Value Variable_name Value
...@@ -1621,8 +1665,6 @@ data int(11) 0 ...@@ -1621,8 +1665,6 @@ data int(11) 0
Grants for root@localhost Grants for root@localhost
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION 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 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 Database Table In_use Name_locked
Privilege Context Comment Privilege Context Comment
Alter Tables To alter the table Alter Tables To alter the table
...@@ -1648,8 +1690,6 @@ Shutdown Server Admin To shut down the server ...@@ -1648,8 +1690,6 @@ Shutdown Server Admin To shut down the server
Super Server Admin To use KILL thread, SET GLOBAL, CHANGE MASTER, etc. Super Server Admin To use KILL thread, SET GLOBAL, CHANGE MASTER, etc.
Update Tables To update existing rows Update Tables To update existing rows
Usage Server Admin No privileges - allow connect only 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 Variable_name Value
Tables_in_test (foo) table_type Tables_in_test (foo) table_type
Variable_name Value Variable_name Value
......
...@@ -103,6 +103,42 @@ create procedure foo() ...@@ -103,6 +103,42 @@ create procedure foo()
begin begin
goto foo; goto foo;
end| 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 # Redefining label
--error 1308 --error 1308
...@@ -380,6 +416,18 @@ begin ...@@ -380,6 +416,18 @@ begin
declare c cursor for select * from t1; declare c cursor for select * from t1;
end| 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 # BUG#1965
# #
......
# #
# Basic stored PROCEDURE tests # Basic stored PROCEDURE tests
# #
# # Please keep this file free of --error cases and other
# things that will not run in a single debugged mysqld
# Let us reset binary logs in order to make show master status # process (e.g. master-slave things).
# in test for bug 4902 repeatable.
reset master;
use test; use test;
...@@ -470,10 +468,10 @@ drop procedure i| ...@@ -470,10 +468,10 @@ drop procedure i|
# The non-standard GOTO, for compatibility # The non-standard GOTO, for compatibility
# #
# QQQ The "label" syntax is temporary. # QQQ The "label" syntax is temporary, it will (hopefully)
# QQQ This is no nearly enough, more tests are needed # change to the more common "L:" syntax soon.
# #
create procedure j() create procedure goto1()
begin begin
declare y int; declare y int;
...@@ -488,12 +486,11 @@ label a; ...@@ -488,12 +486,11 @@ label a;
label b; label b;
end| end|
call j()| call goto1()|
drop procedure goto1|
drop procedure j|
# With dummy handlers, just to test restore of contexts with jumps # With dummy handlers, just to test restore of contexts with jumps
create procedure k(a int) create procedure goto2(a int)
begin begin
declare x int default 0; declare x int default 0;
declare continue handler for sqlstate '42S98' set x = 1; declare continue handler for sqlstate '42S98' set x = 1;
...@@ -520,13 +517,70 @@ b: ...@@ -520,13 +517,70 @@ b:
select * from t1; select * from t1;
end| end|
call k(0)| call goto2(0)|
call k(1)| call goto2(1)|
call k(2)| call goto2(2)|
drop procedure k| drop procedure goto2|
delete from t1| 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 # SELECT with one of more result set sent back to the clinet
insert into t1 values ("foo", 3), ("bar", 19)| insert into t1 values ("foo", 3), ("bar", 19)|
insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)| insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)|
...@@ -1761,11 +1815,8 @@ begin ...@@ -1761,11 +1815,8 @@ begin
show columns from t1; show columns from t1;
show grants for 'root'@'localhost'; show grants for 'root'@'localhost';
show keys from t1; show keys from t1;
show master status;
show open tables like 'foo'; show open tables like 'foo';
show privileges; show privileges;
show slave hosts;
show slave status;
show status like 'foo'; show status like 'foo';
show tables like 'foo'; show tables like 'foo';
show variables like 'foo'; show variables like 'foo';
...@@ -1773,6 +1824,9 @@ begin ...@@ -1773,6 +1824,9 @@ begin
end| end|
#show binlog events; #show binlog events;
#show storage engines; #show storage engines;
#show master status;
#show slave hosts;
#show slave status;
call bug4902()| call bug4902()|
call bug4902()| call bug4902()|
......
...@@ -369,3 +369,4 @@ character-set=latin2 ...@@ -369,3 +369,4 @@ character-set=latin2
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -363,3 +363,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -371,3 +371,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -360,3 +360,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -365,3 +365,4 @@ character-set=latin7
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -360,3 +360,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -372,3 +372,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -360,3 +360,4 @@ character-set=greek
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -362,3 +362,4 @@ character-set=latin2
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -360,3 +360,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -362,3 +362,4 @@ character-set=ujis
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -360,3 +360,4 @@ character-set=euckr
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -362,3 +362,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -362,3 +362,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -364,3 +364,4 @@ character-set=latin2
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -361,3 +361,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -364,3 +364,4 @@ character-set=latin2
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -362,3 +362,4 @@ character-set=koi8r
" view ()" " view ()"
"View '%-.64s.%-.64s' " "View '%-.64s.%-.64s' "
"Can't drop a %s from within another stored routine" "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 ...@@ -366,3 +366,4 @@ character-set=cp1250
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -368,3 +368,4 @@ character-set=latin2
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -362,3 +362,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -360,3 +360,4 @@ character-set=latin1
"View being updated does not have complete key of underlying table in it" "View being updated does not have complete key of underlying table in it"
"View '%-.64s.%-.64s' references invalid table(s) or column(s)" "View '%-.64s.%-.64s' references invalid table(s) or column(s)"
"Can't drop a %s from within another stored routine" "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 ...@@ -365,3 +365,4 @@ character-set=koi8u
"View, , ͦ æ(), Ҧ " "View, , ͦ æ(), Ҧ "
"View '%-.64s.%-.64s' Ŧަ æ æ" "View '%-.64s.%-.64s' Ŧަ æ æ"
"Can't drop a %s from within another stored routine" "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) ...@@ -257,7 +257,7 @@ sp_head::operator delete(void *ptr, size_t size)
sp_head::sp_head() sp_head::sp_head()
:Item_arena((bool)FALSE), m_returns_cs(NULL), m_has_return(FALSE), :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"); DBUG_ENTER("sp_head::sp_head");
...@@ -272,7 +272,7 @@ sp_head::init(LEX *lex) ...@@ -272,7 +272,7 @@ sp_head::init(LEX *lex)
{ {
DBUG_ENTER("sp_head::init"); 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); 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_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= 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) ...@@ -514,10 +514,10 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
{ {
DBUG_ENTER("sp_head::execute_function"); DBUG_ENTER("sp_head::execute_function");
DBUG_PRINT("info", ("function %s", m_name.str)); DBUG_PRINT("info", ("function %s", m_name.str));
uint csize = m_pcont->max_framesize(); uint csize = m_pcont->max_pvars();
uint params = m_pcont->params(); uint params = m_pcont->current_pvars();
uint hmax = m_pcont->handlers(); uint hmax = m_pcont->max_handlers();
uint cmax = m_pcont->cursors(); uint cmax = m_pcont->max_cursors();
sp_rcontext *octx = thd->spcont; sp_rcontext *octx = thd->spcont;
sp_rcontext *nctx = NULL; sp_rcontext *nctx = NULL;
uint i; uint i;
...@@ -594,10 +594,10 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) ...@@ -594,10 +594,10 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
DBUG_ENTER("sp_head::execute_procedure"); DBUG_ENTER("sp_head::execute_procedure");
DBUG_PRINT("info", ("procedure %s", m_name.str)); DBUG_PRINT("info", ("procedure %s", m_name.str));
int ret= 0; int ret= 0;
uint csize = m_pcont->max_framesize(); uint csize = m_pcont->max_pvars();
uint params = m_pcont->params(); uint params = m_pcont->current_pvars();
uint hmax = m_pcont->handlers(); uint hmax = m_pcont->max_handlers();
uint cmax = m_pcont->cursors(); uint cmax = m_pcont->max_cursors();
sp_rcontext *octx = thd->spcont; sp_rcontext *octx = thd->spcont;
sp_rcontext *nctx = NULL; sp_rcontext *nctx = NULL;
my_bool tmp_octx = FALSE; // True if we have allocated a temporary octx my_bool tmp_octx = FALSE; // True if we have allocated a temporary octx
...@@ -851,12 +851,18 @@ sp_head::backpatch(sp_label_t *lab) ...@@ -851,12 +851,18 @@ sp_head::backpatch(sp_label_t *lab)
(bp->lab->type == SP_LAB_REF && (bp->lab->type == SP_LAB_REF &&
my_strcasecmp(system_charset_info, bp->lab->name, lab->name) == 0)) 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; bp->lab= lab;
m_pcont->diff_scopes(0, &sdiff); bp->instr->backpatch(dest, dstlab->ctx);
bp->instr->backpatch(dest, sdiff.hndlrs, sdiff.curs); }
}
} }
} }
} }
...@@ -1236,7 +1242,7 @@ sp_instr_jump::print(String *str) ...@@ -1236,7 +1242,7 @@ sp_instr_jump::print(String *str)
uint uint
sp_instr_jump::opt_mark(sp_head *sp) 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? */ if (m_dest != m_ip+1) /* Jumping to following instruction? */
marked= 1; marked= 1;
m_optdest= sp->get_instr(m_dest); m_optdest= sp->get_instr(m_dest);
...@@ -1244,15 +1250,18 @@ sp_instr_jump::opt_mark(sp_head *sp) ...@@ -1244,15 +1250,18 @@ sp_instr_jump::opt_mark(sp_head *sp)
} }
uint 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; uint dest= m_dest;
sp_instr *i; sp_instr *i;
while ((i= sp->get_instr(dest))) 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) if (ndest == dest)
break; break;
dest= ndest; dest= ndest;
...@@ -1320,7 +1329,7 @@ sp_instr_jump_if::opt_mark(sp_head *sp) ...@@ -1320,7 +1329,7 @@ sp_instr_jump_if::opt_mark(sp_head *sp)
marked= 1; marked= 1;
if ((i= sp->get_instr(m_dest))) 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); m_optdest= sp->get_instr(m_dest);
} }
sp->opt_mark(m_dest); sp->opt_mark(m_dest);
...@@ -1377,7 +1386,7 @@ sp_instr_jump_if_not::opt_mark(sp_head *sp) ...@@ -1377,7 +1386,7 @@ sp_instr_jump_if_not::opt_mark(sp_head *sp)
marked= 1; marked= 1;
if ((i= sp->get_instr(m_dest))) 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); m_optdest= sp->get_instr(m_dest);
} }
sp->opt_mark(m_dest); sp->opt_mark(m_dest);
...@@ -1460,7 +1469,7 @@ sp_instr_hpush_jump::opt_mark(sp_head *sp) ...@@ -1460,7 +1469,7 @@ sp_instr_hpush_jump::opt_mark(sp_head *sp)
marked= 1; marked= 1;
if ((i= sp->get_instr(m_dest))) 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); m_optdest= sp->get_instr(m_dest);
} }
sp->opt_mark(m_dest); sp->opt_mark(m_dest);
...@@ -1487,6 +1496,13 @@ sp_instr_hpop::print(String *str) ...@@ -1487,6 +1496,13 @@ sp_instr_hpop::print(String *str)
str->qs_append(m_count); 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 // sp_instr_hreturn
// //
...@@ -1551,6 +1567,12 @@ sp_instr_cpop::print(String *str) ...@@ -1551,6 +1567,12 @@ sp_instr_cpop::print(String *str)
str->qs_append(m_count); 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 // sp_instr_copen
// //
......
...@@ -86,6 +86,7 @@ class sp_head :private Item_arena ...@@ -86,6 +86,7 @@ class sp_head :private Item_arena
my_bool m_has_return; // For FUNCTIONs only my_bool m_has_return; // For FUNCTIONs only
my_bool m_simple_case; // TRUE if parsing simple case, FALSE otherwise 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_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 uint m_old_cmq; // Old CLIENT_MULTI_QUERIES value
st_sp_chistics *m_chistics; st_sp_chistics *m_chistics;
ulong m_sql_mode; // For SHOW CREATE ulong m_sql_mode; // For SHOW CREATE
...@@ -262,10 +263,11 @@ class sp_instr : public Sql_alloc ...@@ -262,10 +263,11 @@ class sp_instr : public Sql_alloc
uint marked; uint marked;
Item *free_list; // My Items Item *free_list; // My Items
uint m_ip; // My index uint m_ip; // My index
sp_pcontext *m_ctx; // My parse context
// Should give each a name or type code for debugging purposes? // Should give each a name or type code for debugging purposes?
sp_instr(uint ip) sp_instr(uint ip, sp_pcontext *ctx)
:Sql_alloc(), marked(0), free_list(0), m_ip(ip) :Sql_alloc(), marked(0), free_list(0), m_ip(ip), m_ctx(ctx)
{} {}
virtual ~sp_instr() virtual ~sp_instr()
...@@ -279,7 +281,7 @@ class sp_instr : public Sql_alloc ...@@ -279,7 +281,7 @@ class sp_instr : public Sql_alloc
virtual void print(String *str) = 0; 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) virtual uint opt_mark(sp_head *sp)
...@@ -288,7 +290,7 @@ class sp_instr : public Sql_alloc ...@@ -288,7 +290,7 @@ class sp_instr : public Sql_alloc
return m_ip+1; 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; return m_ip;
} }
...@@ -311,8 +313,8 @@ class sp_instr_stmt : public sp_instr ...@@ -311,8 +313,8 @@ class sp_instr_stmt : public sp_instr
public: public:
sp_instr_stmt(uint ip) sp_instr_stmt(uint ip, sp_pcontext *ctx)
: sp_instr(ip), m_lex(NULL) : sp_instr(ip, ctx), m_lex(NULL)
{} {}
virtual ~sp_instr_stmt(); virtual ~sp_instr_stmt();
...@@ -353,8 +355,10 @@ class sp_instr_set : public sp_instr ...@@ -353,8 +355,10 @@ class sp_instr_set : public sp_instr
TABLE_LIST *tables; TABLE_LIST *tables;
sp_instr_set(uint ip, uint offset, Item *val, enum enum_field_types type) sp_instr_set(uint ip, sp_pcontext *ctx,
: sp_instr(ip), tables(NULL), m_offset(offset), m_value(val), m_type(type) 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() virtual ~sp_instr_set()
...@@ -382,12 +386,12 @@ class sp_instr_jump : public sp_instr ...@@ -382,12 +386,12 @@ class sp_instr_jump : public sp_instr
uint m_dest; // Where we will go uint m_dest; // Where we will go
sp_instr_jump(uint ip) sp_instr_jump(uint ip, sp_pcontext *ctx)
: sp_instr(ip), m_dest(0), m_optdest(0) : sp_instr(ip, ctx), m_dest(0), m_optdest(0)
{} {}
sp_instr_jump(uint ip, uint dest) sp_instr_jump(uint ip, sp_pcontext *ctx, uint dest)
: sp_instr(ip), m_dest(dest), m_optdest(0) : sp_instr(ip, ctx), m_dest(dest), m_optdest(0)
{} {}
virtual ~sp_instr_jump() virtual ~sp_instr_jump()
...@@ -399,11 +403,11 @@ class sp_instr_jump : public sp_instr ...@@ -399,11 +403,11 @@ class sp_instr_jump : public sp_instr
virtual uint opt_mark(sp_head *sp); 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 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 if (m_dest == 0) // Don't reset
m_dest= dest; m_dest= dest;
...@@ -425,12 +429,12 @@ class sp_instr_jump_if : public sp_instr_jump ...@@ -425,12 +429,12 @@ class sp_instr_jump_if : public sp_instr_jump
TABLE_LIST *tables; TABLE_LIST *tables;
sp_instr_jump_if(uint ip, Item *i) sp_instr_jump_if(uint ip, sp_pcontext *ctx, Item *i)
: sp_instr_jump(ip), tables(NULL), m_expr(i) : sp_instr_jump(ip, ctx), tables(NULL), m_expr(i)
{} {}
sp_instr_jump_if(uint ip, Item *i, uint dest) sp_instr_jump_if(uint ip, sp_pcontext *ctx, Item *i, uint dest)
: sp_instr_jump(ip, dest), tables(NULL), m_expr(i) : sp_instr_jump(ip, ctx, dest), tables(NULL), m_expr(i)
{} {}
virtual ~sp_instr_jump_if() virtual ~sp_instr_jump_if()
...@@ -442,7 +446,7 @@ class sp_instr_jump_if : public sp_instr_jump ...@@ -442,7 +446,7 @@ class sp_instr_jump_if : public sp_instr_jump
virtual uint opt_mark(sp_head *sp); 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; return m_ip;
} }
...@@ -463,12 +467,12 @@ class sp_instr_jump_if_not : public sp_instr_jump ...@@ -463,12 +467,12 @@ class sp_instr_jump_if_not : public sp_instr_jump
TABLE_LIST *tables; TABLE_LIST *tables;
sp_instr_jump_if_not(uint ip, Item *i) sp_instr_jump_if_not(uint ip, sp_pcontext *ctx, Item *i)
: sp_instr_jump(ip), tables(NULL), m_expr(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_if_not(uint ip, sp_pcontext *ctx, Item *i, uint dest)
: sp_instr_jump(ip, dest), tables(NULL), m_expr(i) : sp_instr_jump(ip, ctx, dest), tables(NULL), m_expr(i)
{} {}
virtual ~sp_instr_jump_if_not() virtual ~sp_instr_jump_if_not()
...@@ -480,7 +484,7 @@ class sp_instr_jump_if_not : public sp_instr_jump ...@@ -480,7 +484,7 @@ class sp_instr_jump_if_not : public sp_instr_jump
virtual uint opt_mark(sp_head *sp); 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; return m_ip;
} }
...@@ -501,8 +505,9 @@ class sp_instr_freturn : public sp_instr ...@@ -501,8 +505,9 @@ class sp_instr_freturn : public sp_instr
TABLE_LIST *tables; TABLE_LIST *tables;
sp_instr_freturn(uint ip, Item *val, enum enum_field_types type) sp_instr_freturn(uint ip, sp_pcontext *ctx,
: sp_instr(ip), tables(NULL), m_value(val), m_type(type) Item *val, enum enum_field_types type)
: sp_instr(ip, ctx), tables(NULL), m_value(val), m_type(type)
{} {}
virtual ~sp_instr_freturn() virtual ~sp_instr_freturn()
...@@ -533,8 +538,8 @@ class sp_instr_hpush_jump : public sp_instr_jump ...@@ -533,8 +538,8 @@ class sp_instr_hpush_jump : public sp_instr_jump
public: public:
sp_instr_hpush_jump(uint ip, int htype, uint fp) sp_instr_hpush_jump(uint ip, sp_pcontext *ctx, int htype, uint fp)
: sp_instr_jump(ip), m_type(htype), m_frame(fp) : sp_instr_jump(ip, ctx), m_type(htype), m_frame(fp)
{ {
m_handler= ip+1; m_handler= ip+1;
m_cond.empty(); m_cond.empty();
...@@ -551,7 +556,7 @@ class sp_instr_hpush_jump : public sp_instr_jump ...@@ -551,7 +556,7 @@ class sp_instr_hpush_jump : public sp_instr_jump
virtual uint opt_mark(sp_head *sp); 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; return m_ip;
} }
...@@ -578,8 +583,8 @@ class sp_instr_hpop : public sp_instr ...@@ -578,8 +583,8 @@ class sp_instr_hpop : public sp_instr
public: public:
sp_instr_hpop(uint ip, uint count) sp_instr_hpop(uint ip, sp_pcontext *ctx, uint count)
: sp_instr(ip), m_count(count) : sp_instr(ip, ctx), m_count(count)
{} {}
virtual ~sp_instr_hpop() virtual ~sp_instr_hpop()
...@@ -589,13 +594,7 @@ class sp_instr_hpop : public sp_instr ...@@ -589,13 +594,7 @@ class sp_instr_hpop : public sp_instr
virtual void print(String *str); virtual void print(String *str);
virtual void backpatch(uint dest, uint hpop, uint cpop) virtual void backpatch(uint dest, sp_pcontext *dst_ctx);
{
if (hpop > m_count)
m_count= 0;
else
m_count-= hpop;
}
virtual uint opt_mark(sp_head *sp) virtual uint opt_mark(sp_head *sp)
{ {
...@@ -618,8 +617,8 @@ class sp_instr_hreturn : public sp_instr ...@@ -618,8 +617,8 @@ class sp_instr_hreturn : public sp_instr
public: public:
sp_instr_hreturn(uint ip, uint fp) sp_instr_hreturn(uint ip, sp_pcontext *ctx, uint fp)
: sp_instr(ip), m_frame(fp) : sp_instr(ip, ctx), m_frame(fp)
{} {}
virtual ~sp_instr_hreturn() virtual ~sp_instr_hreturn()
...@@ -649,8 +648,8 @@ class sp_instr_cpush : public sp_instr ...@@ -649,8 +648,8 @@ class sp_instr_cpush : public sp_instr
public: public:
sp_instr_cpush(uint ip, LEX *lex) sp_instr_cpush(uint ip, sp_pcontext *ctx, LEX *lex)
: sp_instr(ip), m_lex(lex) : sp_instr(ip, ctx), m_lex(lex)
{} {}
virtual ~sp_instr_cpush(); virtual ~sp_instr_cpush();
...@@ -673,8 +672,8 @@ class sp_instr_cpop : public sp_instr ...@@ -673,8 +672,8 @@ class sp_instr_cpop : public sp_instr
public: public:
sp_instr_cpop(uint ip, uint count) sp_instr_cpop(uint ip, sp_pcontext *ctx, uint count)
: sp_instr(ip), m_count(count) : sp_instr(ip, ctx), m_count(count)
{} {}
virtual ~sp_instr_cpop() virtual ~sp_instr_cpop()
...@@ -684,13 +683,7 @@ class sp_instr_cpop : public sp_instr ...@@ -684,13 +683,7 @@ class sp_instr_cpop : public sp_instr
virtual void print(String *str); virtual void print(String *str);
virtual void backpatch(uint dest, uint hpop, uint cpop) virtual void backpatch(uint dest, sp_pcontext *dst_ctx);
{
if (cpop > m_count)
m_count= 0;
else
m_count-= cpop;
}
virtual uint opt_mark(sp_head *sp) virtual uint opt_mark(sp_head *sp)
{ {
...@@ -713,8 +706,8 @@ class sp_instr_copen : public sp_instr_stmt ...@@ -713,8 +706,8 @@ class sp_instr_copen : public sp_instr_stmt
public: public:
sp_instr_copen(uint ip, uint c) sp_instr_copen(uint ip, sp_pcontext *ctx, uint c)
: sp_instr_stmt(ip), m_cursor(c) : sp_instr_stmt(ip, ctx), m_cursor(c)
{} {}
virtual ~sp_instr_copen() virtual ~sp_instr_copen()
...@@ -738,8 +731,8 @@ class sp_instr_cclose : public sp_instr ...@@ -738,8 +731,8 @@ class sp_instr_cclose : public sp_instr
public: public:
sp_instr_cclose(uint ip, uint c) sp_instr_cclose(uint ip, sp_pcontext *ctx, uint c)
: sp_instr(ip), m_cursor(c) : sp_instr(ip, ctx), m_cursor(c)
{} {}
virtual ~sp_instr_cclose() virtual ~sp_instr_cclose()
...@@ -763,8 +756,8 @@ class sp_instr_cfetch : public sp_instr ...@@ -763,8 +756,8 @@ class sp_instr_cfetch : public sp_instr
public: public:
sp_instr_cfetch(uint ip, uint c) sp_instr_cfetch(uint ip, sp_pcontext *ctx, uint c)
: sp_instr(ip), m_cursor(c) : sp_instr(ip, ctx), m_cursor(c)
{ {
m_varlist.empty(); m_varlist.empty();
} }
...@@ -796,8 +789,8 @@ class sp_instr_error : public sp_instr ...@@ -796,8 +789,8 @@ class sp_instr_error : public sp_instr
public: public:
sp_instr_error(uint ip, int errcode) sp_instr_error(uint ip, sp_pcontext *ctx, int errcode)
: sp_instr(ip), m_errcode(errcode) : sp_instr(ip, ctx), m_errcode(errcode)
{} {}
virtual ~sp_instr_error() virtual ~sp_instr_error()
......
...@@ -26,79 +26,98 @@ ...@@ -26,79 +26,98 @@
#include "sp_pcontext.h" #include "sp_pcontext.h"
#include "sp_head.h" #include "sp_head.h"
sp_pcontext::sp_pcontext() sp_pcontext::sp_pcontext(sp_pcontext *prev)
: Sql_alloc(), m_params(0), m_framesize(0), m_handlers(0), m_cursmax(0), : Sql_alloc(), m_psubsize(0), m_csubsize(0), m_hsubsize(0),
m_hndlrlev(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_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_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_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_label.empty();
m_children.empty();
if (!prev)
m_poffset= m_coffset= 0;
else
{
m_poffset= prev->current_pvars();
m_coffset= prev->current_cursors();
}
} }
void void
sp_pcontext::destroy() 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_pvar);
delete_dynamic(&m_cond); delete_dynamic(&m_cond);
delete_dynamic(&m_cursor); delete_dynamic(&m_cursor);
delete_dynamic(&m_scopes);
delete_dynamic(&m_glabel);
m_label.empty();
} }
void sp_pcontext *
sp_pcontext::push_scope() sp_pcontext::push_context()
{ {
sp_scope_t s; sp_pcontext *child= new sp_pcontext(this);
s.vars= m_pvar.elements; if (child)
s.conds= m_cond.elements; m_children.push_back(child);
s.hndlrs= m_hndlrlev; return child;
s.curs= m_cursor.elements;
s.glab= m_glabel.elements;
insert_dynamic(&m_scopes, (gptr)&s);
} }
void sp_pcontext *
sp_pcontext::pop_scope(sp_scope_t *sp) sp_pcontext::pop_context()
{ {
byte *p= pop_dynamic(&m_scopes); uint submax= max_pvars();
if (sp && p) if (submax > m_parent->m_psubsize)
memcpy(sp, p, sizeof(sp_scope_t)); 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 uint
sp_pcontext::diff_scopes(uint sold, sp_scope_t *diffs) sp_pcontext::diff_handlers(sp_pcontext *ctx)
{ {
uint snew= m_scopes.elements; uint n= 0;
sp_scope_t scope; sp_pcontext *pctx= this;
diffs->vars= diffs->conds= diffs->hndlrs= diffs->curs= diffs->glab= 0; while (pctx && pctx != ctx)
while (snew-- > sold)
{ {
get_dynamic(&m_scopes, (gptr)&scope, snew); n+= pctx->max_handlers();
diffs->vars+= scope.vars; pctx= pctx->parent_context();
diffs->conds+= scope.conds;
diffs->hndlrs+= scope.hndlrs;
diffs->curs+= scope.curs;
diffs->glab+= scope.glab;
} }
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); n+= pctx->max_cursors();
diffs->vars-= scope.vars; pctx= pctx->parent_context();
diffs->conds-= scope.conds;
diffs->hndlrs-= scope.hndlrs;
diffs->curs-= scope.curs;
diffs->glab-= scope.glab;
} }
if (pctx)
return n;
return 0; // Didn't find ctx
} }
/* This does a linear search (from newer to older variables, in case /* This does a linear search (from newer to older variables, in case
** we have shadowed names). ** we have shadowed names).
** It's possible to have a more efficient allocation and search method, ** 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) ...@@ -109,20 +128,9 @@ sp_pcontext::diff_scopes(uint sold, sp_scope_t *diffs)
sp_pvar_t * sp_pvar_t *
sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped) sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped)
{ {
uint i = m_pvar.elements; uint i= m_pvar.elements;
uint limit;
if (! scoped || m_scopes.elements == 0) while (i--)
limit= 0;
else
{
sp_scope_t s;
get_dynamic(&m_scopes, (gptr)&s, m_scopes.elements-1);
limit= s.vars;
}
while (i-- > limit)
{ {
sp_pvar_t *p; sp_pvar_t *p;
...@@ -134,6 +142,8 @@ sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped) ...@@ -134,6 +142,8 @@ sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped)
return p; return p;
} }
} }
if (!scoped && m_parent)
return m_parent->find_pvar(name, scoped);
return NULL; return NULL;
} }
...@@ -145,13 +155,13 @@ sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type, ...@@ -145,13 +155,13 @@ sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type,
if (p) if (p)
{ {
if (m_pvar.elements == m_framesize) if (m_pvar.elements == m_psubsize)
m_framesize += 1; m_psubsize+= 1;
p->name.str= name->str; p->name.str= name->str;
p->name.length= name->length; p->name.length= name->length;
p->type= type; p->type= type;
p->mode= mode; p->mode= mode;
p->offset= m_pvar.elements; p->offset= current_pvars();
p->isset= (mode == sp_param_out ? FALSE : TRUE); p->isset= (mode == sp_param_out ? FALSE : TRUE);
p->dflt= NULL; p->dflt= NULL;
insert_dynamic(&m_pvar, (gptr)&p); insert_dynamic(&m_pvar, (gptr)&p);
...@@ -168,7 +178,7 @@ sp_pcontext::push_label(char *name, uint ip) ...@@ -168,7 +178,7 @@ sp_pcontext::push_label(char *name, uint ip)
lab->name= name; lab->name= name;
lab->ip= ip; lab->ip= ip;
lab->type= SP_LAB_GOTO; lab->type= SP_LAB_GOTO;
lab->scopes= 0; lab->ctx= this;
m_label.push_front(lab); m_label.push_front(lab);
} }
return lab; return lab;
...@@ -184,6 +194,8 @@ sp_pcontext::find_label(char *name) ...@@ -184,6 +194,8 @@ sp_pcontext::find_label(char *name)
if (my_strcasecmp(system_charset_info, name, lab->name) == 0) if (my_strcasecmp(system_charset_info, name, lab->name) == 0)
return lab; return lab;
if (m_parent)
return m_parent->find_label(name);
return NULL; return NULL;
} }
...@@ -207,20 +219,9 @@ sp_pcontext::push_cond(LEX_STRING *name, sp_cond_type_t *val) ...@@ -207,20 +219,9 @@ sp_pcontext::push_cond(LEX_STRING *name, sp_cond_type_t *val)
sp_cond_type_t * sp_cond_type_t *
sp_pcontext::find_cond(LEX_STRING *name, my_bool scoped) sp_pcontext::find_cond(LEX_STRING *name, my_bool scoped)
{ {
uint i = m_cond.elements; 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;
}
while (i-- > limit) while (i--)
{ {
sp_cond_t *p; sp_cond_t *p;
...@@ -232,6 +233,8 @@ sp_pcontext::find_cond(LEX_STRING *name, my_bool scoped) ...@@ -232,6 +233,8 @@ sp_pcontext::find_cond(LEX_STRING *name, my_bool scoped)
return p->val; return p->val;
} }
} }
if (!scoped && m_parent)
return m_parent->find_cond(name, scoped);
return NULL; return NULL;
} }
...@@ -240,11 +243,11 @@ sp_pcontext::push_cursor(LEX_STRING *name) ...@@ -240,11 +243,11 @@ sp_pcontext::push_cursor(LEX_STRING *name)
{ {
LEX_STRING n; LEX_STRING n;
if (m_cursor.elements == m_csubsize)
m_csubsize+= 1;
n.str= name->str; n.str= name->str;
n.length= name->length; n.length= name->length;
insert_dynamic(&m_cursor, (gptr)&n); 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) ...@@ -253,20 +256,9 @@ sp_pcontext::push_cursor(LEX_STRING *name)
my_bool my_bool
sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped) sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped)
{ {
uint i = m_cursor.elements; uint i= m_cursor.elements;
uint limit;
if (! scoped || m_scopes.elements == 0) while (i--)
limit= 0;
else
{
sp_scope_t s;
get_dynamic(&m_scopes, (gptr)&s, m_scopes.elements-1);
limit= s.curs;
}
while (i-- > limit)
{ {
LEX_STRING n; LEX_STRING n;
...@@ -279,43 +271,7 @@ sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped) ...@@ -279,43 +271,7 @@ sp_pcontext::find_cursor(LEX_STRING *name, uint *poff, my_bool scoped)
return TRUE; return TRUE;
} }
} }
if (!scoped && m_parent)
return m_parent->find_cursor(name, poff, scoped);
return FALSE; 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 ...@@ -50,7 +50,7 @@ typedef struct sp_label
char *name; char *name;
uint ip; // Instruction index uint ip; // Instruction index
int type; // begin/iter or ref/free 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; } sp_label_t;
typedef struct sp_cond_type typedef struct sp_cond_type
...@@ -66,11 +66,6 @@ typedef struct sp_cond ...@@ -66,11 +66,6 @@ typedef struct sp_cond
sp_cond_type_t *val; sp_cond_type_t *val;
} sp_cond_t; } sp_cond_t;
typedef struct sp_scope
{
uint vars, conds, hndlrs, curs, glab;
} sp_scope_t;
class sp_pcontext : public Sql_alloc class sp_pcontext : public Sql_alloc
{ {
sp_pcontext(const sp_pcontext &); /* Prevent use of these */ sp_pcontext(const sp_pcontext &); /* Prevent use of these */
...@@ -78,28 +73,30 @@ class sp_pcontext : public Sql_alloc ...@@ -78,28 +73,30 @@ class sp_pcontext : public Sql_alloc
public: public:
sp_pcontext(); sp_pcontext(sp_pcontext *prev);
// Free memory // Free memory
void void
destroy(); destroy();
// For error checking of duplicate things sp_pcontext *
void push_context();
push_scope();
void // Returns the previous context, not the one we pop
pop_scope(sp_scope_t *sp = 0); sp_pcontext *
pop_context();
uint sp_pcontext *
scopes() parent_context()
{ {
return m_scopes.elements; return m_parent;
} }
// Sets '*diffs' to the differences between current scope index snew and sold uint
void diff_handlers(sp_pcontext *ctx);
diff_scopes(uint sold, sp_scope_t *diffs);
uint
diff_cursors(sp_pcontext *ctx);
// //
...@@ -107,28 +104,27 @@ class sp_pcontext : public Sql_alloc ...@@ -107,28 +104,27 @@ class sp_pcontext : public Sql_alloc
// //
inline uint inline uint
max_framesize() max_pvars()
{ {
return m_framesize; return m_psubsize + m_pvar.elements;
} }
inline uint inline uint
current_framesize() current_pvars()
{ {
return m_pvar.elements; return m_poffset + m_pvar.elements;
} }
inline uint inline uint
params() context_pvars()
{ {
return m_params; return m_pvar.elements;
} }
// Set the number of parameters to the current esize inline uint
inline void pvar_context2index(uint i)
set_params()
{ {
m_params= m_pvar.elements; return m_poffset + i;
} }
inline void inline void
...@@ -199,7 +195,11 @@ class sp_pcontext : public Sql_alloc ...@@ -199,7 +195,11 @@ class sp_pcontext : public Sql_alloc
inline sp_label_t * inline sp_label_t *
last_label() 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 * inline sp_label_t *
...@@ -236,21 +236,15 @@ class sp_pcontext : public Sql_alloc ...@@ -236,21 +236,15 @@ class sp_pcontext : public Sql_alloc
} }
inline uint inline uint
handlers() max_handlers()
{
return m_handlers;
}
inline void
push_handlers(uint count)
{ {
m_hndlrlev+= count; return m_hsubsize + m_handlers;
} }
inline void 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 ...@@ -263,48 +257,41 @@ class sp_pcontext : public Sql_alloc
my_bool my_bool
find_cursor(LEX_STRING *name, uint *poff, my_bool scoped=0); find_cursor(LEX_STRING *name, uint *poff, my_bool scoped=0);
inline void inline uint
pop_cursor(uint num) max_cursors()
{ {
while (num--) return m_csubsize + m_cursor.elements;
pop_dynamic(&m_cursor);
} }
inline uint inline uint
cursors() current_cursors()
{ {
return m_cursmax; return m_coffset + m_cursor.elements;
} }
// protected:
// GOTO labels
//
sp_label_t * // The maximum sub context's framesizes
push_glabel(char *name, uint ip); uint m_psubsize;
uint m_csubsize;
sp_label_t * uint m_hsubsize;
find_glabel(char *name);
void
pop_glabel(uint count);
private: private:
uint m_params; // The number of parameters sp_pcontext *m_parent; // Parent context
uint m_framesize; // The maximum framesize
uint m_handlers; // The total number of handlers uint m_poffset; // Variable offset for this context
uint m_cursmax; // The maximum number of cursors uint m_coffset; // Cursor offset for this context
uint m_hndlrlev; // Current number of active handlers uint m_handlers; // No. of handlers in this context
DYNAMIC_ARRAY m_pvar; // Parameters/variables DYNAMIC_ARRAY m_pvar; // Parameters/variables
DYNAMIC_ARRAY m_cond; // Conditions DYNAMIC_ARRAY m_cond; // Conditions
DYNAMIC_ARRAY m_cursor; // Cursors 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_label_t> m_label; // The label list
List<sp_pcontext> m_children; // Children contexts, used for destruction
}; // class sp_pcontext : public Sql_alloc }; // class sp_pcontext : public Sql_alloc
......
This diff is collapsed.
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