summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/compat/oracle/r/sp-code.result71
-rw-r--r--mysql-test/suite/compat/oracle/r/sp-cursor-decl.result270
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-code.test54
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-cursor-decl.test274
-rw-r--r--sql/sp_head.cc17
-rw-r--r--sql/sp_head.h3
-rw-r--r--sql/sp_pcontext.h9
-rw-r--r--sql/sql_lex.cc20
-rw-r--r--sql/sql_lex.h3
-rw-r--r--sql/sql_yacc.yy2
-rw-r--r--sql/sql_yacc_ora.yy68
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)))