diff options
author | unknown <pem@mysql.comhem.se> | 2004-08-26 12:54:30 +0200 |
---|---|---|
committer | unknown <pem@mysql.comhem.se> | 2004-08-26 12:54:30 +0200 |
commit | 071651efbd5d910047f458121ca1222428d7aa58 (patch) | |
tree | e80e61a8c32e018499a7a29eacd653c2d0fd2fbd | |
parent | ac06195caa5176a0245e635bb7678413c26cb7ab (diff) | |
download | mariadb-git-071651efbd5d910047f458121ca1222428d7aa58.tar.gz |
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.
33 files changed, 565 insertions, 392 deletions
diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 9798c13c075..3ee12fa9580 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -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 diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index f8d523484d8..6b36b3bb2bf 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -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; diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 5fb641a7db3..e5f80b7a252 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -1,4 +1,3 @@ -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 diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 71b2b91ccb1..f8abab0e7e3 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -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 # diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 3b91725b6a3..560130963f9 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -1,11 +1,9 @@ # # 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()| diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 264bc38117a..9d1c429d5b6 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -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" diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index c0f915e0b53..b2d2fdf4d77 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -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" diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 9bfca16ad54..85c0443869f 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -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" diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index c159e6b49c7..641f267d67e 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -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" diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 4c679a2967a..e64c0c17e74 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -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" diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 2f8cccbc6fb..f3443457346 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -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" diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index dc18cfa9b34..498a230faed 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -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" diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index b8cbe9b5a75..2827517ba9a 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -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" diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index b7cc9fe34d7..fab0b156322 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -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" diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 0c9576cab47..24634514a23 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -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" diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index d5ef9f22a56..68f2857aeca 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -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" diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 4f03bedc717..70267c82364 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -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" diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 821453e6119..1d84a3a5e5a 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -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" diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 5a60042b19e..be881d54473 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -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" diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index 2f9f5b4bbce..8a576b5bf82 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -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" diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 2a32c80138b..6794db726cc 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -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" diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 211a0072934..9eaa4860b64 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -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" diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 907cece485f..eec85d611fc 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -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" diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index 5b74999a3cd..4039268f446 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -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" diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 5d7fce940e2..9be5ce01d6a 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -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" diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 570da612be9..dc15f8b8d5e 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -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" diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 4e97393b0b1..ee5436c3b80 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -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" diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index a043b6eb651..cb1d99e2fec 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -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" diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 5a58c32d2da..fd95767b7cd 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -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) - bp->lab= lab; - m_pcont->diff_scopes(0, &sdiff); - bp->instr->backpatch(dest, sdiff.hndlrs, sdiff.curs); + if (dstlab) + { + bp->lab= lab; + 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 // diff --git a/sql/sp_head.h b/sql/sp_head.h index 9c29297180d..c0881661ad1 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -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() diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index 6f999531e58..c83259c3926 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -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; - - if (! scoped || m_scopes.elements == 0) - limit= 0; - else - { - sp_scope_t s; + uint i= m_pvar.elements; - 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; + uint i= m_cond.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.conds; - } - - 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); -} diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index e3bdc41779a..6db62614aa5 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -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,23 +236,17 @@ class sp_pcontext : public Sql_alloc } inline uint - handlers() + max_handlers() { - return m_handlers; + return m_hsubsize + m_handlers; } inline void - push_handlers(uint count) + push_handlers(uint n) { - m_hndlrlev+= count; + m_handlers+= n; } - inline void - pop_handlers(uint count) - { - m_hndlrlev-= count; - } - // // Cursors // @@ -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 - // - - sp_label_t * - push_glabel(char *name, uint ip); +protected: - 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 diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a01abd9141b..1b15bc9a516 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -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; |