1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

MDEV-12441 Variables declared after cursors with parameters lose values

Parse context frames (sp_pcontext) can have holes in variable run-time offsets,
the missing offsets reside on the children contexts in such cases.

Example:

  CREATE PROCEDURE p1() AS
    x0 INT:=100;        -- context 0, position 0, run-time 0
    CURSOR cur(
      p0 INT,           -- context 1, position 0, run-time 1
      p1 INT            -- context 1, position 1, run-time 2
    ) IS SELECT p0, p1;
    x1 INT:=101;        -- context 0, position 1, run-time 3
  BEGIN
    ...
  END;

Fixing a few methods to take this into account:
- sp_pcontext::find_variable()
- sp_pcontext::retrieve_field_definitions()
- LEX::sp_variable_declarations_init()
- LEX::sp_variable_declarations_finalize()
- LEX::sp_variable_declarations_rowtype_finalize()
- LEX::sp_variable_declarations_with_ref_finalize()

Adding a convenience method:

  sp_pcontext::get_last_context_variable(uint offset_from_the_end);

to access variables from the end, rather than from the beginning.
This helps to loop through the context variable array (m_vars)
on the fragment that does not have any holes.

Additionally, renaming sp_pcontext::find_context_variable() to
sp_pcontext::get_context_variable(). This method simply returns
the variable by its index. So let's rename to avoid assumptions
that some heavy lookup is going on inside.
This commit is contained in:
Alexander Barkov
2017-04-05 10:52:31 +04:00
parent d433277f53
commit e1cff0ac5d
9 changed files with 499 additions and 31 deletions

View File

@ -1348,3 +1348,136 @@ rec1.a
rec2.a
11
DROP PROCEDURE p1;
#
# MDEV-12441 Variables declared after cursors with parameters lose values
#
CREATE PROCEDURE p1() AS
x0 INT:=100;
CURSOR cur(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
x1 INT:=101;
BEGIN
OPEN cur(10,11);
CLOSE cur;
SELECT x0, x1;
END;
$$
SHOW PROCEDURE CODE p1;
Pos Instruction
0 set x0@0 100
1 set x1@3 101
2 cpush cur@0
3 set cp1@1 10
4 set cp2@2 11
5 copen cur@0
6 cclose cur@0
7 stmt 0 "SELECT x0, x1"
8 cpop 1
CALL p1();
x0 x1
100 101
DROP PROCEDURE p1;
CREATE PROCEDURE p1() AS
x0 INT:=100;
CURSOR cur0(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
x1 INT:=101;
CURSOR cur1(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
x2 INT:=102;
CURSOR cur2(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
x3 INT:=103;
BEGIN
OPEN cur0(0,1);
CLOSE cur0;
SELECT x0, x1, x2, x3;
OPEN cur1(10,11);
CLOSE cur1;
SELECT x0, x1, x2, x3;
OPEN cur2(20,21);
CLOSE cur2;
SELECT x0, x1, x2, x3;
END;
$$
SHOW PROCEDURE CODE p1;
Pos Instruction
0 set x0@0 100
1 set x1@3 101
2 set x2@6 102
3 set x3@9 103
4 cpush cur0@0
5 cpush cur1@1
6 cpush cur2@2
7 set cp1@1 0
8 set cp2@2 1
9 copen cur0@0
10 cclose cur0@0
11 stmt 0 "SELECT x0, x1, x2, x3"
12 set cp1@4 10
13 set cp2@5 11
14 copen cur1@1
15 cclose cur1@1
16 stmt 0 "SELECT x0, x1, x2, x3"
17 set cp1@7 20
18 set cp2@8 21
19 copen cur2@2
20 cclose cur2@2
21 stmt 0 "SELECT x0, x1, x2, x3"
22 cpop 3
CALL p1();
x0 x1 x2 x3
100 101 102 103
x0 x1 x2 x3
100 101 102 103
x0 x1 x2 x3
100 101 102 103
DROP PROCEDURE p1;
CREATE TABLE t1 (a INT);
CREATE PROCEDURE p1() AS
x0 INT:=100;
CURSOR cur(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
x1 t1.a%TYPE:=101;
BEGIN
OPEN cur(10,11);
CLOSE cur;
SELECT x0, x1;
END;
$$
SHOW PROCEDURE CODE p1;
Pos Instruction
0 set x0@0 100
1 set x1@3 101
2 cpush cur@0
3 set cp1@1 10
4 set cp2@2 11
5 copen cur@0
6 cclose cur@0
7 stmt 0 "SELECT x0, x1"
8 cpop 1
CALL p1();
x0 x1
100 101
DROP PROCEDURE p1;
DROP TABLE t1;
CREATE PROCEDURE p1() AS
x0 INT:=100;
CURSOR cur(cp1 INT, cp2 INT) IS SELECT cp1+cp2;
x1 ROW(a INT,b INT):=ROW(101,102);
BEGIN
OPEN cur(10,11);
CLOSE cur;
SELECT x0, x1.a, x1.b;
END;
$$
SHOW PROCEDURE CODE p1;
Pos Instruction
0 set x0@0 100
1 set x1@3 (101,102)
2 cpush cur@0
3 set cp1@1 10
4 set cp2@2 11
5 copen cur@0
6 cclose cur@0
7 stmt 0 "SELECT x0, x1.a, x1.b"
8 cpop 1
CALL p1();
x0 x1.a x1.b
100 101 102
DROP PROCEDURE p1;