mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-10598 Variable declarations can go after cursor declarations
Based on a contributed patch from Jerome Brauge.
This commit is contained in:
@@ -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;
|
||||
|
270
mysql-test/suite/compat/oracle/r/sp-cursor-decl.result
Normal file
270
mysql-test/suite/compat/oracle/r/sp-cursor-decl.result
Normal file
@@ -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;
|
@@ -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;
|
||||
|
274
mysql-test/suite/compat/oracle/t/sp-cursor-decl.test
Normal file
274
mysql-test/suite/compat/oracle/t/sp-cursor-decl.test
Normal file
@@ -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;
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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(); }
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
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());
|
||||
return i == NULL ||
|
||||
sphead->add_instr(i) ||
|
||||
spcont->add_cursor(name, param_ctx, cursor_stmt);
|
||||
spcont->current_cursor_count() - 1);
|
||||
return i == NULL || sphead->add_instr(i);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
|
@@ -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)))
|
||||
|
Reference in New Issue
Block a user