diff options
-rw-r--r-- | mysql-test/suite/compat/oracle/r/sp-code.result | 71 | ||||
-rw-r--r-- | mysql-test/suite/compat/oracle/r/sp-cursor-decl.result | 270 | ||||
-rw-r--r-- | mysql-test/suite/compat/oracle/t/sp-code.test | 54 | ||||
-rw-r--r-- | mysql-test/suite/compat/oracle/t/sp-cursor-decl.test | 274 | ||||
-rw-r--r-- | sql/sp_head.cc | 17 | ||||
-rw-r--r-- | sql/sp_head.h | 3 | ||||
-rw-r--r-- | sql/sp_pcontext.h | 9 | ||||
-rw-r--r-- | sql/sql_lex.cc | 20 | ||||
-rw-r--r-- | sql/sql_lex.h | 3 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 2 | ||||
-rw-r--r-- | sql/sql_yacc_ora.yy | 68 |
11 files changed, 763 insertions, 28 deletions
diff --git a/mysql-test/suite/compat/oracle/r/sp-code.result b/mysql-test/suite/compat/oracle/r/sp-code.result index 557906a545f..4ac4b6115ff 100644 --- a/mysql-test/suite/compat/oracle/r/sp-code.result +++ b/mysql-test/suite/compat/oracle/r/sp-code.result @@ -1277,3 +1277,74 @@ Pos Instruction 28 jump 4 29 cpop 1 DROP PROCEDURE p1; +# +# MDEV-10598 sql_mode=ORACLE: Variable declarations can go after cursor declarations +# +# +# Cursor declaration and cursor%ROWTYPE declaration in the same block +# +CREATE TABLE t1 (a INT, b VARCHAR(10)); +INSERT INTO t1 VALUES (1,'a'); +CREATE PROCEDURE p1() +AS +CURSOR cur1 IS SELECT a FROM t1; +rec1 cur1%ROWTYPE; +BEGIN +rec1.a:= 10; +END; +$$ +SHOW PROCEDURE CODE p1; +Pos Instruction +0 cursor_copy_struct cur1 rec1@0 +1 set rec1@0 NULL +2 cpush cur1@0 +3 set rec1.a@0["a"] 10 +4 cpop 1 +CALL p1; +DROP PROCEDURE p1; +DROP TABLE t1; +# +# Recursive cursor and cursor%ROWTYPE declarations in the same block +# +CREATE PROCEDURE p1 +AS +a INT:=10; +CURSOR cur1 IS SELECT a; +rec1 cur1%ROWTYPE; +CURSOR cur2 IS SELECT rec1.a + 1 "a"; +rec2 cur2%ROWTYPE; +BEGIN +OPEN cur1; +FETCH cur1 INTO rec1; +CLOSE cur1; +SELECT rec1.a; +open cur2; +FETCH cur2 INTO rec2; +CLOSE cur2; +SELECT rec2.a; +END; +$$ +SHOW PROCEDURE CODE p1; +Pos Instruction +0 set a@0 10 +1 cursor_copy_struct cur1 rec1@1 +2 set rec1@1 NULL +3 cursor_copy_struct cur2 rec2@2 +4 set rec2@2 NULL +5 cpush cur1@0 +6 cpush cur2@1 +7 copen cur1@0 +8 cfetch cur1@0 rec1@1 +9 cclose cur1@0 +10 stmt 0 "SELECT rec1.a" +11 copen cur2@1 +12 cfetch cur2@1 rec2@2 +13 cclose cur2@1 +14 stmt 0 "SELECT rec2.a" +15 cpop 2 +CALL p1(); +rec1.a +10 +rec2.a +11 +DROP PROCEDURE p1; diff --git a/mysql-test/suite/compat/oracle/r/sp-cursor-decl.result b/mysql-test/suite/compat/oracle/r/sp-cursor-decl.result new file mode 100644 index 00000000000..944426deb23 --- /dev/null +++ b/mysql-test/suite/compat/oracle/r/sp-cursor-decl.result @@ -0,0 +1,270 @@ +SET sql_mode=ORACLE; +# +# MDEV-10598 sql_mode=ORACLE: Variable declarations can go after cursor declarations +# +# +# Variable after cursor declaration +# +CREATE TABLE t1 (a INT); +insert into t1 values (1); +insert into t1 values (2); +CREATE PROCEDURE p1 +AS +CURSOR c IS SELECT a FROM t1; +var1 varchar(10); +BEGIN +OPEN c; +fetch c into var1; +SELECT c%ROWCOUNT,var1; +close c; +END; +$$ +CALL p1; +c%ROWCOUNT var1 +1 1 +DROP PROCEDURE p1; +drop table t1; +# +# Variable after condition declaration +# +CREATE TABLE t1 (col1 INT); +insert into t1 values (1); +create unique index t1_col1 on t1 (col1); +CREATE PROCEDURE p1 +AS +dup_key CONDITION FOR SQLSTATE '23000'; +var1 varchar(40); +CONTINUE HANDLER FOR dup_key +BEGIN +var1:='duplicate key in index'; +END; +BEGIN +var1:=''; +insert into t1 values (1); +select var1; +END; +$$ +CALL p1; +var1 +duplicate key in index +DROP PROCEDURE p1; +drop table t1; +# +# Condition after cursor declaration +# +CREATE TABLE t1 (col1 INT); +insert into t1 values (1); +create unique index t1_col1 on t1 (col1); +CREATE PROCEDURE p1 +AS +var1 varchar(40); +var2 integer; +CURSOR c IS SELECT col1 FROM t1; +dup_key CONDITION FOR SQLSTATE '23000'; +CONTINUE HANDLER FOR dup_key +BEGIN +var1:='duplicate key in index'; +END; +BEGIN +var1:=''; +insert into t1 values (1); +SELECT var1; +END; +$$ +CALL p1; +var1 +duplicate key in index +DROP PROCEDURE p1; +drop table t1; +# +# Cursor after handler declaration +# +CREATE TABLE t1 (col1 INT); +insert into t1 values (1); +create unique index t1_col1 on t1 (col1); +CREATE PROCEDURE p1 +AS +var1 varchar(40); +var2 integer; +dup_key CONDITION FOR SQLSTATE '23000'; +CONTINUE HANDLER FOR dup_key +BEGIN +var1:='duplicate key in index'; +END; +CURSOR c IS SELECT col1 FROM t1; +BEGIN +var1:=''; +insert into t1 values (1); +SELECT var1; +END; +$$ +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'CURSOR c IS SELECT col1 FROM t1; +BEGIN +var1:=''; +insert into t1 values (1); +SELE' at line 10 +drop table t1; +# +# Condition after handler declaration +# +CREATE TABLE t1 (col1 INT); +insert into t1 values (1); +create unique index t1_col1 on t1 (col1); +CREATE PROCEDURE p1 +AS +var1 varchar(40); +var2 integer; +dup_key CONDITION FOR SQLSTATE '23000'; +CURSOR c IS SELECT col1 FROM t1; +CONTINUE HANDLER FOR dup_key +BEGIN +var1:='duplicate key in index'; +END; +divide_by_zero CONDITION FOR SQLSTATE '22012'; +BEGIN +var1:=''; +insert into t1 values (1); +SELECT var1; +END; +$$ +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'divide_by_zero CONDITION FOR SQLSTATE '22012'; +BEGIN +var1:=''; +insert into t1 va' at line 11 +drop table t1; +# +# Variable after handler declaration +# +CREATE TABLE t1 (col1 INT); +insert into t1 values (1); +create unique index t1_col1 on t1 (col1); +CREATE PROCEDURE p1 +AS +var1 varchar(40); +var2 integer; +dup_key CONDITION FOR SQLSTATE '23000'; +CURSOR c IS SELECT col1 FROM t1; +CONTINUE HANDLER FOR dup_key +BEGIN +var1:='duplicate key in index'; +END; +divide_by_zero CONDITION FOR SQLSTATE '22012'; +BEGIN +var1:=''; +insert into t1 values (1); +SELECT var1; +END; +$$ +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'divide_by_zero CONDITION FOR SQLSTATE '22012'; +BEGIN +var1:=''; +insert into t1 va' at line 11 +drop table t1; +# +# Variable after cursor (inner block) +# +CREATE TABLE t1 (col1 INT); +insert into t1 values (1); +insert into t1 values (2); +create unique index t1_col1 on t1 (col1); +CREATE PROCEDURE p1 +AS +CURSOR c IS SELECT col1 FROM t1; +var1 varchar(40); +BEGIN +OPEN c; +begin +declare +CURSOR c IS SELECT col1 FROM t1 where col1=2; +var2 integer; +dup_key CONDITION FOR SQLSTATE '23000'; +CONTINUE HANDLER FOR dup_key +BEGIN +var1:='duplicate key in index'; +END; +begin +OPEN c; +fetch c into var1; +SELECT 'inner cursor',var1; +insert into t1 values (2); +close c; +end; +end; +SELECT var1; +fetch c into var1; +SELECT c%ROWCOUNT,var1; +begin +insert into t1 values (2); +exception when 1062 then +begin +SELECT 'dup key caugth'; +end; +end; +close c; +END; +$$ +CALL p1; +inner cursor var1 +inner cursor 2 +var1 +duplicate key in index +c%ROWCOUNT var1 +1 1 +dup key caugth +dup key caugth +DROP PROCEDURE p1; +drop table t1; +# +# Cursor declaration and row type declaration in same block +# +CREATE TABLE t1 (a INT, b VARCHAR(10)); +insert into t1 values(1,'a'); +CREATE PROCEDURE p1() +AS +CURSOR cur1 IS SELECT a FROM t1; +rec1 cur1%ROWTYPE; +BEGIN +rec1.a:= 10; +END; +$$ +call p1; +DROP PROCEDURE p1; +drop table t1; +# +# Recursive cursor and cursor%ROWTYPE declarations in the same block +# +CREATE PROCEDURE p1 +AS +a INT:=10; +b VARCHAR(10):='b0'; +c DOUBLE:=0.1; +CURSOR cur1 IS SELECT a, b, c; +rec1 cur1%ROWTYPE; +CURSOR cur2 IS SELECT rec1.a + 1 "a", rec1.b||'0' AS b, rec1.c AS c; +rec2 cur2%ROWTYPE; +BEGIN +OPEN cur1; +FETCH cur1 INTO rec1; +CLOSE cur1; +SELECT rec1.a; +OPEN cur2; +FETCH cur2 INTO rec2; +CLOSE cur2; +SELECT rec2.a; +CREATE TABLE t2 AS SELECT rec2.a AS a, rec2.b AS b, rec2.c AS c; +SHOW CREATE TABLE t2; +DROP TABLE t2; +END; +$$ +CALL p1(); +rec1.a +10 +rec2.a +11 +Table Create Table +t2 CREATE TABLE "t2" ( + "a" bigint(21) DEFAULT NULL, + "b" varchar(11) DEFAULT NULL, + "c" double DEFAULT NULL +) +DROP PROCEDURE p1; diff --git a/mysql-test/suite/compat/oracle/t/sp-code.test b/mysql-test/suite/compat/oracle/t/sp-code.test index 00c8109c038..ce2cb011fda 100644 --- a/mysql-test/suite/compat/oracle/t/sp-code.test +++ b/mysql-test/suite/compat/oracle/t/sp-code.test @@ -917,3 +917,57 @@ $$ DELIMITER ;$$ SHOW PROCEDURE CODE p1; DROP PROCEDURE p1; + + +--echo # +--echo # MDEV-10598 sql_mode=ORACLE: Variable declarations can go after cursor declarations +--echo # + +--echo # +--echo # Cursor declaration and cursor%ROWTYPE declaration in the same block +--echo # + +CREATE TABLE t1 (a INT, b VARCHAR(10)); +INSERT INTO t1 VALUES (1,'a'); +DELIMITER $$; +CREATE PROCEDURE p1() +AS + CURSOR cur1 IS SELECT a FROM t1; + rec1 cur1%ROWTYPE; +BEGIN + rec1.a:= 10; +END; +$$ +DELIMITER ;$$ +SHOW PROCEDURE CODE p1; +CALL p1; +DROP PROCEDURE p1; +DROP TABLE t1; + +--echo # +--echo # Recursive cursor and cursor%ROWTYPE declarations in the same block +--echo # + +DELIMITER $$; +CREATE PROCEDURE p1 +AS + a INT:=10; + CURSOR cur1 IS SELECT a; + rec1 cur1%ROWTYPE; + CURSOR cur2 IS SELECT rec1.a + 1 "a"; + rec2 cur2%ROWTYPE; +BEGIN + OPEN cur1; + FETCH cur1 INTO rec1; + CLOSE cur1; + SELECT rec1.a; + open cur2; + FETCH cur2 INTO rec2; + CLOSE cur2; + SELECT rec2.a; +END; +$$ +DELIMITER ;$$ +SHOW PROCEDURE CODE p1; +CALL p1(); +DROP PROCEDURE p1; diff --git a/mysql-test/suite/compat/oracle/t/sp-cursor-decl.test b/mysql-test/suite/compat/oracle/t/sp-cursor-decl.test new file mode 100644 index 00000000000..dd90cd8b815 --- /dev/null +++ b/mysql-test/suite/compat/oracle/t/sp-cursor-decl.test @@ -0,0 +1,274 @@ +SET sql_mode=ORACLE; + +--echo # +--echo # MDEV-10598 sql_mode=ORACLE: Variable declarations can go after cursor declarations +--echo # + +--echo # +--echo # Variable after cursor declaration +--echo # + +CREATE TABLE t1 (a INT); +insert into t1 values (1); +insert into t1 values (2); +DELIMITER $$; +CREATE PROCEDURE p1 +AS + CURSOR c IS SELECT a FROM t1; + var1 varchar(10); +BEGIN + OPEN c; + fetch c into var1; + SELECT c%ROWCOUNT,var1; + close c; +END; +$$ +DELIMITER ;$$ +CALL p1; +DROP PROCEDURE p1; +drop table t1; + +--echo # +--echo # Variable after condition declaration +--echo # + +CREATE TABLE t1 (col1 INT); +insert into t1 values (1); +create unique index t1_col1 on t1 (col1); +DELIMITER $$; +CREATE PROCEDURE p1 +AS + dup_key CONDITION FOR SQLSTATE '23000'; + var1 varchar(40); + CONTINUE HANDLER FOR dup_key + BEGIN + var1:='duplicate key in index'; + END; +BEGIN + var1:=''; + insert into t1 values (1); + select var1; +END; +$$ +DELIMITER ;$$ +CALL p1; +DROP PROCEDURE p1; +drop table t1; + +--echo # +--echo # Condition after cursor declaration +--echo # + +CREATE TABLE t1 (col1 INT); +insert into t1 values (1); +create unique index t1_col1 on t1 (col1); +DELIMITER $$; +CREATE PROCEDURE p1 +AS + var1 varchar(40); + var2 integer; + CURSOR c IS SELECT col1 FROM t1; + dup_key CONDITION FOR SQLSTATE '23000'; + CONTINUE HANDLER FOR dup_key + BEGIN + var1:='duplicate key in index'; + END; +BEGIN + var1:=''; + insert into t1 values (1); + SELECT var1; +END; +$$ +DELIMITER ;$$ +CALL p1; +DROP PROCEDURE p1; +drop table t1; + +--echo # +--echo # Cursor after handler declaration +--echo # + +CREATE TABLE t1 (col1 INT); +insert into t1 values (1); +create unique index t1_col1 on t1 (col1); +DELIMITER $$; +--error ER_PARSE_ERROR +CREATE PROCEDURE p1 +AS + var1 varchar(40); + var2 integer; + dup_key CONDITION FOR SQLSTATE '23000'; + CONTINUE HANDLER FOR dup_key + BEGIN + var1:='duplicate key in index'; + END; + CURSOR c IS SELECT col1 FROM t1; +BEGIN + var1:=''; + insert into t1 values (1); + SELECT var1; +END; +$$ +DELIMITER ;$$ +drop table t1; + +--echo # +--echo # Condition after handler declaration +--echo # + +CREATE TABLE t1 (col1 INT); +insert into t1 values (1); +create unique index t1_col1 on t1 (col1); +DELIMITER $$; +--error ER_PARSE_ERROR +CREATE PROCEDURE p1 +AS + var1 varchar(40); + var2 integer; + dup_key CONDITION FOR SQLSTATE '23000'; + CURSOR c IS SELECT col1 FROM t1; + CONTINUE HANDLER FOR dup_key + BEGIN + var1:='duplicate key in index'; + END; + divide_by_zero CONDITION FOR SQLSTATE '22012'; +BEGIN + var1:=''; + insert into t1 values (1); + SELECT var1; +END; +$$ +DELIMITER ;$$ +drop table t1; + +--echo # +--echo # Variable after handler declaration +--echo # + +CREATE TABLE t1 (col1 INT); +insert into t1 values (1); +create unique index t1_col1 on t1 (col1); +DELIMITER $$; +--error ER_PARSE_ERROR +CREATE PROCEDURE p1 +AS + var1 varchar(40); + var2 integer; + dup_key CONDITION FOR SQLSTATE '23000'; + CURSOR c IS SELECT col1 FROM t1; + CONTINUE HANDLER FOR dup_key + BEGIN + var1:='duplicate key in index'; + END; + divide_by_zero CONDITION FOR SQLSTATE '22012'; +BEGIN + var1:=''; + insert into t1 values (1); + SELECT var1; +END; +$$ +DELIMITER ;$$ +drop table t1; + +--echo # +--echo # Variable after cursor (inner block) +--echo # + +CREATE TABLE t1 (col1 INT); +insert into t1 values (1); +insert into t1 values (2); +create unique index t1_col1 on t1 (col1); +DELIMITER $$; +CREATE PROCEDURE p1 +AS + CURSOR c IS SELECT col1 FROM t1; + var1 varchar(40); +BEGIN + OPEN c; + begin + declare + CURSOR c IS SELECT col1 FROM t1 where col1=2; + var2 integer; + dup_key CONDITION FOR SQLSTATE '23000'; + CONTINUE HANDLER FOR dup_key + BEGIN + var1:='duplicate key in index'; + END; + begin + OPEN c; + fetch c into var1; + SELECT 'inner cursor',var1; + insert into t1 values (2); + close c; + end; + end; + SELECT var1; + fetch c into var1; + SELECT c%ROWCOUNT,var1; + begin + insert into t1 values (2); + exception when 1062 then + begin + SELECT 'dup key caugth'; + end; + end; + close c; +END; +$$ +DELIMITER ;$$ +CALL p1; +DROP PROCEDURE p1; +drop table t1; + +--echo # +--echo # Cursor declaration and row type declaration in same block +--echo # + +CREATE TABLE t1 (a INT, b VARCHAR(10)); +insert into t1 values(1,'a'); +delimiter $$; +CREATE PROCEDURE p1() +AS + CURSOR cur1 IS SELECT a FROM t1; + rec1 cur1%ROWTYPE; +BEGIN + rec1.a:= 10; +END; +$$ +delimiter ;$$ +call p1; +DROP PROCEDURE p1; +drop table t1; + + +--echo # +--echo # Recursive cursor and cursor%ROWTYPE declarations in the same block +--echo # + +delimiter $$; +CREATE PROCEDURE p1 +AS + a INT:=10; + b VARCHAR(10):='b0'; + c DOUBLE:=0.1; + CURSOR cur1 IS SELECT a, b, c; + rec1 cur1%ROWTYPE; + CURSOR cur2 IS SELECT rec1.a + 1 "a", rec1.b||'0' AS b, rec1.c AS c; + rec2 cur2%ROWTYPE; +BEGIN + OPEN cur1; + FETCH cur1 INTO rec1; + CLOSE cur1; + SELECT rec1.a; + OPEN cur2; + FETCH cur2 INTO rec2; + CLOSE cur2; + SELECT rec2.a; + CREATE TABLE t2 AS SELECT rec2.a AS a, rec2.b AS b, rec2.c AS c; + SHOW CREATE TABLE t2; + DROP TABLE t2; +END; +$$ +DELIMITER ;$$ +CALL p1(); +DROP PROCEDURE p1; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 5b7e4f854e7..16dfbe9b700 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2423,6 +2423,23 @@ sp_head::do_cont_backpatch() } } + +bool +sp_head::sp_add_instr_cpush_for_cursors(THD *thd, sp_pcontext *pcontext) +{ + for (uint i= 0; i < pcontext->frame_cursor_count(); i++) + { + const sp_pcursor *c= pcontext->get_cursor_by_local_frame_offset(i); + sp_instr_cpush *instr= new (thd->mem_root) + sp_instr_cpush(instructions(), pcontext, c->lex(), + pcontext->cursor_offset() + i); + if (instr == NULL || add_instr(instr)) + return true; + } + return false; +} + + void sp_head::set_info(longlong created, longlong modified, st_sp_chistics *chistics, sql_mode_t sql_mode) diff --git a/sql/sp_head.h b/sql/sp_head.h index 8322a92636e..d8709feb084 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -573,6 +573,9 @@ public: void do_cont_backpatch(); + /// Add cpush instructions for all cursors declared in the current frame + bool sp_add_instr_cpush_for_cursors(THD *thd, sp_pcontext *pcontext); + char *name(uint *lenp = 0) const { if (lenp) diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index f6ed0ace60c..f8ca45da4ae 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -659,6 +659,15 @@ public: /// Find cursor by offset (for SHOW {PROCEDURE|FUNCTION} CODE only). const sp_pcursor *find_cursor(uint offset) const; + const sp_pcursor *get_cursor_by_local_frame_offset(uint offset) const + { return &m_cursors.at(offset); } + + uint cursor_offset() const + { return m_cursor_offset; } + + uint frame_cursor_count() const + { return m_cursors.elements(); } + uint max_cursor_index() const { return m_max_cursor_index + m_cursors.elements(); } diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index d0d60b2c7b2..7e5d29cd675 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -5628,7 +5628,7 @@ bool LEX::sp_for_loop_cursor_finalize(THD *thd, const Lex_for_loop_st &loop) bool LEX::sp_declare_cursor(THD *thd, const LEX_STRING name, sp_lex_cursor *cursor_stmt, - sp_pcontext *param_ctx) + sp_pcontext *param_ctx, bool add_cpush_instr) { uint offp; sp_instr_cpush *i; @@ -5639,12 +5639,18 @@ bool LEX::sp_declare_cursor(THD *thd, const LEX_STRING name, return true; } cursor_stmt->set_cursor_name(name); - i= new (thd->mem_root) - sp_instr_cpush(sphead->instructions(), spcont, cursor_stmt, - spcont->current_cursor_count()); - return i == NULL || - sphead->add_instr(i) || - spcont->add_cursor(name, param_ctx, cursor_stmt); + + if (spcont->add_cursor(name, param_ctx, cursor_stmt)) + return true; + + if (add_cpush_instr) + { + i= new (thd->mem_root) + sp_instr_cpush(sphead->instructions(), spcont, cursor_stmt, + spcont->current_cursor_count() - 1); + return i == NULL || sphead->add_instr(i); + } + return false; } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 5f02bbac9b6..8afc02a099c 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -3165,7 +3165,8 @@ public: bool sp_declare_cursor(THD *thd, const LEX_STRING name, class sp_lex_cursor *cursor_stmt, - sp_pcontext *param_ctx); + sp_pcontext *param_ctx, bool add_cpush_instr); + bool sp_open_cursor(THD *thd, const LEX_STRING name, List<sp_assignment_lex> *parameters); Item_splocal *create_item_for_sp_var(LEX_STRING name, sp_variable *spvar, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index a796d8af40d..1b87196686f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3022,7 +3022,7 @@ sp_decl_body: } | ident CURSOR_SYM FOR_SYM sp_cursor_stmt { - if (Lex->sp_declare_cursor(thd, $1, $4, NULL)) + if (Lex->sp_declare_cursor(thd, $1, $4, NULL, true)) MYSQL_YYABORT; $$.vars= $$.conds= $$.hndlrs= 0; $$.curs= 1; diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 021d6701f7a..415ea119fa6 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -1335,7 +1335,9 @@ END_OF_INPUT %type <num> sp_decl_idents sp_handler_type sp_hcond_list %type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value -%type <spblock> sp_decl_body sp_decl_body_list opt_sp_decl_body_list +%type <spblock> sp_decl_body_list opt_sp_decl_body_list +%type <spblock> sp_decl_non_handler sp_decl_non_handler_list +%type <spblock> sp_decl_handler sp_decl_handler_list opt_sp_decl_handler_list %type <spblock_handlers> sp_block_statements_and_exceptions %type <sp_instr_addr> sp_instr_addr %type <sp_cursor_name_and_offset> sp_cursor_name_and_offset @@ -2444,12 +2446,37 @@ opt_sp_decl_body_list: ; sp_decl_body_list: - sp_decl_body ';' { $$= $1; } - | sp_decl_body_list sp_decl_body ';' + sp_decl_non_handler_list { - if (Lex->sp_declarations_join(&$$, $1, $2)) + if (Lex->sphead->sp_add_instr_cpush_for_cursors(thd, Lex->spcont)) MYSQL_YYABORT; } + opt_sp_decl_handler_list + { + $$.join($1, $3); + } + | sp_decl_handler_list + ; + +sp_decl_non_handler_list: + sp_decl_non_handler ';' { $$= $1; } + | sp_decl_non_handler_list sp_decl_non_handler ';' + { + $$.join($1, $2); + } + ; + +sp_decl_handler_list: + sp_decl_handler ';' { $$= $1; } + | sp_decl_handler_list sp_decl_handler ';' + { + $$.join($1, $2); + } + ; + +opt_sp_decl_handler_list: + /* Empty*/ { $$.init(); } + | sp_decl_handler_list ; qualified_column_ident: @@ -2527,7 +2554,7 @@ type_or_rowtype: | ROWTYPE_SYM { $$= 1; } ; -sp_decl_body: +sp_decl_non_handler: sp_decl_idents { Lex->sp_variable_declarations_init(thd, $1); @@ -2581,18 +2608,6 @@ sp_decl_body: $$.vars= $$.hndlrs= $$.curs= 0; $$.conds= 1; } - | sp_handler_type HANDLER_SYM FOR_SYM - { - if (Lex->sp_handler_declaration_init(thd, $1)) - MYSQL_YYABORT; - } - sp_hcond_list sp_proc_stmt - { - if (Lex->sp_handler_declaration_finalize(thd, $1)) - MYSQL_YYABORT; - $$.vars= $$.conds= $$.curs= 0; - $$.hndlrs= 1; - } | CURSOR_SYM ident_directly_assignable { Lex->sp_block_init(thd); @@ -2603,13 +2618,28 @@ sp_decl_body: sp_pcontext *param_ctx= Lex->spcont; if (Lex->sp_block_finalize(thd)) MYSQL_YYABORT; - if (Lex->sp_declare_cursor(thd, $2, $6, param_ctx)) + if (Lex->sp_declare_cursor(thd, $2, $6, param_ctx, false)) MYSQL_YYABORT; $$.vars= $$.conds= $$.hndlrs= 0; $$.curs= 1; } ; +sp_decl_handler: + sp_handler_type HANDLER_SYM FOR_SYM + { + if (Lex->sp_handler_declaration_init(thd, $1)) + MYSQL_YYABORT; + } + sp_hcond_list sp_proc_stmt + { + if (Lex->sp_handler_declaration_finalize(thd, $1)) + MYSQL_YYABORT; + $$.vars= $$.conds= $$.curs= 0; + $$.hndlrs= 1; + } + ; + opt_parenthesized_cursor_formal_parameters: /* Empty */ | '(' sp_fdparams ')' @@ -3849,7 +3879,7 @@ sp_for_loop_bounds: { DBUG_ASSERT(Lex->sphead); LEX_STRING name= {C_STRING_WITH_LEN("[implicit_cursor]") }; - if (Lex->sp_declare_cursor(thd, name, $4, NULL)) + if (Lex->sp_declare_cursor(thd, name, $4, NULL, true)) MYSQL_YYABORT; $$.m_direction= 1; if (!($$.m_index= new (thd->mem_root) sp_assignment_lex(thd, thd->lex))) |