MDEV-36047 Package body variables are not allowed as FETCH targets
It was not possible to use a package body variable as a fetch target: CREATE PACKAGE BODY pkg AS vc INT := 0; FUNCTION f1 RETURN INT AS CURSOR cur IS SELECT 1 AS c FROM DUAL; BEGIN OPEN cur; FETCH cur INTO vc; -- this returned "Undeclared variable: vc" error. CLOSE cur; RETURN vc; END; END; FETCH assumed that all fetch targets reside of the same sp_rcontext instance with the cursor. This patch fixes the problem. Now a cursor and its fetch target can reside in different sp_rcontext instances. Details: - Adding a helper class sp_rcontext_addr (a combination of Sp_rcontext_handler pointer and an offset in the rcontext) - Adding a new class sp_fetch_target deriving from sp_rcontext_addr. Fetch targets in "FETCH cur INTO target1, target2 ..." are now collected into this structure instead of sp_variable. sp_variable cannot be used any more to store fetch targets, because it does not have a pointer to Sp_rcontext_handler (it only has the current rcontext offset). - Removing members sp_instr_set members m_rcontext_handler and m_offset. Deriving sp_instr_set from sp_rcontext_addr instead. - Renaming sp_instr_cfetch member "List<sp_variable> m_varlist" to "List<sp_fetch_target> m_fetch_target_list". - Fixing LEX::sp_add_cfetch() to return the pointer to the created sp_fetch_target instance (instead of returning bool). This helps to make the grammar in sql_yacc.c simpler - Renaming LEX::sp_add_cfetch() to LEX::sp_add_instr_cfetch(), as `if(sp_add_cfetch())` changed its meaning to the opposite, to avoid automatic wrong merge from earlier versions. - Chaning the "List<sp_variable> *vars" parameter to sp_cursor::fetch to have the data type "List<sp_fetch_target> *". - Changing the data type of "List<sp_variable> &vars" in sp_cursor::Select_fetch_into_spvars::send_data_to_variable_list() to "List<sp_fetch_target> &". - Adding THD helper methods get_rcontext() and get_variable(). - Moving the code from sql_yacc.yy into a new LEX method LEX::make_fetch_target(). - Simplifying the grammar in sql_yacc.yy using the new LEX method. Changing the data type of the bison rule sp_fetch_list from "void" to "List<sp_fetch_target> *".
This commit is contained in:
parent
6be0940f10
commit
b7d67ceb5f
24
mysql-test/include/sp-cursor-pkg-01.inc
Normal file
24
mysql-test/include/sp-cursor-pkg-01.inc
Normal file
@ -0,0 +1,24 @@
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg
|
||||
FUNCTION f1() RETURNS INT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg
|
||||
DECLARE vc INT DEFAULT 0;
|
||||
FUNCTION f1() RETURNS INT
|
||||
BEGIN
|
||||
DECLARE cur CURSOR FOR SELECT 1 AS c FROM DUAL;
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc; -- SHOW CODE should display vc with a "PACKAGE_BODY" prefix
|
||||
CLOSE cur;
|
||||
RETURN vc;
|
||||
END;
|
||||
BEGIN
|
||||
DECLARE cur CURSOR FOR SELECT 1 AS c FROM DUAL;
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc; -- SHOW CODE should display vc without a prefix
|
||||
CLOSE cur;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
20
mysql-test/include/sp-cursor-pkg-02.inc
Normal file
20
mysql-test/include/sp-cursor-pkg-02.inc
Normal file
@ -0,0 +1,20 @@
|
||||
# Mixing a package body variable and a local variable in the same FETCH.
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg
|
||||
FUNCTION f1() RETURNS TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg
|
||||
DECLARE vc1 INT DEFAULT 0;
|
||||
FUNCTION f1() RETURNS TEXT
|
||||
BEGIN
|
||||
DECLARE vc2 INT DEFAULT 0;
|
||||
DECLARE cur CURSOR FOR SELECT 1 AS c1, 2 AS c2 FROM DUAL;
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc1, vc2;
|
||||
CLOSE cur;
|
||||
RETURN CONCAT(vc1, ' ', vc2);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
19
mysql-test/include/sp-cursor-pkg-03.inc
Normal file
19
mysql-test/include/sp-cursor-pkg-03.inc
Normal file
@ -0,0 +1,19 @@
|
||||
# Fetching into a PACKAGE BODY variable of the ROW type
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg
|
||||
FUNCTION f1() RETURNS TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg
|
||||
DECLARE vc ROW(p1 INT, p2 INT);
|
||||
FUNCTION f1() RETURNS TEXT
|
||||
BEGIN
|
||||
DECLARE cur CURSOR FOR SELECT 1 AS c1, 2 AS c2 FROM DUAL;
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc;
|
||||
CLOSE cur;
|
||||
RETURN CONCAT(vc.p1, ' ', vc.p2);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
@ -852,3 +852,75 @@ ERROR 42000: This version of MariaDB doesn't yet support 'OUT/INOUT cursor param
|
||||
#
|
||||
# End of 10.8 tests
|
||||
#
|
||||
# Start of 11.4 tests
|
||||
#
|
||||
# MDEV-36047 Package body variables are not allowed as FETCH targets
|
||||
#
|
||||
CREATE PACKAGE pkg
|
||||
FUNCTION f1() RETURNS INT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg
|
||||
DECLARE vc INT DEFAULT 0;
|
||||
FUNCTION f1() RETURNS INT
|
||||
BEGIN
|
||||
DECLARE cur CURSOR FOR SELECT 1 AS c FROM DUAL;
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc; -- SHOW CODE should display vc with a "PACKAGE_BODY" prefix
|
||||
CLOSE cur;
|
||||
RETURN vc;
|
||||
END;
|
||||
BEGIN
|
||||
DECLARE cur CURSOR FOR SELECT 1 AS c FROM DUAL;
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc; -- SHOW CODE should display vc without a prefix
|
||||
CLOSE cur;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
SELECT pkg.f1();
|
||||
pkg.f1()
|
||||
1
|
||||
DROP PACKAGE pkg;
|
||||
CREATE PACKAGE pkg
|
||||
FUNCTION f1() RETURNS TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg
|
||||
DECLARE vc1 INT DEFAULT 0;
|
||||
FUNCTION f1() RETURNS TEXT
|
||||
BEGIN
|
||||
DECLARE vc2 INT DEFAULT 0;
|
||||
DECLARE cur CURSOR FOR SELECT 1 AS c1, 2 AS c2 FROM DUAL;
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc1, vc2;
|
||||
CLOSE cur;
|
||||
RETURN CONCAT(vc1, ' ', vc2);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
SELECT pkg.f1();
|
||||
pkg.f1()
|
||||
1 2
|
||||
DROP PACKAGE pkg;
|
||||
CREATE PACKAGE pkg
|
||||
FUNCTION f1() RETURNS TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg
|
||||
DECLARE vc ROW(p1 INT, p2 INT);
|
||||
FUNCTION f1() RETURNS TEXT
|
||||
BEGIN
|
||||
DECLARE cur CURSOR FOR SELECT 1 AS c1, 2 AS c2 FROM DUAL;
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc;
|
||||
CLOSE cur;
|
||||
RETURN CONCAT(vc.p1, ' ', vc.p2);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
SELECT pkg.f1();
|
||||
pkg.f1()
|
||||
1 2
|
||||
DROP PACKAGE pkg;
|
||||
# End of 11.4 tests
|
||||
|
@ -872,3 +872,23 @@ DELIMITER ;$$
|
||||
--echo #
|
||||
--echo # End of 10.8 tests
|
||||
--echo #
|
||||
|
||||
--echo # Start of 11.4 tests
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-36047 Package body variables are not allowed as FETCH targets
|
||||
--echo #
|
||||
|
||||
--source include/sp-cursor-pkg-01.inc
|
||||
SELECT pkg.f1();
|
||||
DROP PACKAGE pkg;
|
||||
|
||||
--source include/sp-cursor-pkg-02.inc
|
||||
SELECT pkg.f1();
|
||||
DROP PACKAGE pkg;
|
||||
|
||||
--source include/sp-cursor-pkg-03.inc
|
||||
SELECT pkg.f1();
|
||||
DROP PACKAGE pkg;
|
||||
|
||||
--echo # End of 11.4 tests
|
||||
|
@ -258,3 +258,105 @@ Pos Instruction
|
||||
6 set a.a@0["a"] b.a@1["a"] + 1
|
||||
DROP PACKAGE pkg1;
|
||||
DROP TABLE t1;
|
||||
# Start of 11.4 tests
|
||||
#
|
||||
# MDEV-36047 Package body variables are not allowed as FETCH targets
|
||||
#
|
||||
CREATE PACKAGE pkg
|
||||
FUNCTION f1() RETURNS INT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg
|
||||
DECLARE vc INT DEFAULT 0;
|
||||
FUNCTION f1() RETURNS INT
|
||||
BEGIN
|
||||
DECLARE cur CURSOR FOR SELECT 1 AS c FROM DUAL;
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc; -- SHOW CODE should display vc with a "PACKAGE_BODY" prefix
|
||||
CLOSE cur;
|
||||
RETURN vc;
|
||||
END;
|
||||
BEGIN
|
||||
DECLARE cur CURSOR FOR SELECT 1 AS c FROM DUAL;
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc; -- SHOW CODE should display vc without a prefix
|
||||
CLOSE cur;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
pkg.f1()
|
||||
1
|
||||
SHOW FUNCTION CODE pkg.f1;
|
||||
Pos Instruction
|
||||
0 cpush cur@0
|
||||
1 copen cur@0
|
||||
2 cfetch cur@0 PACKAGE_BODY.vc@0
|
||||
3 cclose cur@0
|
||||
4 freturn int PACKAGE_BODY.vc@0
|
||||
SHOW PACKAGE BODY CODE pkg;
|
||||
Pos Instruction
|
||||
0 set vc@0 0
|
||||
1 cpush cur@0
|
||||
2 copen cur@0
|
||||
3 cfetch cur@0 vc@0
|
||||
4 cclose cur@0
|
||||
5 cpop 1
|
||||
DROP PACKAGE pkg;
|
||||
CREATE PACKAGE pkg
|
||||
FUNCTION f1() RETURNS TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg
|
||||
DECLARE vc1 INT DEFAULT 0;
|
||||
FUNCTION f1() RETURNS TEXT
|
||||
BEGIN
|
||||
DECLARE vc2 INT DEFAULT 0;
|
||||
DECLARE cur CURSOR FOR SELECT 1 AS c1, 2 AS c2 FROM DUAL;
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc1, vc2;
|
||||
CLOSE cur;
|
||||
RETURN CONCAT(vc1, ' ', vc2);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
pkg.f1()
|
||||
1 2
|
||||
SHOW FUNCTION CODE pkg.f1;
|
||||
Pos Instruction
|
||||
0 set vc2@0 0
|
||||
1 cpush cur@0
|
||||
2 copen cur@0
|
||||
3 cfetch cur@0 PACKAGE_BODY.vc1@0 vc2@0
|
||||
4 cclose cur@0
|
||||
5 freturn blob concat(PACKAGE_BODY.vc1@0,' ',vc2@0)
|
||||
DROP PACKAGE pkg;
|
||||
CREATE PACKAGE pkg
|
||||
FUNCTION f1() RETURNS TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg
|
||||
DECLARE vc ROW(p1 INT, p2 INT);
|
||||
FUNCTION f1() RETURNS TEXT
|
||||
BEGIN
|
||||
DECLARE cur CURSOR FOR SELECT 1 AS c1, 2 AS c2 FROM DUAL;
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc;
|
||||
CLOSE cur;
|
||||
RETURN CONCAT(vc.p1, ' ', vc.p2);
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
pkg.f1()
|
||||
1 2
|
||||
SHOW FUNCTION CODE pkg.f1;
|
||||
Pos Instruction
|
||||
0 cpush cur@0
|
||||
1 copen cur@0
|
||||
2 cfetch cur@0 PACKAGE_BODY.vc@0
|
||||
3 cclose cur@0
|
||||
4 freturn blob concat(PACKAGE_BODY.vc.p1@0[0],' ',PACKAGE_BODY.vc.p2@0[1])
|
||||
DROP PACKAGE pkg;
|
||||
# End of 11.4 tests
|
||||
|
@ -198,3 +198,26 @@ DROP PACKAGE pkg1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo # Start of 11.4 tests
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-36047 Package body variables are not allowed as FETCH targets
|
||||
--echo #
|
||||
|
||||
--source include/sp-cursor-pkg-01.inc
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
SHOW FUNCTION CODE pkg.f1;
|
||||
SHOW PACKAGE BODY CODE pkg;
|
||||
DROP PACKAGE pkg;
|
||||
|
||||
--source include/sp-cursor-pkg-02.inc
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
SHOW FUNCTION CODE pkg.f1;
|
||||
DROP PACKAGE pkg;
|
||||
|
||||
--source include/sp-cursor-pkg-03.inc
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
SHOW FUNCTION CODE pkg.f1;
|
||||
DROP PACKAGE pkg;
|
||||
|
||||
--echo # End of 11.4 tests
|
||||
|
@ -1020,3 +1020,77 @@ ERROR 42000: This version of MariaDB doesn't yet support 'OUT/INOUT cursor param
|
||||
#
|
||||
# End of 10.8 tests
|
||||
#
|
||||
# Start of 11.4 tests
|
||||
#
|
||||
# MDEV-36047 Package body variables are not allowed as FETCH targets
|
||||
#
|
||||
CREATE PACKAGE pkg AS
|
||||
FUNCTION f1 RETURN INT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg AS
|
||||
vc INT := 0;
|
||||
FUNCTION f1 RETURN INT AS
|
||||
CURSOR cur IS SELECT 1 AS c FROM DUAL;
|
||||
BEGIN
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc; -- SHOW CODE should display vc with a "PACKAGE_BODY" prefix
|
||||
CLOSE cur;
|
||||
RETURN vc;
|
||||
END;
|
||||
BEGIN
|
||||
DECLARE
|
||||
CURSOR cur IS SELECT 1 AS c FROM DUAL;
|
||||
BEGIN
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc; -- SHOW CODE should display vc without a prefix
|
||||
CLOSE cur;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
pkg.f1()
|
||||
1
|
||||
DROP PACKAGE pkg;
|
||||
CREATE PACKAGE pkg AS
|
||||
FUNCTION f1 RETURN TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg AS
|
||||
vc1 INT := 0;
|
||||
FUNCTION f1 RETURN TEXT AS
|
||||
CURSOR cur IS SELECT 1 AS c1, 2 AS c2 FROM DUAL;
|
||||
vc2 INT := 0;
|
||||
BEGIN
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc1, vc2;
|
||||
CLOSE cur;
|
||||
RETURN vc1 || ' ' || vc2;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
pkg.f1()
|
||||
1 2
|
||||
DROP PACKAGE pkg;
|
||||
CREATE PACKAGE pkg AS
|
||||
FUNCTION f1 RETURN TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg AS
|
||||
vc ROW(p1 INT, p2 INT);
|
||||
FUNCTION f1 RETURN TEXT AS
|
||||
CURSOR cur IS SELECT 1 AS c1, 2 AS c2 FROM DUAL;
|
||||
BEGIN
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc;
|
||||
CLOSE cur;
|
||||
RETURN vc.p1 || ' ' || vc.p2;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
pkg.f1()
|
||||
1 2
|
||||
DROP PACKAGE pkg;
|
||||
# End of 11.4 tests
|
||||
|
@ -243,3 +243,107 @@ Pos Instruction
|
||||
7 jump 11
|
||||
DROP PACKAGE pkg1;
|
||||
DROP TABLE t1;
|
||||
# Start of 11.4 tests
|
||||
#
|
||||
# MDEV-36047 Package body variables are not allowed as FETCH targets
|
||||
#
|
||||
CREATE PACKAGE pkg AS
|
||||
FUNCTION f1 RETURN INT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg AS
|
||||
vc INT := 0;
|
||||
FUNCTION f1 RETURN INT AS
|
||||
CURSOR cur IS SELECT 1 AS c FROM DUAL;
|
||||
BEGIN
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc; -- SHOW CODE should display vc with a "PACKAGE_BODY" prefix
|
||||
CLOSE cur;
|
||||
RETURN vc;
|
||||
END;
|
||||
BEGIN
|
||||
DECLARE
|
||||
CURSOR cur IS SELECT 1 AS c FROM DUAL;
|
||||
BEGIN
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc; -- SHOW CODE should display vc without a prefix
|
||||
CLOSE cur;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
pkg.f1()
|
||||
1
|
||||
SHOW FUNCTION CODE pkg.f1;
|
||||
Pos Instruction
|
||||
0 cpush cur@0
|
||||
1 copen cur@0
|
||||
2 cfetch cur@0 PACKAGE_BODY.vc@0
|
||||
3 cclose cur@0
|
||||
4 freturn int PACKAGE_BODY.vc@0
|
||||
SHOW PACKAGE BODY CODE pkg;
|
||||
Pos Instruction
|
||||
0 set vc@0 0
|
||||
1 cpush cur@0
|
||||
2 copen cur@0
|
||||
3 cfetch cur@0 vc@0
|
||||
4 cclose cur@0
|
||||
5 cpop 1
|
||||
DROP PACKAGE pkg;
|
||||
CREATE PACKAGE pkg AS
|
||||
FUNCTION f1 RETURN TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg AS
|
||||
vc1 INT := 0;
|
||||
FUNCTION f1 RETURN TEXT AS
|
||||
CURSOR cur IS SELECT 1 AS c1, 2 AS c2 FROM DUAL;
|
||||
vc2 INT := 0;
|
||||
BEGIN
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc1, vc2;
|
||||
CLOSE cur;
|
||||
RETURN vc1 || ' ' || vc2;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
pkg.f1()
|
||||
1 2
|
||||
SHOW FUNCTION CODE pkg.f1;
|
||||
Pos Instruction
|
||||
0 set vc2@0 0
|
||||
1 cpush cur@0
|
||||
2 copen cur@0
|
||||
3 cfetch cur@0 PACKAGE_BODY.vc1@0 vc2@0
|
||||
4 cclose cur@0
|
||||
5 freturn blob concat(concat(PACKAGE_BODY.vc1@0,' '),vc2@0)
|
||||
DROP PACKAGE pkg;
|
||||
CREATE PACKAGE pkg AS
|
||||
FUNCTION f1 RETURN TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg AS
|
||||
vc ROW(p1 INT, p2 INT);
|
||||
FUNCTION f1 RETURN TEXT AS
|
||||
CURSOR cur IS SELECT 1 AS c1, 2 AS c2 FROM DUAL;
|
||||
BEGIN
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc;
|
||||
CLOSE cur;
|
||||
RETURN vc.p1 || ' ' || vc.p2;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
pkg.f1()
|
||||
1 2
|
||||
SHOW FUNCTION CODE pkg.f1;
|
||||
Pos Instruction
|
||||
0 cpush cur@0
|
||||
1 copen cur@0
|
||||
2 cfetch cur@0 PACKAGE_BODY.vc@0
|
||||
3 cclose cur@0
|
||||
4 freturn blob concat(concat(PACKAGE_BODY.vc.p1@0[0],' '),PACKAGE_BODY.vc.p2@0[1])
|
||||
DROP PACKAGE pkg;
|
||||
# End of 11.4 tests
|
||||
|
26
mysql-test/suite/compat/oracle/t/sp-cursor-pkg-01.inc
Normal file
26
mysql-test/suite/compat/oracle/t/sp-cursor-pkg-01.inc
Normal file
@ -0,0 +1,26 @@
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg AS
|
||||
FUNCTION f1 RETURN INT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg AS
|
||||
vc INT := 0;
|
||||
FUNCTION f1 RETURN INT AS
|
||||
CURSOR cur IS SELECT 1 AS c FROM DUAL;
|
||||
BEGIN
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc; -- SHOW CODE should display vc with a "PACKAGE_BODY" prefix
|
||||
CLOSE cur;
|
||||
RETURN vc;
|
||||
END;
|
||||
BEGIN
|
||||
DECLARE
|
||||
CURSOR cur IS SELECT 1 AS c FROM DUAL;
|
||||
BEGIN
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc; -- SHOW CODE should display vc without a prefix
|
||||
CLOSE cur;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
20
mysql-test/suite/compat/oracle/t/sp-cursor-pkg-02.inc
Normal file
20
mysql-test/suite/compat/oracle/t/sp-cursor-pkg-02.inc
Normal file
@ -0,0 +1,20 @@
|
||||
# Mixing a package body variable and a local variable in the same FETCH.
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg AS
|
||||
FUNCTION f1 RETURN TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg AS
|
||||
vc1 INT := 0;
|
||||
FUNCTION f1 RETURN TEXT AS
|
||||
CURSOR cur IS SELECT 1 AS c1, 2 AS c2 FROM DUAL;
|
||||
vc2 INT := 0;
|
||||
BEGIN
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc1, vc2;
|
||||
CLOSE cur;
|
||||
RETURN vc1 || ' ' || vc2;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
19
mysql-test/suite/compat/oracle/t/sp-cursor-pkg-03.inc
Normal file
19
mysql-test/suite/compat/oracle/t/sp-cursor-pkg-03.inc
Normal file
@ -0,0 +1,19 @@
|
||||
# Fetching into a PACKAGE BODY variable of the ROW type
|
||||
DELIMITER $$;
|
||||
CREATE PACKAGE pkg AS
|
||||
FUNCTION f1 RETURN TEXT;
|
||||
END;
|
||||
$$
|
||||
CREATE PACKAGE BODY pkg AS
|
||||
vc ROW(p1 INT, p2 INT);
|
||||
FUNCTION f1 RETURN TEXT AS
|
||||
CURSOR cur IS SELECT 1 AS c1, 2 AS c2 FROM DUAL;
|
||||
BEGIN
|
||||
OPEN cur;
|
||||
FETCH cur INTO vc;
|
||||
CLOSE cur;
|
||||
RETURN vc.p1 || ' ' || vc.p2;
|
||||
END;
|
||||
END;
|
||||
$$
|
||||
DELIMITER ;$$
|
@ -1042,3 +1042,24 @@ DELIMITER ;$$
|
||||
--echo #
|
||||
--echo # End of 10.8 tests
|
||||
--echo #
|
||||
|
||||
|
||||
--echo # Start of 11.4 tests
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-36047 Package body variables are not allowed as FETCH targets
|
||||
--echo #
|
||||
|
||||
--source sp-cursor-pkg-01.inc
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
DROP PACKAGE pkg;
|
||||
|
||||
--source sp-cursor-pkg-02.inc
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
DROP PACKAGE pkg;
|
||||
|
||||
--source sp-cursor-pkg-03.inc
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
DROP PACKAGE pkg;
|
||||
|
||||
--echo # End of 11.4 tests
|
||||
|
@ -180,3 +180,28 @@ SHOW PROCEDURE CODE pkg1.p1;
|
||||
SHOW PACKAGE BODY CODE pkg1;
|
||||
DROP PACKAGE pkg1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo # Start of 11.4 tests
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-36047 Package body variables are not allowed as FETCH targets
|
||||
--echo #
|
||||
|
||||
--source sp-cursor-pkg-01.inc
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
SHOW FUNCTION CODE pkg.f1;
|
||||
SHOW PACKAGE BODY CODE pkg;
|
||||
DROP PACKAGE pkg;
|
||||
|
||||
--source sp-cursor-pkg-02.inc
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
SHOW FUNCTION CODE pkg.f1;
|
||||
DROP PACKAGE pkg;
|
||||
|
||||
--source sp-cursor-pkg-03.inc
|
||||
SELECT pkg.f1() FROM DUAL;
|
||||
SHOW FUNCTION CODE pkg.f1;
|
||||
DROP PACKAGE pkg;
|
||||
|
||||
--echo # End of 11.4 tests
|
||||
|
@ -3858,8 +3858,10 @@ bool sp_head::add_for_loop_open_cursor(THD *thd, sp_pcontext *spcont,
|
||||
spcont, coffset, false);
|
||||
if (instr_cfetch == NULL || add_instr(instr_cfetch))
|
||||
return true;
|
||||
instr_cfetch->add_to_varlist(index);
|
||||
return false;
|
||||
const sp_rcontext_addr raddr(&sp_rcontext_handler_local, index->offset);
|
||||
sp_fetch_target *target=
|
||||
new (thd->mem_root) sp_fetch_target(index->name, raddr);
|
||||
return !target || instr_cfetch->add_to_fetch_target_list(target);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1923,7 +1923,7 @@ sp_instr_cfetch::execute(THD *thd, uint *nextp)
|
||||
Query_arena backup_arena;
|
||||
DBUG_ENTER("sp_instr_cfetch::execute");
|
||||
|
||||
res= c ? c->fetch(thd, &m_varlist, m_error_on_no_data) : -1;
|
||||
res= c ? c->fetch(thd, &m_fetch_target_list, m_error_on_no_data) : -1;
|
||||
|
||||
*nextp= m_ip+1;
|
||||
DBUG_RETURN(res);
|
||||
@ -1933,8 +1933,8 @@ sp_instr_cfetch::execute(THD *thd, uint *nextp)
|
||||
void
|
||||
sp_instr_cfetch::print(String *str)
|
||||
{
|
||||
List_iterator_fast<sp_variable> li(m_varlist);
|
||||
sp_variable *pv;
|
||||
List_iterator_fast<sp_fetch_target> li(m_fetch_target_list);
|
||||
sp_fetch_target *pv;
|
||||
const LEX_CSTRING *cursor_name= m_ctx->find_cursor(m_cursor);
|
||||
|
||||
/* cfetch name@offset vars... */
|
||||
@ -1953,12 +1953,14 @@ sp_instr_cfetch::print(String *str)
|
||||
str->qs_append(m_cursor);
|
||||
while ((pv= li++))
|
||||
{
|
||||
if (str->reserve(pv->name.length+SP_INSTR_UINT_MAXLEN+2))
|
||||
const LEX_CSTRING *prefix= pv->rcontext_handler()->get_name_prefix();
|
||||
if (str->reserve(pv->name.length+prefix->length+SP_INSTR_UINT_MAXLEN+2))
|
||||
return;
|
||||
str->qs_append(' ');
|
||||
str->qs_append(prefix);
|
||||
str->qs_append(&pv->name);
|
||||
str->qs_append('@');
|
||||
str->qs_append(pv->offset);
|
||||
str->qs_append(pv->offset());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -591,7 +591,8 @@ public:
|
||||
}; // class sp_instr_stmt : public sp_lex_instr
|
||||
|
||||
|
||||
class sp_instr_set : public sp_lex_instr
|
||||
class sp_instr_set : public sp_lex_instr,
|
||||
public sp_rcontext_addr
|
||||
{
|
||||
sp_instr_set(const sp_instr_set &); /**< Prevent use of these */
|
||||
void operator=(sp_instr_set &);
|
||||
@ -603,8 +604,7 @@ public:
|
||||
LEX *lex, bool lex_resp,
|
||||
const LEX_CSTRING &expr_str)
|
||||
: sp_lex_instr(ip, ctx, lex, lex_resp),
|
||||
m_rcontext_handler(rh),
|
||||
m_offset(offset),
|
||||
sp_rcontext_addr(rh, offset),
|
||||
m_value(val),
|
||||
m_expr_str(expr_str)
|
||||
{}
|
||||
@ -651,8 +651,6 @@ protected:
|
||||
}
|
||||
|
||||
sp_rcontext *get_rcontext(THD *thd) const;
|
||||
const Sp_rcontext_handler *m_rcontext_handler;
|
||||
uint m_offset; ///< Frame offset
|
||||
Item *m_value;
|
||||
|
||||
private:
|
||||
@ -1490,7 +1488,7 @@ public:
|
||||
m_cursor(c),
|
||||
m_error_on_no_data(error_on_no_data)
|
||||
{
|
||||
m_varlist.empty();
|
||||
m_fetch_target_list.empty();
|
||||
}
|
||||
|
||||
virtual ~sp_instr_cfetch() = default;
|
||||
@ -1499,14 +1497,19 @@ public:
|
||||
|
||||
void print(String *str) override;
|
||||
|
||||
void add_to_varlist(sp_variable *var)
|
||||
bool add_to_fetch_target_list(sp_fetch_target *target)
|
||||
{
|
||||
m_varlist.push_back(var);
|
||||
return m_fetch_target_list.push_back(target);
|
||||
}
|
||||
|
||||
void set_fetch_target_list(List<sp_fetch_target> *list)
|
||||
{
|
||||
m_fetch_target_list= *list;
|
||||
}
|
||||
|
||||
private:
|
||||
uint m_cursor;
|
||||
List<sp_variable> m_varlist;
|
||||
List<sp_fetch_target> m_fetch_target_list;
|
||||
bool m_error_on_no_data;
|
||||
|
||||
public:
|
||||
|
@ -87,6 +87,27 @@ public:
|
||||
uint *row_field_offset);
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
This class stores FETCH statement target variables:
|
||||
FETCH cur INTO t1, t2, t2;
|
||||
Targets can be:
|
||||
- Local SP variables
|
||||
- PACKAGE BODY variables
|
||||
*/
|
||||
class sp_fetch_target: public Sql_alloc,
|
||||
public sp_rcontext_addr
|
||||
{
|
||||
public:
|
||||
LEX_CSTRING name;
|
||||
|
||||
sp_fetch_target(const LEX_CSTRING &name_arg, const sp_rcontext_addr &addr)
|
||||
:sp_rcontext_addr(addr),
|
||||
name(name_arg)
|
||||
{ }
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// This class represents an SQL/PSM label. Can refer to the identifier
|
||||
|
@ -788,7 +788,8 @@ void sp_cursor::destroy()
|
||||
}
|
||||
|
||||
|
||||
int sp_cursor::fetch(THD *thd, List<sp_variable> *vars, bool error_on_no_data)
|
||||
int sp_cursor::fetch(THD *thd, List<sp_fetch_target> *vars,
|
||||
bool error_on_no_data)
|
||||
{
|
||||
if (! server_side_cursor)
|
||||
{
|
||||
@ -798,8 +799,7 @@ int sp_cursor::fetch(THD *thd, List<sp_variable> *vars, bool error_on_no_data)
|
||||
}
|
||||
if (vars->elements != result.get_field_count() &&
|
||||
(vars->elements != 1 ||
|
||||
result.get_field_count() !=
|
||||
thd->spcont->get_variable(vars->head()->offset)->cols()))
|
||||
result.get_field_count() != thd->get_variable(*vars->head())->cols()))
|
||||
{
|
||||
my_message(ER_SP_WRONG_NO_OF_FETCH_ARGS,
|
||||
ER_THD(thd, ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0));
|
||||
@ -866,11 +866,12 @@ int sp_cursor::Select_fetch_into_spvars::prepare(List<Item> &fields,
|
||||
|
||||
|
||||
bool sp_cursor::Select_fetch_into_spvars::
|
||||
send_data_to_variable_list(List<sp_variable> &vars, List<Item> &items)
|
||||
send_data_to_variable_list(List<sp_fetch_target> &vars,
|
||||
List<Item> &items)
|
||||
{
|
||||
List_iterator_fast<sp_variable> spvar_iter(vars);
|
||||
List_iterator_fast<sp_fetch_target> spvar_iter(vars);
|
||||
List_iterator_fast<Item> item_iter(items);
|
||||
sp_variable *spvar;
|
||||
sp_fetch_target *spvar;
|
||||
Item *item;
|
||||
|
||||
/* Must be ensured by the caller */
|
||||
@ -882,7 +883,7 @@ bool sp_cursor::Select_fetch_into_spvars::
|
||||
*/
|
||||
for (; spvar= spvar_iter++, item= item_iter++; )
|
||||
{
|
||||
if (thd->spcont->set_variable(thd, spvar->offset, &item))
|
||||
if (thd->get_rcontext(*spvar)->set_variable(thd, spvar->offset(), &item))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -891,7 +892,6 @@ bool sp_cursor::Select_fetch_into_spvars::
|
||||
|
||||
int sp_cursor::Select_fetch_into_spvars::send_data(List<Item> &items)
|
||||
{
|
||||
Item *item;
|
||||
/*
|
||||
If we have only one variable in spvar_list, and this is a ROW variable,
|
||||
and the number of fields in the ROW variable matches the number of
|
||||
@ -902,10 +902,15 @@ int sp_cursor::Select_fetch_into_spvars::send_data(List<Item> &items)
|
||||
we go through send_data_to_variable_list(). It will report an error
|
||||
on attempt to assign a scalar value to a ROW variable.
|
||||
*/
|
||||
return spvar_list->elements == 1 &&
|
||||
(item= thd->spcont->get_variable(spvar_list->head()->offset)) &&
|
||||
if (m_fetch_target_list->elements == 1)
|
||||
{
|
||||
const sp_fetch_target *target= m_fetch_target_list->head();
|
||||
sp_rcontext *rctx= thd->get_rcontext(*target);
|
||||
Item *item;
|
||||
if ((item= rctx->get_variable(target->offset())) &&
|
||||
item->type_handler() == &type_handler_row &&
|
||||
item->cols() == items.elements ?
|
||||
thd->spcont->set_variable_row(thd, spvar_list->head()->offset, items) :
|
||||
send_data_to_variable_list(*spvar_list, items);
|
||||
item->cols() == items.elements)
|
||||
return rctx->set_variable_row(thd, target->offset(), items);
|
||||
}
|
||||
return send_data_to_variable_list(*m_fetch_target_list, items);
|
||||
}
|
||||
|
@ -4435,6 +4435,18 @@ bool my_var_sp_row_field::set(THD *thd, Item *item)
|
||||
}
|
||||
|
||||
|
||||
sp_rcontext *THD::get_rcontext(const sp_rcontext_addr &addr)
|
||||
{
|
||||
return addr.rcontext_handler()->get_rcontext(spcont);
|
||||
}
|
||||
|
||||
|
||||
Item_field *THD::get_variable(const sp_rcontext_addr &addr)
|
||||
{
|
||||
return get_rcontext(addr)->get_variable(addr.offset());
|
||||
}
|
||||
|
||||
|
||||
bool select_dumpvar::send_data_to_var_list(List<Item> &items)
|
||||
{
|
||||
DBUG_ENTER("select_dumpvar::send_data_to_var_list");
|
||||
|
@ -3985,6 +3985,9 @@ public:
|
||||
|
||||
sp_rcontext *spcont; // SP runtime context
|
||||
|
||||
sp_rcontext *get_rcontext(const sp_rcontext_addr &addr);
|
||||
Item_field *get_variable(const sp_rcontext_addr &addr);
|
||||
|
||||
/** number of name_const() substitutions, see sp_head.cc:subst_spvars() */
|
||||
uint query_name_consts;
|
||||
|
||||
@ -6330,10 +6333,11 @@ private:
|
||||
/// FETCH <cname> INTO <varlist>.
|
||||
class Select_fetch_into_spvars: public select_result_interceptor
|
||||
{
|
||||
List<sp_variable> *spvar_list;
|
||||
List<sp_fetch_target> *m_fetch_target_list;
|
||||
uint field_count;
|
||||
bool m_view_structure_only;
|
||||
bool send_data_to_variable_list(List<sp_variable> &vars, List<Item> &items);
|
||||
bool send_data_to_variable_list(List<sp_fetch_target> &vars,
|
||||
List<Item> &items);
|
||||
public:
|
||||
Select_fetch_into_spvars(THD *thd_arg, bool view_structure_only)
|
||||
:select_result_interceptor(thd_arg),
|
||||
@ -6342,11 +6346,14 @@ private:
|
||||
void reset(THD *thd_arg)
|
||||
{
|
||||
select_result_interceptor::reinit(thd_arg);
|
||||
spvar_list= NULL;
|
||||
m_fetch_target_list= NULL;
|
||||
field_count= 0;
|
||||
}
|
||||
uint get_field_count() { return field_count; }
|
||||
void set_spvar_list(List<sp_variable> *vars) { spvar_list= vars; }
|
||||
void set_spvar_list(List<sp_fetch_target> *vars)
|
||||
{
|
||||
m_fetch_target_list= vars;
|
||||
}
|
||||
|
||||
bool send_eof() override { return FALSE; }
|
||||
int send_data(List<Item> &items) override;
|
||||
@ -6376,7 +6383,7 @@ public:
|
||||
my_bool is_open()
|
||||
{ return MY_TEST(server_side_cursor); }
|
||||
|
||||
int fetch(THD *, List<sp_variable> *vars, bool error_on_no_data);
|
||||
int fetch(THD *, List<sp_fetch_target> *vars, bool error_on_no_data);
|
||||
|
||||
bool export_structure(THD *thd, Row_definition_list *list);
|
||||
|
||||
|
@ -6556,6 +6556,21 @@ LEX::find_variable(const LEX_CSTRING *name,
|
||||
}
|
||||
|
||||
|
||||
sp_fetch_target *LEX::make_fetch_target(THD *thd, const Lex_ident_sys_st &name)
|
||||
{
|
||||
sp_pcontext *spc;
|
||||
const Sp_rcontext_handler *rha;
|
||||
sp_variable *spv= find_variable(&name, &spc, &rha);
|
||||
if (unlikely(!spv))
|
||||
{
|
||||
my_error(ER_SP_UNDECLARED_VAR, MYF(0), name.str);
|
||||
return nullptr;
|
||||
}
|
||||
return new (thd->mem_root) sp_fetch_target(name,
|
||||
sp_rcontext_addr(rha, spv->offset));
|
||||
}
|
||||
|
||||
|
||||
static bool is_new(const char *str)
|
||||
{
|
||||
return (str[0] == 'n' || str[0] == 'N') &&
|
||||
@ -7234,8 +7249,11 @@ bool LEX::sp_for_loop_cursor_iterate(THD *thd, const Lex_for_loop_st &loop)
|
||||
spcont, loop.m_cursor_offset, false);
|
||||
if (unlikely(instr == NULL) || unlikely(sphead->add_instr(instr)))
|
||||
return true;
|
||||
instr->add_to_varlist(loop.m_index);
|
||||
return false;
|
||||
const sp_rcontext_addr raddr(&sp_rcontext_handler_local,
|
||||
loop.m_index->offset);
|
||||
sp_fetch_target *trg=
|
||||
new (thd->mem_root) sp_fetch_target(loop.m_index->name, raddr);
|
||||
return !trg || instr->add_to_fetch_target_list(trg);
|
||||
}
|
||||
|
||||
|
||||
@ -9321,7 +9339,7 @@ int set_statement_var_if_exists(THD *thd, const char *var_name,
|
||||
}
|
||||
|
||||
|
||||
bool LEX::sp_add_cfetch(THD *thd, const LEX_CSTRING *name)
|
||||
sp_instr_cfetch *LEX::sp_add_instr_cfetch(THD *thd, const LEX_CSTRING *name)
|
||||
{
|
||||
uint offset;
|
||||
sp_instr_cfetch *i;
|
||||
@ -9329,14 +9347,14 @@ bool LEX::sp_add_cfetch(THD *thd, const LEX_CSTRING *name)
|
||||
if (!spcont->find_cursor(name, &offset, false))
|
||||
{
|
||||
my_error(ER_SP_CURSOR_MISMATCH, MYF(0), name->str);
|
||||
return true;
|
||||
return nullptr;
|
||||
}
|
||||
i= new (thd->mem_root)
|
||||
sp_instr_cfetch(sphead->instructions(), spcont, offset,
|
||||
!(thd->variables.sql_mode & MODE_ORACLE));
|
||||
if (unlikely(i == NULL) || unlikely(sphead->add_instr(i)))
|
||||
return true;
|
||||
return false;
|
||||
return nullptr;
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
|
@ -294,8 +294,10 @@ class LEX_COLUMN;
|
||||
class sp_head;
|
||||
class sp_name;
|
||||
class sp_instr;
|
||||
class sp_instr_cfetch;
|
||||
class sp_pcontext;
|
||||
class sp_variable;
|
||||
class sp_fetch_target;
|
||||
class sp_expr_lex;
|
||||
class sp_assignment_lex;
|
||||
class partition_info;
|
||||
@ -3994,6 +3996,7 @@ public:
|
||||
sp_pcontext *not_used_ctx;
|
||||
return find_variable(name, ¬_used_ctx, rh);
|
||||
}
|
||||
sp_fetch_target *make_fetch_target(THD *thd, const Lex_ident_sys_st &name);
|
||||
bool set_variable(const Lex_ident_sys_st *name, Item *item,
|
||||
const LEX_CSTRING &expr_str);
|
||||
bool set_variable(const Lex_ident_sys_st *name1,
|
||||
@ -4611,7 +4614,7 @@ public:
|
||||
create_info.add(options);
|
||||
return check_create_options(create_info);
|
||||
}
|
||||
bool sp_add_cfetch(THD *thd, const LEX_CSTRING *name);
|
||||
sp_instr_cfetch *sp_add_instr_cfetch(THD *thd, const LEX_CSTRING *name);
|
||||
bool sp_add_agg_cfetch();
|
||||
|
||||
bool set_command_with_check(enum_sql_command command,
|
||||
|
@ -253,6 +253,7 @@ void _CONCAT_UNDERSCORED(turn_parser_debug_on,yyparse)()
|
||||
Item_basic_constant *item_basic_constant;
|
||||
Key_part_spec *key_part;
|
||||
LEX *lex;
|
||||
sp_instr_cfetch *instr_cfetch;
|
||||
sp_expr_lex *expr_lex;
|
||||
sp_assignment_lex *assignment_lex;
|
||||
class sp_lex_cursor *sp_cursor_stmt;
|
||||
@ -266,6 +267,7 @@ void _CONCAT_UNDERSCORED(turn_parser_debug_on,yyparse)()
|
||||
List<Statement_information_item> *stmt_info_list;
|
||||
List<String> *string_list;
|
||||
List<Lex_ident_sys> *ident_sys_list;
|
||||
List<sp_fetch_target> *fetch_target_list;
|
||||
Statement_information_item *stmt_info_item;
|
||||
String *string;
|
||||
TABLE_LIST *table_list;
|
||||
@ -1566,6 +1568,12 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
|
||||
sp_cursor_stmt_lex
|
||||
sp_cursor_stmt
|
||||
|
||||
%type <instr_cfetch>
|
||||
sp_proc_stmt_fetch_head
|
||||
|
||||
%type <fetch_target_list>
|
||||
sp_fetch_list
|
||||
|
||||
%type <expr_lex>
|
||||
expr_lex
|
||||
|
||||
@ -4146,23 +4154,26 @@ sp_proc_stmt_open:
|
||||
sp_proc_stmt_fetch_head:
|
||||
FETCH_SYM ident INTO
|
||||
{
|
||||
if (unlikely(Lex->sp_add_cfetch(thd, &$2)))
|
||||
if (unlikely(!($$= Lex->sp_add_instr_cfetch(thd, &$2))))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| FETCH_SYM FROM ident INTO
|
||||
{
|
||||
if (unlikely(Lex->sp_add_cfetch(thd, &$3)))
|
||||
if (unlikely(!($$= Lex->sp_add_instr_cfetch(thd, &$3))))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| FETCH_SYM NEXT_SYM FROM ident INTO
|
||||
{
|
||||
if (unlikely(Lex->sp_add_cfetch(thd, &$4)))
|
||||
if (unlikely(!($$= Lex->sp_add_instr_cfetch(thd, &$4))))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
sp_proc_stmt_fetch:
|
||||
sp_proc_stmt_fetch_head sp_fetch_list { }
|
||||
sp_proc_stmt_fetch_head sp_fetch_list
|
||||
{
|
||||
$1->set_fetch_target_list($2);
|
||||
}
|
||||
| FETCH_SYM GROUP_SYM NEXT_SYM ROW_SYM
|
||||
{
|
||||
if (unlikely(Lex->sp_add_agg_cfetch()))
|
||||
@ -4191,35 +4202,16 @@ sp_proc_stmt_close:
|
||||
sp_fetch_list:
|
||||
ident
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp= lex->sphead;
|
||||
sp_pcontext *spc= lex->spcont;
|
||||
sp_variable *spv= likely(spc != NULL)
|
||||
? spc->find_variable(&$1, false)
|
||||
: NULL;
|
||||
|
||||
if (unlikely(!spv))
|
||||
my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
|
||||
|
||||
/* An SP local variable */
|
||||
sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
|
||||
i->add_to_varlist(spv);
|
||||
sp_fetch_target *target= Lex->make_fetch_target(thd, $1);
|
||||
if (!target ||
|
||||
!($$= List<sp_fetch_target>::make(thd->mem_root, target)))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| sp_fetch_list ',' ident
|
||||
{
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp= lex->sphead;
|
||||
sp_pcontext *spc= lex->spcont;
|
||||
sp_variable *spv= likely(spc != NULL)
|
||||
? spc->find_variable(&$3, false)
|
||||
: NULL;
|
||||
|
||||
if (unlikely(!spv))
|
||||
my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $3.str));
|
||||
|
||||
/* An SP local variable */
|
||||
sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction();
|
||||
i->add_to_varlist(spv);
|
||||
sp_fetch_target *target= Lex->make_fetch_target(thd, $3);
|
||||
if (!target || $1->push_back(target, thd->mem_root))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -1060,4 +1060,29 @@ public:
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
A run-time address of an SP variable. Consists of:
|
||||
- The rcontext type (LOCAL, PACKAGE BODY),
|
||||
controlled by m_rcontext_handler
|
||||
- The frame offset
|
||||
*/
|
||||
class sp_rcontext_addr
|
||||
{
|
||||
public:
|
||||
sp_rcontext_addr(const class Sp_rcontext_handler *h, uint offset)
|
||||
:m_rcontext_handler(h), m_offset(offset)
|
||||
{ }
|
||||
const Sp_rcontext_handler *rcontext_handler() const
|
||||
{
|
||||
return m_rcontext_handler;
|
||||
}
|
||||
uint offset() const
|
||||
{
|
||||
return m_offset;
|
||||
}
|
||||
protected:
|
||||
const class Sp_rcontext_handler *m_rcontext_handler;
|
||||
uint m_offset; ///< Frame offset
|
||||
};
|
||||
|
||||
#endif /* STRUCTS_INCLUDED */
|
||||
|
Loading…
x
Reference in New Issue
Block a user