From 52c820fbc500baf8a9fcbf9e09be66914a104713 Mon Sep 17 00:00:00 2001 From: "pem@mysql.comhem.se" <> Date: Mon, 29 Mar 2004 11:16:45 +0200 Subject: [PATCH 1/2] Enforce standard declaration order in SPs. Added new test cases for this, and adjusted old tests accordingly, and new error codes and messages. Fixed bugs in some tests (bug2673 and use test). Added debug printing of instructions in SPs. --- include/mysqld_error.h | 4 +- include/sql_state.h | 2 + mysql-test/r/sp-error.result | 29 ++++- mysql-test/r/sp.result | 17 +-- mysql-test/t/sp-error.test | 30 +++++- mysql-test/t/sp.test | 15 +-- sql/share/czech/errmsg.txt | 2 + sql/share/danish/errmsg.txt | 2 + sql/share/dutch/errmsg.txt | 2 + sql/share/english/errmsg.txt | 2 + sql/share/estonian/errmsg.txt | 2 + sql/share/french/errmsg.txt | 2 + sql/share/german/errmsg.txt | 2 + sql/share/greek/errmsg.txt | 2 + sql/share/hungarian/errmsg.txt | 2 + sql/share/italian/errmsg.txt | 2 + sql/share/japanese/errmsg.txt | 2 + sql/share/korean/errmsg.txt | 2 + sql/share/norwegian-ny/errmsg.txt | 2 + sql/share/norwegian/errmsg.txt | 2 + sql/share/polish/errmsg.txt | 2 + sql/share/portuguese/errmsg.txt | 2 + sql/share/romanian/errmsg.txt | 2 + sql/share/russian/errmsg.txt | 2 + sql/share/serbian/errmsg.txt | 2 + sql/share/slovak/errmsg.txt | 2 + sql/share/spanish/errmsg.txt | 2 + sql/share/swedish/errmsg.txt | 2 + sql/share/ukrainian/errmsg.txt | 2 + sql/sp_head.cc | 173 +++++++++++++++++++++++++++++- sql/sp_head.h | 62 +++++++++-- sql/sql_string.cc | 14 +++ sql/sql_string.h | 2 + sql/sql_yacc.yy | 14 +++ 34 files changed, 378 insertions(+), 30 deletions(-) diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 113eb07ed66..4b01004f1b4 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -340,4 +340,6 @@ #define ER_SP_CANT_ALTER 1321 #define ER_SP_SUBSELECT_NYI 1322 #define ER_SP_NO_USE 1323 -#define ER_ERROR_MESSAGES 324 +#define ER_SP_VARCOND_AFTER_CURSHNDLR 1324 +#define ER_SP_CURSOR_AFTER_HANDLER 1325 +#define ER_ERROR_MESSAGES 326 diff --git a/include/sql_state.h b/include/sql_state.h index c5a71daceb9..0c35f6bf8c9 100644 --- a/include/sql_state.h +++ b/include/sql_state.h @@ -197,3 +197,5 @@ ER_SP_DUP_CURS, "42000", "", /*ER_SP_CANT_ALTER*/ ER_SP_SUBSELECT_NYI, "0A000", "", ER_SP_NO_USE, "42000", "", +ER_SP_VARCOND_AFTER_CURSHNDLR, "42000", "", +ER_SP_CURSOR_AFTER_HANDLER, "42000", "", diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 1877789e2b0..6bc2af9862e 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -194,8 +194,8 @@ create table t1 (val int, x float)| insert into t1 values (42, 3.1), (19, 1.2)| create procedure p() begin -declare c cursor for select * from t1; declare x int; +declare c cursor for select * from t1; open c; fetch c into x, y; close c; @@ -203,8 +203,8 @@ end| ERROR 42000: Undeclared variable: y create procedure p() begin -declare c cursor for select * from t1; declare x int; +declare c cursor for select * from t1; open c; fetch c into x; close c; @@ -214,10 +214,10 @@ ERROR HY000: Wrong number of FETCH variables drop procedure p| create procedure p() begin -declare c cursor for select * from t1; declare x int; declare y float; declare z int; +declare c cursor for select * from t1; open c; fetch c into x, y, z; close c; @@ -252,9 +252,28 @@ declare c cursor for select field from t1; end| ERROR 42000: Duplicate cursor: c create procedure u() -use sptmp; -#| +use sptmp| ERROR 42000: USE is not allowed in a stored procedure +create procedure p() +begin +declare c cursor for select * from t1; +declare x int; +end| +ERROR 42000: Variable or condition declaration after cursor or handler declaration +create procedure p() +begin +declare x int; +declare continue handler for sqlstate '42S99' set x = 1; +declare foo condition for sqlstate '42S99'; +end| +ERROR 42000: Variable or condition declaration after cursor or handler declaration +create procedure p() +begin +declare x int; +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 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 1f3064605bc..bfcf4064cf2 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -660,12 +660,12 @@ drop table t3| drop procedure hndlr4| create procedure cur1() begin -declare done int default 0; -declare continue handler for sqlstate '02000' set done = 1; -declare c cursor for select * from test.t2; declare a char(16); declare b int; declare c double; +declare done int default 0; +declare c cursor for select * from test.t2; +declare continue handler for sqlstate '02000' set done = 1; open c; repeat fetch c into a, b, c; @@ -688,9 +688,9 @@ create table t3 ( s char(16), i int )| create procedure cur2() begin declare done int default 0; -declare continue handler for sqlstate '02000' set done = 1; declare c1 cursor for select id,data from test.t1; declare c2 cursor for select i from test.t2; +declare continue handler for sqlstate '02000' set done = 1; open c1; open c2; repeat @@ -764,8 +764,8 @@ create procedure modes(out c1 int, out c2 int) begin declare done int default 0; declare x int; -declare continue handler for sqlstate '02000' set done = 1; declare c cursor for select data from t1; +declare continue handler for sqlstate '02000' set done = 1; select 1 || 2 into c1; set c2 = 0; open c; @@ -915,8 +915,8 @@ drop procedure bug1874| create procedure bug2260() begin declare v1 int; -declare continue handler for not found set @x2 = 1; declare c1 cursor for select data from t1; +declare continue handler for not found set @x2 = 1; open c1; fetch c1 into v1; set @x2 = 2; @@ -996,10 +996,13 @@ drop table t3| drop procedure bug2614| create function bug2674 () returns int return @@sort_buffer_size| +set @osbs = @@sort_buffer_size| +set @@sort_buffer_size = 262000| select bug2674()| bug2674() -262136 +262000 drop function bug2674| +set @@sort_buffer_size = @osbs| create procedure bug3259_1 () begin end| create procedure BUG3259_2 () begin end| create procedure Bug3259_3 () begin end| diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 43b5c04766a..cbff9b37a11 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -264,8 +264,8 @@ insert into t1 values (42, 3.1), (19, 1.2)| --error 1314 create procedure p() begin - declare c cursor for select * from t1; declare x int; + declare c cursor for select * from t1; open c; fetch c into x, y; @@ -274,8 +274,8 @@ end| create procedure p() begin - declare c cursor for select * from t1; declare x int; + declare c cursor for select * from t1; open c; fetch c into x; @@ -287,10 +287,10 @@ drop procedure p| create procedure p() begin - declare c cursor for select * from t1; declare x int; declare y float; declare z int; + declare c cursor for select * from t1; open c; fetch c into x, y, z; @@ -333,8 +333,30 @@ end| # USE is not allowed --error 1323 create procedure u() - use sptmp; + use sptmp| +# Enforced standard order of declarations +--error 1324 +create procedure p() +begin + declare c cursor for select * from t1; + declare x int; +end| +--error 1324 +create procedure p() +begin + declare x int; + declare continue handler for sqlstate '42S99' set x = 1; + declare foo condition for sqlstate '42S99'; +end| + +--error 1325 +create procedure p() +begin + declare x int; + declare continue handler for sqlstate '42S99' set x = 1; + declare c cursor for select * from t1; +end| # # BUG#1965 diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 69433514728..7e5b734d959 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -776,12 +776,12 @@ drop procedure hndlr4| # create procedure cur1() begin - declare done int default 0; - declare continue handler for sqlstate '02000' set done = 1; - declare c cursor for select * from test.t2; declare a char(16); declare b int; declare c double; + declare done int default 0; + declare c cursor for select * from test.t2; + declare continue handler for sqlstate '02000' set done = 1; open c; repeat @@ -806,9 +806,9 @@ create table t3 ( s char(16), i int )| create procedure cur2() begin declare done int default 0; - declare continue handler for sqlstate '02000' set done = 1; declare c1 cursor for select id,data from test.t1; declare c2 cursor for select i from test.t2; + declare continue handler for sqlstate '02000' set done = 1; open c1; open c2; @@ -879,8 +879,8 @@ create procedure modes(out c1 int, out c2 int) begin declare done int default 0; declare x int; - declare continue handler for sqlstate '02000' set done = 1; declare c cursor for select data from t1; + declare continue handler for sqlstate '02000' set done = 1; select 1 || 2 into c1; set c2 = 0; @@ -1069,8 +1069,8 @@ drop procedure bug1874| create procedure bug2260() begin declare v1 int; - declare continue handler for not found set @x2 = 1; declare c1 cursor for select data from t1; + declare continue handler for not found set @x2 = 1; open c1; fetch c1 into v1; @@ -1156,8 +1156,11 @@ drop procedure bug2614| create function bug2674 () returns int return @@sort_buffer_size| +set @osbs = @@sort_buffer_size| +set @@sort_buffer_size = 262000| select bug2674()| drop function bug2674| +set @@sort_buffer_size = @osbs| # # BUG#3259 diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index eea5912cbdf..6bcdeb9b05a 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -336,3 +336,5 @@ character-set=latin2 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 2c2782d4cf0..2d9543e1076 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -330,3 +330,5 @@ character-set=latin1 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 84bd5781ffb..484892432c0 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -338,3 +338,5 @@ character-set=latin1 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 2c88e1b445f..4d3113d4055 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -327,3 +327,5 @@ character-set=latin1 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index d72d7f94309..ba30d48b895 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -332,3 +332,5 @@ character-set=latin7 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 227b5138e98..1285b7c9d54 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -327,3 +327,5 @@ character-set=latin1 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index d4e42ed5d58..0a6886686b4 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -339,3 +339,5 @@ character-set=latin1 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 44e072bb20e..676beedc8f7 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -327,3 +327,5 @@ character-set=greek "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 72fdf4f8c51..82b96eb8928 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -329,3 +329,5 @@ character-set=latin2 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 6694f220848..aea6afdd304 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -327,3 +327,5 @@ character-set=latin1 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 896146749a9..6838a53ddca 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -329,3 +329,5 @@ character-set=ujis "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 3a92c060c67..04c480108b9 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -327,3 +327,5 @@ character-set=euckr "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index ada0435b52a..0b535727c9f 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -329,3 +329,5 @@ character-set=latin1 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index d0688b2858c..99782982ea7 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -329,3 +329,5 @@ character-set=latin1 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index d0c96146441..16dc1982a70 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -331,3 +331,5 @@ character-set=latin2 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 71be50ba262..1db07659e8f 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -328,3 +328,5 @@ character-set=latin1 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index d800906e663..f58e91e5559 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -331,3 +331,5 @@ character-set=latin2 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index 633e29e8c48..e12c4cbeb1f 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -329,3 +329,5 @@ character-set=koi8r "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index efda5bb12cc..9695ae5d207 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -322,3 +322,5 @@ character-set=cp1250 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 8fa84320a8f..2631a9b8e5e 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -335,3 +335,5 @@ character-set=latin2 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index 75a6d42bec8..e3312dbdb8d 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -329,3 +329,5 @@ character-set=latin1 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 9b743acb930..8e57aaeda51 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -327,3 +327,5 @@ character-set=latin1 "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 2b3587e2028..0a40fe5b2a8 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -332,3 +332,5 @@ character-set=koi8u "Failed to ALTER %s %s" "Subselect value not supported" "USE is not allowed in a stored procedure" +"Variable or condition declaration after cursor or handler declaration" +"Cursor declaration after handler declaration" diff --git a/sql/sp_head.cc b/sql/sp_head.cc index c8be113e2e1..4c883d4cd3d 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -297,6 +297,24 @@ sp_head::create(THD *thd) DBUG_PRINT("info", ("type: %d name: %s params: %s body: %s", m_type, m_name.str, m_params.str, m_body.str)); +#ifndef DBUG_OFF + String s; + sp_instr *i; + uint ip= 0; + while ((i = get_instr(ip))) + { + char buf[8]; + + sprintf(buf, "%4u: ", ip); + s.append(buf); + i->print(&s); + s.append('\n'); + ip+= 1; + } + s.append('\0'); + DBUG_PRINT("info", ("Code %s\n%s", m_qname.str, s.ptr())); +#endif + if (m_type == TYPE_ENUM_FUNCTION) ret= sp_create_function(thd, this); else @@ -622,9 +640,9 @@ sp_head::reset_lex(THD *thd) (void)m_lex.push_front(oldlex); thd->lex= sublex= new st_lex; - sublex->yylineno= oldlex->yylineno; /* Reset most stuff. The length arguments doesn't matter here. */ lex_start(thd, oldlex->buf, oldlex->end_of_query - oldlex->ptr); + sublex->yylineno= oldlex->yylineno; /* We must reset ptr and end_of_query again */ sublex->ptr= oldlex->ptr; sublex->end_of_query= oldlex->end_of_query; @@ -871,6 +889,15 @@ sp_instr_stmt::execute(THD *thd, uint *nextp) DBUG_RETURN(res); } +void +sp_instr_stmt::print(String *str) +{ + str->reserve(12); + str->append("stmt "); + str->qs_append(m_lex->sql_command); +} + + int sp_instr_stmt::exec_stmt(THD *thd, LEX *lex) { @@ -988,6 +1015,16 @@ sp_instr_set::execute(THD *thd, uint *nextp) DBUG_RETURN(0); } +void +sp_instr_set::print(String *str) +{ + str->reserve(12); + str->append("set "); + str->qs_append(m_offset); + str->append(' '); + m_value->print(str); +} + // // sp_instr_jump // @@ -1001,6 +1038,14 @@ sp_instr_jump::execute(THD *thd, uint *nextp) DBUG_RETURN(0); } +void +sp_instr_jump::print(String *str) +{ + str->reserve(12); + str->append("jump "); + str->qs_append(m_dest); +} + // // sp_instr_jump_if // @@ -1018,6 +1063,16 @@ sp_instr_jump_if::execute(THD *thd, uint *nextp) DBUG_RETURN(0); } +void +sp_instr_jump_if::print(String *str) +{ + str->reserve(12); + str->append("jump_if "); + str->qs_append(m_dest); + str->append(' '); + m_expr->print(str); +} + // // sp_instr_jump_if_not // @@ -1035,6 +1090,16 @@ sp_instr_jump_if_not::execute(THD *thd, uint *nextp) DBUG_RETURN(0); } +void +sp_instr_jump_if_not::print(String *str) +{ + str->reserve(16); + str->append("jump_if_not "); + str->qs_append(m_dest); + str->append(' '); + m_expr->print(str); +} + // // sp_instr_freturn // @@ -1047,6 +1112,16 @@ sp_instr_freturn::execute(THD *thd, uint *nextp) DBUG_RETURN(0); } +void +sp_instr_freturn::print(String *str) +{ + str->reserve(12); + str->append("freturn "); + str->qs_append(m_type); + str->append(' '); + m_value->print(str); +} + // // sp_instr_hpush_jump // @@ -1064,6 +1139,18 @@ sp_instr_hpush_jump::execute(THD *thd, uint *nextp) DBUG_RETURN(0); } +void +sp_instr_hpush_jump::print(String *str) +{ + str->reserve(32); + str->append("hpush_jump "); + str->qs_append(m_type); + str->append(' '); + str->qs_append(m_frame); + str->append(' '); + str->qs_append(m_handler); +} + // // sp_instr_hpop // @@ -1076,6 +1163,14 @@ sp_instr_hpop::execute(THD *thd, uint *nextp) DBUG_RETURN(0); } +void +sp_instr_hpop::print(String *str) +{ + str->reserve(12); + str->append("hpop "); + str->qs_append(m_count); +} + // // sp_instr_hreturn // @@ -1088,6 +1183,14 @@ sp_instr_hreturn::execute(THD *thd, uint *nextp) DBUG_RETURN(0); } +void +sp_instr_hreturn::print(String *str) +{ + str->reserve(12); + str->append("hreturn "); + str->qs_append(m_frame); +} + // // sp_instr_cpush // @@ -1106,6 +1209,12 @@ sp_instr_cpush::~sp_instr_cpush() delete m_lex; } +void +sp_instr_cpush::print(String *str) +{ + str->append("cpush"); +} + // // sp_instr_cpop // @@ -1118,6 +1227,14 @@ sp_instr_cpop::execute(THD *thd, uint *nextp) DBUG_RETURN(0); } +void +sp_instr_cpop::print(String *str) +{ + str->reserve(12); + str->append("cpop "); + str->qs_append(m_count); +} + // // sp_instr_copen // @@ -1145,6 +1262,14 @@ sp_instr_copen::execute(THD *thd, uint *nextp) DBUG_RETURN(res); } +void +sp_instr_copen::print(String *str) +{ + str->reserve(12); + str->append("copen "); + str->qs_append(m_cursor); +} + // // sp_instr_cclose // @@ -1163,6 +1288,14 @@ sp_instr_cclose::execute(THD *thd, uint *nextp) DBUG_RETURN(res); } +void +sp_instr_cclose::print(String *str) +{ + str->reserve(12); + str->append("cclose "); + str->qs_append(m_cursor); +} + // // sp_instr_cfetch // @@ -1181,6 +1314,44 @@ sp_instr_cfetch::execute(THD *thd, uint *nextp) DBUG_RETURN(res); } +void +sp_instr_cfetch::print(String *str) +{ + List_iterator_fast li(m_varlist); + sp_pvar_t *pv; + + str->reserve(12); + str->append("cfetch "); + str->qs_append(m_cursor); + while ((pv= li++)) + { + str->reserve(8); + str->append(' '); + str->qs_append(pv->offset); + } +} + +// +// sp_instr_error +// +int +sp_instr_error::execute(THD *thd, uint *nextp) +{ + DBUG_ENTER("sp_instr_error::execute"); + + my_error(m_errcode, MYF(0)); + *nextp= m_ip+1; + DBUG_RETURN(-1); +} + +void +sp_instr_error::print(String *str) +{ + str->reserve(12); + str->append("error "); + str->qs_append(m_errcode); +} + /* ------------------------------------------------------------------ */ diff --git a/sql/sp_head.h b/sql/sp_head.h index 791c6697693..19d1cb8254a 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -262,12 +262,9 @@ public: // instruction to execute. (For most instruction this will be the // instruction following this one.) // Returns 0 on success, non-zero if some error occured. - virtual int - execute(THD *thd, uint *nextp) - { // Default is a no-op. - *nextp = m_ip+1; // Next instruction - return 0; - } + virtual int execute(THD *thd, uint *nextp) = 0; + + virtual void print(String *str) = 0; protected: @@ -294,6 +291,8 @@ public: virtual int execute(THD *thd, uint *nextp); + virtual void print(String *str); + inline void set_lex(LEX *lex) { @@ -333,6 +332,8 @@ public: virtual int execute(THD *thd, uint *nextp); + virtual void print(String *str); + private: uint m_offset; // Frame offset @@ -362,6 +363,8 @@ public: virtual int execute(THD *thd, uint *nextp); + virtual void print(String *str); + virtual void set_destination(uint dest) { @@ -395,6 +398,8 @@ public: virtual int execute(THD *thd, uint *nextp); + virtual void print(String *str); + private: Item *m_expr; // The condition @@ -422,6 +427,8 @@ public: virtual int execute(THD *thd, uint *nextp); + virtual void print(String *str); + private: Item *m_expr; // The condition @@ -445,6 +452,8 @@ public: virtual int execute(THD *thd, uint *nextp); + virtual void print(String *str); + protected: Item *m_value; @@ -474,6 +483,8 @@ public: virtual int execute(THD *thd, uint *nextp); + virtual void print(String *str); + inline void add_condition(struct sp_cond_type *cond) { m_cond.push_front(cond); @@ -505,6 +516,8 @@ public: virtual int execute(THD *thd, uint *nextp); + virtual void print(String *str); + private: uint m_count; @@ -528,6 +541,8 @@ public: virtual int execute(THD *thd, uint *nextp); + virtual void print(String *str); + private: uint m_frame; @@ -550,6 +565,8 @@ public: virtual int execute(THD *thd, uint *nextp); + virtual void print(String *str); + private: LEX *m_lex; @@ -573,6 +590,8 @@ public: virtual int execute(THD *thd, uint *nextp); + virtual void print(String *str); + private: uint m_count; @@ -596,6 +615,8 @@ public: virtual int execute(THD *thd, uint *nextp); + virtual void print(String *str); + private: uint m_cursor; // Stack index @@ -619,6 +640,8 @@ public: virtual int execute(THD *thd, uint *nextp); + virtual void print(String *str); + private: uint m_cursor; @@ -644,6 +667,8 @@ public: virtual int execute(THD *thd, uint *nextp); + virtual void print(String *str); + void add_to_varlist(struct sp_pvar *var) { m_varlist.push_back(var); @@ -657,6 +682,31 @@ private: }; // class sp_instr_cfetch : public sp_instr +class sp_instr_error : public sp_instr +{ + sp_instr_error(const sp_instr_error &); /* Prevent use of these */ + void operator=(sp_instr_error &); + +public: + + sp_instr_error(uint ip, int errcode) + : sp_instr(ip), m_errcode(errcode) + {} + + virtual ~sp_instr_error() + {} + + virtual int execute(THD *thd, uint *nextp); + + virtual void print(String *str); + +private: + + int m_errcode; + +}; // class sp_instr_error : public sp_instr + + struct st_sp_security_context { bool changed; diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 093b85b46b7..cd25b0c27ec 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -698,6 +698,20 @@ void String::qs_append(const char &c) str_length += sizeof(c); } +void String::qs_append(int i) +{ + char *buff = Ptr + str_length; + sprintf(buff,"%d", i); + str_length += strlen(buff); +} + +void String::qs_append(uint i) +{ + char *buff = Ptr + str_length; + sprintf(buff,"%u", i); + str_length += strlen(buff); +} + int sortcmp(const String *x,const String *y, CHARSET_INFO *cs) { diff --git a/sql/sql_string.h b/sql/sql_string.h index 163156fdfe2..d234bf7b507 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -270,6 +270,8 @@ public: void qs_append(double d); void qs_append(double *d); void qs_append(const char &c); + void qs_append(int i); + void qs_append(uint i); /* Inline (general) functions used by the protocol functions */ diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d2f7e73b2b8..b9e9b0126df 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1318,6 +1318,20 @@ sp_decls: } | sp_decls sp_decl ';' { + /* We check for declarations out of (standard) order this way + because letting the grammar rules reflect it caused tricky + shift/reduce conflicts with the wrong result. (And we get + better error handling this way.) */ + if (($2.vars || $2.conds) && ($1.curs || $1.hndlrs)) + { /* Variable or condition following cursor or handler */ + send_error(YYTHD, ER_SP_VARCOND_AFTER_CURSHNDLR); + YYABORT; + } + if ($2.curs && $1.hndlrs) + { /* Cursor following handler */ + send_error(YYTHD, ER_SP_CURSOR_AFTER_HANDLER); + YYABORT; + } $$.vars= $1.vars + $2.vars; $$.conds= $1.conds + $2.conds; $$.hndlrs= $1.hndlrs + $2.hndlrs; From 329013f99e27e81982cf6fc07e0d6d8b4ebe2c91 Mon Sep 17 00:00:00 2001 From: "pem@mysql.comhem.se" <> Date: Mon, 29 Mar 2004 12:29:06 +0200 Subject: [PATCH 2/2] Fixed BUG#3287: Stored Procedure Case Statement Not SQL:2003 Compliant. --- include/mysqld_error.h | 3 ++- include/sql_state.h | 1 + mysql-test/r/sp-error.result | 21 +++++++++++++++++++++ mysql-test/t/sp-error.test | 27 +++++++++++++++++++++++++++ sql/share/czech/errmsg.txt | 1 + sql/share/danish/errmsg.txt | 1 + sql/share/dutch/errmsg.txt | 1 + sql/share/english/errmsg.txt | 1 + sql/share/estonian/errmsg.txt | 1 + sql/share/french/errmsg.txt | 1 + sql/share/german/errmsg.txt | 1 + sql/share/greek/errmsg.txt | 1 + sql/share/hungarian/errmsg.txt | 1 + sql/share/italian/errmsg.txt | 1 + sql/share/japanese/errmsg.txt | 1 + sql/share/korean/errmsg.txt | 1 + sql/share/norwegian-ny/errmsg.txt | 1 + sql/share/norwegian/errmsg.txt | 1 + sql/share/polish/errmsg.txt | 1 + sql/share/portuguese/errmsg.txt | 1 + sql/share/romanian/errmsg.txt | 1 + sql/share/russian/errmsg.txt | 1 + sql/share/serbian/errmsg.txt | 1 + sql/share/slovak/errmsg.txt | 1 + sql/share/spanish/errmsg.txt | 1 + sql/share/swedish/errmsg.txt | 1 + sql/share/ukrainian/errmsg.txt | 1 + sql/sql_yacc.yy | 11 +++++++++-- 28 files changed, 83 insertions(+), 3 deletions(-) diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 4b01004f1b4..b4d7edf3e96 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -342,4 +342,5 @@ #define ER_SP_NO_USE 1323 #define ER_SP_VARCOND_AFTER_CURSHNDLR 1324 #define ER_SP_CURSOR_AFTER_HANDLER 1325 -#define ER_ERROR_MESSAGES 326 +#define ER_SP_CASE_NOT_FOUND 1326 +#define ER_ERROR_MESSAGES 327 diff --git a/include/sql_state.h b/include/sql_state.h index 0c35f6bf8c9..9eff300d494 100644 --- a/include/sql_state.h +++ b/include/sql_state.h @@ -199,3 +199,4 @@ ER_SP_SUBSELECT_NYI, "0A000", "", ER_SP_NO_USE, "42000", "", ER_SP_VARCOND_AFTER_CURSHNDLR, "42000", "", ER_SP_CURSOR_AFTER_HANDLER, "42000", "", +ER_SP_CASE_NOT_FOUND, "20000", "", diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 6bc2af9862e..a48256e6824 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -341,4 +341,25 @@ call bug2329_2()| ERROR 42S22: Unknown column 'v' in 'field list' drop procedure bug2329_1| drop procedure bug2329_2| +create function bug3287() returns int +begin +declare v int default null; +case +when v is not null then return 1; +end case; +return 2; +end| +select bug3287()| +ERROR 20000: Case not found for CASE statement +drop function bug3287| +create procedure bug3287(x int) +case x +when 0 then +insert into test.t1 values (x, 0.1); +when 1 then +insert into test.t1 values (x, 1.1); +end case| +call bug3287(2)| +ERROR 20000: Case not found for CASE statement +drop procedure bug3287| drop table t1| diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index cbff9b37a11..ad96d0b403b 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -473,6 +473,33 @@ call bug2329_2()| drop procedure bug2329_1| drop procedure bug2329_2| +# +# BUG#3287 +# +create function bug3287() returns int +begin + declare v int default null; + + case + when v is not null then return 1; + end case; + return 2; +end| +--error 1326 +select bug3287()| +drop function bug3287| + +create procedure bug3287(x int) +case x +when 0 then + insert into test.t1 values (x, 0.1); +when 1 then + insert into test.t1 values (x, 1.1); +end case| +--error 1326 +call bug3287(2)| +drop procedure bug3287| + drop table t1| delimiter ;| diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 6bcdeb9b05a..dd3ea82790a 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -338,3 +338,4 @@ character-set=latin2 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index 2d9543e1076..c1471c78c7e 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -332,3 +332,4 @@ character-set=latin1 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 484892432c0..0f1f9f65e99 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -340,3 +340,4 @@ character-set=latin1 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index 4d3113d4055..2d5757977a4 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -329,3 +329,4 @@ character-set=latin1 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index ba30d48b895..e610121e278 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -334,3 +334,4 @@ character-set=latin7 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index 1285b7c9d54..04310561c90 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -329,3 +329,4 @@ character-set=latin1 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 0a6886686b4..ccbb0ced3d3 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -341,3 +341,4 @@ character-set=latin1 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 676beedc8f7..f7294fc0697 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -329,3 +329,4 @@ character-set=greek "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 82b96eb8928..a127f35584d 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -331,3 +331,4 @@ character-set=latin2 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index aea6afdd304..e8225c6ba48 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -329,3 +329,4 @@ character-set=latin1 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index 6838a53ddca..af4e626a1fd 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -331,3 +331,4 @@ character-set=ujis "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 04c480108b9..dd67927adef 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -329,3 +329,4 @@ character-set=euckr "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 0b535727c9f..06c26a06e99 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -331,3 +331,4 @@ character-set=latin1 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index 99782982ea7..08358db4b3a 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -331,3 +331,4 @@ character-set=latin1 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index 16dc1982a70..9aa6cf0d453 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -333,3 +333,4 @@ character-set=latin2 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 1db07659e8f..49ccf308634 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -330,3 +330,4 @@ character-set=latin1 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index f58e91e5559..b79926cb7e4 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -333,3 +333,4 @@ character-set=latin2 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index e12c4cbeb1f..be92447d43e 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -331,3 +331,4 @@ character-set=koi8r "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index 9695ae5d207..92710650f50 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -324,3 +324,4 @@ character-set=cp1250 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 2631a9b8e5e..c81d74075ad 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -337,3 +337,4 @@ character-set=latin2 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index e3312dbdb8d..e79af2de398 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -331,3 +331,4 @@ character-set=latin1 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 8e57aaeda51..28314a7367a 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -329,3 +329,4 @@ character-set=latin1 "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index 0a40fe5b2a8..9263ee89400 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -334,3 +334,4 @@ character-set=koi8u "USE is not allowed in a stored procedure" "Variable or condition declaration after cursor or handler declaration" "Cursor declaration after handler declaration" +"Case not found for CASE statement" diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index b9e9b0126df..6a0d254a90c 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1908,9 +1908,16 @@ sp_case: ; sp_whens: - /* Empty */ {} - | WHEN_SYM sp_case {} + /* Empty */ + { + sp_head *sp= Lex->sphead; + uint ip= sp->instructions(); + sp_instr_error *i= new sp_instr_error(ip, ER_SP_CASE_NOT_FOUND); + + sp->add_instr(i); + } | ELSE sp_proc_stmts {} + | WHEN_SYM sp_case {} ; sp_labeled_control: