Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
9c53cbdd
Commit
9c53cbdd
authored
Jun 20, 2018
by
Alexander Barkov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-15941 Explicit cursor FOR loop does not close the cursor
parent
b534a7b8
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
427 additions
and
64 deletions
+427
-64
mysql-test/main/sp-code.result
mysql-test/main/sp-code.result
+32
-26
mysql-test/main/sp-cursor.result
mysql-test/main/sp-cursor.result
+73
-0
mysql-test/main/sp-cursor.test
mysql-test/main/sp-cursor.test
+82
-0
mysql-test/suite/compat/oracle/r/sp-code.result
mysql-test/suite/compat/oracle/r/sp-code.result
+32
-26
mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result
mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result
+87
-0
mysql-test/suite/compat/oracle/t/sp-cursor-rowtype.test
mysql-test/suite/compat/oracle/t/sp-cursor-rowtype.test
+92
-0
sql/sql_lex.cc
sql/sql_lex.cc
+20
-0
sql/sql_lex.h
sql/sql_lex.h
+1
-0
sql/sql_yacc.yy
sql/sql_yacc.yy
+2
-6
sql/sql_yacc_ora.yy
sql/sql_yacc_ora.yy
+2
-6
sql/structs.h
sql/structs.h
+4
-0
No files found.
mysql-test/main/sp-code.result
View file @
9c53cbdd
...
...
@@ -1113,23 +1113,26 @@ Pos Instruction
10 stmt 0 "SELECT rec1.a, rec1.b"
11 cfetch cur1@1 rec1@0
12 jump 6
13 cursor_copy_struct cur0 rec0@1
14 copen cur0@0
15 cfetch cur0@0 rec0@1
16 jump_if_not 21(21) `cur0`%FOUND
17 set rec0.a@1["a"] 10
18 set rec0.b@1["b"] 'b0'
19 cfetch cur0@0 rec0@1
20 jump 16
21 cursor_copy_struct cur2 rec2@2
22 copen cur2@2
23 cfetch cur2@2 rec2@2
24 jump_if_not 29(29) `cur2`%FOUND
25 set rec2.a@2["a"] 10
26 set rec2.b@2["b"] 'b0'
27 cfetch cur2@2 rec2@2
28 jump 24
29 cpop 3
13 cclose cur1@1
14 cursor_copy_struct cur0 rec0@1
15 copen cur0@0
16 cfetch cur0@0 rec0@1
17 jump_if_not 22(22) `cur0`%FOUND
18 set rec0.a@1["a"] 10
19 set rec0.b@1["b"] 'b0'
20 cfetch cur0@0 rec0@1
21 jump 17
22 cclose cur0@0
23 cursor_copy_struct cur2 rec2@2
24 copen cur2@2
25 cfetch cur2@2 rec2@2
26 jump_if_not 31(31) `cur2`%FOUND
27 set rec2.a@2["a"] 10
28 set rec2.b@2["b"] 'b0'
29 cfetch cur2@2 rec2@2
30 jump 26
31 cclose cur2@2
32 cpop 3
DROP PROCEDURE p1;
# Nested explicit cursor FOR loops
CREATE PROCEDURE p1()
...
...
@@ -1164,14 +1167,14 @@ Pos Instruction
1 cursor_copy_struct cur0 rec0@0
2 copen cur0@0
3 cfetch cur0@0 rec0@0
4 jump_if_not
29(29
) `cur0`%FOUND
4 jump_if_not
31(31
) `cur0`%FOUND
5 cpush cur1@1
6 set rec0.a@0["a"] 11
7 set rec0.b@0["b"] 'b0'
8 cursor_copy_struct cur1 rec1@1
9 copen cur1@1
10 cfetch cur1@1 rec1@1
11 jump_if_not 2
6(26
) `cur1`%FOUND
11 jump_if_not 2
7(27
) `cur1`%FOUND
12 set rec1.a@1["a"] 11
13 set rec1.b@1["b"] 'b1'
14 cpush cur2@2
...
...
@@ -1183,13 +1186,16 @@ Pos Instruction
20 set rec2.b@2["b"] 'b2'
21 cfetch cur2@2 rec2@2
22 jump 18
23 cpop 1
24 cfetch cur1@1 rec1@1
25 jump 11
26 cpop 1
27 cfetch cur0@0 rec0@0
28 jump 4
29 cpop 1
23 cclose cur2@2
24 cpop 1
25 cfetch cur1@1 rec1@1
26 jump 11
27 cclose cur1@1
28 cpop 1
29 cfetch cur0@0 rec0@0
30 jump 4
31 cclose cur0@0
32 cpop 1
DROP PROCEDURE p1;
# Implicit cursor FOR loops
CREATE PROCEDURE p1()
...
...
mysql-test/main/sp-cursor.result
View file @
9c53cbdd
...
...
@@ -611,3 +611,76 @@ a b
a b
2 b2
DROP TABLE t1;
#
# MDEV-15941 Explicit cursor FOR loop does not close the cursor
#
BEGIN NOT ATOMIC
DECLARE v INT;
DECLARE cur CURSOR FOR SELECT 1 AS a FROM DUAL;
FOR rec IN cur
DO
SELECT rec.a;
END FOR;
FETCH cur INTO v;
END;
$$
rec.a
1
ERROR 24000: Cursor is not open
BEGIN NOT ATOMIC
DECLARE v INT;
DECLARE cur CURSOR FOR SELECT 1 AS a FROM DUAL;
label:
FOR rec IN cur
DO
SELECT rec.a;
END FOR;
FETCH cur INTO v;
END;
$$
rec.a
1
ERROR 24000: Cursor is not open
BEGIN NOT ATOMIC
DECLARE cur CURSOR FOR SELECT 1 AS a FROM DUAL;
OPEN cur;
FOR rec IN cur DO
SELECT rec.a;
END FOR;
END;
$$
ERROR 24000: Cursor is already open
BEGIN NOT ATOMIC
DECLARE cur CURSOR FOR SELECT 1 AS a FROM DUAL;
FOR rec IN cur
DO
SELECT rec.a;
END FOR;
FOR rec IN cur
DO
SELECT rec.a;
END FOR;
END;
$$
rec.a
1
rec.a
1
BEGIN NOT ATOMIC
DECLARE cur CURSOR FOR SELECT 1 AS a FROM DUAL;
label1:
FOR rec IN cur
DO
SELECT rec.a;
END FOR;
label2:
FOR rec IN cur
DO
SELECT rec.a;
END FOR;
END;
$$
rec.a
1
rec.a
1
mysql-test/main/sp-cursor.test
View file @
9c53cbdd
...
...
@@ -607,3 +607,85 @@ END;
$$
DELIMITER
;
$$
DROP
TABLE
t1
;
--
echo
#
--
echo
# MDEV-15941 Explicit cursor FOR loop does not close the cursor
--
echo
#
DELIMITER
$$
;
--
error
ER_SP_CURSOR_NOT_OPEN
BEGIN
NOT
ATOMIC
DECLARE
v
INT
;
DECLARE
cur
CURSOR
FOR
SELECT
1
AS
a
FROM
DUAL
;
FOR
rec
IN
cur
DO
SELECT
rec
.
a
;
END
FOR
;
FETCH
cur
INTO
v
;
END
;
$$
DELIMITER
;
$$
DELIMITER
$$
;
--
error
ER_SP_CURSOR_NOT_OPEN
BEGIN
NOT
ATOMIC
DECLARE
v
INT
;
DECLARE
cur
CURSOR
FOR
SELECT
1
AS
a
FROM
DUAL
;
label
:
FOR
rec
IN
cur
DO
SELECT
rec
.
a
;
END
FOR
;
FETCH
cur
INTO
v
;
END
;
$$
DELIMITER
;
$$
DELIMITER
$$
;
--
error
ER_SP_CURSOR_ALREADY_OPEN
BEGIN
NOT
ATOMIC
DECLARE
cur
CURSOR
FOR
SELECT
1
AS
a
FROM
DUAL
;
OPEN
cur
;
FOR
rec
IN
cur
DO
SELECT
rec
.
a
;
END
FOR
;
END
;
$$
DELIMITER
;
$$
DELIMITER
$$
;
BEGIN
NOT
ATOMIC
DECLARE
cur
CURSOR
FOR
SELECT
1
AS
a
FROM
DUAL
;
FOR
rec
IN
cur
DO
SELECT
rec
.
a
;
END
FOR
;
FOR
rec
IN
cur
DO
SELECT
rec
.
a
;
END
FOR
;
END
;
$$
DELIMITER
;
$$
DELIMITER
$$
;
BEGIN
NOT
ATOMIC
DECLARE
cur
CURSOR
FOR
SELECT
1
AS
a
FROM
DUAL
;
label1
:
FOR
rec
IN
cur
DO
SELECT
rec
.
a
;
END
FOR
;
label2
:
FOR
rec
IN
cur
DO
SELECT
rec
.
a
;
END
FOR
;
END
;
$$
DELIMITER
;
$$
mysql-test/suite/compat/oracle/r/sp-code.result
View file @
9c53cbdd
...
...
@@ -1084,23 +1084,26 @@ Pos Instruction
10 stmt 0 "SELECT rec1.a, rec1.b"
11 cfetch cur1@1 rec1@0
12 jump 6
13 cursor_copy_struct cur0 rec0@1
14 copen cur0@0
15 cfetch cur0@0 rec0@1
16 jump_if_not 21(21) "cur0"%FOUND
17 set rec0.a@1["a"] 10
18 set rec0.b@1["b"] 'b0'
19 cfetch cur0@0 rec0@1
20 jump 16
21 cursor_copy_struct cur2 rec2@2
22 copen cur2@2
23 cfetch cur2@2 rec2@2
24 jump_if_not 29(29) "cur2"%FOUND
25 set rec2.a@2["a"] 10
26 set rec2.b@2["b"] 'b0'
27 cfetch cur2@2 rec2@2
28 jump 24
29 cpop 3
13 cclose cur1@1
14 cursor_copy_struct cur0 rec0@1
15 copen cur0@0
16 cfetch cur0@0 rec0@1
17 jump_if_not 22(22) "cur0"%FOUND
18 set rec0.a@1["a"] 10
19 set rec0.b@1["b"] 'b0'
20 cfetch cur0@0 rec0@1
21 jump 17
22 cclose cur0@0
23 cursor_copy_struct cur2 rec2@2
24 copen cur2@2
25 cfetch cur2@2 rec2@2
26 jump_if_not 31(31) "cur2"%FOUND
27 set rec2.a@2["a"] 10
28 set rec2.b@2["b"] 'b0'
29 cfetch cur2@2 rec2@2
30 jump 26
31 cclose cur2@2
32 cpop 3
DROP PROCEDURE p1;
CREATE PROCEDURE p1
AS
...
...
@@ -1137,14 +1140,14 @@ Pos Instruction
1 cursor_copy_struct cur0 rec0@0
2 copen cur0@0
3 cfetch cur0@0 rec0@0
4 jump_if_not
29(29
) "cur0"%FOUND
4 jump_if_not
31(31
) "cur0"%FOUND
5 cpush cur1@1
6 set rec0.a@0["a"] 11
7 set rec0.b@0["b"] 'b0'
8 cursor_copy_struct cur1 rec1@1
9 copen cur1@1
10 cfetch cur1@1 rec1@1
11 jump_if_not 2
6(26
) "cur1"%FOUND
11 jump_if_not 2
7(27
) "cur1"%FOUND
12 set rec1.a@1["a"] 11
13 set rec1.b@1["b"] 'b1'
14 cpush cur2@2
...
...
@@ -1156,13 +1159,16 @@ Pos Instruction
20 set rec2.b@2["b"] 'b2'
21 cfetch cur2@2 rec2@2
22 jump 18
23 cpop 1
24 cfetch cur1@1 rec1@1
25 jump 11
26 cpop 1
27 cfetch cur0@0 rec0@0
28 jump 4
29 cpop 1
23 cclose cur2@2
24 cpop 1
25 cfetch cur1@1 rec1@1
26 jump 11
27 cclose cur1@1
28 cpop 1
29 cfetch cur0@0 rec0@0
30 jump 4
31 cclose cur0@0
32 cpop 1
DROP PROCEDURE p1;
#
# MDEV-12098 sql_mode=ORACLE: Implicit cursor FOR loop
...
...
mysql-test/suite/compat/oracle/r/sp-cursor-rowtype.result
View file @
9c53cbdd
...
...
@@ -1331,6 +1331,93 @@ rec2.a rec2.b
DROP PROCEDURE p1;
DROP TABLE t1;
#
# MDEV-15941 Explicit cursor FOR loop does not close the cursor
#
DECLARE
CURSOR cur IS SELECT 1 AS a FROM DUAL;
v INT;
BEGIN
FOR rec IN cur
LOOP
NULL;
END LOOP;
FETCH cur INTO v;
END;
$$
ERROR 24000: Cursor is not open
DECLARE
CURSOR cur IS SELECT 1 AS a FROM DUAL;
v INT;
BEGIN
<<label>>
FOR rec IN cur
LOOP
NULL;
END LOOP label;
FETCH cur INTO v;
END;
$$
ERROR 24000: Cursor is not open
DECLARE
CURSOR cur IS SELECT 1 AS a FROM DUAL;
BEGIN
OPEN cur;
FOR rec IN cur
LOOP
NULL;
END LOOP;
END;
$$
ERROR 24000: Cursor is already open
DECLARE
CURSOR cur IS SELECT 1 AS a FROM DUAL;
BEGIN
FOR rec IN cur
LOOP
SELECT rec.a;
END LOOP;
SELECT cur%ISOPEN;
FOR rec IN cur
LOOP
SELECT rec.a;
END LOOP;
SELECT cur%ISOPEN;
END;
$$
rec.a
1
cur%ISOPEN
0
rec.a
1
cur%ISOPEN
0
DECLARE
CURSOR cur IS SELECT 1 AS a FROM DUAL;
BEGIN
<<label1>>
FOR rec IN cur
LOOP
SELECT rec.a;
END LOOP label1;
SELECT cur%ISOPEN;
<<label2>>
FOR rec IN cur
LOOP
SELECT rec.a;
END LOOP;
SELECT cur%ISOPEN;
END;
$$
rec.a
1
cur%ISOPEN
0
rec.a
1
cur%ISOPEN
0
#
# MDEV-14139 Anchored data types for variables
#
DECLARE
...
...
mysql-test/suite/compat/oracle/t/sp-cursor-rowtype.test
View file @
9c53cbdd
...
...
@@ -1424,6 +1424,98 @@ DROP PROCEDURE p1;
DROP
TABLE
t1
;
--
echo
#
--
echo
# MDEV-15941 Explicit cursor FOR loop does not close the cursor
--
echo
#
DELIMITER
$$
;
--
error
ER_SP_CURSOR_NOT_OPEN
DECLARE
CURSOR
cur
IS
SELECT
1
AS
a
FROM
DUAL
;
v
INT
;
BEGIN
FOR
rec
IN
cur
LOOP
NULL
;
END
LOOP
;
FETCH
cur
INTO
v
;
END
;
$$
DELIMITER
;
$$
DELIMITER
$$
;
--
error
ER_SP_CURSOR_NOT_OPEN
DECLARE
CURSOR
cur
IS
SELECT
1
AS
a
FROM
DUAL
;
v
INT
;
BEGIN
<<
label
>>
FOR
rec
IN
cur
LOOP
NULL
;
END
LOOP
label
;
FETCH
cur
INTO
v
;
END
;
$$
DELIMITER
;
$$
DELIMITER
$$
;
--
error
ER_SP_CURSOR_ALREADY_OPEN
DECLARE
CURSOR
cur
IS
SELECT
1
AS
a
FROM
DUAL
;
BEGIN
OPEN
cur
;
FOR
rec
IN
cur
LOOP
NULL
;
END
LOOP
;
END
;
$$
DELIMITER
;
$$
DELIMITER
$$
;
DECLARE
CURSOR
cur
IS
SELECT
1
AS
a
FROM
DUAL
;
BEGIN
FOR
rec
IN
cur
LOOP
SELECT
rec
.
a
;
END
LOOP
;
SELECT
cur
%
ISOPEN
;
FOR
rec
IN
cur
LOOP
SELECT
rec
.
a
;
END
LOOP
;
SELECT
cur
%
ISOPEN
;
END
;
$$
DELIMITER
;
$$
DELIMITER
$$
;
DECLARE
CURSOR
cur
IS
SELECT
1
AS
a
FROM
DUAL
;
BEGIN
<<
label1
>>
FOR
rec
IN
cur
LOOP
SELECT
rec
.
a
;
END
LOOP
label1
;
SELECT
cur
%
ISOPEN
;
<<
label2
>>
FOR
rec
IN
cur
LOOP
SELECT
rec
.
a
;
END
LOOP
;
SELECT
cur
%
ISOPEN
;
END
;
$$
DELIMITER
;
$$
--
echo
#
--
echo
# MDEV-14139 Anchored data types for variables
--
echo
#
...
...
sql/sql_lex.cc
View file @
9c53cbdd
...
...
@@ -5891,6 +5891,26 @@ bool LEX::sp_for_loop_cursor_finalize(THD *thd, const Lex_for_loop_st &loop)
return
sp_while_loop_finalize
(
thd
);
}
bool
LEX
::
sp_for_loop_outer_block_finalize
(
THD
*
thd
,
const
Lex_for_loop_st
&
loop
)
{
Lex_spblock
tmp
;
tmp
.
curs
=
MY_TEST
(
loop
.
m_implicit_cursor
);
if
(
unlikely
(
sp_block_finalize
(
thd
,
tmp
)))
// The outer DECLARE..BEGIN..END
return
true
;
if
(
!
loop
.
is_for_loop_explicit_cursor
())
return
false
;
/*
Explicit cursor FOR loop must close the cursor automatically.
Note, implicit cursor FOR loop does not need to close the cursor,
it's closed by sp_instr_cpop.
*/
sp_instr_cclose
*
ic
=
new
(
thd
->
mem_root
)
sp_instr_cclose
(
sphead
->
instructions
(),
spcont
,
loop
.
m_cursor_offset
);
return
ic
==
NULL
||
sphead
->
add_instr
(
ic
);
}
/***************************************************************************/
bool
LEX
::
sp_declare_cursor
(
THD
*
thd
,
const
LEX_CSTRING
*
name
,
...
...
sql/sql_lex.h
View file @
9c53cbdd
...
...
@@ -3802,6 +3802,7 @@ struct LEX: public Query_tables_list
sp_for_loop_cursor_finalize
(
thd
,
loop
)
:
sp_for_loop_intrange_finalize
(
thd
,
loop
);
}
bool
sp_for_loop_outer_block_finalize
(
THD
*
thd
,
const
Lex_for_loop_st
&
loop
);
/* End of FOR LOOP methods */
bool
add_signal_statement
(
THD
*
thd
,
const
class
sp_condition_value
*
value
);
...
...
sql/sql_yacc.yy
View file @
9c53cbdd
...
...
@@ -4729,9 +4729,7 @@ sp_labeled_control:
}
pop_sp_loop_label // The inner WHILE block
{
Lex_spblock tmp;
tmp.curs= MY_TEST($4.m_implicit_cursor);
if (unlikely(Lex->sp_block_finalize(thd, tmp))) // The outer DECLARE..BEGIN..END
if (unlikely(Lex->sp_for_loop_outer_block_finalize(thd, $4)))
MYSQL_YYABORT;
}
| sp_label REPEAT_SYM
...
...
@@ -4781,12 +4779,10 @@ sp_unlabeled_control:
sp_proc_stmts1
END FOR_SYM
{
Lex_spblock tmp;
tmp.curs= MY_TEST($3.m_implicit_cursor);
if (unlikely(Lex->sp_for_loop_finalize(thd, $3)))
MYSQL_YYABORT;
Lex->sp_pop_loop_empty_label(thd); // The inner WHILE block
if (unlikely(Lex->sp_
block_finalize(thd, tmp))) // The outer DECLARE..BEGIN..END
if (unlikely(Lex->sp_
for_loop_outer_block_finalize(thd, $3)))
MYSQL_YYABORT;
}
| REPEAT_SYM
...
...
sql/sql_yacc_ora.yy
View file @
9c53cbdd
...
...
@@ -4676,9 +4676,7 @@ sp_labeled_control:
}
pop_sp_loop_label // The inner WHILE block
{
Lex_spblock tmp;
tmp.curs= MY_TEST($4.m_implicit_cursor);
if (unlikely(Lex->sp_block_finalize(thd, tmp))) // The outer DECLARE..BEGIN..END
if (unlikely(Lex->sp_for_loop_outer_block_finalize(thd, $4)))
MYSQL_YYABORT;
}
| labels_declaration_oracle REPEAT_SYM
...
...
@@ -4728,12 +4726,10 @@ sp_unlabeled_control:
sp_proc_stmts1
END LOOP_SYM
{
Lex_spblock tmp;
tmp.curs= MY_TEST($3.m_implicit_cursor);
if (unlikely(Lex->sp_for_loop_finalize(thd, $3)))
MYSQL_YYABORT;
Lex->sp_pop_loop_empty_label(thd); // The inner WHILE block
if (unlikely(Lex->sp_
block_finalize(thd, tmp))) // The outer DECLARE..BEGIN..END
if (unlikely(Lex->sp_
for_loop_outer_block_finalize(thd, $3)))
MYSQL_YYABORT;
}
| REPEAT_SYM
...
...
sql/structs.h
View file @
9c53cbdd
...
...
@@ -720,6 +720,10 @@ struct Lex_for_loop_st
*
this
=
other
;
}
bool
is_for_loop_cursor
()
const
{
return
m_upper_bound
==
NULL
;
}
bool
is_for_loop_explicit_cursor
()
const
{
return
is_for_loop_cursor
()
&&
!
m_implicit_cursor
;
}
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment