summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2021-11-26 06:56:04 +0400
committerAlexander Barkov <bar@mariadb.com>2021-12-16 04:06:54 +0400
commitaff084d139a9fca9d569fedd9ec80bd9576614b1 (patch)
tree41ca142e1c5692c5684b38ffcd9d91970acd1337
parent5d23c67d37e822a994b32990ec1ac57af5896120 (diff)
downloadmariadb-git-preview-10.8-MDEV-10654-inout-params.tar.gz
A clean-up for MDEV-10654 add support IN, OUT, INOUT parameter qualifiers for stored functionspreview-10.8-MDEV-10654-inout-params
Changes: 1. Enabling IN/OUT/INOUT mode for sql_mode=DEFAULT, adding tests for sql_mode=DEFAULT based by mostly translating compat/oracle.sp-inout.test to SQL/PSM with minor changes (e.g. testing trigger OLD.column and NEW.column as IN/OUT parameters). 2. Removing duplicate grammar: sp_pdparam and sp_fdparam implemented exactly the same syntax after - the first patch for MDEV-10654 (for sql_mode=ORACLE) - the change #1 from this patch (for sql_mode=DEFAULT) Removing separate rules and adding a single "sp_param" rule instead, which now covers both PRDEDURE and FUNCTION parameters (and CURSOR parameters as well!). 3. Adding a helper rule sp_param_name_and_mode, which is a combination of the parameter name and the IN/OUT/INOUT mode. It allows to simplify the grammer a bit. 4. The first patch unintentionally allowed IN/OUT/INOUT mode to be specified in CURSOR parameters. This is good for the IN keyword - it is allowed in PL/SQL CURSORs. This is not good the the OUT/INOUT keywords - they should not be allowed. Adding a additional symantic post-check.
-rw-r--r--mysql-test/main/sp-cursor.result40
-rw-r--r--mysql-test/main/sp-cursor.test51
-rw-r--r--mysql-test/main/sp-inout.result2033
-rw-r--r--mysql-test/main/sp-inout.test1964
-rw-r--r--mysql-test/suite/compat/oracle/r/sp-cursor.result43
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-cursor.test55
-rw-r--r--sql/sql_lex.cc21
-rw-r--r--sql/sql_yacc.yy128
8 files changed, 4254 insertions, 81 deletions
diff --git a/mysql-test/main/sp-cursor.result b/mysql-test/main/sp-cursor.result
index 110ae7be03a..dc38ad64069 100644
--- a/mysql-test/main/sp-cursor.result
+++ b/mysql-test/main/sp-cursor.result
@@ -737,3 +737,43 @@ rec.en1
c
DROP PROCEDURE p1;
DROP TABLE t1;
+#
+# Start of 10.8 tests
+#
+#
+# MDEV-10654 IN, OUT, INOUT parameters in CREATE FUNCTION
+#
+BEGIN NOT ATOMIC
+DECLARE va INT;
+DECLARE cur CURSOR (IN a INT) FOR SELECT a FROM dual;
+OPEN cur(1);
+FETCH cur INTO va;
+CLOSE cur;
+SELECT va;
+END;
+$$
+va
+1
+BEGIN NOT ATOMIC
+DECLARE va INT;
+DECLARE cur CURSOR (OUT a INT) FOR SELECT a FROM dual;
+OPEN cur(1);
+FETCH cur INTO va;
+CLOSE cur;
+SELECT va;
+END;
+$$
+ERROR 42000: This version of MariaDB doesn't yet support 'OUT/INOUT cursor parameter'
+BEGIN NOT ATOMIC
+DECLARE va INT;
+DECLARE cur CURSOR (INOUT a INT) FOR SELECT a FROM dual;
+OPEN cur(1);
+FETCH cur INTO va;
+CLOSE cur;
+SELECT va;
+END;
+$$
+ERROR 42000: This version of MariaDB doesn't yet support 'OUT/INOUT cursor parameter'
+#
+# End of 10.8 tests
+#
diff --git a/mysql-test/main/sp-cursor.test b/mysql-test/main/sp-cursor.test
index 97483ef9caf..f86721f41e8 100644
--- a/mysql-test/main/sp-cursor.test
+++ b/mysql-test/main/sp-cursor.test
@@ -744,3 +744,54 @@ DELIMITER ;$$
CALL p1();
DROP PROCEDURE p1;
DROP TABLE t1;
+
+
+--echo #
+--echo # Start of 10.8 tests
+--echo #
+
+--echo #
+--echo # MDEV-10654 IN, OUT, INOUT parameters in CREATE FUNCTION
+--echo #
+
+DELIMITER $$;
+BEGIN NOT ATOMIC
+ DECLARE va INT;
+ DECLARE cur CURSOR (IN a INT) FOR SELECT a FROM dual;
+ OPEN cur(1);
+ FETCH cur INTO va;
+ CLOSE cur;
+ SELECT va;
+END;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--error ER_NOT_SUPPORTED_YET
+BEGIN NOT ATOMIC
+ DECLARE va INT;
+ DECLARE cur CURSOR (OUT a INT) FOR SELECT a FROM dual;
+ OPEN cur(1);
+ FETCH cur INTO va;
+ CLOSE cur;
+ SELECT va;
+END;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--error ER_NOT_SUPPORTED_YET
+BEGIN NOT ATOMIC
+ DECLARE va INT;
+ DECLARE cur CURSOR (INOUT a INT) FOR SELECT a FROM dual;
+ OPEN cur(1);
+ FETCH cur INTO va;
+ CLOSE cur;
+ SELECT va;
+END;
+$$
+DELIMITER ;$$
+
+--echo #
+--echo # End of 10.8 tests
+--echo #
diff --git a/mysql-test/main/sp-inout.result b/mysql-test/main/sp-inout.result
new file mode 100644
index 00000000000..a1e7ffa9799
--- /dev/null
+++ b/mysql-test/main/sp-inout.result
@@ -0,0 +1,2033 @@
+#
+# MDEV-10654 IN, OUT, INOUT parameters in CREATE FUNCTION
+#
+#
+# CREATE FUNCTION with IN, OUT, INOUT qualifiers
+# SHOW CREATE FUNCTION
+#
+CREATE FUNCTION add_func(IN a INT, IN b INT, OUT c INT, INOUT d INT) RETURNS INT
+BEGIN
+SET c= 100;
+SET d= d + 1;
+RETURN a + b;
+END;
+$$
+SHOW CREATE FUNCTION add_func;
+Function sql_mode Create Function character_set_client collation_connection Database Collation
+add_func STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` FUNCTION `add_func`(IN a INT, IN b INT, OUT c INT, INOUT d INT) RETURNS int(11)
+BEGIN
+SET c= 100;
+SET d= d + 1;
+RETURN a + b;
+END latin1 latin1_swedish_ci latin1_swedish_ci
+DROP FUNCTION add_func;
+#
+# CREATE PROCEDURE with IN, OUT, INOUT qualifiers
+# SHOW CREATE PROCEDURE
+#
+CREATE PROCEDURE add_proc(IN a INT, IN b INT, INOUT c INT, OUT d INT)
+BEGIN
+SET d= a + b + c + d;
+END;
+$$
+SHOW CREATE PROCEDURE add_proc;
+Procedure sql_mode Create Procedure character_set_client collation_connection Database Collation
+add_proc STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` PROCEDURE `add_proc`(IN a INT, IN b INT, INOUT c INT, OUT d INT)
+BEGIN
+SET d= a + b + c + d;
+END latin1 latin1_swedish_ci latin1_swedish_ci
+DROP PROCEDURE add_proc;
+#
+# Call function from SELECT query
+# SELECT > FUNCTION(IN)
+#
+CREATE FUNCTION add_func2(IN a INT, IN b INT) RETURNS INT
+BEGIN
+RETURN a + b;
+END;
+$$
+SET @a = 2;
+SET @b = 3;
+SELECT add_func2(@a, @b);
+add_func2(@a, @b)
+5
+DROP FUNCTION add_func2;
+#
+# Call function from SELECT query
+# SELECT > FUNCTION(OUT)
+#
+CREATE FUNCTION add_func3(IN a INT, IN b INT, OUT c INT) RETURNS INT
+BEGIN
+SET c = 100;
+RETURN a + b;
+END;
+$$
+SET @a = 2;
+SET @b = 3;
+SET @c = 0;
+SET @res= add_func3(@a, @b, @c);
+SELECT @res, @a, @b, @c;
+@res @a @b @c
+5 2 3 100
+SELECT add_func3(@a, @b, @c);
+ERROR HY000: OUT or INOUT argument 3 for function add_func3 is not allowed here
+DROP FUNCTION add_func3;
+#
+# Call function from SELECT query
+# SELECT > FUNCTION(INOUT)
+#
+CREATE FUNCTION add_func4(IN a INT, IN b INT, OUT c INT, INOUT d INT) RETURNS INT
+BEGIN
+SET c = 100;
+SET d = d + 1;
+RETURN a + b;
+END;
+$$
+SET @a = 2;
+SET @b = 3;
+SET @c = 0;
+SET @d = 9;
+SET @res= add_func4(@a, @b, @c, @d);
+SELECT @res, @a, @b, @c, @d;
+@res @a @b @c @d
+5 2 3 100 10
+SELECT add_func4(@a, @b, @c, @d);
+ERROR HY000: OUT or INOUT argument 3 for function add_func4 is not allowed here
+DROP FUNCTION add_func4;
+#
+# Call from procedure
+# PROCEDURE(OUT) > FUNCTION(IN)
+#
+CREATE FUNCTION add_func2(IN a INT, IN b INT) RETURNS INT
+BEGIN
+RETURN a + b;
+END;
+$$
+CREATE PROCEDURE add_proc2(IN a INT, IN b INT, OUT c INT)
+BEGIN
+SET c = add_func2(a, b);
+END;
+$$
+SET @a = 2;
+SET @b = 3;
+SET @c = 0;
+CALL add_proc2(@a, @b, @c);
+SELECT @a, @b, @c;
+@a @b @c
+2 3 5
+DROP FUNCTION add_func2;
+DROP PROCEDURE add_proc2;
+#
+# Call from procedure
+# PROCEDURE(OUT) > FUNCTION(OUT)
+#
+CREATE FUNCTION add_func3(IN a INT, IN b INT, OUT c INT) RETURNS INT
+BEGIN
+SET c = 100;
+RETURN a + b;
+END;
+$$
+CREATE PROCEDURE add_proc3(IN a INT, IN b INT, OUT c INT)
+BEGIN
+DECLARE res INT;
+SET res = add_func3(a, b, c);
+END;
+$$
+SET @a = 2;
+SET @b = 3;
+SET @c = 0;
+CALL add_proc3(@a, @b, @c);
+SELECT @a, @b, @c;
+@a @b @c
+2 3 100
+DROP FUNCTION add_func3;
+DROP PROCEDURE add_proc3;
+#
+# Call from procedure
+# PROCEDURE(OUT) > FUNCTION(INOUT)
+#
+CREATE FUNCTION add_func4(IN a INT, IN b INT, OUT c INT, INOUT d INT) RETURNS INT
+BEGIN
+SET c = 100;
+SET d = d + 1;
+RETURN a + b;
+END;
+$$
+CREATE PROCEDURE add_proc4(IN a INT, IN b INT, OUT res INT)
+BEGIN
+DECLARE c INT;
+DECLARE d INT;
+SET d = 30;
+SET res = add_func4(a, b, c, d);
+SET res = c + d;
+END;
+$$
+SET @a = 2;
+SET @b = 3;
+SET @res = 0;
+CALL add_proc4(@a, @b, @res);
+SELECT @a, @b, @res;
+@a @b @res
+2 3 131
+DROP FUNCTION add_func4;
+DROP PROCEDURE add_proc4;
+#
+# Call from procedure
+# PROCEDURE(OUT) > PROCEDURE(OUT)
+#
+CREATE PROCEDURE add_proc(IN a INT, IN b INT, OUT c INT)
+BEGIN
+SET c = a + b;
+END;
+$$
+CREATE PROCEDURE test_proc1(IN a INT, IN b INT, OUT c INT)
+BEGIN
+CALL add_proc(a, b, c);
+END;
+$$
+SET @a = 2;
+SET @b = 3;
+SET @c = 0;
+CALL test_proc1(@a, @b, @c);
+SELECT @a, @b, @c;
+@a @b @c
+2 3 5
+DROP PROCEDURE add_proc;
+DROP PROCEDURE test_proc1;
+#
+# Argument's order change
+# PROCEDURE(a IN, b IN, c OUT) > FUNCTION(b IN, a IN, c OUT)
+#
+CREATE FUNCTION func_sub(IN b INT, IN a INT, OUT c INT) RETURNS INT
+BEGIN
+DECLARE res INT;
+SET c = a - b;
+SET res = a;
+RETURN res;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, IN b INT, OUT c INT)
+BEGIN
+DECLARE res INT;
+SET res = func_sub(b, a, c);
+END;
+$$
+SET @a = 2;
+SET @b = 3;
+SET @c = 0;
+CALL proc_main(@a, @b, @c);
+SELECT @a, @b, @c;
+@a @b @c
+2 3 -1
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+#
+# Argument's order change
+# PROCEDURE(a IN, b IN, c OUT) > FUNCTION(c OUT, b IN, a IN)
+#
+CREATE FUNCTION func_sub(OUT c INT, IN b INT, IN a INT) RETURNS INT
+BEGIN
+DECLARE res INT;
+SET c = a - b;
+SET res = a;
+RETURN res;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, IN b INT, OUT c INT)
+BEGIN
+DECLARE res INT;
+SET res = func_sub(c, b, a);
+END;
+$$
+SET @a = 2;
+SET @b = 3;
+SET @c = 0;
+CALL proc_main(@a, @b, @c);
+SELECT @a, @b, @c;
+@a @b @c
+2 3 -1
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+#
+# Argument's order change
+# PROCEDURE(a IN, b IN, c INOUT, d OUT) > FUNCTION(d OUT, a IN, b IN, c INOUT)
+#
+CREATE FUNCTION func_sub(OUT d INT, IN a INT, IN b INT, INOUT c INT) RETURNS INT
+BEGIN
+SET c = c + 6;
+SET d = 10;
+RETURN a - b;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, IN b INT, INOUT c INT, OUT d INT)
+BEGIN
+DECLARE res INT;
+SET res = func_sub(d, a, b, c);
+SET d = d + c + res;
+END;
+$$
+SET @a = 15;
+SET @b = 5;
+SET @c = 4;
+SET @d= 0;
+CALL proc_main(@a, @b, @c, @d);
+SELECT @a, @b, @c, @d;
+@a @b @c @d
+15 5 10 30
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+#
+# Argument's order change
+# PROCEDURE(IN a INT, IN b INT, INOUT c INT, OUT d INT) > FUNCTION1(c INOUT INT, IN b INT) > FUNCTION2(d OUT INT, IN a INT)
+#
+CREATE FUNCTION func_sub1(INOUT c INT, IN b INT) RETURNS INT
+BEGIN
+SET c = c + b;
+RETURN 0;
+END;
+$$
+CREATE FUNCTION func_sub2(OUT d INT, IN a INT) RETURNS INT
+BEGIN
+SET d = 5 + a;
+RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, IN b INT, INOUT c INT, OUT d INT)
+BEGIN
+DECLARE res1 INT;
+DECLARE res2 INT;
+SET res1 = func_sub1(c, b);
+SET res2 = func_sub2(d, a);
+SET d = d + c;
+END;
+$$
+SET @a = 15;
+SET @b = 6;
+SET @c = 4;
+SET @d= 0;
+CALL proc_main(@a, @b, @c, @d);
+SELECT @a, @b, @c, @d;
+@a @b @c @d
+15 6 10 30
+DROP FUNCTION func_sub1;
+DROP FUNCTION func_sub2;
+DROP PROCEDURE proc_main;
+#
+# Argument's order change
+# FUNCTION1(a IN, b IN) > FUNCTION2(b IN, c OUT, a IN)
+#
+CREATE FUNCTION func_sub(IN b INT, OUT c INT, IN a INT) RETURNS INT
+BEGIN
+SET c = 100;
+RETURN a + b;
+END;
+$$
+CREATE FUNCTION func_main(IN a INT, IN b INT) RETURNS INT
+BEGIN
+DECLARE c INT;
+DECLARE res INT;
+SET res = func_sub(b, c, a);
+RETURN res + c;
+END;
+$$
+SET @a = 2;
+SET @b = 3;
+SELECT func_main(@a, @b);
+func_main(@a, @b)
+105
+DROP FUNCTION func_sub;
+DROP FUNCTION func_main;
+#
+# Call procedure inside function
+# FUNCTION1(a IN, b IN) > PROCEDURE(a IN, b IN, c OUT)
+#
+CREATE PROCEDURE proc_sub(IN a INT, IN b INT, OUT c INT)
+BEGIN
+SET c = a + b;
+END;
+$$
+CREATE FUNCTION func_main(IN b INT, IN a INT) RETURNS INT
+BEGIN
+DECLARE c INT;
+CALL proc_sub(a, b, c);
+RETURN c;
+END;
+$$
+SET @a = 2;
+SET @b = 3;
+SELECT func_main(@a, @b);
+func_main(@a, @b)
+5
+DROP PROCEDURE proc_sub;
+DROP FUNCTION func_main;
+#
+# Call procedure inside function
+# FUNCTION1(a IN, b IN) > PROCEDURE(a IN, b INOUT)
+#
+CREATE PROCEDURE proc_sub(IN a INT, INOUT b INT)
+BEGIN
+SET b = a + b;
+END;
+$$
+CREATE FUNCTION func_main(IN b INT, IN a INT) RETURNS INT
+BEGIN
+CALL proc_sub(a, b);
+RETURN b;
+END;
+$$
+SET @a = 2;
+SET @b = 3;
+SELECT func_main(@a, @b);
+func_main(@a, @b)
+5
+DROP PROCEDURE proc_sub;
+DROP FUNCTION func_main;
+#
+# Call procedure inside function
+# FUNCTION1(a IN, b IN, c OUT) > PROCEDURE(a IN, b IN, c OUT)
+#
+CREATE PROCEDURE proc_sub(IN a INT, IN b INT, OUT c INT)
+BEGIN
+SET c = a + b;
+END;
+$$
+CREATE FUNCTION func_main(IN b INT, IN a INT, OUT c INT) RETURNS INT
+BEGIN
+DECLARE res INT;
+CALL proc_sub(a, b, c);
+RETURN 0;
+END;
+$$
+SET @a = 2;
+SET @b = 3;
+SET @c = 0;
+DO func_main(@a, @b, @c);
+SELECT @a, @b, @c;
+@a @b @c
+2 3 5
+SELECT func_main(@a, @b, @c);
+ERROR HY000: OUT or INOUT argument 3 for function func_main is not allowed here
+DROP PROCEDURE proc_sub;
+DROP FUNCTION func_main;
+#
+# Call function from UPDATE query
+# UPDATE <table> SET <column> = FUNCTION(a IN)
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+CREATE FUNCTION func(IN a INT) RETURNS INT
+BEGIN
+RETURN a * 10;
+END;
+$$
+SET @a = 5;
+UPDATE Persons SET Age = func(@a) WHERE ID = 1;
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 50
+2 BBB 20
+3 CCC 30
+DROP TABLE Persons;
+DROP FUNCTION func;
+#
+# Call function from UPDATE query
+# UPDATE <table> SET <column> = FUNCTION(a OUT)
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+CREATE FUNCTION func(OUT a INT) RETURNS INT
+BEGIN
+SET a = 5;
+RETURN 80;
+END;
+$$
+SET @a = 0;
+UPDATE Persons SET Age = func(@a) WHERE ID = 1;
+ERROR HY000: OUT or INOUT argument 1 for function func is not allowed here
+DROP TABLE Persons;
+DROP FUNCTION func;
+#
+# Call function from INSERT query
+# INSERT INTO <table> SELECT <val1>, <val2>, FUNCTION(a IN)
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+CREATE FUNCTION func(IN a INT) RETURNS INT
+BEGIN
+RETURN a * 10;
+END;
+$$
+SET @a = 4;
+INSERT INTO Persons SELECT 4, 'DDD', func(@a);
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+4 DDD 40
+DROP TABLE Persons;
+DROP FUNCTION func;
+#
+# Call function from INSERT query
+# INSERT INTO <table> SELECT <val1>, <val2>, FUNCTION(a OUT)
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+CREATE FUNCTION func(OUT a INT) RETURNS INT
+BEGIN
+SET a = 45;
+RETURN 40;
+END;
+$$
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+SET @a = 0;
+INSERT INTO Persons SELECT 5, 'EEE', func(@a);
+ERROR HY000: OUT or INOUT argument 1 for function func is not allowed here
+DROP TABLE Persons;
+DROP FUNCTION func;
+#
+# Call function from DELETE query
+# DELETE FROM <table> WHERE <column> = FUNCTION(a IN)
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+CREATE FUNCTION func(IN a INT) RETURNS INT
+BEGIN
+RETURN a;
+END;
+$$
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+4 DDD 40
+SET @a = 4;
+DELETE FROM Persons WHERE ID = func(@a);
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+DROP TABLE Persons;
+DROP FUNCTION func;
+#
+# Call function from DELETE query
+# DELETE FROM <table> WHERE <column> = FUNCTION(a OUT)
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+CREATE FUNCTION func(OUT a INT) RETURNS INT
+BEGIN
+SET a = 40;
+RETURN 4;
+END;
+$$
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+4 DDD 40
+SET @a = 0;
+DELETE FROM Persons WHERE ID = func(@a);
+ERROR HY000: OUT or INOUT argument 1 for function func is not allowed here
+DROP TABLE Persons;
+DROP FUNCTION func;
+#
+# SELECT query inside function
+# FUNCTION(a IN) > SELECT … FROM <table>
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+CREATE FUNCTION func_main(IN a INT) RETURNS INT
+BEGIN
+DECLARE c INT;
+SELECT AGE INTO c FROM Persons WHERE ID = a;
+RETURN c;
+END;
+$$
+SET @a = 3;
+SELECT func_main(@a);
+func_main(@a)
+30
+SELECT * from Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+4 DDD 40
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+#
+# SELECT query inside function
+# FUNCTION(a OUT) > SELECT … FROM <table>
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+CREATE FUNCTION func_main(OUT a INT) RETURNS INT
+BEGIN
+SELECT AGE INTO a FROM Persons WHERE ID = 3;
+RETURN 0;
+END;
+$$
+SET @a = 0;
+SELECT func_main(@a);
+ERROR HY000: OUT or INOUT argument 1 for function func_main is not allowed here
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+#
+# SELECT query inside function
+# FUNCTION(a INOUT) > SELECT … FROM <table>
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+CREATE FUNCTION func_main(INOUT a INT) RETURNS INT
+BEGIN
+SELECT AGE INTO a FROM Persons WHERE ID = a;
+RETURN 0;
+END;
+$$
+SET @a = 1;
+SELECT func_main(@a);
+ERROR HY000: OUT or INOUT argument 1 for function func_main is not allowed here
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+#
+# SELECT query inside function
+# FUNCTION(a IN) > FUNCTION(a IN, b OUT) > SELECT … FROM <table>
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+CREATE FUNCTION func_sub(IN a INT, OUT b INT) RETURNS INT
+BEGIN
+SELECT AGE INTO b FROM Persons WHERE ID = a;
+RETURN 0;
+END;
+$$
+CREATE FUNCTION func_main(IN a INT) RETURNS INT
+BEGIN
+DECLARE b INT;
+DECLARE res INT;
+SET res = func_sub(a, b);
+RETURN b;
+END;
+$$
+SET @a = 2;
+SELECT func_main(@a);
+func_main(@a)
+20
+SELECT * from Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+4 DDD 40
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP FUNCTION func_main;
+#
+# UPDATE query inside function
+# FUNCTION(a IN) > UPDATE <table> SET …
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'EEE', 40);
+CREATE FUNCTION func_main(IN a INT) RETURNS INT
+BEGIN
+DECLARE c INT;
+UPDATE Persons SET AGE = 50 WHERE ID = a;
+SELECT AGE INTO c FROM Persons WHERE ID = a;
+RETURN c;
+END;
+$$
+SELECT * from Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 EEE 40
+SET @a = 5;
+SELECT func_main(@a);
+func_main(@a)
+50
+SELECT * from Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 EEE 50
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+#
+# UPDATE query inside function
+# FUNCTION(a IN, b OUT) > UPDATE <table> SET …
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'EEE', 40);
+CREATE FUNCTION func_main(IN a INT, OUT b INT) RETURNS INT
+BEGIN
+UPDATE Persons SET AGE = 60 WHERE ID = a;
+SELECT AGE INTO b FROM Persons WHERE ID = a;
+RETURN 0;
+END;
+$$
+SET @a = 5;
+SET @b = 0;
+SELECT func_main(@a, @b);
+ERROR HY000: OUT or INOUT argument 2 for function func_main is not allowed here
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+#
+# UPDATE query inside function
+# FUNCTION(a IN, b INOUT) > UPDATE <table> SET …
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'EEE', 40);
+CREATE FUNCTION func_main(IN a INT, INOUT b INT) RETURNS INT
+BEGIN
+UPDATE Persons SET AGE = 60 WHERE ID = a;
+SELECT AGE INTO b FROM Persons WHERE ID = a;
+RETURN 0;
+END;
+$$
+SET @a = 5;
+SET @b = 0;
+SELECT func_main(@a, @b);
+ERROR HY000: OUT or INOUT argument 2 for function func_main is not allowed here
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+#
+# UPDATE query inside function
+# FUNCTION(a IN) > FUNCTION(a IN, b OUT) > UPDATE <table> SET …
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 80);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'EEE', 40);
+CREATE FUNCTION func_sub(IN a INT, OUT b INT) RETURNS INT
+BEGIN
+UPDATE Persons SET AGE = 10 WHERE ID = a;
+SELECT AGE INTO b FROM Persons WHERE ID = a;
+RETURN 0;
+END;
+$$
+CREATE FUNCTION func_main(IN a INT) RETURNS INT
+BEGIN
+DECLARE b INT;
+DECLARE res INT;
+SET res = func_sub(a, b);
+RETURN b;
+END;
+$$
+SELECT * from Persons;
+ID Name Age
+1 AAA 80
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 EEE 40
+SET @a = 1;
+SELECT func_main(@a);
+func_main(@a)
+10
+SELECT * from Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 EEE 40
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP FUNCTION func_main;
+#
+# INSERT query inside function
+# FUNCTION(a IN) > INSERT INTO <table> VALUES …
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'EEE', 50);
+CREATE FUNCTION func_main(IN a INT) RETURNS INT
+BEGIN
+DECLARE b INT;
+INSERT INTO Persons VALUE (a, 'FFF', 60);
+SELECT AGE INTO b FROM Persons WHERE ID = a;
+RETURN b;
+END;
+$$
+SELECT * from Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 EEE 50
+SET @a = 6;
+SELECT func_main(@a);
+func_main(@a)
+60
+SELECT * from Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 EEE 50
+6 FFF 60
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+#
+# INSERT query inside function
+# FUNCTION(a IN, b OUT) > INSERT INTO <table> VALUES …
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'EEE', 50);
+CREATE FUNCTION func_main(IN a INT, OUT b INT) RETURNS INT
+BEGIN
+INSERT INTO Persons VALUE (a, 'FFF', 60);
+SELECT AGE INTO b FROM Persons WHERE ID = a;
+RETURN 0;
+END;
+$$
+SELECT * from Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 EEE 50
+SET @a = 6;
+SET @b = 0;
+SELECT func_main(@a, @b);
+ERROR HY000: OUT or INOUT argument 2 for function func_main is not allowed here
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+#
+# INSERT query inside function
+# FUNCTION(a IN, b INOUT) > INSERT INTO <table> VALUES …
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'EEE', 40);
+CREATE FUNCTION func_main(IN a INT, INOUT b INT) RETURNS INT
+BEGIN
+INSERT INTO Persons VALUE (a, 'FFF', 60);
+SELECT AGE INTO b FROM Persons WHERE ID = a;
+RETURN 0;
+END;
+$$
+SELECT * from Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 EEE 40
+SET @a = 6;
+SET @b = 0;
+SELECT func_main(@a, @b);
+ERROR HY000: OUT or INOUT argument 2 for function func_main is not allowed here
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+#
+# INSERT query inside function
+# FUNCTION(a IN) > FUNCTION(a IN, b OUT) > INSERT INTO <table> VALUES …
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'EEE', 40);
+CREATE FUNCTION func_sub(IN a INT, OUT b INT) RETURNS INT
+BEGIN
+INSERT INTO Persons VALUE (a, 'FFF', 60);
+SELECT AGE INTO b FROM Persons WHERE ID = a;
+RETURN 0;
+END;
+$$
+CREATE FUNCTION func_main(IN a INT) RETURNS INT
+BEGIN
+DECLARE b INT;
+DECLARE res INT;
+SET res = func_sub(a, b);
+RETURN b;
+END;
+$$
+SELECT * from Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 EEE 40
+SET @a = 6;
+SELECT func_main(@a);
+func_main(@a)
+60
+SELECT * from Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 EEE 40
+6 FFF 60
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP FUNCTION func_main;
+#
+# PROCEDURE > FUNCTION > SQL query
+# PROCEDURE(OUT) > FUNCTION(IN) > SELECT FROM <table> …
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+CREATE FUNCTION func_sub(IN a INT) RETURNS INT
+BEGIN
+DECLARE b INT;
+SELECT AGE INTO b FROM Persons WHERE ID = a;
+RETURN b;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+SET b = func_sub(a);
+END;
+$$
+SELECT * from Persons;
+ID Name Age
+1 AAA 50
+2 BBB 20
+3 CCC 30
+4 DDD 40
+SET @a = 2;
+SET @b = 0;
+CALL proc_main(@a, @b);
+SELECT @b;
+@b
+20
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+#
+# PROCEDURE > FUNCTION > SQL query
+# PROCEDURE(OUT) > FUNCTION(OUT) > SELECT FROM <table> …
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+CREATE FUNCTION func_sub(IN a INT, OUT b INT) RETURNS INT
+BEGIN
+SELECT AGE INTO b FROM Persons WHERE ID = a;
+RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+DECLARE res INT;
+SET res = func_sub(a, b);
+END;
+$$
+SELECT * from Persons;
+ID Name Age
+1 AAA 50
+2 BBB 20
+3 CCC 30
+4 DDD 40
+SET @a = 1;
+SET @b = 0;
+CALL proc_main(@a, @b);
+SELECT @b;
+@b
+50
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+#
+# PROCEDURE > FUNCTION > SQL query
+# PROCEDURE(OUT) > FUNCTION(INOUT) > SELECT FROM <table> …
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+CREATE FUNCTION func_sub(IN a INT, INOUT c INT) RETURNS INT
+BEGIN
+DECLARE res INT;
+SELECT AGE INTO res FROM Persons WHERE ID = a;
+SET c = c * 100;
+RETURN res;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+DECLARE c INT;
+DECLARE res INT;
+SET c = 5;
+SET res = func_sub(a, c);
+SET b = c;
+END;
+$$
+SELECT * from Persons;
+ID Name Age
+1 AAA 50
+2 BBB 20
+3 CCC 30
+4 DDD 40
+SET @a = 2;
+SET @b = 0;
+CALL proc_main(@a, @b);
+SELECT @b;
+@b
+500
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+#
+# PROCEDURE > FUNCTION > SQL query
+# PROCEDURE(OUT) > FUNCTION(IN) > INSESRT INTO <table> …
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+CREATE FUNCTION func_sub(IN a INT) RETURNS INT
+BEGIN
+INSERT INTO Persons VALUE (a, 'FFF', 50);
+RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+SET b = func_sub(a);
+END;
+$$
+SELECT * from Persons;
+ID Name Age
+1 AAA 50
+2 BBB 20
+3 CCC 30
+4 DDD 40
+SET @a = 5;
+SET @b = 1;
+CALL proc_main(@a, @b);
+SELECT @b;
+@b
+0
+SELECT * from Persons;
+ID Name Age
+1 AAA 50
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 FFF 50
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+#
+# PROCEDURE > FUNCTION > SQL query
+# PROCEDURE(OUT) > FUNCTION(OUT) > INSESRT INTO <table> …
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'FFF', 50);
+CREATE FUNCTION func_sub(IN a INT, OUT b INT) RETURNS INT
+BEGIN
+INSERT INTO Persons VALUE (a, 'GGG', 60);
+RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+DECLARE res INT;
+SET res = func_sub(a, b);
+END;
+$$
+SELECT * from Persons;
+ID Name Age
+1 AAA 50
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 FFF 50
+SET @a = 6;
+SET @b = 0;
+CALL proc_main(@a, @b);
+SELECT * from Persons;
+ID Name Age
+1 AAA 50
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 FFF 50
+6 GGG 60
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+#
+# PROCEDURE > FUNCTION > SQL query
+# PROCEDURE(OUT) > FUNCTION(INOUT) > INSESRT INTO <table> …
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'FFF', 50);
+INSERT INTO Persons VALUES (6, 'GGG', 60);
+CREATE FUNCTION func_sub(IN a INT, INOUT c INT) RETURNS INT
+BEGIN
+DECLARE res INT;
+INSERT INTO Persons VALUE (a, 'HHH', 70);
+SET c = c * 100;
+RETURN res;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+DECLARE c INT;
+DECLARE res INT;
+SET c = 5;
+SET res = func_sub(a, c);
+SET b = c;
+END;
+$$
+SELECT * from Persons;
+ID Name Age
+1 AAA 50
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 FFF 50
+6 GGG 60
+SET @a = 7;
+SET @b = 0;
+CALL proc_main(@a, @b);
+SELECT @b;
+@b
+500
+SELECT * from Persons;
+ID Name Age
+1 AAA 50
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 FFF 50
+6 GGG 60
+7 HHH 70
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+#
+# PROCEDURE > FUNCTION > SQL query
+# PROCEDURE(OUT) > FUNCTION(IN) > UPDATE <table> SET …
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'FFF', 50);
+INSERT INTO Persons VALUES (6, 'GGG', 60);
+INSERT INTO Persons VALUES (7, 'HHH', 70);
+CREATE FUNCTION func_sub(IN a INT) RETURNS INT
+BEGIN
+UPDATE Persons SET AGE = 100 WHERE ID = a;
+RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+SET b = func_sub(a);
+END;
+$$
+SELECT * from Persons;
+ID Name Age
+1 AAA 50
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 FFF 50
+6 GGG 60
+7 HHH 70
+SET @a = 5;
+SET @b = 0;
+CALL proc_main(@a, @b);
+SELECT * from Persons;
+ID Name Age
+1 AAA 50
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 FFF 100
+6 GGG 60
+7 HHH 70
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+#
+# PROCEDURE > FUNCTION > SQL query
+# PROCEDURE(OUT) > FUNCTION(OUT) > UPDATE <table> SET …
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'FFF', 100);
+INSERT INTO Persons VALUES (6, 'GGG', 60);
+INSERT INTO Persons VALUES (7, 'HHH', 70);
+CREATE FUNCTION func_sub(IN a INT, OUT b INT) RETURNS INT
+BEGIN
+UPDATE Persons SET AGE = 100 WHERE ID = a;
+SET b = 1;
+RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+DECLARE res INT;
+SET res = func_sub(a, b);
+END;
+$$
+SELECT * from Persons;
+ID Name Age
+1 AAA 50
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 FFF 100
+6 GGG 60
+7 HHH 70
+SET @a = 6;
+SET @b = 0;
+CALL proc_main(@a, @b);
+SELECT @b;
+@b
+1
+SELECT * from Persons;
+ID Name Age
+1 AAA 50
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 FFF 100
+6 GGG 100
+7 HHH 70
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+#
+# PROCEDURE > FUNCTION > SQL query
+# PROCEDURE(OUT) > FUNCTION(INOUT) > UPDATE <table> SET …
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'FFF', 100);
+INSERT INTO Persons VALUES (6, 'GGG', 100);
+INSERT INTO Persons VALUES (7, 'HHH', 70);
+CREATE FUNCTION func_sub(IN a INT, INOUT c INT) RETURNS INT
+BEGIN
+DECLARE res INT;
+UPDATE Persons SET AGE = 100 WHERE ID = a;
+SET c = c * 100;
+RETURN res;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+DECLARE c INT;
+DECLARE res INT;
+SET c = 5;
+SET res = func_sub(a, c);
+SET b = c;
+END;
+$$
+SELECT * from Persons;
+ID Name Age
+1 AAA 50
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 FFF 100
+6 GGG 100
+7 HHH 70
+SET @a = 7;
+SET @b = 0;
+CALL proc_main(@a, @b);
+SELECT @b;
+@b
+500
+SELECT * from Persons;
+ID Name Age
+1 AAA 50
+2 BBB 20
+3 CCC 30
+4 DDD 40
+5 FFF 100
+6 GGG 100
+7 HHH 100
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+#
+# Trigger
+# TRIGGER AFTER UPDATE ON TABLE1 > UPDATE TABLE2
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+CREATE TABLE PersonsLog (
+UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+CREATE OR REPLACE TRIGGER my_trigger
+AFTER UPDATE ON Persons
+FOR EACH ROW
+UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+$$
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+0
+UPDATE Persons SET Age = 20 WHERE ID = 1;
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 20
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+1
+DROP TRIGGER my_trigger;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+#
+# Trigger
+# TRIGGER AFTER UPDATE ON TABLE1 > FUNCTION(IN) > UPDATE TABLE2
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+CREATE TABLE PersonsLog (
+UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+CREATE FUNCTION func(IN a INT) RETURNS INT
+BEGIN
+UPDATE PersonsLog SET UpdateCount = UpdateCount+a;
+RETURN 0;
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+AFTER UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+DECLARE a INT;
+DECLARE res INT;
+SET a = 1;
+SET res = 0;
+SET res = func(a);
+END;
+$$
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+0
+UPDATE Persons SET Age = 30 WHERE ID = 1;
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 30
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+1
+DROP TRIGGER my_trigger;
+DROP FUNCTION func;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+#
+# Trigger
+# TRIGGER AFTER UPDATE ON TABLE1 > FUNCTION(OUT) > UPDATE TABLE2
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 40);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+CREATE TABLE PersonsLog (
+UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+CREATE FUNCTION func(IN age_in INT, OUT age_out INT) RETURNS INT
+BEGIN
+UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+SET age_out = age_in + 1;
+RETURN 0;
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+BEFORE UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+DECLARE res INT DEFAULT (func(OLD.age, NEW.age));
+END;
+$$
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 40
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+0
+UPDATE Persons SET Age = 50 WHERE ID = 1;
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 41
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+1
+DROP TRIGGER my_trigger;
+DROP FUNCTION func;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+#
+# Trigger
+# TRIGGER AFTER UPDATE ON TABLE1 > FUNCTION(INOUT) > UPDATE TABLE2
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+CREATE TABLE PersonsLog (
+UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+CREATE FUNCTION func(INOUT a INT) RETURNS INT
+BEGIN
+UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+SET a = 100;
+RETURN 0;
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+AFTER UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+DECLARE a INT;
+DECLARE res INT;
+SET a = 10;
+SET res = 0;
+SET res = func(a);
+END;
+$$
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 50
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+0
+UPDATE Persons SET Age = 60 WHERE ID = 1;
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 60
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+1
+DROP TRIGGER my_trigger;
+DROP FUNCTION func;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+#
+# Trigger
+# TRIGGER AFTER UPDATE ON TABLE1 > PROCEDURE(IN) > UPDATE TABLE2
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+CREATE TABLE PersonsLog (
+UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+CREATE PROCEDURE proc(IN a INT)
+BEGIN
+UPDATE PersonsLog SET UpdateCount = UpdateCount+a;
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+AFTER UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+CALL proc(1);
+END;
+$$
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+0
+UPDATE Persons SET Age = 30 WHERE ID = 1;
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 30
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+1
+DROP TRIGGER my_trigger;
+DROP PROCEDURE proc;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+#
+# Trigger
+# TRIGGER AFTER UPDATE ON TABLE1 > PROCEDURE(OUT) > UPDATE TABLE2
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+CREATE TABLE PersonsLog (
+UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+CREATE PROCEDURE proc(IN old_age INT, OUT new_age INT)
+BEGIN
+UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+SET new_age=old_age+41;
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+BEFORE UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+CALL proc(OLD.age, NEW.age);
+END;
+$$
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+0
+UPDATE Persons SET Age = 50 WHERE ID = 1;
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 51
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+1
+DROP TRIGGER my_trigger;
+DROP PROCEDURE proc;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+#
+# Trigger
+# TRIGGER AFTER UPDATE ON TABLE1 > PROCEDURE(INOUT) > UPDATE TABLE2
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+CREATE TABLE PersonsLog (
+UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+CREATE PROCEDURE proc(INOUT a INT)
+BEGIN
+UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+SET a = 51;
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+BEFORE UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+CALL proc(NEW.age);
+END;
+$$
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+0
+UPDATE Persons SET Age = 50 WHERE ID = 1;
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 51
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+1
+DROP TRIGGER my_trigger;
+DROP PROCEDURE proc;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+#
+# Trigger
+# TRIGGER AFTER UPDATE ON TABLE1 > PROCEDURE(OUT) > FUNCTION(IN) > UPDATE TABLE2
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+CREATE TABLE PersonsLog (
+UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+CREATE FUNCTION func(IN a INT) RETURNS INT
+BEGIN
+UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc(OUT a INT)
+BEGIN
+DECLARE res INT;
+SET a = 100;
+SET res = func(a);
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+AFTER UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+CALL proc(@a);
+END;
+$$
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+0
+UPDATE Persons SET Age = 60 WHERE ID = 1;
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 60
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+1
+DROP TRIGGER my_trigger;
+DROP FUNCTION func;
+DROP PROCEDURE proc;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+#
+# Trigger
+# TRIGGER AFTER UPDATE ON TABLE1 > PROCEDURE(OUT) > FUNCTION(OUT) > UPDATE TABLE2
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+CREATE TABLE PersonsLog (
+UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+CREATE FUNCTION func(OUT a INT) RETURNS INT
+BEGIN
+SET a = 200;
+UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc(OUT a INT)
+BEGIN
+DECLARE res INT;
+SET a = 100;
+SET res = func(a);
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+AFTER UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+CALL proc(@a);
+END;
+$$
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+0
+UPDATE Persons SET Age = 80 WHERE ID = 1;
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 80
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+1
+DROP FUNCTION func;
+DROP PROCEDURE proc;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+#
+# Trigger
+# TRIGGER AFTER UPDATE ON TABLE1 > PROCEDURE(OUT) > FUNCTION(INOUT) > UPDATE TABLE2
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+CREATE TABLE PersonsLog (
+UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+CREATE FUNCTION func(INOUT a INT) RETURNS INT
+BEGIN
+SET a = 200;
+UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc(OUT a INT)
+BEGIN
+DECLARE res INT;
+SET a = 100;
+SET res = func(a);
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+AFTER UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+CALL proc(@a);
+END;
+$$
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+0
+UPDATE Persons SET Age = 90 WHERE ID = 1;
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 90
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+1
+DROP TRIGGER my_trigger;
+DROP FUNCTION func;
+DROP PROCEDURE proc;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+#
+# Trigger
+# TRIGGER AFTER UPDATE ON TABLE1 > PROCEDURE(OUT) > FUNCTION(OUT) > UPDATE TABLE2 with OUT argument (to check if OUT is returning by reference)
+#
+CREATE TABLE Persons (
+ID int,
+Name varchar(255),
+Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+CREATE TABLE PersonsLog (
+UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+CREATE FUNCTION func(OUT a INT) RETURNS INT
+BEGIN
+SET a = 111;
+UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc(OUT a INT)
+BEGIN
+DECLARE res INT;
+SET res = func(a);
+UPDATE PersonsLog SET UpdateCount = a;
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+AFTER UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+CALL proc(@a);
+END;
+$$
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 10
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+0
+UPDATE Persons SET Age = 80 WHERE ID = 1;
+SELECT * FROM Persons;
+ID Name Age
+1 AAA 80
+2 BBB 20
+3 CCC 30
+SELECT * FROM PersonsLog;
+UpdateCount
+111
+DROP TRIGGER my_trigger;
+DROP FUNCTION func;
+DROP PROCEDURE proc;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
diff --git a/mysql-test/main/sp-inout.test b/mysql-test/main/sp-inout.test
new file mode 100644
index 00000000000..8f3f134b675
--- /dev/null
+++ b/mysql-test/main/sp-inout.test
@@ -0,0 +1,1964 @@
+--echo #
+--echo # MDEV-10654 IN, OUT, INOUT parameters in CREATE FUNCTION
+--echo #
+
+
+--echo #
+--echo # CREATE FUNCTION with IN, OUT, INOUT qualifiers
+--echo # SHOW CREATE FUNCTION
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION add_func(IN a INT, IN b INT, OUT c INT, INOUT d INT) RETURNS INT
+BEGIN
+ SET c= 100;
+ SET d= d + 1;
+ RETURN a + b;
+END;
+$$
+DELIMITER ;$$
+
+SHOW CREATE FUNCTION add_func;
+DROP FUNCTION add_func;
+
+--echo #
+--echo # CREATE PROCEDURE with IN, OUT, INOUT qualifiers
+--echo # SHOW CREATE PROCEDURE
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE add_proc(IN a INT, IN b INT, INOUT c INT, OUT d INT)
+BEGIN
+ SET d= a + b + c + d;
+END;
+$$
+DELIMITER ;$$
+
+SHOW CREATE PROCEDURE add_proc;
+DROP PROCEDURE add_proc;
+
+--echo #
+--echo # Call function from SELECT query
+--echo # SELECT > FUNCTION(IN)
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION add_func2(IN a INT, IN b INT) RETURNS INT
+BEGIN
+ RETURN a + b;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 2;
+SET @b = 3;
+SELECT add_func2(@a, @b);
+DROP FUNCTION add_func2;
+
+--echo #
+--echo # Call function from SELECT query
+--echo # SELECT > FUNCTION(OUT)
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION add_func3(IN a INT, IN b INT, OUT c INT) RETURNS INT
+BEGIN
+ SET c = 100;
+ RETURN a + b;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 2;
+SET @b = 3;
+SET @c = 0;
+SET @res= add_func3(@a, @b, @c);
+SELECT @res, @a, @b, @c;
+--error ER_SF_OUT_INOUT_ARG_NOT_ALLOWED
+SELECT add_func3(@a, @b, @c);
+DROP FUNCTION add_func3;
+
+--echo #
+--echo # Call function from SELECT query
+--echo # SELECT > FUNCTION(INOUT)
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION add_func4(IN a INT, IN b INT, OUT c INT, INOUT d INT) RETURNS INT
+BEGIN
+ SET c = 100;
+ SET d = d + 1;
+ RETURN a + b;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 2;
+SET @b = 3;
+SET @c = 0;
+SET @d = 9;
+SET @res= add_func4(@a, @b, @c, @d);
+SELECT @res, @a, @b, @c, @d;
+--error ER_SF_OUT_INOUT_ARG_NOT_ALLOWED
+SELECT add_func4(@a, @b, @c, @d);
+DROP FUNCTION add_func4;
+
+--echo #
+--echo # Call from procedure
+--echo # PROCEDURE(OUT) > FUNCTION(IN)
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION add_func2(IN a INT, IN b INT) RETURNS INT
+BEGIN
+ RETURN a + b;
+END;
+$$
+CREATE PROCEDURE add_proc2(IN a INT, IN b INT, OUT c INT)
+BEGIN
+ SET c = add_func2(a, b);
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 2;
+SET @b = 3;
+SET @c = 0;
+CALL add_proc2(@a, @b, @c);
+SELECT @a, @b, @c;
+DROP FUNCTION add_func2;
+DROP PROCEDURE add_proc2;
+
+--echo #
+--echo # Call from procedure
+--echo # PROCEDURE(OUT) > FUNCTION(OUT)
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION add_func3(IN a INT, IN b INT, OUT c INT) RETURNS INT
+BEGIN
+ SET c = 100;
+ RETURN a + b;
+END;
+$$
+CREATE PROCEDURE add_proc3(IN a INT, IN b INT, OUT c INT)
+BEGIN
+ DECLARE res INT;
+ SET res = add_func3(a, b, c);
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 2;
+SET @b = 3;
+SET @c = 0;
+CALL add_proc3(@a, @b, @c);
+SELECT @a, @b, @c;
+DROP FUNCTION add_func3;
+DROP PROCEDURE add_proc3;
+
+--echo #
+--echo # Call from procedure
+--echo # PROCEDURE(OUT) > FUNCTION(INOUT)
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION add_func4(IN a INT, IN b INT, OUT c INT, INOUT d INT) RETURNS INT
+BEGIN
+ SET c = 100;
+ SET d = d + 1;
+ RETURN a + b;
+END;
+$$
+CREATE PROCEDURE add_proc4(IN a INT, IN b INT, OUT res INT)
+BEGIN
+ DECLARE c INT;
+ DECLARE d INT;
+ SET d = 30;
+ SET res = add_func4(a, b, c, d);
+ SET res = c + d;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 2;
+SET @b = 3;
+SET @res = 0;
+CALL add_proc4(@a, @b, @res);
+SELECT @a, @b, @res;
+DROP FUNCTION add_func4;
+DROP PROCEDURE add_proc4;
+
+--echo #
+--echo # Call from procedure
+--echo # PROCEDURE(OUT) > PROCEDURE(OUT)
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE add_proc(IN a INT, IN b INT, OUT c INT)
+BEGIN
+ SET c = a + b;
+END;
+$$
+CREATE PROCEDURE test_proc1(IN a INT, IN b INT, OUT c INT)
+BEGIN
+ CALL add_proc(a, b, c);
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 2;
+SET @b = 3;
+SET @c = 0;
+CALL test_proc1(@a, @b, @c);
+SELECT @a, @b, @c;
+DROP PROCEDURE add_proc;
+DROP PROCEDURE test_proc1;
+
+--echo #
+--echo # Argument's order change
+--echo # PROCEDURE(a IN, b IN, c OUT) > FUNCTION(b IN, a IN, c OUT)
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION func_sub(IN b INT, IN a INT, OUT c INT) RETURNS INT
+BEGIN
+ DECLARE res INT;
+ SET c = a - b;
+ SET res = a;
+ RETURN res;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, IN b INT, OUT c INT)
+BEGIN
+ DECLARE res INT;
+ SET res = func_sub(b, a, c);
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 2;
+SET @b = 3;
+SET @c = 0;
+CALL proc_main(@a, @b, @c);
+SELECT @a, @b, @c;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+
+--echo #
+--echo # Argument's order change
+--echo # PROCEDURE(a IN, b IN, c OUT) > FUNCTION(c OUT, b IN, a IN)
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION func_sub(OUT c INT, IN b INT, IN a INT) RETURNS INT
+BEGIN
+ DECLARE res INT;
+ SET c = a - b;
+ SET res = a;
+ RETURN res;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, IN b INT, OUT c INT)
+BEGIN
+ DECLARE res INT;
+ SET res = func_sub(c, b, a);
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 2;
+SET @b = 3;
+SET @c = 0;
+CALL proc_main(@a, @b, @c);
+SELECT @a, @b, @c;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+
+--echo #
+--echo # Argument's order change
+--echo # PROCEDURE(a IN, b IN, c INOUT, d OUT) > FUNCTION(d OUT, a IN, b IN, c INOUT)
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION func_sub(OUT d INT, IN a INT, IN b INT, INOUT c INT) RETURNS INT
+BEGIN
+ SET c = c + 6;
+ SET d = 10;
+ RETURN a - b;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, IN b INT, INOUT c INT, OUT d INT)
+BEGIN
+ DECLARE res INT;
+ SET res = func_sub(d, a, b, c);
+ SET d = d + c + res;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 15;
+SET @b = 5;
+SET @c = 4;
+SET @d= 0;
+CALL proc_main(@a, @b, @c, @d);
+SELECT @a, @b, @c, @d;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+
+--echo #
+--echo # Argument's order change
+--echo # PROCEDURE(IN a INT, IN b INT, INOUT c INT, OUT d INT) > FUNCTION1(c INOUT INT, IN b INT) > FUNCTION2(d OUT INT, IN a INT)
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION func_sub1(INOUT c INT, IN b INT) RETURNS INT
+BEGIN
+ SET c = c + b;
+ RETURN 0;
+END;
+$$
+CREATE FUNCTION func_sub2(OUT d INT, IN a INT) RETURNS INT
+BEGIN
+ SET d = 5 + a;
+ RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, IN b INT, INOUT c INT, OUT d INT)
+BEGIN
+ DECLARE res1 INT;
+ DECLARE res2 INT;
+ SET res1 = func_sub1(c, b);
+ SET res2 = func_sub2(d, a);
+ SET d = d + c;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 15;
+SET @b = 6;
+SET @c = 4;
+SET @d= 0;
+CALL proc_main(@a, @b, @c, @d);
+SELECT @a, @b, @c, @d;
+DROP FUNCTION func_sub1;
+DROP FUNCTION func_sub2;
+DROP PROCEDURE proc_main;
+
+--echo #
+--echo # Argument's order change
+--echo # FUNCTION1(a IN, b IN) > FUNCTION2(b IN, c OUT, a IN)
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION func_sub(IN b INT, OUT c INT, IN a INT) RETURNS INT
+BEGIN
+ SET c = 100;
+ RETURN a + b;
+END;
+$$
+CREATE FUNCTION func_main(IN a INT, IN b INT) RETURNS INT
+BEGIN
+ DECLARE c INT;
+ DECLARE res INT;
+ SET res = func_sub(b, c, a);
+ RETURN res + c;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 2;
+SET @b = 3;
+SELECT func_main(@a, @b);
+DROP FUNCTION func_sub;
+DROP FUNCTION func_main;
+
+--echo #
+--echo # Call procedure inside function
+--echo # FUNCTION1(a IN, b IN) > PROCEDURE(a IN, b IN, c OUT)
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE proc_sub(IN a INT, IN b INT, OUT c INT)
+BEGIN
+ SET c = a + b;
+END;
+$$
+CREATE FUNCTION func_main(IN b INT, IN a INT) RETURNS INT
+BEGIN
+ DECLARE c INT;
+ CALL proc_sub(a, b, c);
+ RETURN c;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 2;
+SET @b = 3;
+SELECT func_main(@a, @b);
+DROP PROCEDURE proc_sub;
+DROP FUNCTION func_main;
+
+--echo #
+--echo # Call procedure inside function
+--echo # FUNCTION1(a IN, b IN) > PROCEDURE(a IN, b INOUT)
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE proc_sub(IN a INT, INOUT b INT)
+BEGIN
+ SET b = a + b;
+END;
+$$
+CREATE FUNCTION func_main(IN b INT, IN a INT) RETURNS INT
+BEGIN
+ CALL proc_sub(a, b);
+ RETURN b;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 2;
+SET @b = 3;
+SELECT func_main(@a, @b);
+DROP PROCEDURE proc_sub;
+DROP FUNCTION func_main;
+
+--echo #
+--echo # Call procedure inside function
+--echo # FUNCTION1(a IN, b IN, c OUT) > PROCEDURE(a IN, b IN, c OUT)
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE proc_sub(IN a INT, IN b INT, OUT c INT)
+BEGIN
+ SET c = a + b;
+END;
+$$
+CREATE FUNCTION func_main(IN b INT, IN a INT, OUT c INT) RETURNS INT
+BEGIN
+ DECLARE res INT;
+ CALL proc_sub(a, b, c);
+ RETURN 0;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 2;
+SET @b = 3;
+SET @c = 0;
+DO func_main(@a, @b, @c);
+SELECT @a, @b, @c;
+--error ER_SF_OUT_INOUT_ARG_NOT_ALLOWED
+SELECT func_main(@a, @b, @c);
+DROP PROCEDURE proc_sub;
+DROP FUNCTION func_main;
+
+--echo #
+--echo # Call function from UPDATE query
+--echo # UPDATE <table> SET <column> = FUNCTION(a IN)
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+
+DELIMITER $$;
+CREATE FUNCTION func(IN a INT) RETURNS INT
+BEGIN
+ RETURN a * 10;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 5;
+UPDATE Persons SET Age = func(@a) WHERE ID = 1;
+SELECT * FROM Persons;
+DROP TABLE Persons;
+DROP FUNCTION func;
+
+--echo #
+--echo # Call function from UPDATE query
+--echo # UPDATE <table> SET <column> = FUNCTION(a OUT)
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+
+DELIMITER $$;
+CREATE FUNCTION func(OUT a INT) RETURNS INT
+BEGIN
+ SET a = 5;
+ RETURN 80;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 0;
+--error ER_SF_OUT_INOUT_ARG_NOT_ALLOWED
+UPDATE Persons SET Age = func(@a) WHERE ID = 1;
+DROP TABLE Persons;
+DROP FUNCTION func;
+
+--echo #
+--echo # Call function from INSERT query
+--echo # INSERT INTO <table> SELECT <val1>, <val2>, FUNCTION(a IN)
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+
+DELIMITER $$;
+CREATE FUNCTION func(IN a INT) RETURNS INT
+BEGIN
+ RETURN a * 10;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 4;
+INSERT INTO Persons SELECT 4, 'DDD', func(@a);
+SELECT * FROM Persons;
+DROP TABLE Persons;
+DROP FUNCTION func;
+
+--echo #
+--echo # Call function from INSERT query
+--echo # INSERT INTO <table> SELECT <val1>, <val2>, FUNCTION(a OUT)
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+
+DELIMITER $$;
+CREATE FUNCTION func(OUT a INT) RETURNS INT
+BEGIN
+ SET a = 45;
+ RETURN 40;
+END;
+$$
+DELIMITER ;$$
+
+SELECT * FROM Persons;
+SET @a = 0;
+--error ER_SF_OUT_INOUT_ARG_NOT_ALLOWED
+INSERT INTO Persons SELECT 5, 'EEE', func(@a);
+DROP TABLE Persons;
+DROP FUNCTION func;
+
+--echo #
+--echo # Call function from DELETE query
+--echo # DELETE FROM <table> WHERE <column> = FUNCTION(a IN)
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+
+DELIMITER $$;
+CREATE FUNCTION func(IN a INT) RETURNS INT
+BEGIN
+ RETURN a;
+END;
+$$
+DELIMITER ;$$
+
+SELECT * FROM Persons;
+SET @a = 4;
+DELETE FROM Persons WHERE ID = func(@a);
+SELECT * FROM Persons;
+DROP TABLE Persons;
+DROP FUNCTION func;
+
+--echo #
+--echo # Call function from DELETE query
+--echo # DELETE FROM <table> WHERE <column> = FUNCTION(a OUT)
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+
+DELIMITER $$;
+CREATE FUNCTION func(OUT a INT) RETURNS INT
+BEGIN
+ SET a = 40;
+ RETURN 4;
+END;
+$$
+DELIMITER ;$$
+
+SELECT * FROM Persons;
+SET @a = 0;
+--error ER_SF_OUT_INOUT_ARG_NOT_ALLOWED
+DELETE FROM Persons WHERE ID = func(@a);
+DROP TABLE Persons;
+DROP FUNCTION func;
+
+--echo #
+--echo # SELECT query inside function
+--echo # FUNCTION(a IN) > SELECT … FROM <table>
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+
+DELIMITER $$;
+CREATE FUNCTION func_main(IN a INT) RETURNS INT
+BEGIN
+ DECLARE c INT;
+ SELECT AGE INTO c FROM Persons WHERE ID = a;
+ RETURN c;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 3;
+SELECT func_main(@a);
+SELECT * from Persons;
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+
+--echo #
+--echo # SELECT query inside function
+--echo # FUNCTION(a OUT) > SELECT … FROM <table>
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+
+DELIMITER $$;
+CREATE FUNCTION func_main(OUT a INT) RETURNS INT
+BEGIN
+ SELECT AGE INTO a FROM Persons WHERE ID = 3;
+ RETURN 0;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 0;
+--error ER_SF_OUT_INOUT_ARG_NOT_ALLOWED
+SELECT func_main(@a);
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+
+--echo #
+--echo # SELECT query inside function
+--echo # FUNCTION(a INOUT) > SELECT … FROM <table>
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+
+DELIMITER $$;
+CREATE FUNCTION func_main(INOUT a INT) RETURNS INT
+BEGIN
+ SELECT AGE INTO a FROM Persons WHERE ID = a;
+ RETURN 0;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 1;
+--error ER_SF_OUT_INOUT_ARG_NOT_ALLOWED
+SELECT func_main(@a);
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+
+--echo #
+--echo # SELECT query inside function
+--echo # FUNCTION(a IN) > FUNCTION(a IN, b OUT) > SELECT … FROM <table>
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+
+DELIMITER $$;
+CREATE FUNCTION func_sub(IN a INT, OUT b INT) RETURNS INT
+BEGIN
+ SELECT AGE INTO b FROM Persons WHERE ID = a;
+ RETURN 0;
+END;
+$$
+CREATE FUNCTION func_main(IN a INT) RETURNS INT
+BEGIN
+ DECLARE b INT;
+ DECLARE res INT;
+ SET res = func_sub(a, b);
+ RETURN b;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 2;
+SELECT func_main(@a);
+SELECT * from Persons;
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP FUNCTION func_main;
+
+--echo #
+--echo # UPDATE query inside function
+--echo # FUNCTION(a IN) > UPDATE <table> SET …
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'EEE', 40);
+
+DELIMITER $$;
+CREATE FUNCTION func_main(IN a INT) RETURNS INT
+BEGIN
+ DECLARE c INT;
+ UPDATE Persons SET AGE = 50 WHERE ID = a;
+ SELECT AGE INTO c FROM Persons WHERE ID = a;
+ RETURN c;
+END;
+$$
+DELIMITER ;$$
+
+SELECT * from Persons;
+SET @a = 5;
+SELECT func_main(@a);
+SELECT * from Persons;
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+
+--echo #
+--echo # UPDATE query inside function
+--echo # FUNCTION(a IN, b OUT) > UPDATE <table> SET …
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'EEE', 40);
+
+DELIMITER $$;
+CREATE FUNCTION func_main(IN a INT, OUT b INT) RETURNS INT
+BEGIN
+ UPDATE Persons SET AGE = 60 WHERE ID = a;
+ SELECT AGE INTO b FROM Persons WHERE ID = a;
+ RETURN 0;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 5;
+SET @b = 0;
+--error ER_SF_OUT_INOUT_ARG_NOT_ALLOWED
+SELECT func_main(@a, @b);
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+
+--echo #
+--echo # UPDATE query inside function
+--echo # FUNCTION(a IN, b INOUT) > UPDATE <table> SET …
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'EEE', 40);
+
+DELIMITER $$;
+CREATE FUNCTION func_main(IN a INT, INOUT b INT) RETURNS INT
+BEGIN
+ UPDATE Persons SET AGE = 60 WHERE ID = a;
+ SELECT AGE INTO b FROM Persons WHERE ID = a;
+ RETURN 0;
+END;
+$$
+DELIMITER ;$$
+
+SET @a = 5;
+SET @b = 0;
+--error ER_SF_OUT_INOUT_ARG_NOT_ALLOWED
+SELECT func_main(@a, @b);
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+
+--echo #
+--echo # UPDATE query inside function
+--echo # FUNCTION(a IN) > FUNCTION(a IN, b OUT) > UPDATE <table> SET …
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 80);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'EEE', 40);
+
+DELIMITER $$;
+CREATE FUNCTION func_sub(IN a INT, OUT b INT) RETURNS INT
+BEGIN
+ UPDATE Persons SET AGE = 10 WHERE ID = a;
+ SELECT AGE INTO b FROM Persons WHERE ID = a;
+ RETURN 0;
+END;
+$$
+CREATE FUNCTION func_main(IN a INT) RETURNS INT
+BEGIN
+ DECLARE b INT;
+ DECLARE res INT;
+ SET res = func_sub(a, b);
+ RETURN b;
+END;
+$$
+DELIMITER ;$$
+
+SELECT * from Persons;
+SET @a = 1;
+SELECT func_main(@a);
+SELECT * from Persons;
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP FUNCTION func_main;
+
+
+--echo #
+--echo # INSERT query inside function
+--echo # FUNCTION(a IN) > INSERT INTO <table> VALUES …
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'EEE', 50);
+
+DELIMITER $$;
+CREATE FUNCTION func_main(IN a INT) RETURNS INT
+BEGIN
+ DECLARE b INT;
+ INSERT INTO Persons VALUE (a, 'FFF', 60);
+ SELECT AGE INTO b FROM Persons WHERE ID = a;
+ RETURN b;
+END;
+$$
+DELIMITER ;$$
+
+SELECT * from Persons;
+SET @a = 6;
+SELECT func_main(@a);
+SELECT * from Persons;
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+
+--echo #
+--echo # INSERT query inside function
+--echo # FUNCTION(a IN, b OUT) > INSERT INTO <table> VALUES …
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'EEE', 50);
+
+DELIMITER $$;
+CREATE FUNCTION func_main(IN a INT, OUT b INT) RETURNS INT
+BEGIN
+ INSERT INTO Persons VALUE (a, 'FFF', 60);
+ SELECT AGE INTO b FROM Persons WHERE ID = a;
+ RETURN 0;
+END;
+$$
+DELIMITER ;$$
+
+SELECT * from Persons;
+SET @a = 6;
+SET @b = 0;
+--error ER_SF_OUT_INOUT_ARG_NOT_ALLOWED
+SELECT func_main(@a, @b);
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+
+--echo #
+--echo # INSERT query inside function
+--echo # FUNCTION(a IN, b INOUT) > INSERT INTO <table> VALUES …
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'EEE', 40);
+
+DELIMITER $$;
+CREATE FUNCTION func_main(IN a INT, INOUT b INT) RETURNS INT
+BEGIN
+ INSERT INTO Persons VALUE (a, 'FFF', 60);
+ SELECT AGE INTO b FROM Persons WHERE ID = a;
+ RETURN 0;
+END;
+$$
+DELIMITER ;$$
+
+SELECT * from Persons;
+SET @a = 6;
+SET @b = 0;
+--error ER_SF_OUT_INOUT_ARG_NOT_ALLOWED
+SELECT func_main(@a, @b);
+DROP TABLE Persons;
+DROP FUNCTION func_main;
+
+--echo #
+--echo # INSERT query inside function
+--echo # FUNCTION(a IN) > FUNCTION(a IN, b OUT) > INSERT INTO <table> VALUES …
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'EEE', 40);
+
+DELIMITER $$;
+CREATE FUNCTION func_sub(IN a INT, OUT b INT) RETURNS INT
+BEGIN
+ INSERT INTO Persons VALUE (a, 'FFF', 60);
+ SELECT AGE INTO b FROM Persons WHERE ID = a;
+ RETURN 0;
+END;
+$$
+CREATE FUNCTION func_main(IN a INT) RETURNS INT
+BEGIN
+ DECLARE b INT;
+ DECLARE res INT;
+ SET res = func_sub(a, b);
+ RETURN b;
+END;
+$$
+DELIMITER ;$$
+
+SELECT * from Persons;
+SET @a = 6;
+SELECT func_main(@a);
+SELECT * from Persons;
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP FUNCTION func_main;
+
+--echo #
+--echo # PROCEDURE > FUNCTION > SQL query
+--echo # PROCEDURE(OUT) > FUNCTION(IN) > SELECT FROM <table> …
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+
+DELIMITER $$;
+CREATE FUNCTION func_sub(IN a INT) RETURNS INT
+BEGIN
+ DECLARE b INT;
+ SELECT AGE INTO b FROM Persons WHERE ID = a;
+ RETURN b;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+ SET b = func_sub(a);
+END;
+$$
+DELIMITER ;$$
+
+SELECT * from Persons;
+SET @a = 2;
+SET @b = 0;
+CALL proc_main(@a, @b);
+SELECT @b;
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+
+--echo #
+--echo # PROCEDURE > FUNCTION > SQL query
+--echo # PROCEDURE(OUT) > FUNCTION(OUT) > SELECT FROM <table> …
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+
+DELIMITER $$;
+CREATE FUNCTION func_sub(IN a INT, OUT b INT) RETURNS INT
+BEGIN
+ SELECT AGE INTO b FROM Persons WHERE ID = a;
+ RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+ DECLARE res INT;
+ SET res = func_sub(a, b);
+END;
+$$
+DELIMITER ;$$
+
+SELECT * from Persons;
+SET @a = 1;
+SET @b = 0;
+CALL proc_main(@a, @b);
+SELECT @b;
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+
+--echo #
+--echo # PROCEDURE > FUNCTION > SQL query
+--echo # PROCEDURE(OUT) > FUNCTION(INOUT) > SELECT FROM <table> …
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+
+DELIMITER $$;
+CREATE FUNCTION func_sub(IN a INT, INOUT c INT) RETURNS INT
+BEGIN
+ DECLARE res INT;
+ SELECT AGE INTO res FROM Persons WHERE ID = a;
+ SET c = c * 100;
+ RETURN res;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+ DECLARE c INT;
+ DECLARE res INT;
+ SET c = 5;
+ SET res = func_sub(a, c);
+ SET b = c;
+END;
+$$
+DELIMITER ;$$
+
+SELECT * from Persons;
+SET @a = 2;
+SET @b = 0;
+CALL proc_main(@a, @b);
+SELECT @b;
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+
+
+--echo #
+--echo # PROCEDURE > FUNCTION > SQL query
+--echo # PROCEDURE(OUT) > FUNCTION(IN) > INSESRT INTO <table> …
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+
+DELIMITER $$;
+CREATE FUNCTION func_sub(IN a INT) RETURNS INT
+BEGIN
+ INSERT INTO Persons VALUE (a, 'FFF', 50);
+ RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+ SET b = func_sub(a);
+END;
+$$
+DELIMITER ;$$
+
+SELECT * from Persons;
+SET @a = 5;
+SET @b = 1;
+CALL proc_main(@a, @b);
+SELECT @b;
+SELECT * from Persons;
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+
+
+--echo #
+--echo # PROCEDURE > FUNCTION > SQL query
+--echo # PROCEDURE(OUT) > FUNCTION(OUT) > INSESRT INTO <table> …
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'FFF', 50);
+
+DELIMITER $$;
+CREATE FUNCTION func_sub(IN a INT, OUT b INT) RETURNS INT
+BEGIN
+ INSERT INTO Persons VALUE (a, 'GGG', 60);
+ RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+ DECLARE res INT;
+ SET res = func_sub(a, b);
+END;
+$$
+DELIMITER ;$$
+
+SELECT * from Persons;
+SET @a = 6;
+SET @b = 0;
+CALL proc_main(@a, @b);
+SELECT * from Persons;
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+
+
+--echo #
+--echo # PROCEDURE > FUNCTION > SQL query
+--echo # PROCEDURE(OUT) > FUNCTION(INOUT) > INSESRT INTO <table> …
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'FFF', 50);
+INSERT INTO Persons VALUES (6, 'GGG', 60);
+
+DELIMITER $$;
+CREATE FUNCTION func_sub(IN a INT, INOUT c INT) RETURNS INT
+BEGIN
+ DECLARE res INT;
+ INSERT INTO Persons VALUE (a, 'HHH', 70);
+ SET c = c * 100;
+ RETURN res;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+ DECLARE c INT;
+ DECLARE res INT;
+ SET c = 5;
+ SET res = func_sub(a, c);
+ SET b = c;
+END;
+$$
+DELIMITER ;$$
+
+SELECT * from Persons;
+SET @a = 7;
+SET @b = 0;
+CALL proc_main(@a, @b);
+SELECT @b;
+SELECT * from Persons;
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+
+
+--echo #
+--echo # PROCEDURE > FUNCTION > SQL query
+--echo # PROCEDURE(OUT) > FUNCTION(IN) > UPDATE <table> SET …
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'FFF', 50);
+INSERT INTO Persons VALUES (6, 'GGG', 60);
+INSERT INTO Persons VALUES (7, 'HHH', 70);
+
+DELIMITER $$;
+CREATE FUNCTION func_sub(IN a INT) RETURNS INT
+BEGIN
+ UPDATE Persons SET AGE = 100 WHERE ID = a;
+ RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+ SET b = func_sub(a);
+END;
+$$
+DELIMITER ;$$
+
+SELECT * from Persons;
+SET @a = 5;
+SET @b = 0;
+CALL proc_main(@a, @b);
+SELECT * from Persons;
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+
+--echo #
+--echo # PROCEDURE > FUNCTION > SQL query
+--echo # PROCEDURE(OUT) > FUNCTION(OUT) > UPDATE <table> SET …
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'FFF', 100);
+INSERT INTO Persons VALUES (6, 'GGG', 60);
+INSERT INTO Persons VALUES (7, 'HHH', 70);
+
+DELIMITER $$;
+CREATE FUNCTION func_sub(IN a INT, OUT b INT) RETURNS INT
+BEGIN
+ UPDATE Persons SET AGE = 100 WHERE ID = a;
+ SET b = 1;
+ RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+ DECLARE res INT;
+ SET res = func_sub(a, b);
+END;
+$$
+DELIMITER ;$$
+
+SELECT * from Persons;
+SET @a = 6;
+SET @b = 0;
+CALL proc_main(@a, @b);
+SELECT @b;
+SELECT * from Persons;
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+
+
+--echo #
+--echo # PROCEDURE > FUNCTION > SQL query
+--echo # PROCEDURE(OUT) > FUNCTION(INOUT) > UPDATE <table> SET …
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+INSERT INTO Persons VALUES (4, 'DDD', 40);
+INSERT INTO Persons VALUES (5, 'FFF', 100);
+INSERT INTO Persons VALUES (6, 'GGG', 100);
+INSERT INTO Persons VALUES (7, 'HHH', 70);
+
+DELIMITER $$;
+CREATE FUNCTION func_sub(IN a INT, INOUT c INT) RETURNS INT
+BEGIN
+ DECLARE res INT;
+ UPDATE Persons SET AGE = 100 WHERE ID = a;
+ SET c = c * 100;
+ RETURN res;
+END;
+$$
+CREATE PROCEDURE proc_main(IN a INT, OUT b INT)
+BEGIN
+ DECLARE c INT;
+ DECLARE res INT;
+ SET c = 5;
+ SET res = func_sub(a, c);
+ SET b = c;
+END;
+$$
+DELIMITER ;$$
+
+SELECT * from Persons;
+SET @a = 7;
+SET @b = 0;
+CALL proc_main(@a, @b);
+SELECT @b;
+SELECT * from Persons;
+DROP TABLE Persons;
+DROP FUNCTION func_sub;
+DROP PROCEDURE proc_main;
+
+
+--echo #
+--echo # Trigger
+--echo # TRIGGER AFTER UPDATE ON TABLE1 > UPDATE TABLE2
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+
+CREATE TABLE PersonsLog (
+ UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+
+DELIMITER $$;
+CREATE OR REPLACE TRIGGER my_trigger
+AFTER UPDATE ON Persons
+FOR EACH ROW
+ UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+$$
+DELIMITER ;$$
+
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+UPDATE Persons SET Age = 20 WHERE ID = 1;
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+DROP TRIGGER my_trigger;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+
+--echo #
+--echo # Trigger
+--echo # TRIGGER AFTER UPDATE ON TABLE1 > FUNCTION(IN) > UPDATE TABLE2
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+
+CREATE TABLE PersonsLog (
+ UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+
+DELIMITER $$;
+CREATE FUNCTION func(IN a INT) RETURNS INT
+BEGIN
+ UPDATE PersonsLog SET UpdateCount = UpdateCount+a;
+ RETURN 0;
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+AFTER UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+ DECLARE a INT;
+ DECLARE res INT;
+ SET a = 1;
+ SET res = 0;
+ SET res = func(a);
+END;
+$$
+DELIMITER ;$$
+
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+UPDATE Persons SET Age = 30 WHERE ID = 1;
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+DROP TRIGGER my_trigger;
+DROP FUNCTION func;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+
+--echo #
+--echo # Trigger
+--echo # TRIGGER AFTER UPDATE ON TABLE1 > FUNCTION(OUT) > UPDATE TABLE2
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 40);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+
+CREATE TABLE PersonsLog (
+ UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+
+DELIMITER $$;
+CREATE FUNCTION func(IN age_in INT, OUT age_out INT) RETURNS INT
+BEGIN
+ UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+ SET age_out = age_in + 1;
+ RETURN 0;
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+BEFORE UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+ DECLARE res INT DEFAULT (func(OLD.age, NEW.age));
+END;
+$$
+DELIMITER ;$$
+
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+UPDATE Persons SET Age = 50 WHERE ID = 1;
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+DROP TRIGGER my_trigger;
+DROP FUNCTION func;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+
+--echo #
+--echo # Trigger
+--echo # TRIGGER AFTER UPDATE ON TABLE1 > FUNCTION(INOUT) > UPDATE TABLE2
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 50);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+
+CREATE TABLE PersonsLog (
+ UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+
+DELIMITER $$;
+CREATE FUNCTION func(INOUT a INT) RETURNS INT
+BEGIN
+ UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+ SET a = 100;
+ RETURN 0;
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+AFTER UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+ DECLARE a INT;
+ DECLARE res INT;
+ SET a = 10;
+ SET res = 0;
+ SET res = func(a);
+END;
+$$
+DELIMITER ;$$
+
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+UPDATE Persons SET Age = 60 WHERE ID = 1;
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+DROP TRIGGER my_trigger;
+DROP FUNCTION func;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+
+--echo #
+--echo # Trigger
+--echo # TRIGGER AFTER UPDATE ON TABLE1 > PROCEDURE(IN) > UPDATE TABLE2
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+
+CREATE TABLE PersonsLog (
+ UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+
+DELIMITER $$;
+CREATE PROCEDURE proc(IN a INT)
+BEGIN
+ UPDATE PersonsLog SET UpdateCount = UpdateCount+a;
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+AFTER UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+ CALL proc(1);
+END;
+$$
+DELIMITER ;$$
+
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+UPDATE Persons SET Age = 30 WHERE ID = 1;
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+DROP TRIGGER my_trigger;
+DROP PROCEDURE proc;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+
+--echo #
+--echo # Trigger
+--echo # TRIGGER AFTER UPDATE ON TABLE1 > PROCEDURE(OUT) > UPDATE TABLE2
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+
+CREATE TABLE PersonsLog (
+ UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+
+DELIMITER $$;
+CREATE PROCEDURE proc(IN old_age INT, OUT new_age INT)
+BEGIN
+ UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+ SET new_age=old_age+41;
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+BEFORE UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+ CALL proc(OLD.age, NEW.age);
+END;
+$$
+DELIMITER ;$$
+
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+UPDATE Persons SET Age = 50 WHERE ID = 1;
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+DROP TRIGGER my_trigger;
+DROP PROCEDURE proc;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+
+--echo #
+--echo # Trigger
+--echo # TRIGGER AFTER UPDATE ON TABLE1 > PROCEDURE(INOUT) > UPDATE TABLE2
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+
+CREATE TABLE PersonsLog (
+ UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+
+DELIMITER $$;
+CREATE PROCEDURE proc(INOUT a INT)
+BEGIN
+ UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+ SET a = 51;
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+BEFORE UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+ CALL proc(NEW.age);
+END;
+$$
+DELIMITER ;$$
+
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+UPDATE Persons SET Age = 50 WHERE ID = 1;
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+DROP TRIGGER my_trigger;
+DROP PROCEDURE proc;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+
+--echo #
+--echo # Trigger
+--echo # TRIGGER AFTER UPDATE ON TABLE1 > PROCEDURE(OUT) > FUNCTION(IN) > UPDATE TABLE2
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+
+CREATE TABLE PersonsLog (
+ UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+
+DELIMITER $$;
+CREATE FUNCTION func(IN a INT) RETURNS INT
+BEGIN
+ UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+ RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc(OUT a INT)
+BEGIN
+ DECLARE res INT;
+ SET a = 100;
+ SET res = func(a);
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+AFTER UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+ CALL proc(@a);
+END;
+$$
+DELIMITER ;$$
+
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+UPDATE Persons SET Age = 60 WHERE ID = 1;
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+DROP TRIGGER my_trigger;
+DROP FUNCTION func;
+DROP PROCEDURE proc;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+
+--echo #
+--echo # Trigger
+--echo # TRIGGER AFTER UPDATE ON TABLE1 > PROCEDURE(OUT) > FUNCTION(OUT) > UPDATE TABLE2
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+
+CREATE TABLE PersonsLog (
+ UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+
+DELIMITER $$;
+CREATE FUNCTION func(OUT a INT) RETURNS INT
+BEGIN
+ SET a = 200;
+ UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+ RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc(OUT a INT)
+BEGIN
+ DECLARE res INT;
+ SET a = 100;
+ SET res = func(a);
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+AFTER UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+ CALL proc(@a);
+END;
+$$
+DELIMITER ;$$
+
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+UPDATE Persons SET Age = 80 WHERE ID = 1;
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+DROP FUNCTION func;
+DROP PROCEDURE proc;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+
+--echo #
+--echo # Trigger
+--echo # TRIGGER AFTER UPDATE ON TABLE1 > PROCEDURE(OUT) > FUNCTION(INOUT) > UPDATE TABLE2
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+
+CREATE TABLE PersonsLog (
+ UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+
+DELIMITER $$;
+CREATE FUNCTION func(INOUT a INT) RETURNS INT
+BEGIN
+ SET a = 200;
+ UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+ RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc(OUT a INT)
+BEGIN
+ DECLARE res INT;
+ SET a = 100;
+ SET res = func(a);
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+AFTER UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+ CALL proc(@a);
+END;
+$$
+DELIMITER ;$$
+
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+UPDATE Persons SET Age = 90 WHERE ID = 1;
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+DROP TRIGGER my_trigger;
+DROP FUNCTION func;
+DROP PROCEDURE proc;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
+
+--echo #
+--echo # Trigger
+--echo # TRIGGER AFTER UPDATE ON TABLE1 > PROCEDURE(OUT) > FUNCTION(OUT) > UPDATE TABLE2 with OUT argument (to check if OUT is returning by reference)
+--echo #
+
+CREATE TABLE Persons (
+ ID int,
+ Name varchar(255),
+ Age int
+);
+INSERT INTO Persons VALUES (1, 'AAA', 10);
+INSERT INTO Persons VALUES (2, 'BBB', 20);
+INSERT INTO Persons VALUES (3, 'CCC', 30);
+
+CREATE TABLE PersonsLog (
+ UpdateCount int
+);
+INSERT INTO PersonsLog VALUES (0);
+
+DELIMITER $$;
+CREATE FUNCTION func(OUT a INT) RETURNS INT
+BEGIN
+ SET a = 111;
+ UPDATE PersonsLog SET UpdateCount = UpdateCount+1;
+ RETURN 0;
+END;
+$$
+CREATE PROCEDURE proc(OUT a INT)
+BEGIN
+ DECLARE res INT;
+ SET res = func(a);
+ UPDATE PersonsLog SET UpdateCount = a;
+END;
+$$
+CREATE OR REPLACE TRIGGER my_trigger
+AFTER UPDATE ON Persons
+FOR EACH ROW
+BEGIN
+ CALL proc(@a);
+END;
+$$
+DELIMITER ;$$
+
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+UPDATE Persons SET Age = 80 WHERE ID = 1;
+SELECT * FROM Persons;
+SELECT * FROM PersonsLog;
+DROP TRIGGER my_trigger;
+DROP FUNCTION func;
+DROP PROCEDURE proc;
+DROP TABLE Persons;
+DROP TABLE PersonsLog;
diff --git a/mysql-test/suite/compat/oracle/r/sp-cursor.result b/mysql-test/suite/compat/oracle/r/sp-cursor.result
index d7e88430bc7..aa9c5de8bc9 100644
--- a/mysql-test/suite/compat/oracle/r/sp-cursor.result
+++ b/mysql-test/suite/compat/oracle/r/sp-cursor.result
@@ -977,3 +977,46 @@ $$
CALL p1();
DROP PROCEDURE p1;
DROP TABLE t1;
+#
+# Start of 10.8 tests
+#
+#
+# MDEV-10654 IN, OUT, INOUT parameters in CREATE FUNCTION
+#
+DECLARE
+va INT;
+CURSOR cur (a IN INT) IS SELECT a FROM dual;
+BEGIN
+OPEN cur(1);
+FETCH cur INTO va;
+CLOSE cur;
+SELECT va;
+END;
+$$
+va
+1
+DECLARE
+va INT;
+CURSOR cur (a OUT INT) IS SELECT a FROM dual;
+BEGIN
+OPEN cur(1);
+FETCH cur INTO va;
+CLOSE cur;
+SELECT va;
+END;
+$$
+ERROR 42000: This version of MariaDB doesn't yet support 'OUT/INOUT cursor parameter'
+DECLARE
+va INT;
+CURSOR cur (a INOUT INT) IS SELECT a FROM dual;
+BEGIN
+OPEN cur(1);
+FETCH cur INTO va;
+CLOSE cur;
+SELECT va;
+END;
+$$
+ERROR 42000: This version of MariaDB doesn't yet support 'OUT/INOUT cursor parameter'
+#
+# End of 10.8 tests
+#
diff --git a/mysql-test/suite/compat/oracle/t/sp-cursor.test b/mysql-test/suite/compat/oracle/t/sp-cursor.test
index 03b8b016ee0..d7e2a5dee68 100644
--- a/mysql-test/suite/compat/oracle/t/sp-cursor.test
+++ b/mysql-test/suite/compat/oracle/t/sp-cursor.test
@@ -987,3 +987,58 @@ DELIMITER ;$$
CALL p1();
DROP PROCEDURE p1;
DROP TABLE t1;
+
+
+--echo #
+--echo # Start of 10.8 tests
+--echo #
+
+--echo #
+--echo # MDEV-10654 IN, OUT, INOUT parameters in CREATE FUNCTION
+--echo #
+
+DELIMITER $$;
+DECLARE
+ va INT;
+ CURSOR cur (a IN INT) IS SELECT a FROM dual;
+BEGIN
+ OPEN cur(1);
+ FETCH cur INTO va;
+ CLOSE cur;
+ SELECT va;
+END;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--error ER_NOT_SUPPORTED_YET
+DECLARE
+ va INT;
+ CURSOR cur (a OUT INT) IS SELECT a FROM dual;
+BEGIN
+ OPEN cur(1);
+ FETCH cur INTO va;
+ CLOSE cur;
+ SELECT va;
+END;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--error ER_NOT_SUPPORTED_YET
+DECLARE
+ va INT;
+ CURSOR cur (a INOUT INT) IS SELECT a FROM dual;
+BEGIN
+ OPEN cur(1);
+ FETCH cur INTO va;
+ CLOSE cur;
+ SELECT va;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # End of 10.8 tests
+--echo #
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index b5f8cf4a886..2ca44721df7 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -7130,6 +7130,27 @@ bool LEX::sp_declare_cursor(THD *thd, const LEX_CSTRING *name,
uint offp;
sp_instr_cpush *i;
+ /* In some cases param_ctx can be NULL. e.g.: FOR rec IN (SELECT...) */
+ if (param_ctx)
+ {
+ for (uint prm= 0; prm < param_ctx->context_var_count(); prm++)
+ {
+ const sp_variable *param= param_ctx->get_context_variable(prm);
+ if (param->mode != sp_variable::MODE_IN)
+ {
+ /*
+ PL/SQL supports the IN keyword in cursor parameters.
+ We also support this for compatibility. Note, OUT/INOUT parameters
+ will unlikely be ever supported. So "YET" may sound confusing here.
+ But it should be better than using a generic error. Adding a dedicated
+ error message for this small issue is not desirable.
+ */
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "OUT/INOUT cursor parameter");
+ return true;
+ }
+ }
+ }
+
if (spcont->find_cursor(name, &offp, true))
{
my_error(ER_SP_DUP_CURS, MYF(0), name->str);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index d80a33bb8b2..d147dd28ba8 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1748,8 +1748,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize);
%type <num> sp_handler_type sp_hcond_list
%type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value
%type <spname> sp_name
-%type <spvar> sp_param_name sp_param_name_and_type
-%type <spvar> sp_param_name_and_type_anchored
+%type <spvar> sp_param_name sp_param_name_and_mode sp_param
+%type <spvar> sp_param_anchored
%type <for_loop> sp_for_loop_index_and_bounds
%type <for_loop_bounds> sp_for_loop_bounds
%type <trim> trim_operands
@@ -3049,8 +3049,8 @@ sp_fdparam_list:
;
sp_fdparams:
- sp_fdparams ',' sp_param_name_and_type
- | sp_param_name_and_type
+ sp_fdparams ',' sp_param
+ | sp_param
;
sp_param_name:
@@ -3068,8 +3068,8 @@ sp_pdparam_list:
;
sp_pdparams:
- sp_pdparams ',' sp_pdparam
- | sp_pdparam
+ sp_pdparams ',' sp_param
+ | sp_param
;
sp_parameter_type:
@@ -18028,11 +18028,6 @@ sp_opt_default:
| DEFAULT expr { $$ = $2; }
;
-sp_pdparam:
- sp_parameter_type sp_param_name_and_type { $2->mode=$1; }
- | sp_param_name_and_type { $1->mode= sp_variable::MODE_IN; }
- ;
-
sp_decl_variable_list_anchored:
sp_decl_idents_init_vars
TYPE_SYM OF_SYM optionally_qualified_column_ident
@@ -18052,40 +18047,49 @@ sp_decl_variable_list_anchored:
}
;
-sp_param_name_and_type:
- sp_param_name field_type
+sp_param_name_and_mode:
+ sp_parameter_type sp_param_name
+ {
+ $2->mode= $1;
+ $$= $2;
+ }
+ | sp_param_name
+ ;
+
+sp_param:
+ sp_param_name_and_mode field_type
{
if (unlikely(Lex->sp_param_fill_definition($$= $1, $2)))
MYSQL_YYABORT;
}
- | sp_param_name ROW_SYM row_type_body
+ | sp_param_name_and_mode ROW_SYM row_type_body
{
if (unlikely(Lex->sphead->spvar_fill_row(thd, $$= $1, $3)))
MYSQL_YYABORT;
}
- | sp_param_name_and_type_anchored
+ | sp_param_anchored
;
-sp_param_name_and_type_anchored:
- sp_param_name TYPE_SYM OF_SYM ident '.' ident
+sp_param_anchored:
+ sp_param_name_and_mode TYPE_SYM OF_SYM ident '.' ident
{
if (unlikely(Lex->sphead->spvar_fill_type_reference(thd,
$$= $1, $4,
$6)))
MYSQL_YYABORT;
}
- | sp_param_name TYPE_SYM OF_SYM ident '.' ident '.' ident
+ | sp_param_name_and_mode TYPE_SYM OF_SYM ident '.' ident '.' ident
{
if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $$= $1,
$4, $6, $8)))
MYSQL_YYABORT;
}
- | sp_param_name ROW_SYM TYPE_SYM OF_SYM ident
+ | sp_param_name_and_mode ROW_SYM TYPE_SYM OF_SYM ident
{
if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $$= $1, $5)))
MYSQL_YYABORT;
}
- | sp_param_name ROW_SYM TYPE_SYM OF_SYM ident '.' ident
+ | sp_param_name_and_mode ROW_SYM TYPE_SYM OF_SYM ident '.' ident
{
if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $$= $1, $5, $7)))
MYSQL_YYABORT;
@@ -18469,46 +18473,6 @@ sp_opt_inout:
| IN_SYM OUT_SYM { $$= sp_variable::MODE_INOUT; }
;
-sp_pdparam:
- sp_param_name sp_opt_inout field_type
- {
- $1->mode= $2;
- if (unlikely(Lex->sp_param_fill_definition($1, $3)))
- MYSQL_YYABORT;
- }
- | sp_param_name sp_opt_inout sp_decl_ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
- {
- $1->mode= $2;
- if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $1, $3, $5)))
- MYSQL_YYABORT;
- }
- | sp_param_name sp_opt_inout sp_decl_ident '.' ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
- {
- $1->mode= $2;
- if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $1, $3, $5, $7)))
- MYSQL_YYABORT;
- }
- | sp_param_name sp_opt_inout sp_decl_ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
- {
- $1->mode= $2;
- if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $1, $3)))
- MYSQL_YYABORT;
- }
- | sp_param_name sp_opt_inout sp_decl_ident '.' ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
- {
- $1->mode= $2;
- if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $1, $3, $5)))
- MYSQL_YYABORT;
- }
- | sp_param_name sp_opt_inout ROW_SYM row_type_body
- {
- $1->mode= $2;
- if (unlikely(Lex->sphead->spvar_fill_row(thd, $1, $4)))
- MYSQL_YYABORT;
- }
- ;
-
-
sp_proc_stmts1_implicit_block:
{
Lex->sp_block_init(thd);
@@ -18940,45 +18904,47 @@ sp_decl_variable_list_anchored:
}
;
-sp_param_name_and_type:
- sp_param_name sp_opt_inout field_type
+sp_param_name_and_mode:
+ sp_param_name sp_opt_inout
+ {
+ $1->mode= $2;
+ $$= $1;
+ }
+ ;
+
+sp_param:
+ sp_param_name_and_mode field_type
{
- $1->mode= $2;
- if (unlikely(Lex->sp_param_fill_definition($$= $1, $3)))
+ if (unlikely(Lex->sp_param_fill_definition($$= $1, $2)))
MYSQL_YYABORT;
}
- | sp_param_name sp_opt_inout ROW_SYM row_type_body
+ | sp_param_name_and_mode ROW_SYM row_type_body
{
- $1->mode= $2;
- if (unlikely(Lex->sphead->spvar_fill_row(thd, $$= $1, $4)))
+ if (unlikely(Lex->sphead->spvar_fill_row(thd, $$= $1, $3)))
MYSQL_YYABORT;
}
- | sp_param_name_and_type_anchored
+ | sp_param_anchored
;
-sp_param_name_and_type_anchored:
- sp_param_name sp_opt_inout sp_decl_ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
+sp_param_anchored:
+ sp_param_name_and_mode sp_decl_ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
{
- $1->mode= $2;
- if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $$= $1, $3, $5)))
+ if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $$= $1, $2, $4)))
MYSQL_YYABORT;
}
- | sp_param_name sp_opt_inout sp_decl_ident '.' ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
+ | sp_param_name_and_mode sp_decl_ident '.' ident '.' ident PERCENT_ORACLE_SYM TYPE_SYM
{
- $1->mode= $2;
- if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $$= $1, $3, $5, $7)))
+ if (unlikely(Lex->sphead->spvar_fill_type_reference(thd, $$= $1, $2, $4, $6)))
MYSQL_YYABORT;
}
- | sp_param_name sp_opt_inout sp_decl_ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
+ | sp_param_name_and_mode sp_decl_ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
{
- $1->mode= $2;
- if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $$= $1, $3)))
+ if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $$= $1, $2)))
MYSQL_YYABORT;
}
- | sp_param_name sp_opt_inout sp_decl_ident '.' ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
+ | sp_param_name_and_mode sp_decl_ident '.' ident PERCENT_ORACLE_SYM ROWTYPE_ORACLE_SYM
{
- $1->mode= $2;
- if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $$= $1, $3, $5)))
+ if (unlikely(Lex->sphead->spvar_fill_table_rowtype_reference(thd, $$= $1, $2, $4)))
MYSQL_YYABORT;
}
;