summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2017-02-02 22:59:07 +0400
committerAlexander Barkov <bar@mariadb.org>2017-04-05 15:02:56 +0400
commit72f43df623261d5fe579cb355451d84216c8882d (patch)
tree6d2921d9e807e624244af9273b2332e184a5bc60
parentffbb2bbc09e7fc8c0f60d5c42ce521b4c31c94a7 (diff)
downloadmariadb-git-72f43df623261d5fe579cb355451d84216c8882d.tar.gz
MDEV-10914 ROW data type for stored routine variables
-rw-r--r--mysql-test/r/keywords.result2
-rw-r--r--mysql-test/r/sp-row.result2122
-rw-r--r--mysql-test/r/sp-vars.result1
-rw-r--r--mysql-test/r/variables.result4
-rw-r--r--mysql-test/suite/binlog/r/binlog_stm_sp_type_row.result179
-rw-r--r--mysql-test/suite/binlog/t/binlog_stm_sp_type_row.test81
-rw-r--r--mysql-test/suite/compat/oracle/r/binlog_stm_sp.result179
-rw-r--r--mysql-test/suite/compat/oracle/r/func_concat.result2
-rw-r--r--mysql-test/suite/compat/oracle/r/sp-code.result95
-rw-r--r--mysql-test/suite/compat/oracle/r/sp-row.result2200
-rw-r--r--mysql-test/suite/compat/oracle/t/binlog_stm_sp.test81
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-code.test85
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-row-vs-var.inc6
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-row.test1398
-rw-r--r--mysql-test/t/keywords.test2
-rw-r--r--mysql-test/t/sp-row-vs-var.inc6
-rw-r--r--mysql-test/t/sp-row.test1329
-rw-r--r--mysql-test/t/variables.test4
-rw-r--r--sql/field.cc1
-rw-r--r--sql/field.h70
-rw-r--r--sql/item.cc120
-rw-r--r--sql/item.h245
-rw-r--r--sql/item_func.cc55
-rw-r--r--sql/item_func.h8
-rw-r--r--sql/share/errmsg-utf8.txt2
-rw-r--r--sql/sp_head.cc157
-rw-r--r--sql/sp_head.h42
-rw-r--r--sql/sp_pcontext.cc21
-rw-r--r--sql/sp_pcontext.h14
-rw-r--r--sql/sp_rcontext.cc122
-rw-r--r--sql/sp_rcontext.h4
-rw-r--r--sql/sql_class.cc5
-rw-r--r--sql/sql_class.h16
-rw-r--r--sql/sql_lex.cc230
-rw-r--r--sql/sql_lex.h130
-rw-r--r--sql/sql_list.h12
-rw-r--r--sql/sql_select.cc17
-rw-r--r--sql/sql_test.cc6
-rw-r--r--sql/sql_type.cc18
-rw-r--r--sql/sql_yacc.yy214
-rw-r--r--sql/sql_yacc_ora.yy238
-rw-r--r--sql/structs.h6
42 files changed, 9226 insertions, 303 deletions
diff --git a/mysql-test/r/keywords.result b/mysql-test/r/keywords.result
index 687a122d628..e2f29f7cfb5 100644
--- a/mysql-test/r/keywords.result
+++ b/mysql-test/r/keywords.result
@@ -274,7 +274,7 @@ drop table option;
set option=1;
ERROR HY000: Unknown system variable 'option'
set option option=1;
-ERROR HY000: Unknown system variable 'option'
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'option=1' at line 1
#
# MDEV-9979 Keywords UNBOUNDED, PRECEDING, FOLLOWING, TIES, OTHERS should be non-reserved
#
diff --git a/mysql-test/r/sp-row.result b/mysql-test/r/sp-row.result
new file mode 100644
index 00000000000..8c4973ba46c
--- /dev/null
+++ b/mysql-test/r/sp-row.result
@@ -0,0 +1,2122 @@
+#
+# MDEV-10914 ROW data type for stored routine variables
+#
+#
+# ROW of ROWs is not supported yet
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW(a ROW(a INT));
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ROW(a INT));
+END' at line 3
+#
+# Returning the entire ROW parameter from a function
+#
+CREATE FUNCTION f1(a ROW(a INT, b INT)) RETURNS INT
+BEGIN
+RETURN a;
+END;
+$$
+SELECT f1(ROW(10,20));
+ERROR 21000: Operand should contain 1 column(s)
+DROP FUNCTION f1;
+#
+# ROW as an SP parameter
+#
+CREATE FUNCTION f1(a ROW(a INT,b INT)) RETURNS INT
+BEGIN
+RETURN a.b;
+END;
+$$
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW(a INT,b INT) DEFAULT (11,21);
+SELECT f1(a);
+END;
+$$
+SELECT f1(ROW(10,20));
+f1(ROW(10,20))
+20
+SELECT f1(10);
+ERROR 21000: Operand should contain 2 column(s)
+SELECT f1(ROW(10,20,30));
+ERROR 21000: Operand should contain 2 column(s)
+CALL p1();
+f1(a)
+21
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+CREATE PROCEDURE p1(a ROW(a INT,b INT))
+BEGIN
+SELECT a.a, a.b;
+END;
+$$
+CALL p1(ROW(10,20));
+a.a a.b
+10 20
+CALL p1(10);
+ERROR 21000: Operand should contain 2 column(s)
+CALL p1(ROW(10,20,30));
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# ROW as an SP OUT parameter
+#
+CREATE PROCEDURE p1(OUT a ROW(a INT,b INT))
+BEGIN
+SET a.a=10;
+SET a.b=20;
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+DECLARE a ROW(a INT,b INT) DEFAULT (11,21);
+CALL p1(a);
+SELECT a.a,a.b;
+END;
+$$
+CALL p2();
+a.a a.b
+10 20
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+#
+# ROW as an SP return value is not supported yet
+#
+CREATE FUNCTION p1() RETURNS ROW(a INT)
+BEGIN
+RETURN NULL;
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ROW(a INT)
+BEGIN
+RETURN NULL;
+END' at line 1
+#
+# Diplicate row field
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT, a DOUBLE);
+SELECT a.a;
+END;
+$$
+ERROR 42S21: Duplicate column name 'a'
+#
+# Bad scalar default value
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT, b DOUBLE) DEFAULT 1;
+SELECT a.a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# Bad ROW default value with a wrong number of fields
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT, b DOUBLE) DEFAULT ROW(1,2,3);
+SELECT a.a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# Bad usage of a scalar variable as a row
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a INT;
+SELECT a.x FROM t1;
+END;
+$$
+ERROR HY000: 'a' is not a row variable
+#
+# Using the entire ROW variable in select list
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT);
+SELECT a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT,b INT);
+SELECT a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Using the entire ROW variable in functions
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT);
+SELECT COALESCE(a);
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT,b INT);
+SELECT COALESCE(a);
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT);
+SELECT a+1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT,b INT);
+SELECT a+1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Comparing the entire ROW to a scalar value
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT,b INT);
+SELECT a=1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT,b INT);
+SELECT 1=a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Passing the entire ROW to a stored function
+#
+CREATE FUNCTION f1(a INT) RETURNS INT
+BEGIN
+RETURN a;
+END;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW (a INT,b INT);
+SELECT f1(a);
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+#
+# Assigning a scalar value to a ROW variable with 1 column
+#
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT);
+SET rec=1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Assigning a scalar value to a ROW variable with 2 columns
+#
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT,b INT);
+SET rec=1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# Assigning a ROW value to a ROW variable with different number of columns
+#
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT,b INT);
+SET rec=ROW(1,2,3);
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# Returning the entire ROW from a function is not supported yet
+# This syntax would be needed: SELECT f1().x FROM DUAL;
+#
+CREATE FUNCTION f1(a INT) RETURNS INT
+BEGIN
+DECLARE rec ROW(a INT);
+RETURN rec;
+END;
+$$
+SELECT f1(10);
+ERROR 21000: Operand should contain 1 column(s)
+DROP FUNCTION f1;
+#
+# Using the entire ROW in SELECT..CREATE
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT,b INT);
+CREATE TABLE t1 AS SELECT rec;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Using the entire ROW in LIMIT
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT);
+SET rec.a= '10';
+SELECT * FROM t1 LIMIT rec;
+END;
+$$
+ERROR HY000: A variable of a non-integer based type in LIMIT clause
+#
+# Setting ROW fields using a SET command
+#
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT,b DOUBLE,c VARCHAR(10));
+DECLARE a INT;
+SET @a= 10, rec.a=10, rec.b=20, rec.c= 'test', a= 5;
+SELECT rec.a, rec.b, rec.c, a;
+END;
+$$
+CALL p1();
+rec.a rec.b rec.c a
+10 20 test 5
+DROP PROCEDURE p1;
+#
+# Assigning a ROW variable from a ROW value
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT,b INT);
+SET rec=ROW(1,2);
+SELECT rec.a, rec.b;
+END;
+$$
+CALL p1();
+rec.a rec.b
+1 2
+DROP PROCEDURE p1;
+#
+# Assigning a ROW variable from another ROW value
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW(a INT,b INT);
+DECLARE rec2 ROW(a INT,b INT);
+SET rec1=ROW(1,2);
+SET rec2=rec1;
+SELECT rec2.a, rec2.b;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+1 2
+DROP PROCEDURE p1;
+#
+# Comparing a ROW variable to a ROW() function
+#
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT,b INT);
+SET rec.a= 1;
+SET rec.b= 2;
+SELECT rec=(0,0), rec=ROW(0,0), (0,0)=rec, ROW(0,0)=rec;
+SELECT rec=(1,2), rec=ROW(1,2), (1,2)=rec, ROW(1,2)=rec;
+SELECT rec=(NULL,0), rec=ROW(NULL,0);
+SELECT rec=(NULL,2), rec=ROW(NULL,2);
+SELECT rec<>(0,0), rec<>ROW(0,0);
+SELECT rec<>(1,2), rec<>ROW(1,2);
+SELECT rec<>(NULL,0), rec<>ROW(NULL,0);
+SELECT rec<>(NULL,2), rec<>ROW(NULL,2);
+SELECT rec IN ((0,0)), rec IN (ROW(0,0));
+SELECT rec IN ((1,2)), rec IN (ROW(1,2));
+SELECT rec IN ((0,NULL),(1,2));
+SELECT rec NOT IN ((0,NULL),(1,1));
+SELECT rec NOT IN ((1,NULL),(1,1));
+END;
+$$
+CALL p1();
+rec=(0,0) rec=ROW(0,0) (0,0)=rec ROW(0,0)=rec
+0 0 0 0
+rec=(1,2) rec=ROW(1,2) (1,2)=rec ROW(1,2)=rec
+1 1 1 1
+rec=(NULL,0) rec=ROW(NULL,0)
+0 0
+rec=(NULL,2) rec=ROW(NULL,2)
+NULL NULL
+rec<>(0,0) rec<>ROW(0,0)
+1 1
+rec<>(1,2) rec<>ROW(1,2)
+0 0
+rec<>(NULL,0) rec<>ROW(NULL,0)
+1 1
+rec<>(NULL,2) rec<>ROW(NULL,2)
+NULL NULL
+rec IN ((0,0)) rec IN (ROW(0,0))
+0 0
+rec IN ((1,2)) rec IN (ROW(1,2))
+1 1
+rec IN ((0,NULL),(1,2))
+1
+rec NOT IN ((0,NULL),(1,1))
+1
+rec NOT IN ((1,NULL),(1,1))
+NULL
+DROP PROCEDURE p1;
+#
+# Comparing a ROW variable to another ROW variable
+#
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+DECLARE rec1,rec2,rec3 ROW(a INT,b INT);
+SET rec1.a= 1;
+SET rec1.b= 2;
+SET rec2.a= 11;
+SET rec2.b= 12;
+SET rec3.a= 11;
+SET rec3.b= 12;
+SELECT rec1=rec2, rec2=rec1, rec2=rec3, rec3=rec2;
+END;
+$$
+CALL p1();
+rec1=rec2 rec2=rec1 rec2=rec3 rec3=rec2
+0 0 1 1
+DROP PROCEDURE p1;
+#
+# Referencing a non-existing row variable
+#
+CREATE PROCEDURE p1()
+BEGIN
+SET a.b=1;
+END;
+$$
+ERROR HY000: Unknown structured system variable or ROW routine variable 'a'
+#
+# Referencing a non-existing row field
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW(a INT,b INT);
+SELECT a.c FROM t1;
+END;
+$$
+ERROR HY000: Row variable 'a' does not have a field 'c'
+#
+# ROW and scalar variables with the same name shadowing each other
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW(a INT);
+SET a.a=100;
+SELECT a.a;
+BEGIN
+DECLARE a INT DEFAULT 200;
+SELECT a;
+BEGIN
+DECLARE a ROW(a INT);
+SET a.a=300;
+SELECT a.a;
+END;
+SELECT a;
+END;
+SELECT a.a;
+END;
+$$
+CALL p1();
+a.a
+100
+a
+200
+a.a
+300
+a
+200
+a.a
+100
+DROP PROCEDURE p1;
+#
+# ROW with good default values
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE a ROW(a INT,b INT) DEFAULT (10,20);
+DECLARE b ROW(a INT,b INT) DEFAULT (11,21);
+DECLARE c ROW(a INT,b INT) DEFAULT a;
+SELECT a.a, a.b, b.a, b.b, c.a, c.b FROM DUAL;
+END;
+$$
+CALL p1;
+a.a a.b b.a b.b c.a c.b
+10 20 11 21 10 20
+DROP PROCEDURE p1;
+#
+# ROW in WHERE clause
+#
+CREATE TABLE t1 (a INT,b INT);
+INSERT INTO t1 VALUES (10,20);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT,b INT) DEFAULT ROW(10,20);
+SELECT * FROM t1 WHERE rec=ROW(a,b);
+SELECT * FROM t1 WHERE ROW(a,b)=rec;
+SELECT * FROM t1 WHERE rec=ROW(10,20);
+SELECT * FROM t1 WHERE ROW(10,20)=rec;
+END;
+$$
+CALL p1();
+a b
+10 20
+a b
+10 20
+a b
+10 20
+a b
+10 20
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields in WHERE clause
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT);
+SET rec.a= 10;
+SELECT * FROM t1 WHERE a=rec.a;
+END;
+$$
+CALL p1();
+a
+10
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields in HAVING clause
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT);
+SET rec.a= 10;
+SELECT * FROM t1 HAVING a=rec.a;
+SELECT * FROM t1 HAVING MIN(a)=rec.a;
+END;
+$$
+CALL p1();
+a
+10
+a
+10
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields in LIMIT clause
+#
+CREATE TABLE t1 (a INT);
+SELECT 1 FROM t1 LIMIT t1.a;
+ERROR 42000: Undeclared variable: t1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT);
+SET rec.a= 10;
+SELECT * FROM t1 LIMIT rec.a;
+END;
+$$
+CALL p1();
+a
+10
+20
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a VARCHAR(10));
+SET rec.a= '10';
+SELECT * FROM t1 LIMIT rec.a;
+END;
+$$
+ERROR HY000: A variable of a non-integer based type in LIMIT clause
+#
+# ROW fields in select list
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE t1 ROW(a INT);
+SET t1.a= 10;
+SELECT t1.a, 'This is the variable t1.a value, rather than the column t1.a' AS comm FROM t1;
+SELECT t1.a, t2.a, t1.a+t2.a FROM t1 t2;
+END;
+$$
+CALL p1();
+t1.a comm
+10 This is the variable t1.a value, rather than the column t1.a
+10 This is the variable t1.a value, rather than the column t1.a
+t1.a a t1.a+t2.a
+10 10 20
+10 20 30
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields as insert values
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT, b VARCHAR(10));
+SET rec.a= 10;
+SET rec.b= 'test';
+INSERT INTO t1 VALUES (rec.a, rec.b);
+END;
+$$
+CALL p1();
+SELECT * FROM t1;
+a b
+10 test
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields as SP out parameters
+#
+CREATE PROCEDURE p1(OUT a INT, OUT b VARCHAR(32))
+BEGIN
+SET a= 10;
+SET b= 'test';
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+DECLARE rec ROW(a INT, b VARCHAR(10));
+CALL p1(rec.a, rec.b);
+SELECT rec.a, rec.b;
+END;
+$$
+CALL p2;
+rec.a rec.b
+10 test
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+#
+# ROW fields as dynamic SQL out parameters
+#
+CREATE PROCEDURE p1(OUT a INT, OUT b VARCHAR(32))
+BEGIN
+SET a= 20;
+SET b= 'test-dynamic-sql';
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+DECLARE rec ROW(a INT, b VARCHAR(30));
+EXECUTE IMMEDIATE 'CALL p1(?,?)' USING rec.a, rec.b;
+SELECT rec.a, rec.b;
+END;
+$$
+CALL p2;
+rec.a rec.b
+20 test-dynamic-sql
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+#
+# ROW fields as SELECT..INTO targets
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT, b VARCHAR(10));
+SELECT 10,'test' INTO rec.a,rec.b;
+SELECT rec.a, rec.b;
+END;
+$$
+CALL p1;
+rec.a rec.b
+10 test
+DROP PROCEDURE p1;
+#
+# Implicit default NULL handling
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec ROW(a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,0), e TIME, f DATETIME);
+SELECT rec.a, rec.b, rec.c, rec.d, rec.e, rec.f FROM DUAL;
+END;
+$$
+CALL p1();
+rec.a rec.b rec.c rec.d rec.e rec.f
+NULL NULL NULL NULL NULL NULL
+DROP PROCEDURE p1;
+#
+# NULL handling
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1 ROW(a INT, b VARCHAR(10)) DEFAULT (NULL,NULL);
+DECLARE rec2 ROW(a INT, b VARCHAR(10)) DEFAULT rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+SET rec1= (10,20);
+SET rec2= rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+SET rec1= (NULL,20);
+SET rec2= rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+SET rec1= (10,NULL);
+SET rec2= rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+SET rec1= (NULL,NULL);
+SET rec2= rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+END;
+$$
+CALL p1;
+rec1.a rec1.b rec2.a rec2.b
+NULL NULL NULL NULL
+rec1.a rec1.b rec2.a rec2.b
+10 20 10 20
+rec1.a rec1.b rec2.a rec2.b
+NULL 20 NULL 20
+rec1.a rec1.b rec2.a rec2.b
+10 NULL 10 NULL
+rec1.a rec1.b rec2.a rec2.b
+NULL NULL NULL NULL
+DROP PROCEDURE p1;
+#
+# Testing multiple ROW variable declarations
+# This makes sure that fill_field_definitions() is called only once
+# per a ROW field, so create length is not converted to internal length
+# multiple times.
+#
+CREATE PROCEDURE p1()
+BEGIN
+DECLARE rec1, rec2, rec3 ROW(a VARCHAR(10) CHARACTER SET utf8);
+CREATE TABLE t1 AS SELECT rec1.a, rec2.a, rec3.a;
+END;
+$$
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `rec1.a` varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ `rec2.a` varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ `rec3.a` varchar(10) CHARACTER SET utf8 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# INT
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var INT; DECLARE rec ROW(var INT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(11) DEFAULT NULL,
+ `rec.var` bigint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(1); DECLARE rec ROW(var INT(1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(11) DEFAULT NULL,
+ `rec.var` bigint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(2); DECLARE rec ROW(var INT(2)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(11) DEFAULT NULL,
+ `rec.var` bigint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(3); DECLARE rec ROW(var INT(3)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(11) DEFAULT NULL,
+ `rec.var` bigint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(4); DECLARE rec ROW(var INT(4)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(11) DEFAULT NULL,
+ `rec.var` bigint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(5); DECLARE rec ROW(var INT(5)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(11) DEFAULT NULL,
+ `rec.var` bigint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(6); DECLARE rec ROW(var INT(6)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(11) DEFAULT NULL,
+ `rec.var` bigint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(7); DECLARE rec ROW(var INT(7)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(11) DEFAULT NULL,
+ `rec.var` bigint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(8); DECLARE rec ROW(var INT(8)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(11) DEFAULT NULL,
+ `rec.var` bigint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(9); DECLARE rec ROW(var INT(9)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(11) DEFAULT NULL,
+ `rec.var` bigint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(10); DECLARE rec ROW(var INT(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(11) DEFAULT NULL,
+ `rec.var` bigint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(11); DECLARE rec ROW(var INT(11)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(11) DEFAULT NULL,
+ `rec.var` bigint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(12); DECLARE rec ROW(var INT(12)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(12) DEFAULT NULL,
+ `rec.var` bigint(12) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(13); DECLARE rec ROW(var INT(13)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(13) DEFAULT NULL,
+ `rec.var` bigint(13) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(14); DECLARE rec ROW(var INT(14)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(14) DEFAULT NULL,
+ `rec.var` bigint(14) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(20); DECLARE rec ROW(var INT(20)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var INT(21); DECLARE rec ROW(var INT(21)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(21) DEFAULT NULL,
+ `rec.var` bigint(21) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# TINYINT
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT; DECLARE rec ROW(var TINYINT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(4) DEFAULT NULL,
+ `rec.var` int(4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(1); DECLARE rec ROW(var TINYINT(1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(4) DEFAULT NULL,
+ `rec.var` int(4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(2); DECLARE rec ROW(var TINYINT(2)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(4) DEFAULT NULL,
+ `rec.var` int(4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(3); DECLARE rec ROW(var TINYINT(3)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(4) DEFAULT NULL,
+ `rec.var` int(4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(4); DECLARE rec ROW(var TINYINT(4)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(4) DEFAULT NULL,
+ `rec.var` int(4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(5); DECLARE rec ROW(var TINYINT(5)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(5) DEFAULT NULL,
+ `rec.var` int(5) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(6); DECLARE rec ROW(var TINYINT(6)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(6) DEFAULT NULL,
+ `rec.var` int(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(7); DECLARE rec ROW(var TINYINT(7)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(7) DEFAULT NULL,
+ `rec.var` int(7) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(8); DECLARE rec ROW(var TINYINT(8)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(8) DEFAULT NULL,
+ `rec.var` int(8) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(9); DECLARE rec ROW(var TINYINT(9)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(9) DEFAULT NULL,
+ `rec.var` int(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(10); DECLARE rec ROW(var TINYINT(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(10) DEFAULT NULL,
+ `rec.var` bigint(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(11); DECLARE rec ROW(var TINYINT(11)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(11) DEFAULT NULL,
+ `rec.var` bigint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(12); DECLARE rec ROW(var TINYINT(12)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(12) DEFAULT NULL,
+ `rec.var` bigint(12) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(13); DECLARE rec ROW(var TINYINT(13)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(13) DEFAULT NULL,
+ `rec.var` bigint(13) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(14); DECLARE rec ROW(var TINYINT(14)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(14) DEFAULT NULL,
+ `rec.var` bigint(14) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(20); DECLARE rec ROW(var TINYINT(20)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYINT(21); DECLARE rec ROW(var TINYINT(21)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(21) DEFAULT NULL,
+ `rec.var` bigint(21) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# SMALLINT
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT; DECLARE rec ROW(var SMALLINT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(6) DEFAULT NULL,
+ `rec.var` int(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(1); DECLARE rec ROW(var SMALLINT(1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(6) DEFAULT NULL,
+ `rec.var` int(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(2); DECLARE rec ROW(var SMALLINT(2)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(6) DEFAULT NULL,
+ `rec.var` int(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(3); DECLARE rec ROW(var SMALLINT(3)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(6) DEFAULT NULL,
+ `rec.var` int(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(4); DECLARE rec ROW(var SMALLINT(4)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(6) DEFAULT NULL,
+ `rec.var` int(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(5); DECLARE rec ROW(var SMALLINT(5)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(6) DEFAULT NULL,
+ `rec.var` int(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(6); DECLARE rec ROW(var SMALLINT(6)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(6) DEFAULT NULL,
+ `rec.var` int(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(7); DECLARE rec ROW(var SMALLINT(7)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(7) DEFAULT NULL,
+ `rec.var` int(7) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(8); DECLARE rec ROW(var SMALLINT(8)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(8) DEFAULT NULL,
+ `rec.var` int(8) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(9); DECLARE rec ROW(var SMALLINT(9)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(9) DEFAULT NULL,
+ `rec.var` int(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(10); DECLARE rec ROW(var SMALLINT(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(10) DEFAULT NULL,
+ `rec.var` bigint(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(11); DECLARE rec ROW(var SMALLINT(11)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(11) DEFAULT NULL,
+ `rec.var` bigint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(12); DECLARE rec ROW(var SMALLINT(12)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(12) DEFAULT NULL,
+ `rec.var` bigint(12) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(13); DECLARE rec ROW(var SMALLINT(13)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(13) DEFAULT NULL,
+ `rec.var` bigint(13) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(14); DECLARE rec ROW(var SMALLINT(14)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(14) DEFAULT NULL,
+ `rec.var` bigint(14) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(20); DECLARE rec ROW(var SMALLINT(20)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var SMALLINT(21); DECLARE rec ROW(var SMALLINT(21)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(21) DEFAULT NULL,
+ `rec.var` bigint(21) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# MEDIUMINT
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT; DECLARE rec ROW(var MEDIUMINT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(9) DEFAULT NULL,
+ `rec.var` int(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(1); DECLARE rec ROW(var MEDIUMINT(1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(9) DEFAULT NULL,
+ `rec.var` int(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(2); DECLARE rec ROW(var MEDIUMINT(2)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(9) DEFAULT NULL,
+ `rec.var` int(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(3); DECLARE rec ROW(var MEDIUMINT(3)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(9) DEFAULT NULL,
+ `rec.var` int(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(4); DECLARE rec ROW(var MEDIUMINT(4)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(9) DEFAULT NULL,
+ `rec.var` int(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(5); DECLARE rec ROW(var MEDIUMINT(5)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(9) DEFAULT NULL,
+ `rec.var` int(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(6); DECLARE rec ROW(var MEDIUMINT(6)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(9) DEFAULT NULL,
+ `rec.var` int(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(7); DECLARE rec ROW(var MEDIUMINT(7)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(9) DEFAULT NULL,
+ `rec.var` int(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(8); DECLARE rec ROW(var MEDIUMINT(8)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(9) DEFAULT NULL,
+ `rec.var` int(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(9); DECLARE rec ROW(var MEDIUMINT(9)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` int(9) DEFAULT NULL,
+ `rec.var` int(9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(10); DECLARE rec ROW(var MEDIUMINT(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(10) DEFAULT NULL,
+ `rec.var` bigint(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(11); DECLARE rec ROW(var MEDIUMINT(11)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(11) DEFAULT NULL,
+ `rec.var` bigint(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(12); DECLARE rec ROW(var MEDIUMINT(12)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(12) DEFAULT NULL,
+ `rec.var` bigint(12) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(13); DECLARE rec ROW(var MEDIUMINT(13)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(13) DEFAULT NULL,
+ `rec.var` bigint(13) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(14); DECLARE rec ROW(var MEDIUMINT(14)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(14) DEFAULT NULL,
+ `rec.var` bigint(14) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(20); DECLARE rec ROW(var MEDIUMINT(20)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMINT(21); DECLARE rec ROW(var MEDIUMINT(21)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(21) DEFAULT NULL,
+ `rec.var` bigint(21) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# BIGINT
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT; DECLARE rec ROW(var BIGINT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(1); DECLARE rec ROW(var BIGINT(1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(2); DECLARE rec ROW(var BIGINT(2)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(3); DECLARE rec ROW(var BIGINT(3)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(4); DECLARE rec ROW(var BIGINT(4)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(5); DECLARE rec ROW(var BIGINT(5)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(6); DECLARE rec ROW(var BIGINT(6)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(7); DECLARE rec ROW(var BIGINT(7)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(8); DECLARE rec ROW(var BIGINT(8)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(9); DECLARE rec ROW(var BIGINT(9)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(10); DECLARE rec ROW(var BIGINT(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(11); DECLARE rec ROW(var BIGINT(11)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(12); DECLARE rec ROW(var BIGINT(12)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(13); DECLARE rec ROW(var BIGINT(13)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(14); DECLARE rec ROW(var BIGINT(14)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(20); DECLARE rec ROW(var BIGINT(20)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(20) DEFAULT NULL,
+ `rec.var` bigint(20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BIGINT(21); DECLARE rec ROW(var BIGINT(21)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` bigint(21) DEFAULT NULL,
+ `rec.var` bigint(21) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# DOUBLE
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE; DECLARE rec ROW(var DOUBLE); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double DEFAULT NULL,
+ `rec.var` double DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,1); DECLARE rec ROW(var DOUBLE(30,1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,1) DEFAULT NULL,
+ `rec.var` double(30,1) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,2); DECLARE rec ROW(var DOUBLE(30,2)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,2) DEFAULT NULL,
+ `rec.var` double(30,2) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,3); DECLARE rec ROW(var DOUBLE(30,3)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,3) DEFAULT NULL,
+ `rec.var` double(30,3) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,4); DECLARE rec ROW(var DOUBLE(30,4)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,4) DEFAULT NULL,
+ `rec.var` double(30,4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,5); DECLARE rec ROW(var DOUBLE(30,5)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,5) DEFAULT NULL,
+ `rec.var` double(30,5) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,6); DECLARE rec ROW(var DOUBLE(30,6)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,6) DEFAULT NULL,
+ `rec.var` double(30,6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,7); DECLARE rec ROW(var DOUBLE(30,7)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,7) DEFAULT NULL,
+ `rec.var` double(30,7) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,8); DECLARE rec ROW(var DOUBLE(30,8)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,8) DEFAULT NULL,
+ `rec.var` double(30,8) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,9); DECLARE rec ROW(var DOUBLE(30,9)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,9) DEFAULT NULL,
+ `rec.var` double(30,9) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,10); DECLARE rec ROW(var DOUBLE(30,10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,10) DEFAULT NULL,
+ `rec.var` double(30,10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,11); DECLARE rec ROW(var DOUBLE(30,11)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,11) DEFAULT NULL,
+ `rec.var` double(30,11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,12); DECLARE rec ROW(var DOUBLE(30,12)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,12) DEFAULT NULL,
+ `rec.var` double(30,12) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,13); DECLARE rec ROW(var DOUBLE(30,13)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,13) DEFAULT NULL,
+ `rec.var` double(30,13) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,14); DECLARE rec ROW(var DOUBLE(30,14)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,14) DEFAULT NULL,
+ `rec.var` double(30,14) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,20); DECLARE rec ROW(var DOUBLE(30,20)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,20) DEFAULT NULL,
+ `rec.var` double(30,20) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DOUBLE(30,21); DECLARE rec ROW(var DOUBLE(30,21)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` double(30,21) DEFAULT NULL,
+ `rec.var` double(30,21) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# VARCHAR
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var CHAR; DECLARE rec ROW(var CHAR); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varchar(1) DEFAULT NULL,
+ `rec.var` varchar(1) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BINARY; DECLARE rec ROW(var BINARY); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varbinary(1) DEFAULT NULL,
+ `rec.var` varbinary(1) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var CHAR(1); DECLARE rec ROW(var CHAR(1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varchar(1) DEFAULT NULL,
+ `rec.var` varchar(1) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var CHAR(10); DECLARE rec ROW(var CHAR(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varchar(10) DEFAULT NULL,
+ `rec.var` varchar(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var NCHAR(10); DECLARE rec ROW(var NCHAR(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ `rec.var` varchar(10) CHARACTER SET utf8 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var BINARY(10); DECLARE rec ROW(var BINARY(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varbinary(10) DEFAULT NULL,
+ `rec.var` varbinary(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var VARBINARY(10); DECLARE rec ROW(var VARBINARY(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varbinary(10) DEFAULT NULL,
+ `rec.var` varbinary(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var VARCHAR(10); DECLARE rec ROW(var VARCHAR(10)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varchar(10) DEFAULT NULL,
+ `rec.var` varchar(10) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var VARCHAR(10) CHARACTER SET utf8; DECLARE rec ROW(var VARCHAR(10) CHARACTER SET utf8); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ `rec.var` varchar(10) CHARACTER SET utf8 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_bin; DECLARE rec ROW(var VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_bin); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
+ `rec.var` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# TIME
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var TIME; DECLARE rec ROW(var TIME); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` time DEFAULT NULL,
+ `rec.var` time DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TIME(1); DECLARE rec ROW(var TIME(1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` time(1) DEFAULT NULL,
+ `rec.var` time(1) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TIME(2); DECLARE rec ROW(var TIME(2)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` time(2) DEFAULT NULL,
+ `rec.var` time(2) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TIME(3); DECLARE rec ROW(var TIME(3)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` time(3) DEFAULT NULL,
+ `rec.var` time(3) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TIME(4); DECLARE rec ROW(var TIME(4)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` time(4) DEFAULT NULL,
+ `rec.var` time(4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TIME(5); DECLARE rec ROW(var TIME(5)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` time(5) DEFAULT NULL,
+ `rec.var` time(5) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TIME(6); DECLARE rec ROW(var TIME(6)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` time(6) DEFAULT NULL,
+ `rec.var` time(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# DATETIME
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var DATETIME; DECLARE rec ROW(var DATETIME); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` datetime DEFAULT NULL,
+ `rec.var` datetime DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DATETIME(1); DECLARE rec ROW(var DATETIME(1)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` datetime(1) DEFAULT NULL,
+ `rec.var` datetime(1) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DATETIME(2); DECLARE rec ROW(var DATETIME(2)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` datetime(2) DEFAULT NULL,
+ `rec.var` datetime(2) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DATETIME(3); DECLARE rec ROW(var DATETIME(3)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` datetime(3) DEFAULT NULL,
+ `rec.var` datetime(3) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DATETIME(4); DECLARE rec ROW(var DATETIME(4)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` datetime(4) DEFAULT NULL,
+ `rec.var` datetime(4) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DATETIME(5); DECLARE rec ROW(var DATETIME(5)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` datetime(5) DEFAULT NULL,
+ `rec.var` datetime(5) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var DATETIME(6); DECLARE rec ROW(var DATETIME(6)); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` datetime(6) DEFAULT NULL,
+ `rec.var` datetime(6) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# LOB
+#
+CREATE PROCEDURE p1() BEGIN DECLARE var TEXT; DECLARE rec ROW(var TEXT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` text DEFAULT NULL,
+ `rec.var` text DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYTEXT; DECLARE rec ROW(var TINYTEXT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varchar(255) DEFAULT NULL,
+ `rec.var` varchar(255) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMTEXT; DECLARE rec ROW(var MEDIUMTEXT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumtext DEFAULT NULL,
+ `rec.var` mediumtext DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var LONGTEXT; DECLARE rec ROW(var LONGTEXT); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` longtext DEFAULT NULL,
+ `rec.var` longtext DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TEXT CHARACTER SET utf8; DECLARE rec ROW(var TEXT CHARACTER SET utf8); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` mediumtext CHARACTER SET utf8 DEFAULT NULL,
+ `rec.var` mediumtext CHARACTER SET utf8 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var TINYTEXT CHARACTER SET utf8; DECLARE rec ROW(var TINYTEXT CHARACTER SET utf8); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
+ `rec.var` varchar(255) CHARACTER SET utf8 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var MEDIUMTEXT CHARACTER SET utf8; DECLARE rec ROW(var MEDIUMTEXT CHARACTER SET utf8); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` longtext CHARACTER SET utf8 DEFAULT NULL,
+ `rec.var` longtext CHARACTER SET utf8 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() BEGIN DECLARE var LONGTEXT CHARACTER SET utf8; DECLARE rec ROW(var LONGTEXT CHARACTER SET utf8); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `var` longtext CHARACTER SET utf8 DEFAULT NULL,
+ `rec.var` longtext CHARACTER SET utf8 DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# End of MDEV-10914 ROW data type for stored routine variables
+#
diff --git a/mysql-test/r/sp-vars.result b/mysql-test/r/sp-vars.result
index 0a7ea0d68c5..c2f36437c9d 100644
--- a/mysql-test/r/sp-vars.result
+++ b/mysql-test/r/sp-vars.result
@@ -673,7 +673,6 @@ vb IS TRUE;
END|
call p1();
HEX(b) b = 0 b = FALSE b IS FALSE b = 1 b = TRUE b IS TRUE
-
0 1 1 1 0 0 0
1 0 0 0 1 1 1
call p2();
diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result
index bca59b5225a..676432690b4 100644
--- a/mysql-test/r/variables.result
+++ b/mysql-test/r/variables.result
@@ -672,9 +672,9 @@ select @a, @b;
@a @b
2 1
set @@global.global.key_buffer_size= 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key_buffer_size= 1' at line 1
+ERROR HY000: Unknown structured system variable or ROW routine variable 'global'
set GLOBAL global.key_buffer_size= 1;
-ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key_buffer_size= 1' at line 1
+ERROR HY000: Unknown structured system variable or ROW routine variable 'global'
SELECT @@global.global.key_buffer_size;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'key_buffer_size' at line 1
SELECT @@global.session.key_buffer_size;
diff --git a/mysql-test/suite/binlog/r/binlog_stm_sp_type_row.result b/mysql-test/suite/binlog/r/binlog_stm_sp_type_row.result
new file mode 100644
index 00000000000..55d0dc13e56
--- /dev/null
+++ b/mysql-test/suite/binlog/r/binlog_stm_sp_type_row.result
@@ -0,0 +1,179 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-10914 ROW data type for stored routine variables
+#
+CREATE TABLE t1 (a INT, b INT);
+CREATE PROCEDURE p1
+AS
+rec ROW(a INT,b INT);
+BEGIN
+rec.a:=100;
+rec.b:=200;
+INSERT INTO t1 VALUES (rec.a,rec.b);
+INSERT INTO t1 VALUES (10, rec=ROW(100,200));
+INSERT INTO t1 VALUES (10, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.a:=NULL;
+INSERT INTO t1 VALUES (11, rec=ROW(100,200));
+INSERT INTO t1 VALUES (11, rec=ROW(100,201));
+INSERT INTO t1 VALUES (11, ROW(100,200)=rec);
+INSERT INTO t1 VALUES (11, ROW(100,201)=rec);
+INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.b:=NULL;
+INSERT INTO t1 VALUES (12, rec=ROW(100,200));
+INSERT INTO t1 VALUES (12, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=rec;
+END;
+$$
+CALL p1();
+SELECT * FROM t1;
+a b
+100 200
+10 1
+10 1
+10 20
+10 21
+11 NULL
+11 0
+11 NULL
+11 0
+12 NULL
+12 NULL
+DROP TABLE t1;
+DROP PROCEDURE p1;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b INT)
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
+AS
+rec ROW(a INT,b INT);
+BEGIN
+rec.a:=100;
+rec.b:=200;
+INSERT INTO t1 VALUES (rec.a,rec.b);
+INSERT INTO t1 VALUES (10, rec=ROW(100,200));
+INSERT INTO t1 VALUES (10, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.a:=NULL;
+INSERT INTO t1 VALUES (11, rec=ROW(100,200));
+INSERT INTO t1 VALUES (11, rec=ROW(100,201));
+INSERT INTO t1 VALUES (11, ROW(100,200)=rec);
+INSERT INTO t1 VALUES (11, ROW(100,201)=rec);
+INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.b:=NULL;
+INSERT INTO t1 VALUES (12, rec=ROW(100,200));
+INSERT INTO t1 VALUES (12, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=rec;
+END
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('rec.a',100), NAME_CONST('rec.b',200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10, ROW(100,200)=ROW(100,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10, ROW(100,200)=ROW(100,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE ROW(100,200)=ROW(100,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=ROW(100,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(NULL,200)=ROW(100,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(NULL,200)=ROW(100,201))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(100,200)=ROW(NULL,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(100,201)=ROW(NULL,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE ROW(NULL,200)=ROW(100,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=ROW(NULL,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (12, ROW(NULL,NULL)=ROW(100,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (12, ROW(100,200)=ROW(NULL,NULL))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE ROW(NULL,NULL)=ROW(100,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=ROW(NULL,NULL)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; DROP TABLE "t1" /* generated by server */
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; DROP PROCEDURE p1
+#
+# Testing ROW fields in LIMIT
+#
+FLUSH LOGS;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(10);
+CREATE TABLE t2 (a INT);
+CREATE PROCEDURE p1()
+AS
+a INT:= 1;
+rec ROW(a INT);
+BEGIN
+rec.a:= 1;
+INSERT INTO t2 SELECT 1 FROM t1 LIMIT a;
+INSERT INTO t2 SELECT 2 FROM t1 LIMIT rec.a;
+END;
+$$
+CALL p1();
+Warnings:
+Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted
+DROP TABLE t1,t2;
+DROP PROCEDURE p1;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000002 # Binlog_checkpoint # # master-bin.000002
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE TABLE t1 (a INT)
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (10),(10)
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE TABLE t2 (a INT)
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
+AS
+a INT:= 1;
+rec ROW(a INT);
+BEGIN
+rec.a:= 1;
+INSERT INTO t2 SELECT 1 FROM t1 LIMIT a;
+INSERT INTO t2 SELECT 2 FROM t1 LIMIT rec.a;
+END
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t2 SELECT 1 FROM t1 LIMIT 1
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t2 SELECT 2 FROM t1 LIMIT 1
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; DROP TABLE "t1","t2" /* generated by server */
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; DROP PROCEDURE p1
+#
+# End of MDEV-10914 ROW data type for stored routine variables
+#
diff --git a/mysql-test/suite/binlog/t/binlog_stm_sp_type_row.test b/mysql-test/suite/binlog/t/binlog_stm_sp_type_row.test
new file mode 100644
index 00000000000..cd0d9111107
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_stm_sp_type_row.test
@@ -0,0 +1,81 @@
+--source include/not_embedded.inc
+--source include/have_binlog_format_statement.inc
+
+--disable_query_log
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+reset master; # get rid of previous tests binlog
+--enable_query_log
+
+
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-10914 ROW data type for stored routine variables
+--echo #
+
+CREATE TABLE t1 (a INT, b INT);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec ROW(a INT,b INT);
+BEGIN
+ rec.a:=100;
+ rec.b:=200;
+ INSERT INTO t1 VALUES (rec.a,rec.b);
+ INSERT INTO t1 VALUES (10, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (10, ROW(100,200)=rec);
+ INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=rec;
+ rec.a:=NULL;
+ INSERT INTO t1 VALUES (11, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (11, rec=ROW(100,201));
+ INSERT INTO t1 VALUES (11, ROW(100,200)=rec);
+ INSERT INTO t1 VALUES (11, ROW(100,201)=rec);
+ INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=rec;
+ rec.b:=NULL;
+ INSERT INTO t1 VALUES (12, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (12, ROW(100,200)=rec);
+ INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=rec;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+
+--echo #
+--echo # Testing ROW fields in LIMIT
+--echo #
+
+FLUSH LOGS;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(10);
+CREATE TABLE t2 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a INT:= 1;
+ rec ROW(a INT);
+BEGIN
+ rec.a:= 1;
+ INSERT INTO t2 SELECT 1 FROM t1 LIMIT a;
+ INSERT INTO t2 SELECT 2 FROM t1 LIMIT rec.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1,t2;
+DROP PROCEDURE p1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+
+--echo #
+--echo # End of MDEV-10914 ROW data type for stored routine variables
+--echo #
diff --git a/mysql-test/suite/compat/oracle/r/binlog_stm_sp.result b/mysql-test/suite/compat/oracle/r/binlog_stm_sp.result
new file mode 100644
index 00000000000..55d0dc13e56
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/binlog_stm_sp.result
@@ -0,0 +1,179 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-10914 ROW data type for stored routine variables
+#
+CREATE TABLE t1 (a INT, b INT);
+CREATE PROCEDURE p1
+AS
+rec ROW(a INT,b INT);
+BEGIN
+rec.a:=100;
+rec.b:=200;
+INSERT INTO t1 VALUES (rec.a,rec.b);
+INSERT INTO t1 VALUES (10, rec=ROW(100,200));
+INSERT INTO t1 VALUES (10, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.a:=NULL;
+INSERT INTO t1 VALUES (11, rec=ROW(100,200));
+INSERT INTO t1 VALUES (11, rec=ROW(100,201));
+INSERT INTO t1 VALUES (11, ROW(100,200)=rec);
+INSERT INTO t1 VALUES (11, ROW(100,201)=rec);
+INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.b:=NULL;
+INSERT INTO t1 VALUES (12, rec=ROW(100,200));
+INSERT INTO t1 VALUES (12, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=rec;
+END;
+$$
+CALL p1();
+SELECT * FROM t1;
+a b
+100 200
+10 1
+10 1
+10 20
+10 21
+11 NULL
+11 0
+11 NULL
+11 0
+12 NULL
+12 NULL
+DROP TABLE t1;
+DROP PROCEDURE p1;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE TABLE t1 (a INT, b INT)
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
+AS
+rec ROW(a INT,b INT);
+BEGIN
+rec.a:=100;
+rec.b:=200;
+INSERT INTO t1 VALUES (rec.a,rec.b);
+INSERT INTO t1 VALUES (10, rec=ROW(100,200));
+INSERT INTO t1 VALUES (10, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.a:=NULL;
+INSERT INTO t1 VALUES (11, rec=ROW(100,200));
+INSERT INTO t1 VALUES (11, rec=ROW(100,201));
+INSERT INTO t1 VALUES (11, ROW(100,200)=rec);
+INSERT INTO t1 VALUES (11, ROW(100,201)=rec);
+INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=rec;
+rec.b:=NULL;
+INSERT INTO t1 VALUES (12, rec=ROW(100,200));
+INSERT INTO t1 VALUES (12, ROW(100,200)=rec);
+INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE rec=ROW(100,200);
+INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=rec;
+END
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES ( NAME_CONST('rec.a',100), NAME_CONST('rec.b',200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10, ROW(100,200)=ROW(100,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (10, ROW(100,200)=ROW(100,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE ROW(100,200)=ROW(100,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=ROW(100,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(NULL,200)=ROW(100,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(NULL,200)=ROW(100,201))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(100,200)=ROW(NULL,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (11, ROW(100,201)=ROW(NULL,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE ROW(NULL,200)=ROW(100,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=ROW(NULL,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (12, ROW(NULL,NULL)=ROW(100,200))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (12, ROW(100,200)=ROW(NULL,NULL))
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE ROW(NULL,NULL)=ROW(100,200)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # BEGIN GTID #-#-#
+master-bin.000001 # Query # # use `test`; INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=ROW(NULL,NULL)
+master-bin.000001 # Query # # COMMIT
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; DROP TABLE "t1" /* generated by server */
+master-bin.000001 # Gtid # # GTID #-#-#
+master-bin.000001 # Query # # use `test`; DROP PROCEDURE p1
+#
+# Testing ROW fields in LIMIT
+#
+FLUSH LOGS;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(10);
+CREATE TABLE t2 (a INT);
+CREATE PROCEDURE p1()
+AS
+a INT:= 1;
+rec ROW(a INT);
+BEGIN
+rec.a:= 1;
+INSERT INTO t2 SELECT 1 FROM t1 LIMIT a;
+INSERT INTO t2 SELECT 2 FROM t1 LIMIT rec.a;
+END;
+$$
+CALL p1();
+Warnings:
+Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted
+DROP TABLE t1,t2;
+DROP PROCEDURE p1;
+include/show_binlog_events.inc
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000002 # Binlog_checkpoint # # master-bin.000002
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE TABLE t1 (a INT)
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t1 VALUES (10),(10)
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE TABLE t2 (a INT)
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; CREATE DEFINER="root"@"localhost" PROCEDURE "p1"()
+AS
+a INT:= 1;
+rec ROW(a INT);
+BEGIN
+rec.a:= 1;
+INSERT INTO t2 SELECT 1 FROM t1 LIMIT a;
+INSERT INTO t2 SELECT 2 FROM t1 LIMIT rec.a;
+END
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t2 SELECT 1 FROM t1 LIMIT 1
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # BEGIN GTID #-#-#
+master-bin.000002 # Query # # use `test`; INSERT INTO t2 SELECT 2 FROM t1 LIMIT 1
+master-bin.000002 # Query # # COMMIT
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; DROP TABLE "t1","t2" /* generated by server */
+master-bin.000002 # Gtid # # GTID #-#-#
+master-bin.000002 # Query # # use `test`; DROP PROCEDURE p1
+#
+# End of MDEV-10914 ROW data type for stored routine variables
+#
diff --git a/mysql-test/suite/compat/oracle/r/func_concat.result b/mysql-test/suite/compat/oracle/r/func_concat.result
index 5d66fba220f..d938c013ba7 100644
--- a/mysql-test/suite/compat/oracle/r/func_concat.result
+++ b/mysql-test/suite/compat/oracle/r/func_concat.result
@@ -141,7 +141,7 @@ INSERT INTO t1 VALUES (NULL, NULL, '');
INSERT INTO t1 VALUES (NULL, NULL, 'c');
INSERT INTO t1 VALUES (NULL, NULL, NULL);
SELECT LENGTH(a||b||c), a||b||c FROM t1 ORDER BY a,b,c;
-LENGTH(a||b||c) a||b||c
+LENGTH(a||b||c) a||b||c
NULL NULL
0
1 c
diff --git a/mysql-test/suite/compat/oracle/r/sp-code.result b/mysql-test/suite/compat/oracle/r/sp-code.result
index 5a67e8c3c1d..8bc940fc154 100644
--- a/mysql-test/suite/compat/oracle/r/sp-code.result
+++ b/mysql-test/suite/compat/oracle/r/sp-code.result
@@ -887,3 +887,98 @@ DROP PROCEDURE p1;
#
# End of MDEV-10597 Cursors with parameters
#
+#
+# MDEV-10914 ROW data type for stored routine variables
+#
+CREATE FUNCTION f1() RETURN INT
+AS
+a ROW(a INT, b INT);
+BEGIN
+a.b:= 200;
+RETURN a.b;
+END;
+$$
+SHOW FUNCTION CODE f1;
+Pos Instruction
+0 set a@0 NULL
+1 set a.b@0[1] 200
+2 freturn 3 a.b@0[1]
+SELECT f1();
+f1()
+200
+DROP FUNCTION f1;
+CREATE PROCEDURE p1
+AS
+rec ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10));
+BEGIN
+rec:= ROW(10,20.123456,30.123,'test');
+SELECT rec.a, rec.b, rec.c, rec.d;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set rec@0 NULL
+1 set rec@0 (10,20.123456,30.123,'test')
+2 stmt 0 "SELECT rec.a, rec.b, rec.c, rec.d"
+CALL p1;
+rec.a rec.b rec.c rec.d
+10 20.123456 30.123 test
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+rec ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10)) :=
+ROW(10,20.123456,30.123,'test');
+BEGIN
+SELECT rec.a, rec.b, rec.c, rec.d;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set rec@0 (10,20.123456,30.123,'test')
+1 stmt 0 "SELECT rec.a, rec.b, rec.c, rec.d"
+CALL p1;
+rec.a rec.b rec.c rec.d
+10 20.123456 30.123 test
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+rec1 ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10));
+rec2 ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10));
+BEGIN
+rec1:= ROW(10,20.123456,30.123,'test');
+rec2:= rec1;
+SELECT rec2.a, rec2.b, rec2.c, rec2.d;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set rec1@0 NULL
+1 set rec2@1 NULL
+2 set rec1@0 (10,20.123456,30.123,'test')
+3 set rec2@1 rec1@0
+4 stmt 0 "SELECT rec2.a, rec2.b, rec2.c, rec2.d"
+CALL p1;
+rec2.a rec2.b rec2.c rec2.d
+10 20.123456 30.123 test
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1
+AS
+rec1 ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10)) :=
+ROW(10,20.123456,30.123,'test');
+rec2 ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10)) := rec1;
+BEGIN
+SELECT rec2.a, rec2.b, rec2.c, rec2.d;
+END;
+$$
+SHOW PROCEDURE CODE p1;
+Pos Instruction
+0 set rec1@0 (10,20.123456,30.123,'test')
+1 set rec2@1 rec1@0
+2 stmt 0 "SELECT rec2.a, rec2.b, rec2.c, rec2.d"
+CALL p1;
+rec2.a rec2.b rec2.c rec2.d
+10 20.123456 30.123 test
+DROP PROCEDURE p1;
+#
+# End of MDEV-10914 ROW data type for stored routine variables
+#
diff --git a/mysql-test/suite/compat/oracle/r/sp-row.result b/mysql-test/suite/compat/oracle/r/sp-row.result
new file mode 100644
index 00000000000..bffdb7c619f
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/r/sp-row.result
@@ -0,0 +1,2200 @@
+SET sql_mode=ORACLE;
+#
+# MDEV-10914 ROW data type for stored routine variables
+#
+#
+# ROW of ROWs is not supported yet
+#
+CREATE PROCEDURE p1()
+AS
+a ROW(a ROW(a INT));
+BEGIN
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ROW(a INT));
+BEGIN
+END' at line 3
+#
+# Returning the entire ROW parameter from a function
+#
+CREATE FUNCTION f1(a ROW(a INT, b INT)) RETURN INT
+AS
+BEGIN
+RETURN a;
+END;
+$$
+SELECT f1(ROW(10,20));
+ERROR 21000: Operand should contain 1 column(s)
+DROP FUNCTION f1;
+#
+# ROW as an SP parameter
+#
+CREATE FUNCTION f1(a ROW(a INT,b INT)) RETURN INT
+AS
+BEGIN
+RETURN a.b;
+END;
+$$
+CREATE PROCEDURE p1()
+AS
+a ROW(a INT,b INT):=(11,21);
+BEGIN
+SELECT f1(a);
+END;
+$$
+SELECT f1(ROW(10,20));
+f1(ROW(10,20))
+20
+SELECT f1(10);
+ERROR 21000: Operand should contain 2 column(s)
+SELECT f1(ROW(10,20,30));
+ERROR 21000: Operand should contain 2 column(s)
+CALL p1();
+f1(a)
+21
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+CREATE PROCEDURE p1(a ROW(a INT,b INT))
+AS
+BEGIN
+SELECT a.a, a.b;
+END;
+$$
+CALL p1(ROW(10,20));
+a.a a.b
+10 20
+CALL p1(10);
+ERROR 21000: Operand should contain 2 column(s)
+CALL p1(ROW(10,20,30));
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# ROW as an SP OUT parameter
+#
+CREATE PROCEDURE p1(a OUT ROW(a INT,b INT))
+AS
+BEGIN
+a.a:=10;
+a.b:=20;
+END;
+$$
+CREATE PROCEDURE p2
+AS
+a ROW(a INT,b INT):=(11,21);
+BEGIN
+CALL p1(a);
+SELECT a.a,a.b;
+END;
+$$
+CALL p2();
+a.a a.b
+10 20
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+#
+# ROW as an SP return value is not supported yet
+#
+CREATE FUNCTION p1() RETURN ROW(a INT)
+AS
+BEGIN
+RETURN NULL;
+END;
+$$
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'ROW(a INT)
+AS
+BEGIN
+RETURN NULL;
+END' at line 1
+#
+# Diplicate row field
+#
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT, a DOUBLE);
+BEGIN
+SELECT a.a;
+END;
+$$
+ERROR 42S21: Duplicate column name 'a'
+#
+# Bad scalar default value
+#
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT, b DOUBLE):= 1;
+BEGIN
+SELECT a.a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# Bad ROW default value with a wrong number of fields
+#
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT, b DOUBLE):= ROW(1,2,3);
+BEGIN
+SELECT a.a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# Bad usage of a scalar variable as a row
+#
+CREATE PROCEDURE p1()
+AS
+a INT;
+BEGIN
+SELECT a.x FROM t1;
+END;
+$$
+ERROR HY000: 'a' is not a row variable
+#
+# Using the entire ROW variable in select list
+#
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT);
+BEGIN
+SELECT a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT,b INT);
+BEGIN
+SELECT a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Using the entire ROW variable in functions
+#
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT);
+BEGIN
+SELECT COALESCE(a);
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT,b INT);
+BEGIN
+SELECT COALESCE(a);
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT);
+BEGIN
+SELECT a+1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT,b INT);
+BEGIN
+SELECT a+1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Comparing the entire ROW to a scalar value
+#
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT,b INT);
+BEGIN
+SELECT a=1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT,b INT);
+BEGIN
+SELECT 1=a;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Passing the entire ROW to a stored function
+#
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+BEGIN
+RETURN a;
+END;
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT,b INT);
+BEGIN
+SELECT f1(a);
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+BEGIN
+RETURN a;
+END;
+CREATE PROCEDURE p1()
+AS
+a ROW (a INT);
+BEGIN
+SELECT f1(a);
+END;
+$$
+CALL p1();
+f1(a)
+NULL
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+#
+# Assigning a scalar value to a ROW variable with 1 column
+#
+CREATE OR REPLACE PROCEDURE p1
+AS
+rec ROW(a INT);
+BEGIN
+rec:=1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Assigning a scalar value to a ROW variable with 2 columns
+#
+CREATE OR REPLACE PROCEDURE p1
+AS
+rec ROW(a INT,b INT);
+BEGIN
+rec:=1;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# Assigning a ROW value to a ROW variable with different number of columns
+#
+CREATE OR REPLACE PROCEDURE p1
+AS
+rec ROW(a INT,b INT);
+BEGIN
+rec:=ROW(1,2,3);
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 2 column(s)
+DROP PROCEDURE p1;
+#
+# Returning the entire ROW from a function is not supported yet
+# This syntax would be needed: SELECT f1().x FROM DUAL;
+#
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+rec ROW(a INT);
+BEGIN
+RETURN rec;
+END;
+$$
+SELECT f1(10);
+ERROR 21000: Operand should contain 1 column(s)
+DROP FUNCTION f1;
+#
+# Using the entire ROW in SELECT..CREATE
+#
+CREATE PROCEDURE p1
+AS
+rec ROW(a INT,b INT);
+BEGIN
+CREATE TABLE t1 AS SELECT rec;
+END;
+$$
+CALL p1();
+ERROR 21000: Operand should contain 1 column(s)
+DROP PROCEDURE p1;
+#
+# Using the entire ROW in LIMIT
+#
+CREATE PROCEDURE p1()
+AS
+rec ROW(a INT);
+BEGIN
+rec.a:= '10';
+SELECT * FROM t1 LIMIT rec;
+END;
+$$
+ERROR HY000: A variable of a non-integer based type in LIMIT clause
+#
+# Setting ROW fields using a SET command
+#
+CREATE OR REPLACE PROCEDURE p1
+AS
+rec ROW(a INT,b DOUBLE,c VARCHAR(10));
+a INT;
+BEGIN
+SET @a= 10, rec.a=10, rec.b=20, rec.c= 'test', a= 5;
+SELECT rec.a, rec.b, rec.c, a;
+END;
+$$
+CALL p1();
+rec.a rec.b rec.c a
+10 20 test 5
+DROP PROCEDURE p1;
+#
+# Assigning a ROW variable from a ROW value
+#
+CREATE PROCEDURE p1
+AS
+rec ROW(a INT,b INT);
+BEGIN
+rec:=ROW(1,2);
+SELECT rec.a, rec.b;
+END;
+$$
+CALL p1();
+rec.a rec.b
+1 2
+DROP PROCEDURE p1;
+#
+# Assigning a ROW variable from another ROW value
+#
+CREATE PROCEDURE p1
+AS
+rec1 ROW(a INT,b INT);
+rec2 ROW(a INT,b INT);
+BEGIN
+rec1:=ROW(1,2);
+rec2:=rec1;
+SELECT rec2.a, rec2.b;
+END;
+$$
+CALL p1();
+rec2.a rec2.b
+1 2
+DROP PROCEDURE p1;
+#
+# Comparing a ROW variable to a ROW() function
+#
+CREATE OR REPLACE PROCEDURE p1
+AS
+rec ROW(a INT,b INT);
+BEGIN
+rec.a:= 1;
+rec.b:= 2;
+SELECT rec=(0,0), rec=ROW(0,0), (0,0)=rec, ROW(0,0)=rec;
+SELECT rec=(1,2), rec=ROW(1,2), (1,2)=rec, ROW(1,2)=rec;
+SELECT rec=(NULL,0), rec=ROW(NULL,0);
+SELECT rec=(NULL,2), rec=ROW(NULL,2);
+SELECT rec<>(0,0), rec<>ROW(0,0);
+SELECT rec<>(1,2), rec<>ROW(1,2);
+SELECT rec<>(NULL,0), rec<>ROW(NULL,0);
+SELECT rec<>(NULL,2), rec<>ROW(NULL,2);
+SELECT rec IN ((0,0)), rec IN (ROW(0,0));
+SELECT rec IN ((1,2)), rec IN (ROW(1,2));
+SELECT rec IN ((0,NULL),(1,2));
+SELECT rec NOT IN ((0,NULL),(1,1));
+SELECT rec NOT IN ((1,NULL),(1,1));
+END;
+$$
+CALL p1();
+rec=(0,0) rec=ROW(0,0) (0,0)=rec ROW(0,0)=rec
+0 0 0 0
+rec=(1,2) rec=ROW(1,2) (1,2)=rec ROW(1,2)=rec
+1 1 1 1
+rec=(NULL,0) rec=ROW(NULL,0)
+0 0
+rec=(NULL,2) rec=ROW(NULL,2)
+NULL NULL
+rec<>(0,0) rec<>ROW(0,0)
+1 1
+rec<>(1,2) rec<>ROW(1,2)
+0 0
+rec<>(NULL,0) rec<>ROW(NULL,0)
+1 1
+rec<>(NULL,2) rec<>ROW(NULL,2)
+NULL NULL
+rec IN ((0,0)) rec IN (ROW(0,0))
+0 0
+rec IN ((1,2)) rec IN (ROW(1,2))
+1 1
+rec IN ((0,NULL),(1,2))
+1
+rec NOT IN ((0,NULL),(1,1))
+1
+rec NOT IN ((1,NULL),(1,1))
+NULL
+DROP PROCEDURE p1;
+#
+# Comparing a ROW variable to another ROW variable
+#
+CREATE OR REPLACE PROCEDURE p1
+AS
+rec1,rec2,rec3 ROW(a INT,b INT);
+BEGIN
+rec1.a:= 1;
+rec1.b:= 2;
+rec2.a:= 11;
+rec2.b:= 12;
+rec3.a:= 11;
+rec3.b:= 12;
+SELECT rec1=rec2, rec2=rec1, rec2=rec3, rec3=rec2;
+END;
+$$
+CALL p1();
+rec1=rec2 rec2=rec1 rec2=rec3 rec3=rec2
+0 0 1 1
+DROP PROCEDURE p1;
+#
+# Referencing a non-existing row variable
+#
+CREATE PROCEDURE p1()
+AS
+BEGIN
+SET a.b=1;
+END;
+$$
+ERROR HY000: Unknown structured system variable or ROW routine variable 'a'
+CREATE PROCEDURE p1()
+AS
+BEGIN
+a.b:=1;
+END;
+$$
+ERROR HY000: Unknown structured system variable or ROW routine variable 'a'
+#
+# Referencing a non-existing row field
+#
+CREATE PROCEDURE p1()
+AS
+a ROW(a INT,b INT);
+BEGIN
+SELECT a.c FROM t1;
+END;
+$$
+ERROR HY000: Row variable 'a' does not have a field 'c'
+#
+# ROW and scalar variables with the same name shadowing each other
+#
+CREATE PROCEDURE p1()
+AS
+a ROW(a INT);
+BEGIN
+a.a:=100;
+DECLARE
+a INT:= 200;
+BEGIN
+SELECT a;
+DECLARE
+a ROW(a INT);
+BEGIN
+a.a:=300;
+SELECT a.a;
+END;
+SELECT a;
+END;
+SELECT a.a;
+END;
+$$
+CALL p1();
+a
+200
+a.a
+300
+a
+200
+a.a
+100
+DROP PROCEDURE p1;
+#
+# ROW with good default values
+#
+CREATE PROCEDURE p1()
+AS
+a ROW(a INT,b INT):= (10,20);
+b ROW(a INT,b INT):= (11,21);
+c ROW(a INT,b INT):= a;
+BEGIN
+SELECT a.a, a.b, b.a, b.b, c.a, c.b FROM DUAL;
+END;
+$$
+CALL p1;
+a.a a.b b.a b.b c.a c.b
+10 20 11 21 10 20
+DROP PROCEDURE p1;
+#
+# ROW in WHERE clause
+#
+CREATE TABLE t1 (a INT,b INT);
+INSERT INTO t1 VALUES (10,20);
+CREATE PROCEDURE p1()
+AS
+rec ROW(a INT,b INT):=ROW(10,20);
+BEGIN
+SELECT * FROM t1 WHERE rec=ROW(a,b);
+SELECT * FROM t1 WHERE ROW(a,b)=rec;
+SELECT * FROM t1 WHERE rec=ROW(10,20);
+SELECT * FROM t1 WHERE ROW(10,20)=rec;
+END;
+$$
+CALL p1();
+a b
+10 20
+a b
+10 20
+a b
+10 20
+a b
+10 20
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields in WHERE clause
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+AS
+rec ROW(a INT);
+BEGIN
+rec.a:= 10;
+SELECT * FROM t1 WHERE a=rec.a;
+END;
+$$
+CALL p1();
+a
+10
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields in HAVING clause
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+AS
+rec ROW(a INT);
+BEGIN
+rec.a:= 10;
+SELECT * FROM t1 HAVING a=rec.a;
+SELECT * FROM t1 HAVING MIN(a)=rec.a;
+END;
+$$
+CALL p1();
+a
+10
+a
+10
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields in LIMIT clause
+#
+CREATE TABLE t1 (a INT);
+SELECT 1 FROM t1 LIMIT t1.a;
+ERROR 42000: Undeclared variable: t1
+DROP TABLE t1;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+AS
+rec ROW(a INT);
+BEGIN
+rec.a:= 10;
+SELECT * FROM t1 LIMIT rec.a;
+END;
+$$
+CALL p1();
+a
+10
+20
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1()
+AS
+rec ROW(a VARCHAR(10));
+BEGIN
+rec.a:= '10';
+SELECT * FROM t1 LIMIT rec.a;
+END;
+$$
+ERROR HY000: A variable of a non-integer based type in LIMIT clause
+#
+# ROW fields in select list
+#
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+CREATE PROCEDURE p1()
+AS
+t1 ROW(a INT);
+BEGIN
+t1.a:= 10;
+SELECT t1.a, 'This is the variable t1.a value, rather than the column t1.a' AS comm FROM t1;
+SELECT t1.a, t2.a, t1.a+t2.a FROM t1 t2;
+END;
+$$
+CALL p1();
+t1.a comm
+10 This is the variable t1.a value, rather than the column t1.a
+10 This is the variable t1.a value, rather than the column t1.a
+t1.a a t1.a+t2.a
+10 10 20
+10 20 30
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields as insert values
+#
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+CREATE PROCEDURE p1()
+AS
+rec ROW(a INT, b VARCHAR(10));
+BEGIN
+rec.a:= 10;
+rec.b:= 'test';
+INSERT INTO t1 VALUES (rec.a, rec.b);
+END;
+$$
+CALL p1();
+SELECT * FROM t1;
+a b
+10 test
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# ROW fields as SP out parameters
+#
+CREATE PROCEDURE p1(a OUT INT, b OUT VARCHAR)
+AS
+BEGIN
+a:= 10;
+b:= 'test';
+END;
+$$
+CREATE PROCEDURE p2
+AS
+rec ROW(a INT, b VARCHAR(10));
+BEGIN
+CALL p1(rec.a, rec.b);
+SELECT rec.a, rec.b;
+END;
+$$
+CALL p2;
+rec.a rec.b
+10 test
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+#
+# ROW fields as dynamic SQL out parameters
+#
+CREATE PROCEDURE p1(a OUT INT, b OUT VARCHAR)
+AS
+BEGIN
+a:= 20;
+b:= 'test-dynamic-sql';
+END;
+$$
+CREATE PROCEDURE p2
+AS
+rec ROW(a INT, b VARCHAR(30));
+BEGIN
+EXECUTE IMMEDIATE 'CALL p1(?,?)' USING rec.a, rec.b;
+SELECT rec.a, rec.b;
+END;
+$$
+CALL p2;
+rec.a rec.b
+20 test-dynamic-sql
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+#
+# ROW fields as SELECT..INTO targets
+#
+CREATE PROCEDURE p1
+AS
+rec ROW(a INT, b VARCHAR(10));
+BEGIN
+SELECT 10,'test' INTO rec.a,rec.b;
+SELECT rec.a, rec.b;
+END;
+$$
+CALL p1;
+rec.a rec.b
+10 test
+DROP PROCEDURE p1;
+#
+# Implicit default NULL handling
+#
+CREATE PROCEDURE p1
+AS
+rec ROW(a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,0), e TIME, f DATETIME);
+BEGIN
+SELECT rec.a, rec.b, rec.c, rec.d, rec.e, rec.f FROM DUAL;
+END;
+$$
+CALL p1();
+rec.a rec.b rec.c rec.d rec.e rec.f
+NULL NULL NULL NULL NULL NULL
+DROP PROCEDURE p1;
+#
+# NULL handling
+#
+CREATE PROCEDURE p1
+AS
+rec1 ROW(a INT, b VARCHAR(10)):=(NULL,NULL);
+rec2 ROW(a INT, b VARCHAR(10)):=rec1;
+BEGIN
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+rec1:= (10,20);
+rec2:= rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+rec1:= (NULL,20);
+rec2:= rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+rec1:= (10,NULL);
+rec2:= rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+rec1:= (NULL,NULL);
+rec2:= rec1;
+SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+END;
+$$
+CALL p1;
+rec1.a rec1.b rec2.a rec2.b
+NULL NULL NULL NULL
+rec1.a rec1.b rec2.a rec2.b
+10 20 10 20
+rec1.a rec1.b rec2.a rec2.b
+NULL 20 NULL 20
+rec1.a rec1.b rec2.a rec2.b
+10 NULL 10 NULL
+rec1.a rec1.b rec2.a rec2.b
+NULL NULL NULL NULL
+DROP PROCEDURE p1;
+#
+# Testing multiple ROW variable declarations
+# This makes sure that fill_field_definitions() is called only once
+# per a ROW field, so create length is not converted to internal length
+# multiple times.
+#
+CREATE PROCEDURE p1
+AS
+rec1, rec2, rec3 ROW(a VARCHAR(10) CHARACTER SET utf8);
+BEGIN
+CREATE TABLE t1 AS SELECT rec1.a, rec2.a, rec3.a;
+END;
+$$
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "rec1.a" varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ "rec2.a" varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ "rec3.a" varchar(10) CHARACTER SET utf8 DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# INT
+#
+CREATE PROCEDURE p1() AS var INT; rec ROW(var INT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(11) DEFAULT NULL,
+ "rec.var" bigint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(1); rec ROW(var INT(1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(11) DEFAULT NULL,
+ "rec.var" bigint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(2); rec ROW(var INT(2)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(11) DEFAULT NULL,
+ "rec.var" bigint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(3); rec ROW(var INT(3)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(11) DEFAULT NULL,
+ "rec.var" bigint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(4); rec ROW(var INT(4)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(11) DEFAULT NULL,
+ "rec.var" bigint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(5); rec ROW(var INT(5)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(11) DEFAULT NULL,
+ "rec.var" bigint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(6); rec ROW(var INT(6)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(11) DEFAULT NULL,
+ "rec.var" bigint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(7); rec ROW(var INT(7)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(11) DEFAULT NULL,
+ "rec.var" bigint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(8); rec ROW(var INT(8)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(11) DEFAULT NULL,
+ "rec.var" bigint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(9); rec ROW(var INT(9)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(11) DEFAULT NULL,
+ "rec.var" bigint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(10); rec ROW(var INT(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(11) DEFAULT NULL,
+ "rec.var" bigint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(11); rec ROW(var INT(11)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(11) DEFAULT NULL,
+ "rec.var" bigint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(12); rec ROW(var INT(12)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(12) DEFAULT NULL,
+ "rec.var" bigint(12) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(13); rec ROW(var INT(13)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(13) DEFAULT NULL,
+ "rec.var" bigint(13) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(14); rec ROW(var INT(14)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(14) DEFAULT NULL,
+ "rec.var" bigint(14) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(20); rec ROW(var INT(20)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var INT(21); rec ROW(var INT(21)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(21) DEFAULT NULL,
+ "rec.var" bigint(21) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# TINYINT
+#
+CREATE PROCEDURE p1() AS var TINYINT; rec ROW(var TINYINT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(4) DEFAULT NULL,
+ "rec.var" int(4) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(1); rec ROW(var TINYINT(1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(4) DEFAULT NULL,
+ "rec.var" int(4) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(2); rec ROW(var TINYINT(2)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(4) DEFAULT NULL,
+ "rec.var" int(4) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(3); rec ROW(var TINYINT(3)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(4) DEFAULT NULL,
+ "rec.var" int(4) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(4); rec ROW(var TINYINT(4)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(4) DEFAULT NULL,
+ "rec.var" int(4) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(5); rec ROW(var TINYINT(5)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(5) DEFAULT NULL,
+ "rec.var" int(5) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(6); rec ROW(var TINYINT(6)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(6) DEFAULT NULL,
+ "rec.var" int(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(7); rec ROW(var TINYINT(7)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(7) DEFAULT NULL,
+ "rec.var" int(7) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(8); rec ROW(var TINYINT(8)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(8) DEFAULT NULL,
+ "rec.var" int(8) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(9); rec ROW(var TINYINT(9)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(9) DEFAULT NULL,
+ "rec.var" int(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(10); rec ROW(var TINYINT(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(10) DEFAULT NULL,
+ "rec.var" bigint(10) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(11); rec ROW(var TINYINT(11)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(11) DEFAULT NULL,
+ "rec.var" bigint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(12); rec ROW(var TINYINT(12)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(12) DEFAULT NULL,
+ "rec.var" bigint(12) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(13); rec ROW(var TINYINT(13)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(13) DEFAULT NULL,
+ "rec.var" bigint(13) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(14); rec ROW(var TINYINT(14)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(14) DEFAULT NULL,
+ "rec.var" bigint(14) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(20); rec ROW(var TINYINT(20)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYINT(21); rec ROW(var TINYINT(21)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(21) DEFAULT NULL,
+ "rec.var" bigint(21) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# SMALLINT
+#
+CREATE PROCEDURE p1() AS var SMALLINT; rec ROW(var SMALLINT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(6) DEFAULT NULL,
+ "rec.var" int(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(1); rec ROW(var SMALLINT(1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(6) DEFAULT NULL,
+ "rec.var" int(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(2); rec ROW(var SMALLINT(2)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(6) DEFAULT NULL,
+ "rec.var" int(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(3); rec ROW(var SMALLINT(3)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(6) DEFAULT NULL,
+ "rec.var" int(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(4); rec ROW(var SMALLINT(4)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(6) DEFAULT NULL,
+ "rec.var" int(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(5); rec ROW(var SMALLINT(5)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(6) DEFAULT NULL,
+ "rec.var" int(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(6); rec ROW(var SMALLINT(6)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(6) DEFAULT NULL,
+ "rec.var" int(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(7); rec ROW(var SMALLINT(7)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(7) DEFAULT NULL,
+ "rec.var" int(7) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(8); rec ROW(var SMALLINT(8)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(8) DEFAULT NULL,
+ "rec.var" int(8) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(9); rec ROW(var SMALLINT(9)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(9) DEFAULT NULL,
+ "rec.var" int(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(10); rec ROW(var SMALLINT(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(10) DEFAULT NULL,
+ "rec.var" bigint(10) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(11); rec ROW(var SMALLINT(11)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(11) DEFAULT NULL,
+ "rec.var" bigint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(12); rec ROW(var SMALLINT(12)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(12) DEFAULT NULL,
+ "rec.var" bigint(12) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(13); rec ROW(var SMALLINT(13)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(13) DEFAULT NULL,
+ "rec.var" bigint(13) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(14); rec ROW(var SMALLINT(14)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(14) DEFAULT NULL,
+ "rec.var" bigint(14) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(20); rec ROW(var SMALLINT(20)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var SMALLINT(21); rec ROW(var SMALLINT(21)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(21) DEFAULT NULL,
+ "rec.var" bigint(21) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# MEDIUMINT
+#
+CREATE PROCEDURE p1() AS var MEDIUMINT; rec ROW(var MEDIUMINT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(9) DEFAULT NULL,
+ "rec.var" int(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(1); rec ROW(var MEDIUMINT(1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(9) DEFAULT NULL,
+ "rec.var" int(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(2); rec ROW(var MEDIUMINT(2)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(9) DEFAULT NULL,
+ "rec.var" int(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(3); rec ROW(var MEDIUMINT(3)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(9) DEFAULT NULL,
+ "rec.var" int(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(4); rec ROW(var MEDIUMINT(4)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(9) DEFAULT NULL,
+ "rec.var" int(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(5); rec ROW(var MEDIUMINT(5)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(9) DEFAULT NULL,
+ "rec.var" int(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(6); rec ROW(var MEDIUMINT(6)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(9) DEFAULT NULL,
+ "rec.var" int(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(7); rec ROW(var MEDIUMINT(7)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(9) DEFAULT NULL,
+ "rec.var" int(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(8); rec ROW(var MEDIUMINT(8)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(9) DEFAULT NULL,
+ "rec.var" int(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(9); rec ROW(var MEDIUMINT(9)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" int(9) DEFAULT NULL,
+ "rec.var" int(9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(10); rec ROW(var MEDIUMINT(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(10) DEFAULT NULL,
+ "rec.var" bigint(10) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(11); rec ROW(var MEDIUMINT(11)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(11) DEFAULT NULL,
+ "rec.var" bigint(11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(12); rec ROW(var MEDIUMINT(12)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(12) DEFAULT NULL,
+ "rec.var" bigint(12) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(13); rec ROW(var MEDIUMINT(13)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(13) DEFAULT NULL,
+ "rec.var" bigint(13) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(14); rec ROW(var MEDIUMINT(14)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(14) DEFAULT NULL,
+ "rec.var" bigint(14) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(20); rec ROW(var MEDIUMINT(20)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMINT(21); rec ROW(var MEDIUMINT(21)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(21) DEFAULT NULL,
+ "rec.var" bigint(21) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# BIGINT
+#
+CREATE PROCEDURE p1() AS var BIGINT; rec ROW(var BIGINT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(1); rec ROW(var BIGINT(1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(2); rec ROW(var BIGINT(2)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(3); rec ROW(var BIGINT(3)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(4); rec ROW(var BIGINT(4)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(5); rec ROW(var BIGINT(5)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(6); rec ROW(var BIGINT(6)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(7); rec ROW(var BIGINT(7)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(8); rec ROW(var BIGINT(8)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(9); rec ROW(var BIGINT(9)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(10); rec ROW(var BIGINT(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(11); rec ROW(var BIGINT(11)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(12); rec ROW(var BIGINT(12)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(13); rec ROW(var BIGINT(13)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(14); rec ROW(var BIGINT(14)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(20); rec ROW(var BIGINT(20)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(20) DEFAULT NULL,
+ "rec.var" bigint(20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BIGINT(21); rec ROW(var BIGINT(21)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" bigint(21) DEFAULT NULL,
+ "rec.var" bigint(21) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# DOUBLE
+#
+CREATE PROCEDURE p1() AS var DOUBLE; rec ROW(var DOUBLE); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double DEFAULT NULL,
+ "rec.var" double DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,1); rec ROW(var DOUBLE(30,1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,1) DEFAULT NULL,
+ "rec.var" double(30,1) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,2); rec ROW(var DOUBLE(30,2)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,2) DEFAULT NULL,
+ "rec.var" double(30,2) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,3); rec ROW(var DOUBLE(30,3)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,3) DEFAULT NULL,
+ "rec.var" double(30,3) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,4); rec ROW(var DOUBLE(30,4)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,4) DEFAULT NULL,
+ "rec.var" double(30,4) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,5); rec ROW(var DOUBLE(30,5)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,5) DEFAULT NULL,
+ "rec.var" double(30,5) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,6); rec ROW(var DOUBLE(30,6)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,6) DEFAULT NULL,
+ "rec.var" double(30,6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,7); rec ROW(var DOUBLE(30,7)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,7) DEFAULT NULL,
+ "rec.var" double(30,7) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,8); rec ROW(var DOUBLE(30,8)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,8) DEFAULT NULL,
+ "rec.var" double(30,8) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,9); rec ROW(var DOUBLE(30,9)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,9) DEFAULT NULL,
+ "rec.var" double(30,9) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,10); rec ROW(var DOUBLE(30,10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,10) DEFAULT NULL,
+ "rec.var" double(30,10) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,11); rec ROW(var DOUBLE(30,11)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,11) DEFAULT NULL,
+ "rec.var" double(30,11) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,12); rec ROW(var DOUBLE(30,12)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,12) DEFAULT NULL,
+ "rec.var" double(30,12) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,13); rec ROW(var DOUBLE(30,13)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,13) DEFAULT NULL,
+ "rec.var" double(30,13) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,14); rec ROW(var DOUBLE(30,14)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,14) DEFAULT NULL,
+ "rec.var" double(30,14) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,20); rec ROW(var DOUBLE(30,20)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,20) DEFAULT NULL,
+ "rec.var" double(30,20) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DOUBLE(30,21); rec ROW(var DOUBLE(30,21)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" double(30,21) DEFAULT NULL,
+ "rec.var" double(30,21) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# VARCHAR
+#
+CREATE PROCEDURE p1() AS var CHAR; rec ROW(var CHAR); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varchar(1) DEFAULT NULL,
+ "rec.var" varchar(1) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BINARY; rec ROW(var BINARY); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varbinary(1) DEFAULT NULL,
+ "rec.var" varbinary(1) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var CHAR(1); rec ROW(var CHAR(1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varchar(1) DEFAULT NULL,
+ "rec.var" varchar(1) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var CHAR(10); rec ROW(var CHAR(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varchar(10) DEFAULT NULL,
+ "rec.var" varchar(10) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var NCHAR(10); rec ROW(var NCHAR(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ "rec.var" varchar(10) CHARACTER SET utf8 DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var BINARY(10); rec ROW(var BINARY(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varbinary(10) DEFAULT NULL,
+ "rec.var" varbinary(10) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var VARBINARY(10); rec ROW(var VARBINARY(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varbinary(10) DEFAULT NULL,
+ "rec.var" varbinary(10) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var VARCHAR(10); rec ROW(var VARCHAR(10)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varchar(10) DEFAULT NULL,
+ "rec.var" varchar(10) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var VARCHAR(10) CHARACTER SET utf8; rec ROW(var VARCHAR(10) CHARACTER SET utf8); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varchar(10) CHARACTER SET utf8 DEFAULT NULL,
+ "rec.var" varchar(10) CHARACTER SET utf8 DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_bin; rec ROW(var VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_bin); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varchar(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL,
+ "rec.var" varchar(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# TIME
+#
+CREATE PROCEDURE p1() AS var TIME; rec ROW(var TIME); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" time DEFAULT NULL,
+ "rec.var" time DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TIME(1); rec ROW(var TIME(1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" time(1) DEFAULT NULL,
+ "rec.var" time(1) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TIME(2); rec ROW(var TIME(2)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" time(2) DEFAULT NULL,
+ "rec.var" time(2) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TIME(3); rec ROW(var TIME(3)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" time(3) DEFAULT NULL,
+ "rec.var" time(3) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TIME(4); rec ROW(var TIME(4)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" time(4) DEFAULT NULL,
+ "rec.var" time(4) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TIME(5); rec ROW(var TIME(5)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" time(5) DEFAULT NULL,
+ "rec.var" time(5) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TIME(6); rec ROW(var TIME(6)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" time(6) DEFAULT NULL,
+ "rec.var" time(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# DATETIME
+#
+CREATE PROCEDURE p1() AS var DATETIME; rec ROW(var DATETIME); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" datetime DEFAULT NULL,
+ "rec.var" datetime DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DATETIME(1); rec ROW(var DATETIME(1)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" datetime(1) DEFAULT NULL,
+ "rec.var" datetime(1) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DATETIME(2); rec ROW(var DATETIME(2)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" datetime(2) DEFAULT NULL,
+ "rec.var" datetime(2) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DATETIME(3); rec ROW(var DATETIME(3)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" datetime(3) DEFAULT NULL,
+ "rec.var" datetime(3) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DATETIME(4); rec ROW(var DATETIME(4)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" datetime(4) DEFAULT NULL,
+ "rec.var" datetime(4) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DATETIME(5); rec ROW(var DATETIME(5)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" datetime(5) DEFAULT NULL,
+ "rec.var" datetime(5) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var DATETIME(6); rec ROW(var DATETIME(6)); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" datetime(6) DEFAULT NULL,
+ "rec.var" datetime(6) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# LOB
+#
+CREATE PROCEDURE p1() AS var TEXT; rec ROW(var TEXT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" text DEFAULT NULL,
+ "rec.var" text DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYTEXT; rec ROW(var TINYTEXT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varchar(255) DEFAULT NULL,
+ "rec.var" varchar(255) DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMTEXT; rec ROW(var MEDIUMTEXT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumtext DEFAULT NULL,
+ "rec.var" mediumtext DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var LONGTEXT; rec ROW(var LONGTEXT); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" longtext DEFAULT NULL,
+ "rec.var" longtext DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TEXT CHARACTER SET utf8; rec ROW(var TEXT CHARACTER SET utf8); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" mediumtext CHARACTER SET utf8 DEFAULT NULL,
+ "rec.var" mediumtext CHARACTER SET utf8 DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var TINYTEXT CHARACTER SET utf8; rec ROW(var TINYTEXT CHARACTER SET utf8); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" varchar(255) CHARACTER SET utf8 DEFAULT NULL,
+ "rec.var" varchar(255) CHARACTER SET utf8 DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var MEDIUMTEXT CHARACTER SET utf8; rec ROW(var MEDIUMTEXT CHARACTER SET utf8); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" longtext CHARACTER SET utf8 DEFAULT NULL,
+ "rec.var" longtext CHARACTER SET utf8 DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+CREATE PROCEDURE p1() AS var LONGTEXT CHARACTER SET utf8; rec ROW(var LONGTEXT CHARACTER SET utf8); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END;
+CALL p1();
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE "t1" (
+ "var" longtext CHARACTER SET utf8 DEFAULT NULL,
+ "rec.var" longtext CHARACTER SET utf8 DEFAULT NULL
+)
+DROP TABLE t1;
+DROP PROCEDURE p1;
+#
+# End of MDEV-10914 ROW data type for stored routine variables
+#
diff --git a/mysql-test/suite/compat/oracle/t/binlog_stm_sp.test b/mysql-test/suite/compat/oracle/t/binlog_stm_sp.test
new file mode 100644
index 00000000000..cd0d9111107
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/binlog_stm_sp.test
@@ -0,0 +1,81 @@
+--source include/not_embedded.inc
+--source include/have_binlog_format_statement.inc
+
+--disable_query_log
+call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
+reset master; # get rid of previous tests binlog
+--enable_query_log
+
+
+SET sql_mode=ORACLE;
+
+--echo #
+--echo # MDEV-10914 ROW data type for stored routine variables
+--echo #
+
+CREATE TABLE t1 (a INT, b INT);
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec ROW(a INT,b INT);
+BEGIN
+ rec.a:=100;
+ rec.b:=200;
+ INSERT INTO t1 VALUES (rec.a,rec.b);
+ INSERT INTO t1 VALUES (10, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (10, ROW(100,200)=rec);
+ INSERT INTO t1 SELECT 10, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 10, 21 FROM DUAL WHERE ROW(100,200)=rec;
+ rec.a:=NULL;
+ INSERT INTO t1 VALUES (11, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (11, rec=ROW(100,201));
+ INSERT INTO t1 VALUES (11, ROW(100,200)=rec);
+ INSERT INTO t1 VALUES (11, ROW(100,201)=rec);
+ INSERT INTO t1 SELECT 11, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 11, 21 FROM DUAL WHERE ROW(100,200)=rec;
+ rec.b:=NULL;
+ INSERT INTO t1 VALUES (12, rec=ROW(100,200));
+ INSERT INTO t1 VALUES (12, ROW(100,200)=rec);
+ INSERT INTO t1 SELECT 12, 20 FROM DUAL WHERE rec=ROW(100,200);
+ INSERT INTO t1 SELECT 12, 21 FROM DUAL WHERE ROW(100,200)=rec;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+
+--echo #
+--echo # Testing ROW fields in LIMIT
+--echo #
+
+FLUSH LOGS;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(10);
+CREATE TABLE t2 (a INT);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a INT:= 1;
+ rec ROW(a INT);
+BEGIN
+ rec.a:= 1;
+ INSERT INTO t2 SELECT 1 FROM t1 LIMIT a;
+ INSERT INTO t2 SELECT 2 FROM t1 LIMIT rec.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1,t2;
+DROP PROCEDURE p1;
+--let $binlog_file = LAST
+source include/show_binlog_events.inc;
+
+
+--echo #
+--echo # End of MDEV-10914 ROW data type for stored routine variables
+--echo #
diff --git a/mysql-test/suite/compat/oracle/t/sp-code.test b/mysql-test/suite/compat/oracle/t/sp-code.test
index 637251af96c..5e20db1ceda 100644
--- a/mysql-test/suite/compat/oracle/t/sp-code.test
+++ b/mysql-test/suite/compat/oracle/t/sp-code.test
@@ -657,3 +657,88 @@ DROP PROCEDURE p1;
--echo #
--echo # End of MDEV-10597 Cursors with parameters
--echo #
+
+
+--echo #
+--echo # MDEV-10914 ROW data type for stored routine variables
+--echo #
+DELIMITER $$;
+CREATE FUNCTION f1() RETURN INT
+AS
+ a ROW(a INT, b INT);
+BEGIN
+ a.b:= 200;
+ RETURN a.b;
+END;
+$$
+DELIMITER ;$$
+SHOW FUNCTION CODE f1;
+SELECT f1();
+DROP FUNCTION f1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10));
+BEGIN
+ rec:= ROW(10,20.123456,30.123,'test');
+ SELECT rec.a, rec.b, rec.c, rec.d;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+CALL p1;
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10)) :=
+ ROW(10,20.123456,30.123,'test');
+BEGIN
+ SELECT rec.a, rec.b, rec.c, rec.d;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+CALL p1;
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec1 ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10));
+ rec2 ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10));
+BEGIN
+ rec1:= ROW(10,20.123456,30.123,'test');
+ rec2:= rec1;
+ SELECT rec2.a, rec2.b, rec2.c, rec2.d;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+CALL p1;
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec1 ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10)) :=
+ ROW(10,20.123456,30.123,'test');
+ rec2 ROW(a INT,b DOUBLE,c DECIMAL(10,3),d VARCHAR(10)) := rec1;
+BEGIN
+ SELECT rec2.a, rec2.b, rec2.c, rec2.d;
+END;
+$$
+DELIMITER ;$$
+SHOW PROCEDURE CODE p1;
+CALL p1;
+DROP PROCEDURE p1;
+
+--echo #
+--echo # End of MDEV-10914 ROW data type for stored routine variables
+--echo #
diff --git a/mysql-test/suite/compat/oracle/t/sp-row-vs-var.inc b/mysql-test/suite/compat/oracle/t/sp-row-vs-var.inc
new file mode 100644
index 00000000000..14f6f7dfd44
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/sp-row-vs-var.inc
@@ -0,0 +1,6 @@
+--let $query= CREATE PROCEDURE p1() AS var $type; rec ROW(var $type); BEGIN CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END
+--eval $query
+CALL p1();
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
diff --git a/mysql-test/suite/compat/oracle/t/sp-row.test b/mysql-test/suite/compat/oracle/t/sp-row.test
new file mode 100644
index 00000000000..b86b087f7b6
--- /dev/null
+++ b/mysql-test/suite/compat/oracle/t/sp-row.test
@@ -0,0 +1,1398 @@
+SET sql_mode=ORACLE;
+
+
+--echo #
+--echo # MDEV-10914 ROW data type for stored routine variables
+--echo #
+
+
+
+--echo #
+--echo # ROW of ROWs is not supported yet
+--echo #
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE PROCEDURE p1()
+AS
+ a ROW(a ROW(a INT));
+BEGIN
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Returning the entire ROW parameter from a function
+--echo #
+# TODO: this should probably return an error at compile time
+DELIMITER $$;
+CREATE FUNCTION f1(a ROW(a INT, b INT)) RETURN INT
+AS
+BEGIN
+ RETURN a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+SELECT f1(ROW(10,20));
+DROP FUNCTION f1;
+
+
+
+--echo #
+--echo # ROW as an SP parameter
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION f1(a ROW(a INT,b INT)) RETURN INT
+AS
+BEGIN
+ RETURN a.b;
+END;
+$$
+CREATE PROCEDURE p1()
+AS
+ a ROW(a INT,b INT):=(11,21);
+BEGIN
+ SELECT f1(a);
+END;
+$$
+DELIMITER ;$$
+SELECT f1(ROW(10,20));
+--error ER_OPERAND_COLUMNS
+SELECT f1(10);
+--error ER_OPERAND_COLUMNS
+SELECT f1(ROW(10,20,30));
+CALL p1();
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a ROW(a INT,b INT))
+AS
+BEGIN
+ SELECT a.a, a.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1(ROW(10,20));
+--error ER_OPERAND_COLUMNS
+CALL p1(10);
+--error ER_OPERAND_COLUMNS
+CALL p1(ROW(10,20,30));
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW as an SP OUT parameter
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a OUT ROW(a INT,b INT))
+AS
+BEGIN
+ a.a:=10;
+ a.b:=20;
+END;
+$$
+CREATE PROCEDURE p2
+AS
+ a ROW(a INT,b INT):=(11,21);
+BEGIN
+ CALL p1(a);
+ SELECT a.a,a.b;
+END;
+$$
+DELIMITER ;$$
+CALL p2();
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW as an SP return value is not supported yet
+--echo #
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE FUNCTION p1() RETURN ROW(a INT)
+AS
+BEGIN
+ RETURN NULL;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Diplicate row field
+--echo #
+DELIMITER $$;
+--error ER_DUP_FIELDNAME
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT, a DOUBLE);
+BEGIN
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Bad scalar default value
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT, b DOUBLE):= 1;
+BEGIN
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+--echo #
+--echo # Bad ROW default value with a wrong number of fields
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT, b DOUBLE):= ROW(1,2,3);
+BEGIN
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Bad usage of a scalar variable as a row
+--echo #
+
+DELIMITER $$;
+--error ER_UNKNOWN_ERROR
+CREATE PROCEDURE p1()
+AS
+ a INT;
+BEGIN
+ SELECT a.x FROM t1;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Using the entire ROW variable in select list
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT);
+BEGIN
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT,b INT);
+BEGIN
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Using the entire ROW variable in functions
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT);
+BEGIN
+ SELECT COALESCE(a);
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT,b INT);
+BEGIN
+ SELECT COALESCE(a);
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT);
+BEGIN
+ SELECT a+1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT,b INT);
+BEGIN
+ SELECT a+1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Comparing the entire ROW to a scalar value
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT,b INT);
+BEGIN
+ SELECT a=1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT,b INT);
+BEGIN
+ SELECT 1=a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Passing the entire ROW to a stored function
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+BEGIN
+ RETURN a;
+END;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT,b INT);
+BEGIN
+ SELECT f1(a);
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+
+
+DELIMITER $$;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+BEGIN
+ RETURN a;
+END;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT);
+BEGIN
+ SELECT f1(a);
+END;
+$$
+DELIMITER ;$$
+#--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+
+
+--echo #
+--echo # Assigning a scalar value to a ROW variable with 1 column
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1
+AS
+ rec ROW(a INT);
+BEGIN
+ rec:=1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning a scalar value to a ROW variable with 2 columns
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1
+AS
+ rec ROW(a INT,b INT);
+BEGIN
+ rec:=1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning a ROW value to a ROW variable with different number of columns
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1
+AS
+ rec ROW(a INT,b INT);
+BEGIN
+ rec:=ROW(1,2,3);
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+--echo #
+--echo # Returning the entire ROW from a function is not supported yet
+--echo # This syntax would be needed: SELECT f1().x FROM DUAL;
+--echo #
+DELIMITER $$;
+CREATE FUNCTION f1(a INT) RETURN INT
+AS
+ rec ROW(a INT);
+BEGIN
+ RETURN rec;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+SELECT f1(10);
+DROP FUNCTION f1;
+
+
+--echo #
+--echo # Using the entire ROW in SELECT..CREATE
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec ROW(a INT,b INT);
+BEGIN
+ CREATE TABLE t1 AS SELECT rec;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Using the entire ROW in LIMIT
+--echo #
+DELIMITER $$;
+--error ER_WRONG_SPVAR_TYPE_IN_LIMIT
+CREATE PROCEDURE p1()
+AS
+ rec ROW(a INT);
+BEGIN
+ rec.a:= '10';
+ SELECT * FROM t1 LIMIT rec;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Setting ROW fields using a SET command
+--echo #
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1
+AS
+ rec ROW(a INT,b DOUBLE,c VARCHAR(10));
+ a INT;
+BEGIN
+ SET @a= 10, rec.a=10, rec.b=20, rec.c= 'test', a= 5;
+ SELECT rec.a, rec.b, rec.c, a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning a ROW variable from a ROW value
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec ROW(a INT,b INT);
+BEGIN
+ rec:=ROW(1,2);
+ SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning a ROW variable from another ROW value
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec1 ROW(a INT,b INT);
+ rec2 ROW(a INT,b INT);
+BEGIN
+ rec1:=ROW(1,2);
+ rec2:=rec1;
+ SELECT rec2.a, rec2.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Comparing a ROW variable to a ROW() function
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1
+AS
+ rec ROW(a INT,b INT);
+BEGIN
+ rec.a:= 1;
+ rec.b:= 2;
+ SELECT rec=(0,0), rec=ROW(0,0), (0,0)=rec, ROW(0,0)=rec;
+ SELECT rec=(1,2), rec=ROW(1,2), (1,2)=rec, ROW(1,2)=rec;
+ SELECT rec=(NULL,0), rec=ROW(NULL,0);
+ SELECT rec=(NULL,2), rec=ROW(NULL,2);
+ SELECT rec<>(0,0), rec<>ROW(0,0);
+ SELECT rec<>(1,2), rec<>ROW(1,2);
+ SELECT rec<>(NULL,0), rec<>ROW(NULL,0);
+ SELECT rec<>(NULL,2), rec<>ROW(NULL,2);
+ SELECT rec IN ((0,0)), rec IN (ROW(0,0));
+ SELECT rec IN ((1,2)), rec IN (ROW(1,2));
+ SELECT rec IN ((0,NULL),(1,2));
+ SELECT rec NOT IN ((0,NULL),(1,1));
+ SELECT rec NOT IN ((1,NULL),(1,1));
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Comparing a ROW variable to another ROW variable
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1
+AS
+ rec1,rec2,rec3 ROW(a INT,b INT);
+BEGIN
+ rec1.a:= 1;
+ rec1.b:= 2;
+ rec2.a:= 11;
+ rec2.b:= 12;
+ rec3.a:= 11;
+ rec3.b:= 12;
+ SELECT rec1=rec2, rec2=rec1, rec2=rec3, rec3=rec2;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Referencing a non-existing row variable
+--echo #
+DELIMITER $$;
+--error ER_UNKNOWN_STRUCTURED_VARIABLE
+CREATE PROCEDURE p1()
+AS
+BEGIN
+ SET a.b=1;
+END;
+$$
+DELIMITER ;$$
+
+DELIMITER $$;
+--error ER_UNKNOWN_STRUCTURED_VARIABLE
+CREATE PROCEDURE p1()
+AS
+BEGIN
+ a.b:=1;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Referencing a non-existing row field
+--echo #
+DELIMITER $$;
+--error ER_UNKNOWN_ERROR
+CREATE PROCEDURE p1()
+AS
+ a ROW(a INT,b INT);
+BEGIN
+ SELECT a.c FROM t1;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # ROW and scalar variables with the same name shadowing each other
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW(a INT);
+BEGIN
+ a.a:=100;
+ DECLARE
+ a INT:= 200;
+ BEGIN
+ SELECT a;
+ DECLARE
+ a ROW(a INT);
+ BEGIN
+ a.a:=300;
+ SELECT a.a;
+ END;
+ SELECT a;
+ END;
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW with good default values
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW(a INT,b INT):= (10,20);
+ b ROW(a INT,b INT):= (11,21);
+ c ROW(a INT,b INT):= a;
+BEGIN
+ SELECT a.a, a.b, b.a, b.b, c.a, c.b FROM DUAL;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW in WHERE clause
+--echo #
+
+CREATE TABLE t1 (a INT,b INT);
+INSERT INTO t1 VALUES (10,20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec ROW(a INT,b INT):=ROW(10,20);
+BEGIN
+ SELECT * FROM t1 WHERE rec=ROW(a,b);
+ SELECT * FROM t1 WHERE ROW(a,b)=rec;
+ SELECT * FROM t1 WHERE rec=ROW(10,20);
+ SELECT * FROM t1 WHERE ROW(10,20)=rec;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields in WHERE clause
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec ROW(a INT);
+BEGIN
+ rec.a:= 10;
+ SELECT * FROM t1 WHERE a=rec.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields in HAVING clause
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec ROW(a INT);
+BEGIN
+ rec.a:= 10;
+ SELECT * FROM t1 HAVING a=rec.a;
+ SELECT * FROM t1 HAVING MIN(a)=rec.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields in LIMIT clause
+--echo #
+
+CREATE TABLE t1 (a INT);
+--error ER_SP_UNDECLARED_VAR
+SELECT 1 FROM t1 LIMIT t1.a;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec ROW(a INT);
+BEGIN
+ rec.a:= 10;
+ SELECT * FROM t1 LIMIT rec.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+--error ER_WRONG_SPVAR_TYPE_IN_LIMIT
+CREATE PROCEDURE p1()
+AS
+ rec ROW(a VARCHAR(10));
+BEGIN
+ rec.a:= '10';
+ SELECT * FROM t1 LIMIT rec.a;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # ROW fields in select list
+--echo #
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ t1 ROW(a INT);
+BEGIN
+ t1.a:= 10;
+ SELECT t1.a, 'This is the variable t1.a value, rather than the column t1.a' AS comm FROM t1;
+ SELECT t1.a, t2.a, t1.a+t2.a FROM t1 t2;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields as insert values
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ rec ROW(a INT, b VARCHAR(10));
+BEGIN
+ rec.a:= 10;
+ rec.b:= 'test';
+ INSERT INTO t1 VALUES (rec.a, rec.b);
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields as SP out parameters
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a OUT INT, b OUT VARCHAR)
+AS
+BEGIN
+ a:= 10;
+ b:= 'test';
+END;
+$$
+CREATE PROCEDURE p2
+AS
+ rec ROW(a INT, b VARCHAR(10));
+BEGIN
+ CALL p1(rec.a, rec.b);
+ SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p2;
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+
+
+--echo #
+--echo # ROW fields as dynamic SQL out parameters
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a OUT INT, b OUT VARCHAR)
+AS
+BEGIN
+ a:= 20;
+ b:= 'test-dynamic-sql';
+END;
+$$
+CREATE PROCEDURE p2
+AS
+ rec ROW(a INT, b VARCHAR(30));
+BEGIN
+ EXECUTE IMMEDIATE 'CALL p1(?,?)' USING rec.a, rec.b;
+ SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p2;
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+
+
+--echo #
+--echo # ROW fields as SELECT..INTO targets
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec ROW(a INT, b VARCHAR(10));
+BEGIN
+ SELECT 10,'test' INTO rec.a,rec.b;
+ SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Implicit default NULL handling
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec ROW(a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,0), e TIME, f DATETIME);
+BEGIN
+ SELECT rec.a, rec.b, rec.c, rec.d, rec.e, rec.f FROM DUAL;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # NULL handling
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec1 ROW(a INT, b VARCHAR(10)):=(NULL,NULL);
+ rec2 ROW(a INT, b VARCHAR(10)):=rec1;
+BEGIN
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+
+ rec1:= (10,20);
+ rec2:= rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+
+ rec1:= (NULL,20);
+ rec2:= rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+
+ rec1:= (10,NULL);
+ rec2:= rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+
+ rec1:= (NULL,NULL);
+ rec2:= rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Testing multiple ROW variable declarations
+--echo # This makes sure that fill_field_definitions() is called only once
+--echo # per a ROW field, so create length is not converted to internal length
+--echo # multiple times.
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1
+AS
+ rec1, rec2, rec3 ROW(a VARCHAR(10) CHARACTER SET utf8);
+BEGIN
+ CREATE TABLE t1 AS SELECT rec1.a, rec2.a, rec3.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+--echo #
+--echo # INT
+--echo #
+
+--let type=INT
+--source sp-row-vs-var.inc
+
+--let type=INT(1)
+--source sp-row-vs-var.inc
+
+--let type=INT(2)
+--source sp-row-vs-var.inc
+
+--let type=INT(3)
+--source sp-row-vs-var.inc
+
+--let type=INT(4)
+--source sp-row-vs-var.inc
+
+--let type=INT(5)
+--source sp-row-vs-var.inc
+
+--let type=INT(6)
+--source sp-row-vs-var.inc
+
+--let type=INT(7)
+--source sp-row-vs-var.inc
+
+--let type=INT(8)
+--source sp-row-vs-var.inc
+
+--let type=INT(9)
+--source sp-row-vs-var.inc
+
+--let type=INT(10)
+--source sp-row-vs-var.inc
+
+--let type=INT(11)
+--source sp-row-vs-var.inc
+
+--let type=INT(12)
+--source sp-row-vs-var.inc
+
+--let type=INT(13)
+--source sp-row-vs-var.inc
+
+--let type=INT(14)
+--source sp-row-vs-var.inc
+
+--let type=INT(20)
+--source sp-row-vs-var.inc
+
+--let type=INT(21)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # TINYINT
+--echo #
+
+--let type=TINYINT
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(1)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(2)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(3)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(4)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(5)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(6)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(7)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(8)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(9)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(10)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(11)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(12)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(13)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(14)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(20)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(21)
+--source sp-row-vs-var.inc
+
+--echo #
+--echo # SMALLINT
+--echo #
+
+--let type=SMALLINT
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(1)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(2)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(3)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(4)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(5)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(6)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(7)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(8)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(9)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(10)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(11)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(12)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(13)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(14)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(20)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(21)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # MEDIUMINT
+--echo #
+
+--let type=MEDIUMINT
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(1)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(2)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(3)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(4)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(5)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(6)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(7)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(8)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(9)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(10)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(11)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(12)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(13)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(14)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(20)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(21)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # BIGINT
+--echo #
+
+--let type=BIGINT
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(1)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(2)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(3)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(4)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(5)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(6)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(7)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(8)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(9)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(10)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(11)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(12)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(13)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(14)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(20)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(21)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # DOUBLE
+--echo #
+
+--let type=DOUBLE
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,1)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,2)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,3)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,4)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,5)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,6)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,7)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,8)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,9)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,10)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,11)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,12)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,13)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,14)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,20)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,21)
+--source sp-row-vs-var.inc
+
+--echo #
+--echo # VARCHAR
+--echo #
+
+--let type=CHAR
+--source sp-row-vs-var.inc
+
+--let type=BINARY
+--source sp-row-vs-var.inc
+
+--let type=CHAR(1)
+--source sp-row-vs-var.inc
+
+--let type=CHAR(10)
+--source sp-row-vs-var.inc
+
+--let type=NCHAR(10)
+--source sp-row-vs-var.inc
+
+--let type=BINARY(10)
+--source sp-row-vs-var.inc
+
+--let type=VARBINARY(10)
+--source sp-row-vs-var.inc
+
+--let type=VARCHAR(10)
+--source sp-row-vs-var.inc
+
+--let type=VARCHAR(10) CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+--let type=VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_bin
+--source sp-row-vs-var.inc
+
+--echo #
+--echo # TIME
+--echo #
+
+--let type=TIME
+--source sp-row-vs-var.inc
+
+--let type=TIME(1)
+--source sp-row-vs-var.inc
+
+--let type=TIME(2)
+--source sp-row-vs-var.inc
+
+--let type=TIME(3)
+--source sp-row-vs-var.inc
+
+--let type=TIME(4)
+--source sp-row-vs-var.inc
+
+--let type=TIME(5)
+--source sp-row-vs-var.inc
+
+--let type=TIME(6)
+--source sp-row-vs-var.inc
+
+--echo #
+--echo # DATETIME
+--echo #
+
+--let type=DATETIME
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(1)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(2)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(3)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(4)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(5)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(6)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # LOB
+--echo #
+
+--let type=TEXT
+--source sp-row-vs-var.inc
+
+--let type=TINYTEXT
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMTEXT
+--source sp-row-vs-var.inc
+
+--let type=LONGTEXT
+--source sp-row-vs-var.inc
+
+--let type=TEXT CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+--let type=TINYTEXT CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMTEXT CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+--let type=LONGTEXT CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # End of MDEV-10914 ROW data type for stored routine variables
+--echo #
diff --git a/mysql-test/t/keywords.test b/mysql-test/t/keywords.test
index cf087590df2..4ac8f56afc5 100644
--- a/mysql-test/t/keywords.test
+++ b/mysql-test/t/keywords.test
@@ -171,7 +171,7 @@ create table option (option int not null);
drop table option;
--error 1193
set option=1;
---error 1193
+--error ER_PARSE_ERROR
set option option=1;
--echo #
diff --git a/mysql-test/t/sp-row-vs-var.inc b/mysql-test/t/sp-row-vs-var.inc
new file mode 100644
index 00000000000..54d323f7341
--- /dev/null
+++ b/mysql-test/t/sp-row-vs-var.inc
@@ -0,0 +1,6 @@
+--let $query= CREATE PROCEDURE p1() BEGIN DECLARE var $type; DECLARE rec ROW(var $type); CREATE TABLE t1 AS SELECT var,rec.var FROM DUAL;END
+--eval $query
+CALL p1();
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
diff --git a/mysql-test/t/sp-row.test b/mysql-test/t/sp-row.test
new file mode 100644
index 00000000000..42fafb75077
--- /dev/null
+++ b/mysql-test/t/sp-row.test
@@ -0,0 +1,1329 @@
+--echo #
+--echo # MDEV-10914 ROW data type for stored routine variables
+--echo #
+
+
+
+--echo #
+--echo # ROW of ROWs is not supported yet
+--echo #
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW(a ROW(a INT));
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Returning the entire ROW parameter from a function
+--echo #
+# TODO: this should probably return an error at compile time
+DELIMITER $$;
+CREATE FUNCTION f1(a ROW(a INT, b INT)) RETURNS INT
+BEGIN
+ RETURN a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+SELECT f1(ROW(10,20));
+DROP FUNCTION f1;
+
+
+
+--echo #
+--echo # ROW as an SP parameter
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION f1(a ROW(a INT,b INT)) RETURNS INT
+BEGIN
+ RETURN a.b;
+END;
+$$
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW(a INT,b INT) DEFAULT (11,21);
+ SELECT f1(a);
+END;
+$$
+DELIMITER ;$$
+SELECT f1(ROW(10,20));
+--error ER_OPERAND_COLUMNS
+SELECT f1(10);
+--error ER_OPERAND_COLUMNS
+SELECT f1(ROW(10,20,30));
+CALL p1();
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1(a ROW(a INT,b INT))
+BEGIN
+ SELECT a.a, a.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1(ROW(10,20));
+--error ER_OPERAND_COLUMNS
+CALL p1(10);
+--error ER_OPERAND_COLUMNS
+CALL p1(ROW(10,20,30));
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW as an SP OUT parameter
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(OUT a ROW(a INT,b INT))
+BEGIN
+ SET a.a=10;
+ SET a.b=20;
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+ DECLARE a ROW(a INT,b INT) DEFAULT (11,21);
+ CALL p1(a);
+ SELECT a.a,a.b;
+END;
+$$
+DELIMITER ;$$
+CALL p2();
+DROP PROCEDURE p2;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW as an SP return value is not supported yet
+--echo #
+
+DELIMITER $$;
+--error ER_PARSE_ERROR
+CREATE FUNCTION p1() RETURNS ROW(a INT)
+BEGIN
+ RETURN NULL;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Diplicate row field
+--echo #
+DELIMITER $$;
+--error ER_DUP_FIELDNAME
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT, a DOUBLE);
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Bad scalar default value
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT, b DOUBLE) DEFAULT 1;
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+--echo #
+--echo # Bad ROW default value with a wrong number of fields
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT, b DOUBLE) DEFAULT ROW(1,2,3);
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Bad usage of a scalar variable as a row
+--echo #
+
+DELIMITER $$;
+--error ER_UNKNOWN_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a INT;
+ SELECT a.x FROM t1;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Using the entire ROW variable in select list
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT);
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT,b INT);
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Using the entire ROW variable in functions
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT);
+ SELECT COALESCE(a);
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT,b INT);
+ SELECT COALESCE(a);
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT);
+ SELECT a+1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT,b INT);
+ SELECT a+1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Comparing the entire ROW to a scalar value
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT,b INT);
+ SELECT a=1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT,b INT);
+ SELECT 1=a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Passing the entire ROW to a stored function
+--echo #
+
+DELIMITER $$;
+CREATE FUNCTION f1(a INT) RETURNS INT
+BEGIN
+ RETURN a;
+END;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW (a INT,b INT);
+ SELECT f1(a);
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+DROP FUNCTION f1;
+
+
+#DELIMITER $$;
+#CREATE FUNCTION f1(a INT) RETURNS INT
+#BEGIN
+# RETURN a;
+#END;
+#CREATE PROCEDURE p1()
+#BEGIN
+# DECLARE a ROW (a INT);
+# SELECT f1(a);
+#END;
+#$$
+#DELIMITER ;$$
+##--error ER_OPERAND_COLUMNS
+#CALL p1();
+#DROP PROCEDURE p1;
+#DROP FUNCTION f1;
+
+
+--echo #
+--echo # Assigning a scalar value to a ROW variable with 1 column
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT);
+ SET rec=1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning a scalar value to a ROW variable with 2 columns
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT,b INT);
+ SET rec=1;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning a ROW value to a ROW variable with different number of columns
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT,b INT);
+ SET rec=ROW(1,2,3);
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+--echo #
+--echo # Returning the entire ROW from a function is not supported yet
+--echo # This syntax would be needed: SELECT f1().x FROM DUAL;
+--echo #
+DELIMITER $$;
+CREATE FUNCTION f1(a INT) RETURNS INT
+BEGIN
+ DECLARE rec ROW(a INT);
+ RETURN rec;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+SELECT f1(10);
+DROP FUNCTION f1;
+
+
+--echo #
+--echo # Using the entire ROW in SELECT..CREATE
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT,b INT);
+ CREATE TABLE t1 AS SELECT rec;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Using the entire ROW in LIMIT
+--echo #
+DELIMITER $$;
+--error ER_WRONG_SPVAR_TYPE_IN_LIMIT
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT);
+ SET rec.a= '10';
+ SELECT * FROM t1 LIMIT rec;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # Setting ROW fields using a SET command
+--echo #
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT,b DOUBLE,c VARCHAR(10));
+ DECLARE a INT;
+ SET @a= 10, rec.a=10, rec.b=20, rec.c= 'test', a= 5;
+ SELECT rec.a, rec.b, rec.c, a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning a ROW variable from a ROW value
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT,b INT);
+ SET rec=ROW(1,2);
+ SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Assigning a ROW variable from another ROW value
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW(a INT,b INT);
+ DECLARE rec2 ROW(a INT,b INT);
+ SET rec1=ROW(1,2);
+ SET rec2=rec1;
+ SELECT rec2.a, rec2.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Comparing a ROW variable to a ROW() function
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT,b INT);
+ SET rec.a= 1;
+ SET rec.b= 2;
+ SELECT rec=(0,0), rec=ROW(0,0), (0,0)=rec, ROW(0,0)=rec;
+ SELECT rec=(1,2), rec=ROW(1,2), (1,2)=rec, ROW(1,2)=rec;
+ SELECT rec=(NULL,0), rec=ROW(NULL,0);
+ SELECT rec=(NULL,2), rec=ROW(NULL,2);
+ SELECT rec<>(0,0), rec<>ROW(0,0);
+ SELECT rec<>(1,2), rec<>ROW(1,2);
+ SELECT rec<>(NULL,0), rec<>ROW(NULL,0);
+ SELECT rec<>(NULL,2), rec<>ROW(NULL,2);
+ SELECT rec IN ((0,0)), rec IN (ROW(0,0));
+ SELECT rec IN ((1,2)), rec IN (ROW(1,2));
+ SELECT rec IN ((0,NULL),(1,2));
+ SELECT rec NOT IN ((0,NULL),(1,1));
+ SELECT rec NOT IN ((1,NULL),(1,1));
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Comparing a ROW variable to another ROW variable
+--echo #
+
+DELIMITER $$;
+CREATE OR REPLACE PROCEDURE p1()
+BEGIN
+ DECLARE rec1,rec2,rec3 ROW(a INT,b INT);
+ SET rec1.a= 1;
+ SET rec1.b= 2;
+ SET rec2.a= 11;
+ SET rec2.b= 12;
+ SET rec3.a= 11;
+ SET rec3.b= 12;
+ SELECT rec1=rec2, rec2=rec1, rec2=rec3, rec3=rec2;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Referencing a non-existing row variable
+--echo #
+DELIMITER $$;
+--error ER_UNKNOWN_STRUCTURED_VARIABLE
+CREATE PROCEDURE p1()
+BEGIN
+ SET a.b=1;
+END;
+$$
+DELIMITER ;$$
+
+--echo #
+--echo # Referencing a non-existing row field
+--echo #
+DELIMITER $$;
+--error ER_UNKNOWN_ERROR
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW(a INT,b INT);
+ SELECT a.c FROM t1;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # ROW and scalar variables with the same name shadowing each other
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW(a INT);
+ SET a.a=100;
+ SELECT a.a;
+ BEGIN
+ DECLARE a INT DEFAULT 200;
+ SELECT a;
+ BEGIN
+ DECLARE a ROW(a INT);
+ SET a.a=300;
+ SELECT a.a;
+ END;
+ SELECT a;
+ END;
+ SELECT a.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW with good default values
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE a ROW(a INT,b INT) DEFAULT (10,20);
+ DECLARE b ROW(a INT,b INT) DEFAULT (11,21);
+ DECLARE c ROW(a INT,b INT) DEFAULT a;
+ SELECT a.a, a.b, b.a, b.b, c.a, c.b FROM DUAL;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW in WHERE clause
+--echo #
+
+CREATE TABLE t1 (a INT,b INT);
+INSERT INTO t1 VALUES (10,20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT,b INT) DEFAULT ROW(10,20);
+ SELECT * FROM t1 WHERE rec=ROW(a,b);
+ SELECT * FROM t1 WHERE ROW(a,b)=rec;
+ SELECT * FROM t1 WHERE rec=ROW(10,20);
+ SELECT * FROM t1 WHERE ROW(10,20)=rec;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields in WHERE clause
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT);
+ SET rec.a= 10;
+ SELECT * FROM t1 WHERE a=rec.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields in HAVING clause
+--echo #
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT);
+ SET rec.a= 10;
+ SELECT * FROM t1 HAVING a=rec.a;
+ SELECT * FROM t1 HAVING MIN(a)=rec.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields in LIMIT clause
+--echo #
+
+CREATE TABLE t1 (a INT);
+--error ER_SP_UNDECLARED_VAR
+SELECT 1 FROM t1 LIMIT t1.a;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT);
+ SET rec.a= 10;
+ SELECT * FROM t1 LIMIT rec.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+DELIMITER $$;
+--error ER_WRONG_SPVAR_TYPE_IN_LIMIT
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a VARCHAR(10));
+ SET rec.a= '10';
+ SELECT * FROM t1 LIMIT rec.a;
+END;
+$$
+DELIMITER ;$$
+
+
+--echo #
+--echo # ROW fields in select list
+--echo #
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (10),(20);
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE t1 ROW(a INT);
+ SET t1.a= 10;
+ SELECT t1.a, 'This is the variable t1.a value, rather than the column t1.a' AS comm FROM t1;
+ SELECT t1.a, t2.a, t1.a+t2.a FROM t1 t2;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields as insert values
+--echo #
+
+CREATE TABLE t1 (a INT, b VARCHAR(10));
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT, b VARCHAR(10));
+ SET rec.a= 10;
+ SET rec.b= 'test';
+ INSERT INTO t1 VALUES (rec.a, rec.b);
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SELECT * FROM t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # ROW fields as SP out parameters
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(OUT a INT, OUT b VARCHAR(32))
+BEGIN
+ SET a= 10;
+ SET b= 'test';
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+ DECLARE rec ROW(a INT, b VARCHAR(10));
+ CALL p1(rec.a, rec.b);
+ SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p2;
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+
+
+--echo #
+--echo # ROW fields as dynamic SQL out parameters
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1(OUT a INT, OUT b VARCHAR(32))
+BEGIN
+ SET a= 20;
+ SET b= 'test-dynamic-sql';
+END;
+$$
+CREATE PROCEDURE p2()
+BEGIN
+ DECLARE rec ROW(a INT, b VARCHAR(30));
+ EXECUTE IMMEDIATE 'CALL p1(?,?)' USING rec.a, rec.b;
+ SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p2;
+DROP PROCEDURE p1;
+DROP PROCEDURE p2;
+
+
+--echo #
+--echo # ROW fields as SELECT..INTO targets
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT, b VARCHAR(10));
+ SELECT 10,'test' INTO rec.a,rec.b;
+ SELECT rec.a, rec.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Implicit default NULL handling
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec ROW(a INT, b VARCHAR(10), c DOUBLE, d DECIMAL(10,0), e TIME, f DATETIME);
+ SELECT rec.a, rec.b, rec.c, rec.d, rec.e, rec.f FROM DUAL;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # NULL handling
+--echo #
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1 ROW(a INT, b VARCHAR(10)) DEFAULT (NULL,NULL);
+ DECLARE rec2 ROW(a INT, b VARCHAR(10)) DEFAULT rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+
+ SET rec1= (10,20);
+ SET rec2= rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+
+ SET rec1= (NULL,20);
+ SET rec2= rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+
+ SET rec1= (10,NULL);
+ SET rec2= rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+
+ SET rec1= (NULL,NULL);
+ SET rec2= rec1;
+ SELECT rec1.a, rec1.b, rec2.a, rec2.b;
+END;
+$$
+DELIMITER ;$$
+CALL p1;
+DROP PROCEDURE p1;
+
+
+--echo #
+--echo # Testing multiple ROW variable declarations
+--echo # This makes sure that fill_field_definitions() is called only once
+--echo # per a ROW field, so create length is not converted to internal length
+--echo # multiple times.
+--echo #
+DELIMITER $$;
+CREATE PROCEDURE p1()
+BEGIN
+ DECLARE rec1, rec2, rec3 ROW(a VARCHAR(10) CHARACTER SET utf8);
+ CREATE TABLE t1 AS SELECT rec1.a, rec2.a, rec3.a;
+END;
+$$
+DELIMITER ;$$
+CALL p1();
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+DROP PROCEDURE p1;
+
+--echo #
+--echo # INT
+--echo #
+
+--let type=INT
+--source sp-row-vs-var.inc
+
+--let type=INT(1)
+--source sp-row-vs-var.inc
+
+--let type=INT(2)
+--source sp-row-vs-var.inc
+
+--let type=INT(3)
+--source sp-row-vs-var.inc
+
+--let type=INT(4)
+--source sp-row-vs-var.inc
+
+--let type=INT(5)
+--source sp-row-vs-var.inc
+
+--let type=INT(6)
+--source sp-row-vs-var.inc
+
+--let type=INT(7)
+--source sp-row-vs-var.inc
+
+--let type=INT(8)
+--source sp-row-vs-var.inc
+
+--let type=INT(9)
+--source sp-row-vs-var.inc
+
+--let type=INT(10)
+--source sp-row-vs-var.inc
+
+--let type=INT(11)
+--source sp-row-vs-var.inc
+
+--let type=INT(12)
+--source sp-row-vs-var.inc
+
+--let type=INT(13)
+--source sp-row-vs-var.inc
+
+--let type=INT(14)
+--source sp-row-vs-var.inc
+
+--let type=INT(20)
+--source sp-row-vs-var.inc
+
+--let type=INT(21)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # TINYINT
+--echo #
+
+--let type=TINYINT
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(1)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(2)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(3)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(4)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(5)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(6)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(7)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(8)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(9)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(10)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(11)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(12)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(13)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(14)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(20)
+--source sp-row-vs-var.inc
+
+--let type=TINYINT(21)
+--source sp-row-vs-var.inc
+
+--echo #
+--echo # SMALLINT
+--echo #
+
+--let type=SMALLINT
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(1)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(2)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(3)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(4)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(5)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(6)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(7)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(8)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(9)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(10)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(11)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(12)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(13)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(14)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(20)
+--source sp-row-vs-var.inc
+
+--let type=SMALLINT(21)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # MEDIUMINT
+--echo #
+
+--let type=MEDIUMINT
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(1)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(2)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(3)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(4)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(5)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(6)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(7)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(8)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(9)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(10)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(11)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(12)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(13)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(14)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(20)
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMINT(21)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # BIGINT
+--echo #
+
+--let type=BIGINT
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(1)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(2)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(3)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(4)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(5)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(6)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(7)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(8)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(9)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(10)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(11)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(12)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(13)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(14)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(20)
+--source sp-row-vs-var.inc
+
+--let type=BIGINT(21)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # DOUBLE
+--echo #
+
+--let type=DOUBLE
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,1)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,2)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,3)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,4)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,5)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,6)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,7)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,8)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,9)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,10)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,11)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,12)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,13)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,14)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,20)
+--source sp-row-vs-var.inc
+
+--let type=DOUBLE(30,21)
+--source sp-row-vs-var.inc
+
+--echo #
+--echo # VARCHAR
+--echo #
+
+--let type=CHAR
+--source sp-row-vs-var.inc
+
+--let type=BINARY
+--source sp-row-vs-var.inc
+
+--let type=CHAR(1)
+--source sp-row-vs-var.inc
+
+--let type=CHAR(10)
+--source sp-row-vs-var.inc
+
+--let type=NCHAR(10)
+--source sp-row-vs-var.inc
+
+--let type=BINARY(10)
+--source sp-row-vs-var.inc
+
+--let type=VARBINARY(10)
+--source sp-row-vs-var.inc
+
+--let type=VARCHAR(10)
+--source sp-row-vs-var.inc
+
+--let type=VARCHAR(10) CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+--let type=VARCHAR(10) CHARACTER SET utf8 COLLATE utf8_bin
+--source sp-row-vs-var.inc
+
+--echo #
+--echo # TIME
+--echo #
+
+--let type=TIME
+--source sp-row-vs-var.inc
+
+--let type=TIME(1)
+--source sp-row-vs-var.inc
+
+--let type=TIME(2)
+--source sp-row-vs-var.inc
+
+--let type=TIME(3)
+--source sp-row-vs-var.inc
+
+--let type=TIME(4)
+--source sp-row-vs-var.inc
+
+--let type=TIME(5)
+--source sp-row-vs-var.inc
+
+--let type=TIME(6)
+--source sp-row-vs-var.inc
+
+--echo #
+--echo # DATETIME
+--echo #
+
+--let type=DATETIME
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(1)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(2)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(3)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(4)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(5)
+--source sp-row-vs-var.inc
+
+--let type=DATETIME(6)
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # LOB
+--echo #
+
+--let type=TEXT
+--source sp-row-vs-var.inc
+
+--let type=TINYTEXT
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMTEXT
+--source sp-row-vs-var.inc
+
+--let type=LONGTEXT
+--source sp-row-vs-var.inc
+
+--let type=TEXT CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+--let type=TINYTEXT CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+--let type=MEDIUMTEXT CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+--let type=LONGTEXT CHARACTER SET utf8
+--source sp-row-vs-var.inc
+
+
+--echo #
+--echo # End of MDEV-10914 ROW data type for stored routine variables
+--echo #
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index ed6e92f145e..1ba20f0ac9e 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -438,9 +438,9 @@ select @a, @b;
#
# Bug#2586:Disallow global/session/local as structured var. instance names
#
---error ER_PARSE_ERROR
+--error ER_UNKNOWN_STRUCTURED_VARIABLE
set @@global.global.key_buffer_size= 1;
---error ER_PARSE_ERROR
+--error ER_UNKNOWN_STRUCTURED_VARIABLE
set GLOBAL global.key_buffer_size= 1;
--error ER_PARSE_ERROR
SELECT @@global.global.key_buffer_size;
diff --git a/sql/field.cc b/sql/field.cc
index 40bd6a8a2dd..06cf9fbee58 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -10203,6 +10203,7 @@ bool Column_definition::check(THD *thd)
((length > max_field_charlength &&
sql_type != MYSQL_TYPE_VARCHAR) ||
(length == 0 &&
+ sql_type != MYSQL_TYPE_NULL /* e.g. a ROW variable */ &&
sql_type != MYSQL_TYPE_ENUM && sql_type != MYSQL_TYPE_SET &&
sql_type != MYSQL_TYPE_STRING && sql_type != MYSQL_TYPE_VARCHAR &&
sql_type != MYSQL_TYPE_GEOMETRY)))
diff --git a/sql/field.h b/sql/field.h
index 359101530f3..68327159a22 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -3958,11 +3958,47 @@ public:
/**
+ List of ROW element definitions, e.g.:
+ DECLARE a ROW(a INT,b VARCHAR(10))
+*/
+class Row_definition_list: public List<class Spvar_definition>
+{
+public:
+ inline bool eq_name(const Spvar_definition *def, const char *name) const;
+ /**
+ Find a ROW field by name.
+ @param [IN] name - the name
+ @param [OUT] offset - if the ROW field found, its offset it returned here
+ @retval NULL - the ROW field was not found
+ @retval !NULL - the pointer to the found ROW field
+ */
+ Spvar_definition *find_row_field_by_name(const char *name, uint *offset) const
+ {
+ // Cast-off the "const" qualifier
+ List_iterator<Spvar_definition> it(*((List<Spvar_definition>*)this));
+ Spvar_definition *def;
+ for (*offset= 0; (def= it++); (*offset)++)
+ {
+ if (eq_name(def, name))
+ return def;
+ }
+ return 0;
+ }
+};
+
+
+/**
This class is used during a stored routine or a trigger execution,
at sp_rcontext::create() time.
Currently it can represent:
- variables with explicit data types: DECLARE a INT;
- variables with data type references: DECLARE a t1.a%TYPE;
+ - ROW type variables
+
+ Notes:
+ - Scalar variables have m_field_definitions==NULL.
+ - ROW variables are defined as having MYSQL_TYPE_NULL,
+ with a non-empty m_field_definitions.
Data type references to other object types will be added soon, e.g.:
- DECLARE a table_name%ROWTYPE;
@@ -3973,9 +4009,11 @@ public:
class Spvar_definition: public Column_definition
{
class Qualified_column_ident *m_column_type_ref; // for %TYPE
+ Row_definition_list *m_row_field_definitions; // for ROW
public:
Spvar_definition()
- :m_column_type_ref(NULL) { }
+ :m_column_type_ref(NULL),
+ m_row_field_definitions(NULL) { }
bool is_column_type_ref() const { return m_column_type_ref != 0; }
class Qualified_column_ident *column_type_ref() const
{
@@ -3985,9 +4023,39 @@ public:
{
m_column_type_ref= ref;
}
+
+ /*
+ Find a ROW field by name.
+ See Row_field_list::find_row_field_by_name() for details.
+ */
+ Spvar_definition *find_row_field_by_name(const char *name, uint *offset) const
+ {
+ DBUG_ASSERT(m_row_field_definitions);
+ return m_row_field_definitions->find_row_field_by_name(name, offset);
+ }
+ uint is_row() const
+ {
+ return m_row_field_definitions != NULL;
+ }
+ Row_definition_list *row_field_definitions() const
+ {
+ return m_row_field_definitions;
+ }
+ void set_row_field_definitions(Row_definition_list *list)
+ {
+ m_row_field_definitions= list;
+ }
+
};
+inline bool Row_definition_list::eq_name(const Spvar_definition *def,
+ const char *name) const
+{
+ return my_strcasecmp(system_charset_info, def->field_name, name) == 0;
+}
+
+
class Create_field :public Column_definition
{
public:
diff --git a/sql/item.cc b/sql/item.cc
index 9ad54cfad70..56428fb39bb 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1653,6 +1653,126 @@ bool Item_splocal::set_value(THD *thd, sp_rcontext *ctx, Item **it)
}
+/**
+ These two declarations are different:
+ x INT;
+ ROW(x INT);
+ A ROW with one elements should not be comparable to scalar value.
+
+ TODO: Currently we don't support one argument with the function ROW(), so
+ this query returns a syntax error, meaning that more arguments are expected:
+ SELECT ROW(1);
+
+ Therefore, all around the code we assume that cols()==1 means a scalar value
+ and cols()>1 means a ROW value. With adding ROW SP variables this
+ assumption is not true any more. ROW variables with one element are
+ now possible.
+
+ To implement Item::check_cols() correctly, we now should extend it to
+ know if a ROW or a scalar value is being tested. For example,
+ these new prototypes should work:
+ virtual bool check_cols(Item_result result, uint c);
+ or
+ virtual bool check_cols(const Type_handler *type, uint c);
+
+ The current implementation of Item_splocal::check_cols() is a compromise
+ that should be more or less fine until we extend check_cols().
+ It disallows ROW variables to appear in a scalar context.
+ The "|| n == 1" part of the conditon is responsible for this.
+ For example, it disallows ROW variables to appear in SELECT list:
+
+DELIMITER $$;
+CREATE PROCEDURE p1()
+AS
+ a ROW (a INT);
+BEGIN
+ SELECT a;
+END;
+$$
+DELIMITER ;$$
+--error ER_OPERAND_COLUMNS
+CALL p1();
+
+ But is produces false negatives with ROW variables consisting of one element.
+ For example, this script fails:
+
+SET sql_mode=ORACLE;
+DROP PROCEDURE IF EXISTS p1;
+DELIMITER $$
+CREATE PROCEDURE p1
+AS
+ a ROW(a INT);
+ b ROW(a INT);
+BEGIN
+ SELECT a=b;
+END;
+$$
+DELIMITER ;
+CALL p1();
+
+ and returns "ERROR 1241 (21000): Operand should contain 1 column(s)".
+ This will be fixed that we change check_cols().
+*/
+
+bool Item_splocal::check_cols(uint n)
+{
+ DBUG_ASSERT(m_thd->spcont);
+ if (cmp_type() != ROW_RESULT)
+ return Item::check_cols(n);
+
+ if (n != this_item()->cols() || n == 1)
+ {
+ my_error(ER_OPERAND_COLUMNS, MYF(0), n);
+ return true;
+ }
+ return false;
+}
+
+
+Item *
+Item_splocal_row_field::this_item()
+{
+ DBUG_ASSERT(m_sp == m_thd->spcont->sp);
+ return m_thd->spcont->get_item(m_var_idx)->element_index(m_field_idx);
+}
+
+
+const Item *
+Item_splocal_row_field::this_item() const
+{
+ DBUG_ASSERT(m_sp == m_thd->spcont->sp);
+ return m_thd->spcont->get_item(m_var_idx)->element_index(m_field_idx);
+}
+
+
+Item **
+Item_splocal_row_field::this_item_addr(THD *thd, Item **)
+{
+ DBUG_ASSERT(m_sp == thd->spcont->sp);
+ return thd->spcont->get_item(m_var_idx)->addr(m_field_idx);
+}
+
+
+void Item_splocal_row_field::print(String *str, enum_query_type)
+{
+ str->reserve(m_name.length + m_field_name.length + 8);
+ str->append(m_name.str, m_name.length);
+ str->append('.');
+ str->append(m_field_name.str, m_field_name.length);
+ str->append('@');
+ str->qs_append(m_var_idx);
+ str->append('[');
+ str->qs_append(m_field_idx);
+ str->append(']');
+}
+
+
+bool Item_splocal_row_field::set_value(THD *thd, sp_rcontext *ctx, Item **it)
+{
+ return ctx->set_variable_row_field(thd, m_var_idx, m_field_idx, it);
+}
+
+
/*****************************************************************************
Item_case_expr methods
*****************************************************************************/
diff --git a/sql/item.h b/sql/item.h
index 4e737d09952..01573c9e6ea 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1843,6 +1843,94 @@ inline Item* get_item_copy (THD *thd, MEM_ROOT *mem_root, T* item)
bool cmp_items(Item *a, Item *b);
+/**
+ Array of items, e.g. function or aggerate function arguments.
+*/
+class Item_args
+{
+protected:
+ Item **args, *tmp_arg[2];
+ uint arg_count;
+ bool alloc_arguments(THD *thd, uint count);
+ void set_arguments(THD *thd, List<Item> &list);
+ bool walk_args(Item_processor processor, bool walk_subquery, void *arg)
+ {
+ for (uint i= 0; i < arg_count; i++)
+ {
+ if (args[i]->walk(processor, walk_subquery, arg))
+ return true;
+ }
+ return false;
+ }
+ bool transform_args(THD *thd, Item_transformer transformer, uchar *arg);
+ void propagate_equal_fields(THD *, const Item::Context &, COND_EQUAL *);
+public:
+ Item_args(void)
+ :args(NULL), arg_count(0)
+ { }
+ Item_args(Item *a)
+ :args(tmp_arg), arg_count(1)
+ {
+ args[0]= a;
+ }
+ Item_args(Item *a, Item *b)
+ :args(tmp_arg), arg_count(2)
+ {
+ args[0]= a; args[1]= b;
+ }
+ Item_args(THD *thd, Item *a, Item *b, Item *c)
+ {
+ arg_count= 0;
+ if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 3)))
+ {
+ arg_count= 3;
+ args[0]= a; args[1]= b; args[2]= c;
+ }
+ }
+ Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d)
+ {
+ arg_count= 0;
+ if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 4)))
+ {
+ arg_count= 4;
+ args[0]= a; args[1]= b; args[2]= c; args[3]= d;
+ }
+ }
+ Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e)
+ {
+ arg_count= 5;
+ if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 5)))
+ {
+ arg_count= 5;
+ args[0]= a; args[1]= b; args[2]= c; args[3]= d; args[4]= e;
+ }
+ }
+ Item_args(THD *thd, List<Item> &list)
+ {
+ set_arguments(thd, list);
+ }
+ Item_args(THD *thd, const Item_args *other);
+ inline Item **arguments() const { return args; }
+ inline uint argument_count() const { return arg_count; }
+ inline void remove_arguments() { arg_count=0; }
+};
+
+
+class Item_spvar_args: public Item_args
+{
+ TABLE *m_table;
+public:
+ Item_spvar_args():Item_args(), m_table(NULL) { }
+ ~Item_spvar_args();
+ bool row_create_items(THD *thd, List<Spvar_definition> *list);
+ Field *get_row_field(uint i) const
+ {
+ DBUG_ASSERT(m_table);
+ return m_table->field[i];
+ }
+};
+
+
/*
Class to be used to enumerate all field references in an item tree. This
includes references to outside but not fields of the tables within a
@@ -2076,9 +2164,12 @@ class Item_splocal :public Item_sp_variable,
public Rewritable_query_parameter,
public Type_handler_hybrid_field_type
{
+protected:
uint m_var_idx;
Type m_type;
+
+ bool append_value_for_log(THD *thd, String *str);
public:
Item_splocal(THD *thd, const LEX_STRING &sp_var_name, uint sp_var_idx,
enum_field_types sp_var_type,
@@ -2104,6 +2195,10 @@ public:
{ return Type_handler_hybrid_field_type::result_type(); }
enum Item_result cmp_type () const
{ return Type_handler_hybrid_field_type::cmp_type(); }
+ uint cols() { return this_item()->cols(); }
+ Item* element_index(uint i) { return this_item()->element_index(i); }
+ Item** addr(uint i) { return this_item()->addr(i); }
+ bool check_cols(uint c);
private:
bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
@@ -2123,6 +2218,20 @@ public:
};
+class Item_splocal_row: public Item_splocal
+{
+public:
+ Item_splocal_row(THD *thd, const LEX_STRING &sp_var_name,
+ uint sp_var_idx, uint pos_in_q, uint len_in_q)
+ :Item_splocal(thd, sp_var_name, sp_var_idx, MYSQL_TYPE_NULL,
+ pos_in_q, len_in_q)
+ {
+ set_handler(&type_handler_row);
+ }
+ enum Type type() const { return ROW_ITEM; }
+};
+
+
/**
An Item_splocal variant whose data type becomes known only at
sp_rcontext creation time, e.g. "DECLARE var1 t1.col1%TYPE".
@@ -2156,6 +2265,37 @@ public:
{ return tmp_table_field_from_field_type(table, false, true); }
};
+
+/**
+ SP variables that are fields of a ROW.
+ DELCARE r ROW(a INT,b INT);
+ SELECT r.a; -- This is handled by Item_splocal_row_field
+*/
+class Item_splocal_row_field :public Item_splocal
+{
+ LEX_STRING m_field_name;
+ uint m_field_idx;
+ bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
+public:
+ Item_splocal_row_field(THD *thd,
+ const LEX_STRING &sp_var_name,
+ const LEX_STRING &sp_field_name,
+ uint sp_var_idx, uint sp_field_idx,
+ enum_field_types sp_var_type,
+ uint pos_in_q= 0, uint len_in_q= 0)
+ :Item_splocal(thd, sp_var_name, sp_var_idx, sp_var_type,
+ pos_in_q, len_in_q),
+ m_field_name(sp_field_name),
+ m_field_idx(sp_field_idx)
+ { }
+ Item *this_item();
+ const Item *this_item() const;
+ Item **this_item_addr(THD *thd, Item **);
+ bool append_for_log(THD *thd, String *str);
+ void print(String *str, enum_query_type query_type);
+};
+
+
/*****************************************************************************
Item_splocal inline implementation.
*****************************************************************************/
@@ -2599,6 +2739,39 @@ public:
};
+/**
+ Item_field for the ROW data type
+*/
+class Item_field_row: public Item_field,
+ public Item_spvar_args
+{
+public:
+ Item_field_row(THD *thd, Field *field)
+ :Item_field(thd, field),
+ Item_spvar_args()
+ { }
+
+ Item *get_copy(THD *thd, MEM_ROOT *mem_root)
+ { return get_item_copy<Item_field_row>(thd, mem_root, this); }
+
+ const Type_handler *type_handler() const { return &type_handler_row; }
+ Item_result result_type() const{ return ROW_RESULT ; }
+ Item_result cmp_type() const { return ROW_RESULT; }
+ uint cols() { return arg_count; }
+ Item* element_index(uint i) { return arg_count ? args[i] : this; }
+ Item** addr(uint i) { return arg_count ? args + i : NULL; }
+ bool check_cols(uint c)
+ {
+ if (cols() != c)
+ {
+ my_error(ER_OPERAND_COLUMNS, MYF(0), c);
+ return true;
+ }
+ return false;
+ }
+};
+
+
/*
@brief
Item_temptable_field is the same as Item_field, except that print()
@@ -3785,78 +3958,6 @@ public:
};
-/**
- Array of items, e.g. function or aggerate function arguments.
-*/
-class Item_args
-{
-protected:
- Item **args, *tmp_arg[2];
- uint arg_count;
- void set_arguments(THD *thd, List<Item> &list);
- bool walk_args(Item_processor processor, bool walk_subquery, void *arg)
- {
- for (uint i= 0; i < arg_count; i++)
- {
- if (args[i]->walk(processor, walk_subquery, arg))
- return true;
- }
- return false;
- }
- bool transform_args(THD *thd, Item_transformer transformer, uchar *arg);
- void propagate_equal_fields(THD *, const Item::Context &, COND_EQUAL *);
-public:
- Item_args(void)
- :args(NULL), arg_count(0)
- { }
- Item_args(Item *a)
- :args(tmp_arg), arg_count(1)
- {
- args[0]= a;
- }
- Item_args(Item *a, Item *b)
- :args(tmp_arg), arg_count(2)
- {
- args[0]= a; args[1]= b;
- }
- Item_args(THD *thd, Item *a, Item *b, Item *c)
- {
- arg_count= 0;
- if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 3)))
- {
- arg_count= 3;
- args[0]= a; args[1]= b; args[2]= c;
- }
- }
- Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d)
- {
- arg_count= 0;
- if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 4)))
- {
- arg_count= 4;
- args[0]= a; args[1]= b; args[2]= c; args[3]= d;
- }
- }
- Item_args(THD *thd, Item *a, Item *b, Item *c, Item *d, Item* e)
- {
- arg_count= 5;
- if ((args= (Item**) thd_alloc(thd, sizeof(Item*) * 5)))
- {
- arg_count= 5;
- args[0]= a; args[1]= b; args[2]= c; args[3]= d; args[4]= e;
- }
- }
- Item_args(THD *thd, List<Item> &list)
- {
- set_arguments(thd, list);
- }
- Item_args(THD *thd, const Item_args *other);
- inline Item **arguments() const { return args; }
- inline uint argument_count() const { return arg_count; }
- inline void remove_arguments() { arg_count=0; }
-};
-
-
class Used_tables_and_const_cache
{
public:
diff --git a/sql/item_func.cc b/sql/item_func.cc
index e981722a123..7eeb9547c89 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -89,23 +89,35 @@ static inline bool test_if_sum_overflows_ull(ulonglong arg1, ulonglong arg2)
}
-void Item_args::set_arguments(THD *thd, List<Item> &list)
+/**
+ Allocate memory for arguments using tmp_args or thd->alloc().
+ @retval false - success
+ @retval true - error (arg_count is set to 0 for conveniece)
+*/
+bool Item_args::alloc_arguments(THD *thd, uint count)
{
- arg_count= list.elements;
- if (arg_count <= 2)
+ if (count <= 2)
{
args= tmp_arg;
+ return false;
}
- else if (!(args= (Item**) thd->alloc(sizeof(Item*) * arg_count)))
+ if ((args= (Item**) thd->alloc(sizeof(Item*) * count)) == NULL)
{
arg_count= 0;
- return;
+ return true;
}
- uint i= 0;
+ return false;
+}
+
+
+void Item_args::set_arguments(THD *thd, List<Item> &list)
+{
+ if (alloc_arguments(thd, list.elements))
+ return;
List_iterator_fast<Item> li(list);
Item *item;
- while ((item= li++))
- args[i++]= item;
+ for (arg_count= 0; (item= li++); )
+ args[arg_count++]= item;
}
@@ -138,6 +150,19 @@ void Item_func::sync_with_sum_func_and_with_field(List<Item> &list)
}
+bool Item_func::check_allowed_arg_cols(uint n)
+{
+ if (allowed_arg_cols)
+ return args[n]->check_cols(allowed_arg_cols);
+
+ /* we have to fetch allowed_arg_cols from first argument */
+ DBUG_ASSERT(n == 0); // it is first argument
+ allowed_arg_cols= args[n]->cols();
+ DBUG_ASSERT(allowed_arg_cols); // Can't be 0 any more
+ return false;
+}
+
+
/*
Resolve references to table column for a function and its argument
@@ -210,18 +235,8 @@ Item_func::fix_fields(THD *thd, Item **ref)
return TRUE; /* purecov: inspected */
item= *arg;
- if (allowed_arg_cols)
- {
- if (item->check_cols(allowed_arg_cols))
- return 1;
- }
- else
- {
- /* we have to fetch allowed_arg_cols from first argument */
- DBUG_ASSERT(arg == args); // it is first argument
- allowed_arg_cols= item->cols();
- DBUG_ASSERT(allowed_arg_cols); // Can't be 0 any more
- }
+ if (check_allowed_arg_cols(arg - args))
+ return true;
if (item->maybe_null)
maybe_null=1;
diff --git a/sql/item_func.h b/sql/item_func.h
index 88fa78cd4a4..5b39c2ef0d8 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -53,6 +53,7 @@ protected:
set_if_bigger(res, item[i]->decimals);
return res;
}
+ virtual bool check_allowed_arg_cols(uint argno);
public:
void aggregate_attributes_int(Item **items, uint nitems)
{
@@ -2547,7 +2548,12 @@ private:
protected:
bool is_expensive_processor(void *arg)
{ return is_expensive(); }
-
+
+ bool check_allowed_arg_cols(uint n)
+ {
+ // sp_prepare_func_item() checks that the number of columns is correct
+ return false;
+ }
public:
Item_func_sp(THD *thd, Name_resolution_context *context_arg, sp_name *name);
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 3f4299e2166..8b0bd18e95a 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -7460,3 +7460,5 @@ ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION
ER_WRONG_PARAMCOUNT_TO_CURSOR 42000
eng "Incorrect parameter count to cursor '%-.192s'"
rus "Некорректное количество параметров для курсора '%-.192s'"
+ER_UNKNOWN_STRUCTURED_VARIABLE
+ eng "Unknown structured system variable or ROW routine variable '%-.*s'"
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 7fd2624ab7a..471e6d46828 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -100,19 +100,51 @@ bool Item_splocal::append_for_log(THD *thd, String *str)
if (limit_clause_param)
return str->append_ulonglong(val_uint());
+ /*
+ ROW variables are currently not allowed in select_list, e.g.:
+ SELECT row_variable;
+ ROW variables can appear in query parts where name is not important, e.g.:
+ SELECT ROW(1,2)=row_variable FROM t1;
+ So we can skip using NAME_CONST() and use ROW() constants directly.
+ */
+ if (type_handler() == &type_handler_row)
+ return append_value_for_log(thd, str);
+
if (str->append(STRING_WITH_LEN(" NAME_CONST('")) ||
str->append(&m_name) ||
str->append(STRING_WITH_LEN("',")))
return true;
+ return append_value_for_log(thd, str) || str->append(')');
+}
+
+bool Item_splocal::append_value_for_log(THD *thd, String *str)
+{
StringBuffer<STRING_BUFFER_USUAL_SIZE> str_value_holder(&my_charset_latin1);
Item *item= this_item();
String *str_value= item->type_handler()->print_item_value(thd, item,
&str_value_holder);
- if (str_value)
- return str->append(*str_value) || str->append(')');
- else
- return str->append(STRING_WITH_LEN("NULL)"));
+ return str_value ?
+ str->append(*str_value) :
+ str->append(STRING_WITH_LEN("NULL"));
+}
+
+
+bool Item_splocal_row_field::append_for_log(THD *thd, String *str)
+{
+ if (fix_fields(thd, NULL))
+ return true;
+
+ if (limit_clause_param)
+ return str->append_ulonglong(val_uint());
+
+ if (str->append(STRING_WITH_LEN(" NAME_CONST('")) ||
+ str->append(&m_name) ||
+ str->append(".") ||
+ str->append(&m_field_name) ||
+ str->append(STRING_WITH_LEN("',")))
+ return true;
+ return append_value_for_log(thd, str) || str->append(')');
}
@@ -308,14 +340,14 @@ sp_get_flags_for_command(LEX *lex)
*/
Item *
-sp_prepare_func_item(THD* thd, Item **it_addr)
+sp_prepare_func_item(THD* thd, Item **it_addr, uint cols)
{
DBUG_ENTER("sp_prepare_func_item");
it_addr= (*it_addr)->this_item_addr(thd, it_addr);
- if (!(*it_addr)->fixed &&
- ((*it_addr)->fix_fields(thd, it_addr) ||
- (*it_addr)->check_cols(1)))
+ if ((!(*it_addr)->fixed &&
+ (*it_addr)->fix_fields(thd, it_addr)) ||
+ (*it_addr)->check_cols(cols))
{
DBUG_PRINT("info", ("fix_fields() failed"));
DBUG_RETURN(NULL);
@@ -338,7 +370,8 @@ sp_prepare_func_item(THD* thd, Item **it_addr)
*/
bool
-sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr)
+sp_eval_expr(THD *thd, Item *result_item, Field *result_field,
+ Item **expr_item_ptr)
{
Item *expr_item;
enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
@@ -351,10 +384,21 @@ sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr)
if (!*expr_item_ptr)
goto error;
- if (!(expr_item= sp_prepare_func_item(thd, expr_item_ptr)))
+ if (!(expr_item= sp_prepare_func_item(thd, expr_item_ptr,
+ result_item ? result_item->cols() : 1)))
goto error;
/*
+ expr_item is now fixed, it's safe to call cmp_type()
+ If result_item is NULL, then we're setting the RETURN value.
+ */
+ if (!result_item && expr_item->cmp_type() == ROW_RESULT)
+ {
+ my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
+ goto error;
+ }
+
+ /*
Set THD flags to emit warnings/errors in case of overflow/type errors
during saving the item into the field.
@@ -3185,6 +3229,56 @@ sp_instr_set::print(String *str)
/*
+ sp_instr_set_field class functions
+*/
+
+int
+sp_instr_set_row_field::exec_core(THD *thd, uint *nextp)
+{
+ int res= thd->spcont->set_variable_row_field(thd, m_offset, m_field_offset,
+ &m_value);
+ if (res)
+ {
+ /* Failed to evaluate the value. Reset the variable to NULL. */
+ thd->spcont->set_variable_row_field_to_null(thd, m_offset, m_field_offset);
+ }
+ delete_explain_query(thd->lex);
+ *nextp= m_ip + 1;
+ return res;
+}
+
+
+void
+sp_instr_set_row_field::print(String *str)
+{
+ /* set name@offset[field_offset] ... */
+ int rsrv= SP_INSTR_UINT_MAXLEN + 6 + 6 + 3;
+ sp_variable *var= m_ctx->find_variable(m_offset);
+ DBUG_ASSERT(var);
+ DBUG_ASSERT(var->field_def.is_row());
+ const Column_definition *def=
+ var->field_def.row_field_definitions()->elem(m_field_offset);
+ DBUG_ASSERT(def);
+
+ rsrv+= var->name.length + strlen(def->field_name);
+ if (str->reserve(rsrv))
+ return;
+ str->qs_append(STRING_WITH_LEN("set "));
+ str->qs_append(var->name.str, var->name.length);
+ str->qs_append('.');
+ str->qs_append(def->field_name);
+ str->qs_append('@');
+ str->qs_append(m_offset);
+ str->qs_append('[');
+ str->qs_append(m_field_offset);
+ str->qs_append(']');
+ str->qs_append(' ');
+ m_value->print(str, enum_query_type(QT_ORDINARY |
+ QT_ITEM_ORIGINAL_FUNC_NULLIF));
+}
+
+
+/*
sp_instr_set_trigger_field class functions
*/
@@ -4209,6 +4303,11 @@ sp_add_to_query_tables(THD *thd, LEX *lex,
}
+Item *sp_head::adjust_assignment_source(THD *thd, Item *val, Item *val2)
+{
+ return val ? val : val2 ? val2 : new (thd->mem_root) Item_null(thd);
+}
+
/**
Helper action for a SET statement.
Used to push a SP local variable into the assignment list.
@@ -4223,28 +4322,40 @@ bool
sp_head::set_local_variable(THD *thd, sp_pcontext *spcont,
sp_variable *spv, Item *val, LEX *lex)
{
- Item *it;
-
- if (val)
- it= val;
- else if (spv->default_value)
- it= spv->default_value;
- else
- {
- it= new (thd->mem_root) Item_null(thd);
- if (it == NULL)
- return TRUE;
- }
+ if (!(val= adjust_assignment_source(thd, val, spv->default_value)))
+ return true;
sp_instr_set *sp_set= new (thd->mem_root)
sp_instr_set(instructions(), spcont,
- spv->offset, it, spv->sql_type(),
+ spv->offset, val, spv->sql_type(),
lex, true);
return sp_set == NULL || add_instr(sp_set);
}
+/**
+ Similar to set_local_variable(), but for ROW variable fields.
+*/
+bool
+sp_head::set_local_variable_row_field(THD *thd, sp_pcontext *spcont,
+ sp_variable *spv, uint field_idx,
+ Item *val, LEX *lex)
+{
+ if (!(val= adjust_assignment_source(thd, val, NULL)))
+ return true;
+
+ sp_instr_set_row_field *sp_set= new (thd->mem_root)
+ sp_instr_set_row_field(instructions(),
+ spcont,
+ spv->offset,
+ field_idx, val,
+ spv->sql_type(),
+ lex, true);
+ return sp_set == NULL || add_instr(sp_set);
+}
+
+
bool sp_head::add_open_cursor(THD *thd, sp_pcontext *spcont, uint offset,
sp_pcontext *param_spcont,
List<sp_assignment_lex> *parameters)
diff --git a/sql/sp_head.h b/sql/sp_head.h
index ec19058a7f1..fc3dfa49f63 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -360,9 +360,12 @@ public:
spcont->last_label());
}
+ Item *adjust_assignment_source(THD *thd, Item *val, Item *val2);
bool set_local_variable(THD *thd, sp_pcontext *spcont,
sp_variable *spv, Item *val, LEX *lex);
-
+ bool set_local_variable_row_field(THD *thd, sp_pcontext *spcont,
+ sp_variable *spv, uint field_idx,
+ Item *val, LEX *lex);
private:
/**
Generate a code to set a single cursor parameter variable.
@@ -992,7 +995,7 @@ public:
virtual void print(String *str);
-private:
+protected:
uint m_offset; ///< Frame offset
Item *m_value;
@@ -1002,6 +1005,36 @@ private:
}; // class sp_instr_set : public sp_instr
+/*
+ This class handles assignments of a ROW fields:
+ DECLARE rec ROW (a INT,b INT);
+ SET rec.a= 10;
+*/
+class sp_instr_set_row_field : public sp_instr_set
+{
+ sp_instr_set_row_field(const sp_instr_set_row_field &); // Prevent use of this
+ void operator=(sp_instr_set_row_field &);
+ uint m_field_offset;
+
+public:
+
+ sp_instr_set_row_field(uint ip, sp_pcontext *ctx,
+ uint offset, uint field_offset,
+ Item *val, enum enum_field_types type_arg,
+ LEX *lex, bool lex_resp)
+ : sp_instr_set(ip, ctx, offset, val, type_arg, lex, lex_resp),
+ m_field_offset(field_offset)
+ {}
+
+ virtual ~sp_instr_set_row_field()
+ {}
+
+ virtual int exec_core(THD *thd, uint *nextp);
+
+ virtual void print(String *str);
+}; // class sp_instr_set_field : public sp_instr_set
+
+
/**
Set NEW/OLD row field value instruction. Used in triggers.
*/
@@ -1603,10 +1636,11 @@ sp_add_to_query_tables(THD *thd, LEX *lex,
enum_mdl_type mdl_type);
Item *
-sp_prepare_func_item(THD* thd, Item **it_addr);
+sp_prepare_func_item(THD* thd, Item **it_addr, uint cols= 1);
bool
-sp_eval_expr(THD *thd, Field *result_field, Item **expr_item_ptr);
+sp_eval_expr(THD *thd, Item *result_item, Field *result_field,
+ Item **expr_item_ptr);
/**
@} (end of group Stored_Routines)
diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc
index 642f1f16d29..06c51642d68 100644
--- a/sql/sp_pcontext.cc
+++ b/sql/sp_pcontext.cc
@@ -563,3 +563,24 @@ const sp_pcursor *sp_pcontext::find_cursor(uint offset) const
m_parent->find_cursor(offset) : // Some previous frame
NULL; // Index out of bounds
}
+
+
+const Spvar_definition *
+sp_variable::find_row_field(const LEX_STRING &var_name,
+ const LEX_STRING &field_name,
+ uint *row_field_offset)
+{
+ if (!field_def.is_row())
+ {
+ my_printf_error(ER_UNKNOWN_ERROR,
+ "'%s' is not a row variable", MYF(0), var_name.str);
+ return NULL;
+ }
+ const Spvar_definition *def;
+ if ((def= field_def.find_row_field_by_name(field_name.str, row_field_offset)))
+ return def;
+ my_printf_error(ER_UNKNOWN_ERROR,
+ "Row variable '%s' does not have a field '%s'",
+ MYF(0), var_name.str, field_name.str);
+ return NULL;
+}
diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h
index 414a3cbc7cc..00cc81964eb 100644
--- a/sql/sp_pcontext.h
+++ b/sql/sp_pcontext.h
@@ -69,6 +69,20 @@ public:
offset(_offset),
default_value(NULL)
{ }
+ /*
+ Find a ROW field by its qualified name.
+ @param var_name - the name of the variable
+ @param field_name - the name of the variable field
+ @param[OUT] row_field_offset - the index of the field
+
+ @retval NULL if the variable with the given name was not found,
+ or it is not a row variable, or it does not have a field
+ with the given name, or a non-null pointer otherwise.
+ row_field_offset[0] is set only when the method returns !NULL.
+ */
+ const Spvar_definition *find_row_field(const LEX_STRING &var_name,
+ const LEX_STRING &field_name,
+ uint *row_field_offset);
};
///////////////////////////////////////////////////////////////////////////
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 5fcdbf42313..17c91b09727 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -222,23 +222,65 @@ bool sp_rcontext::init_var_items(THD *thd,
if (!m_var_items.array())
return true;
- for (uint idx = 0; idx < num_vars; ++idx)
+ DBUG_ASSERT(field_def_lst.elements == num_vars);
+ List_iterator<Spvar_definition> it(field_def_lst);
+ Spvar_definition *def= it++;
+
+ for (uint idx= 0; idx < num_vars; ++idx, def= it++)
{
- if (!(m_var_items[idx]= new (thd->mem_root) Item_field(thd, m_var_table->field[idx])))
- return true;
+ Field *field= m_var_table->field[idx];
+ if (def->is_row())
+ {
+ Item_field_row *item= new (thd->mem_root) Item_field_row(thd, field);
+ if (!(m_var_items[idx]= item) ||
+ item->row_create_items(thd, def->row_field_definitions()))
+ return true;
+ }
+ else
+ {
+ if (!(m_var_items[idx]= new (thd->mem_root) Item_field(thd, field)))
+ return true;
+ }
}
+ return false;
+}
+
+
+bool Item_spvar_args::row_create_items(THD *thd, List<Spvar_definition> *list)
+{
+ DBUG_ASSERT(list);
+ if (!(m_table= create_virtual_tmp_table(thd, *list)))
+ return true;
+
+ if (alloc_arguments(thd, list->elements))
+ return true;
+ List_iterator<Spvar_definition> it(*list);
+ Spvar_definition *def;
+ for (arg_count= 0; (def= it++); arg_count++)
+ {
+ if (!(args[arg_count]= new (thd->mem_root)
+ Item_field(thd, m_table->field[arg_count])))
+ return true;
+ }
return false;
}
+Item_spvar_args::~Item_spvar_args()
+{
+ if (m_table)
+ free_blobs(m_table);
+}
+
+
bool sp_rcontext::set_return_value(THD *thd, Item **return_value_item)
{
DBUG_ASSERT(m_return_value_fld);
m_return_value_set = true;
- return sp_eval_expr(thd, m_return_value_fld, return_value_item);
+ return sp_eval_expr(thd, NULL, m_return_value_fld, return_value_item);
}
@@ -455,8 +497,78 @@ int sp_rcontext::set_variable(THD *thd, uint idx, Item **value)
field->set_null();
return 0;
}
+ Item *dst= m_var_items[idx];
+
+ if (dst->cmp_type() != ROW_RESULT)
+ return sp_eval_expr(thd, dst, m_var_table->field[idx], value);
+
+ DBUG_ASSERT(dst->type() == Item::FIELD_ITEM);
+ if (value[0]->type() == Item::NULL_ITEM)
+ {
+ /*
+ We're in a auto-generated sp_inst_set, to assign
+ the explicit default NULL value to a ROW variable.
+ */
+ for (uint i= 0; i < dst->cols(); i++)
+ {
+ Item_field_row *item_field_row= (Item_field_row*) dst;
+ item_field_row->get_row_field(i)->set_null();
+ }
+ return false;
+ }
+
+ /**
+ - In case if we're assigning a ROW variable from another ROW variable,
+ value[0] points to Item_splocal. sp_prepare_func_item() will return the
+ fixed underlying Item_field_spvar with ROW members in its aguments().
+ - In case if we're assigning from a ROW() value, src and value[0] will
+ point to the same Item_row.
+ */
+ Item *src;
+ if (!(src= sp_prepare_func_item(thd, value, dst->cols())) ||
+ src->cmp_type() != ROW_RESULT)
+ {
+ my_error(ER_OPERAND_COLUMNS, MYF(0), dst->cols());
+ return true;
+ }
+ DBUG_ASSERT(dst->cols() == src->cols());
+ for (uint i= 0; i < src->cols(); i++)
+ set_variable_row_field(thd, idx, i, src->addr(i));
+ return false;
+}
+
+
+void sp_rcontext::set_variable_row_field_to_null(THD *thd,
+ uint var_idx,
+ uint field_idx)
+{
+ Item *dst= get_item(var_idx);
+ DBUG_ASSERT(dst->type() == Item::FIELD_ITEM);
+ DBUG_ASSERT(dst->cmp_type() == ROW_RESULT);
+ Item_field_row *item_field_row= (Item_field_row*) dst;
+ item_field_row->get_row_field(field_idx)->set_null();
+}
+
- return sp_eval_expr(thd, field, value);
+int sp_rcontext::set_variable_row_field(THD *thd, uint var_idx, uint field_idx,
+ Item **value)
+{
+ DBUG_ASSERT(value);
+ Item *dst= get_item(var_idx);
+ DBUG_ASSERT(dst->type() == Item::FIELD_ITEM);
+ DBUG_ASSERT(dst->cmp_type() == ROW_RESULT);
+ Item_field_row *item_field_row= (Item_field_row*) dst;
+
+ Item *expr_item= sp_prepare_func_item(thd, value);
+ if (!expr_item)
+ {
+ DBUG_ASSERT(thd->is_error());
+ return true;
+ }
+ return sp_eval_expr(thd,
+ item_field_row->arguments()[field_idx],
+ item_field_row->get_row_field(field_idx),
+ value);
}
diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h
index 061f736f6e9..78cbfd9ec26 100644
--- a/sql/sp_rcontext.h
+++ b/sql/sp_rcontext.h
@@ -187,7 +187,9 @@ public:
/////////////////////////////////////////////////////////////////////////
int set_variable(THD *thd, uint var_idx, Item **value);
-
+ void set_variable_row_field_to_null(THD *thd, uint var_idx, uint field_idx);
+ int set_variable_row_field(THD *thd, uint var_idx, uint field_idx,
+ Item **value);
Item *get_item(uint var_idx) const
{ return m_var_items[var_idx]; }
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 65a4dabb85b..5ddb0a86592 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -3839,6 +3839,11 @@ bool my_var_sp::set(THD *thd, Item *item)
return thd->spcont->set_variable(thd, offset, &item);
}
+bool my_var_sp_row_field::set(THD *thd, Item *item)
+{
+ return thd->spcont->set_variable_row_field(thd, offset, m_field_offset, &item);
+}
+
int select_dumpvar::send_data(List<Item> &items)
{
List_iterator_fast<my_var> var_li(var_list);
diff --git a/sql/sql_class.h b/sql/sql_class.h
index cac1cdd8fd3..1cc2e22bb17 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -5522,6 +5522,22 @@ public:
bool set(THD *thd, Item *val);
};
+/*
+ This class handles fields of a ROW SP variable when it's used as a OUT
+ parameter in a stored procedure.
+*/
+class my_var_sp_row_field: public my_var_sp
+{
+ uint m_field_offset;
+public:
+ my_var_sp_row_field(const LEX_STRING &varname, const LEX_STRING &fieldname,
+ uint var_idx, uint field_idx, sp_head *s)
+ :my_var_sp(varname, var_idx, MYSQL_TYPE_DOUBLE/*Not really used*/, s),
+ m_field_offset(field_idx)
+ { }
+ bool set(THD *thd, Item *val);
+};
+
class my_var_user: public my_var {
public:
my_var_user(const LEX_STRING& j)
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 83983a1a357..b0647f6b404 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -5153,7 +5153,8 @@ bool LEX::init_internal_variable(struct sys_var_with_base *variable,
{
if (check_reserved_words(&dbname))
{
- thd->parse_error();
+ my_error(ER_UNKNOWN_STRUCTURED_VARIABLE, MYF(0),
+ (int) dbname.length, dbname.str);
return true;
}
if (is_trigger_new_or_old_reference(dbname))
@@ -5179,9 +5180,13 @@ bool LEX::init_internal_variable(struct sys_var_with_base *variable,
return false;
}
- sys_var *tmp= find_sys_var(thd, name.str, name.length);
+ sys_var *tmp= find_sys_var_ex(thd, name.str, name.length, true, false);
if (!tmp)
+ {
+ my_error(ER_UNKNOWN_STRUCTURED_VARIABLE, MYF(0),
+ (int) dbname.length, dbname.str);
return true;
+ }
if (!tmp->is_struct())
my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), name.str);
variable->var= tmp;
@@ -5219,6 +5224,7 @@ void LEX::sp_variable_declarations_init(THD *thd, int nvars)
bool LEX::sp_variable_declarations_finalize(THD *thd, int nvars,
const Column_definition *cdef,
+ Row_definition_list *row,
Item *dflt_value_item)
{
uint num_vars= spcont->context_var_count();
@@ -5226,7 +5232,31 @@ bool LEX::sp_variable_declarations_finalize(THD *thd, int nvars,
if (!dflt_value_item &&
!(dflt_value_item= new (thd->mem_root) Item_null(thd)))
return true;
- /* QQ Set to the var_type with null_value? */
+
+ if (row)
+ {
+ /*
+ Prepare all row fields. This will (among other things)
+ - convert VARCHAR lengths from character length to octet length
+ - calculate interval lengths for SET and ENUM
+ Note, we do it only one time outside of the below loop.
+ The converted list in "row" is further reused by all variable
+ declarations processed by the current call.
+ Example:
+ DECLARE
+ a, b, c ROW(x VARCHAR(10) CHARACTER SET utf8);
+ BEGIN
+ ...
+ END;
+ */
+ List_iterator<Spvar_definition> it(*row);
+ for (Spvar_definition *def= it++; def; def= it++)
+ {
+ def->pack_flag|= FIELDFLAG_MAYBE_NULL;
+ if (sphead->fill_field_definition(thd, def))
+ return true;
+ }
+ }
for (uint i= num_vars - nvars ; i < num_vars ; i++)
{
@@ -5246,6 +5276,7 @@ bool LEX::sp_variable_declarations_finalize(THD *thd, int nvars,
if (sphead->fill_spvar_definition(thd, &spvar->field_def, spvar->name.str))
return true;
}
+ spvar->field_def.set_row_field_definitions(row);
/* The last instruction is responsible for freeing LEX. */
sp_instr_set *is= new (this->thd->mem_root)
@@ -5274,7 +5305,7 @@ LEX::sp_variable_declarations_with_ref_finalize(THD *thd, int nvars,
spvar->field_def.field_name= spvar->name.str;
}
sphead->m_flags|= sp_head::HAS_COLUMN_TYPE_REFS;
- return sp_variable_declarations_finalize(thd, nvars, NULL, def);
+ return sp_variable_declarations_finalize(thd, nvars, NULL, NULL, def);
}
@@ -5315,7 +5346,7 @@ sp_variable *LEX::sp_add_for_loop_variable(THD *thd, const LEX_STRING name,
*/
spvar->field_def.pack_flag= (FIELDFLAG_NUMBER |
f_settype((uint) MYSQL_TYPE_LONGLONG));
- if (sp_variable_declarations_finalize(thd, 1, NULL, value))
+ if (sp_variable_declarations_finalize(thd, 1, NULL, NULL, value))
return NULL;
return spvar;
}
@@ -5953,11 +5984,9 @@ Item_param *LEX::add_placeholder(THD *thd, char *name,
}
-Item_param *LEX::add_placeholder(THD *thd, char *name,
- const char *pos, const char *end)
+const char *LEX::substatement_query(THD *thd) const
{
- const char *query_start= sphead ? sphead->m_tmp_query : thd->query();
- return add_placeholder(thd, name, pos - query_start, end - pos);
+ return sphead ? sphead->m_tmp_query : thd->query();
}
@@ -5979,6 +6008,160 @@ bool LEX::add_resignal_statement(THD *thd, const sp_condition_value *v)
}
+Item *LEX::create_item_ident_nospvar(THD *thd,
+ const LEX_STRING &a,
+ const LEX_STRING &b)
+{
+ DBUG_ASSERT(this == thd->lex);
+ /*
+ FIXME This will work ok in simple_ident_nospvar case because
+ we can't meet simple_ident_nospvar in trigger now. But it
+ should be changed in future.
+ */
+ if (is_trigger_new_or_old_reference(a))
+ {
+ bool new_row= (a.str[0]=='N' || a.str[0]=='n');
+
+ return create_and_link_Item_trigger_field(thd, b.str, new_row);
+ }
+
+ if (current_select->no_table_names_allowed)
+ {
+ my_error(ER_TABLENAME_NOT_ALLOWED_HERE, MYF(0), a.str, thd->where);
+ return NULL;
+ }
+ if ((current_select->parsing_place != IN_HAVING) ||
+ (current_select->get_in_sum_expr() > 0))
+ return new (thd->mem_root) Item_field(thd, current_context(),
+ NullS, a.str, b.str);
+ return new (thd->mem_root) Item_ref(thd, current_context(),
+ NullS, a.str, b.str);
+}
+
+
+Item_splocal_row_field *LEX::create_item_spvar_row_field(THD *thd,
+ const LEX_STRING &a,
+ const LEX_STRING &b,
+ sp_variable *spv,
+ uint pos_in_q,
+ uint length_in_q)
+{
+ if (!parsing_options.allows_variable)
+ {
+ my_error(ER_VIEW_SELECT_VARIABLE, MYF(0));
+ return NULL;
+ }
+
+ uint row_field_offset;
+ const Spvar_definition *def;
+ if (!(def= spv->find_row_field(a, b, &row_field_offset)))
+ return NULL;
+
+ Item_splocal_row_field *item;
+ if (!(item= new (thd->mem_root)
+ Item_splocal_row_field(thd, a, b,
+ spv->offset, row_field_offset,
+ def->sql_type, pos_in_q, length_in_q)))
+ return NULL;
+#ifndef DBUG_OFF
+ item->m_sp= sphead;
+#endif
+ safe_to_cache_query=0;
+ return item;
+}
+
+
+my_var *LEX::create_outvar(THD *thd,
+ const LEX_STRING &a,
+ const LEX_STRING &b)
+{
+ sp_variable *t;
+ if (!spcont || !(t= spcont->find_variable(a, false)))
+ {
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), a.str);
+ return NULL;
+ }
+ uint row_field_offset;
+ if (!t->find_row_field(a, b, &row_field_offset))
+ return NULL;
+ return result ?
+ new (thd->mem_root) my_var_sp_row_field(a, b, t->offset,
+ row_field_offset, sphead) :
+ NULL;
+}
+
+
+Item *LEX::create_item_ident(THD *thd,
+ const LEX_STRING &a,
+ const LEX_STRING &b,
+ uint pos_in_q, uint length_in_q)
+{
+ sp_variable *spv;
+ if (spcont && (spv= spcont->find_variable(a, false)))
+ return create_item_spvar_row_field(thd, a, b, spv, pos_in_q, length_in_q);
+ return create_item_ident_nospvar(thd, a, b);
+}
+
+
+
+Item *LEX::create_item_limit(THD *thd,
+ const LEX_STRING &a,
+ uint pos_in_q, uint length_in_q)
+{
+ sp_variable *spv;
+ if (!spcont || !(spv= spcont->find_variable(a, false)))
+ {
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), a.str);
+ return NULL;
+ }
+
+ Item_splocal *item;
+ if (!(item= new (thd->mem_root) Item_splocal(thd, a,
+ spv->offset, spv->sql_type(),
+ pos_in_q, length_in_q)))
+ return NULL;
+#ifndef DBUG_OFF
+ item->m_sp= sphead;
+#endif
+ safe_to_cache_query= 0;
+
+ if (item->type() != Item::INT_ITEM)
+ {
+ my_error(ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0));
+ return NULL;
+ }
+ item->limit_clause_param= true;
+ return item;
+}
+
+
+Item *LEX::create_item_limit(THD *thd,
+ const LEX_STRING &a,
+ const LEX_STRING &b,
+ uint pos_in_q, uint length_in_q)
+{
+ sp_variable *spv;
+ if (!spcont || !(spv= spcont->find_variable(a, false)))
+ {
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), a.str);
+ return NULL;
+ }
+ // Qualified %TYPE variables are not possible
+ DBUG_ASSERT(!spv->field_def.column_type_ref());
+ Item_splocal *item;
+ if (!(item= create_item_spvar_row_field(thd, a, b, spv,
+ pos_in_q, length_in_q)))
+ return NULL;
+ if (item->type() != Item::INT_ITEM)
+ {
+ my_error(ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0));
+ return NULL;
+ }
+ item->limit_clause_param= true;
+ return item;
+}
+
+
/*
Perform assignment for a trigger, a system variable, or an SP variable.
"variable" be previously set by init_internal_variable(variable, name).
@@ -6040,6 +6223,9 @@ Item *LEX::create_item_ident_sp(THD *thd, LEX_STRING name,
spv->offset,
start_in_q,
length_in_q) :
+ spv->field_def.is_row() ?
+ new (thd->mem_root) Item_splocal_row(thd, name, spv->offset,
+ start_in_q, length_in_q) :
new (thd->mem_root) Item_splocal(thd, name,
spv->offset, spv->sql_type(),
start_in_q, length_in_q);
@@ -6073,6 +6259,32 @@ Item *LEX::create_item_ident_sp(THD *thd, LEX_STRING name,
}
+/**
+ Generate instructions for:
+ SET x.y= expr;
+*/
+bool LEX::set_variable(const LEX_STRING &name1,
+ const LEX_STRING &name2,
+ Item *item)
+{
+ sp_variable *spv;
+ if (spcont && (spv= spcont->find_variable(name1, false)))
+ {
+ // A field of a ROW variable
+ uint row_field_offset;
+ return !spv->find_row_field(name1, name2, &row_field_offset) ||
+ sphead->set_local_variable_row_field(thd, spcont,
+ spv, row_field_offset,
+ item, this);
+ }
+
+ // A trigger field or a system variable
+ sys_var_with_base sysvar;
+ return init_internal_variable(&sysvar, name1, name2) ||
+ set_variable(&sysvar, item);
+}
+
+
#ifdef MYSQL_SERVER
uint binlog_unsafe_map[256];
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index c3ef0710112..913478b9589 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -96,6 +96,7 @@ class Key_part_spec;
class Item_window_func;
struct sql_digest_state;
class With_clause;
+class my_var;
#define ALLOC_ROOT_SET 1024
@@ -2226,6 +2227,20 @@ public:
return m_cpp_tok_end;
}
+ /**
+ Get the token end position in the pre-processed buffer,
+ with trailing spaces removed.
+ */
+ const char *get_cpp_tok_end_rtrim()
+ {
+ const char *p;
+ for (p= m_cpp_tok_end;
+ p > m_cpp_buf && my_isspace(system_charset_info, p[-1]);
+ p--)
+ { }
+ return p;
+ }
+
/** Get the current stream pointer, in the pre-processed buffer. */
const char *get_cpp_ptr()
{
@@ -2923,6 +2938,8 @@ public:
void start(THD *thd);
+ const char *substatement_query(THD *thd) const;
+
inline bool is_ps_or_view_context_analysis()
{
return (context_analysis_only &
@@ -3108,10 +3125,25 @@ public:
bool init_default_internal_variable(struct sys_var_with_base *variable,
LEX_STRING name);
bool set_variable(struct sys_var_with_base *variable, Item *item);
+ bool set_variable(const LEX_STRING &name1, const LEX_STRING &name2,
+ Item *item);
void sp_variable_declarations_init(THD *thd, int nvars);
bool sp_variable_declarations_finalize(THD *thd, int nvars,
const Column_definition *cdef,
+ Row_definition_list *row,
Item *def);
+ bool sp_variable_declarations_finalize(THD *thd, int nvars,
+ const Column_definition *cdef,
+ Item *def)
+ {
+ return sp_variable_declarations_finalize(thd, nvars, cdef, NULL, def);
+ }
+ bool sp_variable_declarations_row_finalize(THD *thd, int nvars,
+ Row_definition_list *row,
+ Item *def)
+ {
+ return sp_variable_declarations_finalize(thd, nvars, NULL, row, def);
+ }
bool sp_variable_declarations_with_ref_finalize(THD *thd, int nvars,
Qualified_column_ident *col,
Item *def);
@@ -3141,6 +3173,98 @@ public:
create_item_ident_sp(thd, name, start_in_q, end_in_q) :
create_item_ident_nosp(thd, name);
}
+
+ /*
+ Create an Item corresponding to a qualified name: a.b
+ when the parser is out of an SP context.
+ @param THD - THD, for mem_root
+ @param a - the first name
+ @param b - the second name
+ @retval - a pointer to a created item, or NULL on error.
+
+ Possible Item types that can be created:
+ - Item_trigger_field
+ - Item_field
+ - Item_ref
+ */
+ Item *create_item_ident_nospvar(THD *thd,
+ const LEX_STRING &a,
+ const LEX_STRING &b);
+ /*
+ Create an Item corresponding to a ROW field valiable: var.field
+ @param THD - THD, for mem_root
+ @param var - the ROW variable name
+ @param field - the ROW variable field name
+ @param spvar - the variable that was previously found by name
+ using "var_name".
+ @pos_in_q - position in the query (for binary log)
+ @length_in_q - length in the query (for binary log)
+ */
+ Item_splocal_row_field *create_item_spvar_row_field(THD *thd,
+ const LEX_STRING &var,
+ const LEX_STRING &field,
+ sp_variable *spvar,
+ uint pos_in_q,
+ uint length_in_q);
+ /*
+ Create an item from its qualified name.
+ Depending on context, it can be either a ROW variable field,
+ or trigger, table field, table field reference.
+ See comments to create_item_spvar_row_field() and
+ create_item_ident_nospvar().
+ @param thd - THD, for mem_root
+ @param a - the first name
+ @param b - the second name
+ @param pos_in_q - position in the query (for binary log)
+ @param length_in_q - length in the query (for binary log)
+ @retval - NULL on error, or a pointer to a new Item.
+ */
+ Item *create_item_ident(THD *thd,
+ const LEX_STRING &a,
+ const LEX_STRING &b,
+ uint pos_in_q, uint length_in_q);
+ /*
+ Create an item for a name in LIMIT clause: LIMIT var
+ @param THD - THD, for mem_root
+ @param var_name - the variable name
+ @param pos_in_q - position in the query (for binary log)
+ @param length_in_q - length in the query (for binary log)
+ @retval - a new Item corresponding to the SP variable,
+ or NULL on error
+ (non in SP, unknown variable, wrong data type).
+ */
+ Item *create_item_limit(THD *thd,
+ const LEX_STRING &var_name,
+ uint pos_in_q, uint length_in_q);
+
+ /*
+ Create an item for a qualified name in LIMIT clause: LIMIT var.field
+ @param THD - THD, for mem_root
+ @param var_name - the variable name
+ @param field_name - the variable field name
+ @param pos_in_q - position in the query (for binary log)
+ @param length_in_q - length in the query (for binary log)
+ @retval - a new Item corresponding to the SP variable,
+ or NULL on error
+ (non in SP, unknown variable, unknown ROW field,
+ wrong data type).
+ */
+ Item *create_item_limit(THD *thd,
+ const LEX_STRING &var_name,
+ const LEX_STRING &field_name,
+ uint pos_in_q, uint length_in_q);
+
+ /*
+ Create a my_var instance for a ROW field variable that was used
+ as an OUT SP parameter: CALL p1(var.field);
+ @param THD - THD, for mem_root
+ @param var_name - the variable name
+ @param field_name - the variable field name
+ */
+ my_var *create_outvar(THD *thd,
+ const LEX_STRING &var_name,
+ const LEX_STRING &field_name);
+
bool is_trigger_new_or_old_reference(const LEX_STRING name);
Item *create_and_link_Item_trigger_field(THD *thd, const char *name,
@@ -3209,8 +3333,10 @@ public:
Item_param *add_placeholder(THD *thd, char *name,
uint pos_in_query, uint len_in_query);
Item_param *add_placeholder(THD *thd, char *name,
- const char *pos, const char *end);
-
+ const char *pos, const char *end)
+ {
+ return add_placeholder(thd, name, pos - substatement_query(thd), end - pos);
+ }
sp_variable *sp_add_for_loop_variable(THD *thd, const LEX_STRING name,
Item *value);
sp_variable *sp_add_for_loop_upper_bound(THD *thd, Item *value)
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 8f6f7337f1c..217cdad5abb 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -334,16 +334,15 @@ public:
friend class error_list;
friend class error_list_iterator;
-#ifndef DBUG_OFF
/*
- Debugging help: return N-th element in the list, or NULL if the list has
+ Return N-th element in the list, or NULL if the list has
less than N elements.
*/
- void *elem(int n)
+ void *elem(uint n)
{
list_node *node= first;
void *data= NULL;
- for (int i=0; i <= n; i++)
+ for (uint i= 0; i <= n; i++)
{
if (node == &end_of_list)
{
@@ -355,7 +354,6 @@ public:
}
return data;
}
-#endif
#ifdef LIST_EXTRA_DEBUG
/*
@@ -546,9 +544,7 @@ public:
}
empty();
}
-#ifndef DBUG_OFF
- T *elem(int n) { return (T*)base_list::elem(n); }
-#endif
+ T *elem(uint n) { return (T*) base_list::elem(n); }
};
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ed6a412fdc5..d3f2a674664 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -12955,6 +12955,14 @@ static bool check_row_equality(THD *thd, const Arg_comparator *comparators,
if (left_item->type() == Item::ROW_ITEM &&
right_item->type() == Item::ROW_ITEM)
{
+ /*
+ Item_splocal for ROW SP variables return Item::ROW_ITEM.
+ Here we know that left_item and right_item are not Item_splocal,
+ because ROW SP variables with nested ROWs are not supported yet.
+ It's safe to cast left_item and right_item to Item_row.
+ */
+ DBUG_ASSERT(!left_item->get_item_splocal());
+ DBUG_ASSERT(!right_item->get_item_splocal());
is_converted= check_row_equality(thd,
comparators[i].subcomparators(),
(Item_row *) left_item,
@@ -13025,6 +13033,15 @@ bool Item_func_eq::check_equality(THD *thd, COND_EQUAL *cond_equal,
if (left_item->type() == Item::ROW_ITEM &&
right_item->type() == Item::ROW_ITEM)
{
+ /*
+ Item_splocal::type() for ROW variables returns Item::ROW_ITEM.
+ Distinguish ROW-type Item_splocal from Item_row.
+ Example query:
+ SELECT 1 FROM DUAL WHERE row_sp_variable=ROW(100,200);
+ */
+ if (left_item->get_item_splocal() ||
+ right_item->get_item_splocal())
+ return false;
return check_row_equality(thd,
cmp.subcomparators(),
(Item_row *) left_item,
diff --git a/sql/sql_test.cc b/sql/sql_test.cc
index e70872af6c5..804a6b5c493 100644
--- a/sql/sql_test.cc
+++ b/sql/sql_test.cc
@@ -385,10 +385,10 @@ void print_sjm(SJ_MATERIALIZATION_INFO *sjm)
/*
Debugging help: force List<...>::elem function not be removed as unused.
*/
-Item* (List<Item>:: *dbug_list_item_elem_ptr)(int)= &List<Item>::elem;
-Item_equal* (List<Item_equal>:: *dbug_list_item_equal_elem_ptr)(int)=
+Item* (List<Item>:: *dbug_list_item_elem_ptr)(uint)= &List<Item>::elem;
+Item_equal* (List<Item_equal>:: *dbug_list_item_equal_elem_ptr)(uint)=
&List<Item_equal>::elem;
-TABLE_LIST* (List<TABLE_LIST>:: *dbug_list_table_list_elem_ptr)(int) =
+TABLE_LIST* (List<TABLE_LIST>:: *dbug_list_table_list_elem_ptr)(uint) =
&List<TABLE_LIST>::elem;
#endif
diff --git a/sql/sql_type.cc b/sql/sql_type.cc
index 2679795eaa5..055a8969787 100644
--- a/sql/sql_type.cc
+++ b/sql/sql_type.cc
@@ -2225,8 +2225,22 @@ bool Type_handler_temporal_result::
String *Type_handler_row::
print_item_value(THD *thd, Item *item, String *str) const
{
- DBUG_ASSERT(0);
- return NULL;
+ CHARSET_INFO *cs= thd->variables.character_set_client;
+ StringBuffer<STRING_BUFFER_USUAL_SIZE> val(cs);
+ str->append(C_STRING_WITH_LEN("ROW("));
+ for (uint i= 0 ; i < item->cols(); i++)
+ {
+ if (i > 0)
+ str->append(',');
+ Item *elem= item->element_index(i);
+ String *tmp= elem->type_handler()->print_item_value(thd, elem, &val);
+ if (tmp)
+ str->append(*tmp);
+ else
+ str->append(STRING_WITH_LEN("NULL"));
+ }
+ str->append(C_STRING_WITH_LEN(")"));
+ return str;
}
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 321e4e58d61..3115f9603e3 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -761,6 +761,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
LEX_SYMBOL symbol;
Lex_string_with_metadata_st lex_string_with_metadata;
struct sys_var_with_base variable;
+ Lex_string_with_pos_st lex_string_with_pos;
Lex_spblock_st spblock;
Lex_spblock_handlers_st spblock_handlers;
Lex_length_and_dec_st Lex_length_and_dec;
@@ -771,6 +772,8 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
/* pointers */
Create_field *create_field;
+ Spvar_definition *spvar_definition;
+ Row_definition_list *spvar_definition_list;
CHARSET_INFO *charset;
Condition_information_item *cond_info_item;
DYNCALL_CREATE_DEF *dyncol_def;
@@ -1579,7 +1582,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <lex_str>
IDENT IDENT_QUOTED DECIMAL_NUM FLOAT_NUM NUM LONG_NUM
HEX_NUM HEX_STRING
- LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text
+ LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident_or_text
IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
opt_component key_cache_name
sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty
@@ -1593,6 +1596,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <lex_str_ptr>
opt_table_alias
+%type <lex_string_with_pos>
+ ident ident_with_tok_start
+
%type <table>
table_ident table_ident_nodb references xid
table_ident_opt_wild create_like
@@ -1679,7 +1685,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
geometry_function signed_literal expr_or_literal
opt_escape
sp_opt_default
- simple_ident_nospvar simple_ident_q
+ simple_ident_nospvar simple_ident_q simple_ident_q2
field_or_var limit_option
part_func_expr
window_func_expr
@@ -1886,6 +1892,9 @@ END_OF_INPUT
%type <cond_info_item_name> condition_information_item_name;
%type <cond_info_list> condition_information;
+%type <spvar_definition> row_field_name row_field_definition
+%type <spvar_definition_list> row_field_definition_list field_type_row
+
%type <NONE> opt_window_clause window_def_list window_def window_spec
%type <lex_str_ptr> window_name
%type <NONE> opt_window_ref opt_window_frame_clause
@@ -2853,6 +2862,12 @@ sp_param_name_and_type:
if (Lex->sp_param_fill_definition($$= $1))
MYSQL_YYABORT;
}
+ | sp_param_name field_type_row
+ {
+ $$= $1;
+ $$->field_def.field_name= $$->name.str;
+ $$->field_def.set_row_field_definitions($2);
+ }
;
/* Stored PROCEDURE parameter declaration list */
@@ -2931,6 +2946,44 @@ sp_decl:
DECLARE_SYM sp_decl_body { $$= $2; }
;
+row_field_name:
+ ident
+ {
+ if (check_string_char_length(&$1, 0, NAME_CHAR_LEN,
+ system_charset_info, 1))
+ my_yyabort_error((ER_TOO_LONG_IDENT, MYF(0), $1.str));
+ if (!($$= new (thd->mem_root) Spvar_definition()))
+ MYSQL_YYABORT;
+ Lex->init_last_field($$, $1.str, thd->variables.collation_database);
+ }
+ ;
+
+row_field_definition:
+ row_field_name type_with_opt_collate
+ ;
+
+row_field_definition_list:
+ row_field_definition
+ {
+ if (!($$= new (thd->mem_root) Row_definition_list()))
+ MYSQL_YYABORT;
+ $$->push_back($1, thd->mem_root);
+ }
+ | row_field_definition_list ',' row_field_definition
+ {
+ uint unused;
+ if ($1->find_row_field_by_name($3->field_name, &unused))
+ my_yyabort_error((ER_DUP_FIELDNAME, MYF(0), $3->field_name));
+ $$= $1;
+ $$->push_back($3, thd->mem_root);
+ }
+ ;
+
+field_type_row:
+ ROW_SYM '(' row_field_definition_list ')' { $$= $3; }
+ ;
+
+
sp_decl_body:
sp_decl_idents
{
@@ -2942,8 +2995,18 @@ sp_decl_body:
if (Lex->sp_variable_declarations_finalize(thd, $1,
&Lex->last_field[0], $4))
MYSQL_YYABORT;
- $$.vars= $1;
- $$.conds= $$.hndlrs= $$.curs= 0;
+ $$.init_using_vars($1);
+ }
+ | sp_decl_idents
+ {
+ Lex->sp_variable_declarations_init(thd, $1);
+ }
+ field_type_row
+ sp_opt_default
+ {
+ if (Lex->sp_variable_declarations_row_finalize(thd, $1, $3, $4))
+ MYSQL_YYABORT;
+ $$.init_using_vars($1);
}
| ident CONDITION_SYM FOR_SYM sp_cond
{
@@ -8357,7 +8420,7 @@ remember_name:
remember_end:
{
- $$= (char*) YYLIP->get_cpp_tok_end();
+ $$= (char*) YYLIP->get_cpp_tok_end_rtrim();
}
;
@@ -11421,32 +11484,25 @@ limit_options:
;
limit_option:
- ident
+ ident_with_tok_start
{
- Item_splocal *splocal;
LEX *lex= thd->lex;
Lex_input_stream *lip= & thd->m_parser_state->m_lip;
- sp_variable *spv;
- sp_pcontext *spc = lex->spcont;
- if (spc && (spv = spc->find_variable($1, false)))
- {
- splocal= new (thd->mem_root)
- Item_splocal(thd, $1, spv->offset, spv->sql_type(),
- lip->get_tok_start() - lex->sphead->m_tmp_query,
- lip->get_ptr() - lip->get_tok_start());
- if (splocal == NULL)
- MYSQL_YYABORT;
-#ifndef DBUG_OFF
- splocal->m_sp= lex->sphead;
-#endif
- lex->safe_to_cache_query=0;
- }
- else
- my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
- if (splocal->type() != Item::INT_ITEM)
- my_yyabort_error((ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0)));
- splocal->limit_clause_param= TRUE;
- $$= splocal;
+ if (!($$= lex->create_item_limit(thd, $1,
+ $1.m_pos -
+ lex->substatement_query(thd),
+ lip->get_tok_end() - $1.m_pos)))
+ MYSQL_YYABORT;
+ }
+ | ident_with_tok_start '.' ident
+ {
+ LEX *lex= thd->lex;
+ Lex_input_stream *lip= & thd->m_parser_state->m_lip;
+ if (!($$= lex->create_item_limit(thd, $1, $3,
+ $1.m_pos -
+ lex->substatement_query(thd),
+ lip->get_ptr() - $1.m_pos)))
+ MYSQL_YYABORT;
}
| param_marker
{
@@ -11655,6 +11711,11 @@ select_outvar:
Lex->sphead)) :
NULL;
}
+ | ident '.' ident
+ {
+ if (!($$= Lex->create_outvar(thd, $1, $3)))
+ MYSQL_YYABORT;
+ }
;
into:
@@ -13706,7 +13767,16 @@ simple_ident:
lip->get_tok_end())))
MYSQL_YYABORT;
}
- | simple_ident_q { $$= $1; }
+ | simple_ident_q2 { $$= $1; }
+ | ident '.' ident
+ {
+ LEX *lex= thd->lex;
+ if (!($$= lex->create_item_ident(thd, $1, $3,
+ $1.m_pos -
+ lex->substatement_query(thd),
+ YYLIP->get_tok_end() - $1.m_pos)))
+ MYSQL_YYABORT;
+ }
;
simple_ident_nospvar:
@@ -13721,45 +13791,14 @@ simple_ident_nospvar:
simple_ident_q:
ident '.' ident
{
- LEX *lex= thd->lex;
-
- /*
- FIXME This will work ok in simple_ident_nospvar case because
- we can't meet simple_ident_nospvar in trigger now. But it
- should be changed in future.
- */
- if (lex->is_trigger_new_or_old_reference($1))
- {
- bool new_row= ($1.str[0]=='N' || $1.str[0]=='n');
-
- if (!($$= lex->create_and_link_Item_trigger_field(thd, $3.str,
- new_row)))
- MYSQL_YYABORT;
- }
- else
- {
- SELECT_LEX *sel= lex->current_select;
- if (sel->no_table_names_allowed)
- {
- my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
- MYF(0), $1.str, thd->where);
- }
- if ((sel->parsing_place != IN_HAVING) ||
- (sel->get_in_sum_expr() > 0))
- {
- $$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
- NullS, $1.str, $3.str);
- }
- else
- {
- $$= new (thd->mem_root) Item_ref(thd, Lex->current_context(),
- NullS, $1.str, $3.str);
- }
- if ($$ == NULL)
- MYSQL_YYABORT;
- }
+ if (!($$= Lex->create_item_ident_nospvar(thd, $1, $3)))
+ MYSQL_YYABORT;
}
- | '.' ident '.' ident
+ | simple_ident_q2
+ ;
+
+simple_ident_q2:
+ '.' ident '.' ident
{
LEX *lex= thd->lex;
SELECT_LEX *sel= lex->current_select;
@@ -13951,13 +13990,33 @@ TEXT_STRING_filesystem:
;
ident:
- IDENT_sys { $$=$1; }
+ IDENT_sys
+ {
+ (LEX_STRING &)$$= $1;
+ $$.m_pos= (char *) YYLIP->get_tok_start_prev();
+ }
| keyword
{
$$.str= thd->strmake($1.str, $1.length);
if ($$.str == NULL)
MYSQL_YYABORT;
$$.length= $1.length;
+ $$.m_pos= (char *) YYLIP->get_tok_start_prev();
+ }
+ ;
+
+ident_with_tok_start:
+ IDENT_sys
+ {
+ (LEX_STRING &)$$= $1;
+ $$.m_pos= (char *) YYLIP->get_tok_start();
+ }
+ | keyword
+ {
+ if (!($$.str= thd->strmake($1.str, $1.length)))
+ MYSQL_YYABORT;
+ $$.length= $1.length;
+ $$.m_pos= (char *) YYLIP->get_tok_start();
}
;
@@ -14616,9 +14675,24 @@ option_value_following_option_type:
// Option values without preceding option_type.
option_value_no_option_type:
- internal_variable_name equal set_expr_or_default
+ ident equal set_expr_or_default
+ {
+ struct sys_var_with_base var;
+ if (Lex->init_internal_variable(&var, $1) ||
+ Lex->set_variable(&var, $3))
+ MYSQL_YYABORT;
+ }
+ | ident '.' ident equal set_expr_or_default
+ {
+ DBUG_ASSERT(Lex->var_list.is_empty());
+ if (Lex->set_variable($1, $3, $5))
+ MYSQL_YYABORT;
+ }
+ | DEFAULT '.' ident equal set_expr_or_default
{
- if (Lex->set_variable(&$1, $3))
+ struct sys_var_with_base var;
+ if (Lex->init_default_internal_variable(&var, $3) ||
+ Lex->set_variable(&var, $5))
MYSQL_YYABORT;
}
| '@' ident_or_text equal expr
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index de712e33bc3..c652192622e 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -171,6 +171,7 @@ void ORAerror(THD *thd, const char *s)
LEX_SYMBOL symbol;
Lex_string_with_metadata_st lex_string_with_metadata;
struct sys_var_with_base variable;
+ Lex_string_with_pos_st lex_string_with_pos;
Lex_spblock_st spblock;
Lex_spblock_handlers_st spblock_handlers;
Lex_length_and_dec_st Lex_length_and_dec;
@@ -186,6 +187,8 @@ void ORAerror(THD *thd, const char *s)
/* pointers */
Create_field *create_field;
+ Spvar_definition *spvar_definition;
+ Row_definition_list *spvar_definition_list;
CHARSET_INFO *charset;
Condition_information_item *cond_info_item;
DYNCALL_CREATE_DEF *dyncol_def;
@@ -997,7 +1000,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <lex_str>
IDENT IDENT_QUOTED DECIMAL_NUM FLOAT_NUM NUM LONG_NUM
HEX_NUM HEX_STRING
- LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident ident_or_text
+ LEX_HOSTNAME ULONGLONG_NUM field_ident select_alias ident_or_text
IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
opt_component key_cache_name
sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty
@@ -1013,6 +1016,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <lex_str_ptr>
opt_table_alias
+%type <lex_string_with_pos>
+ ident ident_with_tok_start
+
%type <table>
table_ident table_ident_nodb references xid
table_ident_opt_wild create_like
@@ -1113,7 +1119,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
geometry_function signed_literal expr_or_literal
opt_escape
sp_opt_default
- simple_ident_nospvar simple_ident_q
+ simple_ident_nospvar simple_ident_q simple_ident_q2
field_or_var limit_option
part_func_expr
window_func_expr
@@ -1346,6 +1352,9 @@ END_OF_INPUT
%type <cond_info_item_name> condition_information_item_name;
%type <cond_info_list> condition_information;
+%type <spvar_definition> row_field_name row_field_definition
+%type <spvar_definition_list> row_field_definition_list field_type_row
+
%type <NONE> opt_window_clause window_def_list window_def window_spec
%type <lex_str_ptr> window_name
%type <NONE> opt_window_ref opt_window_frame_clause
@@ -2318,6 +2327,12 @@ sp_param_name_and_type:
{
Lex->sphead->fill_spvar_using_type_reference($$= $1, $2);
}
+ | sp_param_name field_type_row
+ {
+ $$= $1;
+ $$->field_def.field_name= $$->name.str;
+ $$->field_def.set_row_field_definitions($2);
+ }
;
/* Stored PROCEDURE parameter declaration list */
@@ -2342,6 +2357,12 @@ sp_pdparam:
{
Lex->sphead->fill_spvar_using_type_reference($1, $3);
}
+ | sp_param_name sp_opt_inout field_type_row
+ {
+ $1->mode= $2;
+ $1->field_def.field_name= $1->name.str;
+ $1->field_def.set_row_field_definitions($3);
+ }
;
sp_opt_inout:
@@ -2435,6 +2456,44 @@ qualified_column_ident:
}
;
+row_field_name:
+ ident_directly_assignable
+ {
+ if (check_string_char_length(&$1, 0, NAME_CHAR_LEN,
+ system_charset_info, 1))
+ my_yyabort_error((ER_TOO_LONG_IDENT, MYF(0), $1.str));
+ if (!($$= new (thd->mem_root) Spvar_definition()))
+ MYSQL_YYABORT;
+ Lex->init_last_field($$, $1.str, thd->variables.collation_database);
+ }
+ ;
+
+row_field_definition:
+ row_field_name type_with_opt_collate
+ ;
+
+row_field_definition_list:
+ row_field_definition
+ {
+ if (!($$= new (thd->mem_root) Row_definition_list()))
+ MYSQL_YYABORT;
+ $$->push_back($1, thd->mem_root);
+ }
+ | row_field_definition_list ',' row_field_definition
+ {
+ uint unused;
+ if ($1->find_row_field_by_name($3->field_name, &unused))
+ my_yyabort_error((ER_DUP_FIELDNAME, MYF(0), $3->field_name));
+ $$= $1;
+ $$->push_back($3, thd->mem_root);
+ }
+ ;
+
+field_type_row:
+ ROW_SYM '(' row_field_definition_list ')' { $$= $3; }
+ ;
+
+
sp_decl_body:
sp_decl_idents
{
@@ -2459,6 +2518,17 @@ sp_decl_body:
MYSQL_YYABORT;
$$.init_using_vars($1);
}
+ | sp_decl_idents
+ {
+ Lex->sp_variable_declarations_init(thd, $1);
+ }
+ field_type_row
+ sp_opt_default
+ {
+ if (Lex->sp_variable_declarations_row_finalize(thd, $1, $3, $4))
+ MYSQL_YYABORT;
+ $$.init_using_vars($1);
+ }
| ident_directly_assignable CONDITION_SYM FOR_SYM sp_cond
{
if (Lex->spcont->declare_condition(thd, $1, $4))
@@ -8360,7 +8430,7 @@ remember_name:
remember_end:
{
- $$= (char*) YYLIP->get_cpp_tok_end();
+ $$= (char*) YYLIP->get_cpp_tok_end_rtrim();
}
;
@@ -11516,32 +11586,25 @@ limit_options:
;
limit_option:
- ident
+ ident_with_tok_start
{
- Item_splocal *splocal;
LEX *lex= thd->lex;
Lex_input_stream *lip= & thd->m_parser_state->m_lip;
- sp_variable *spv;
- sp_pcontext *spc = lex->spcont;
- if (spc && (spv = spc->find_variable($1, false)))
- {
- splocal= new (thd->mem_root)
- Item_splocal(thd, $1, spv->offset, spv->sql_type(),
- lip->get_tok_start() - lex->sphead->m_tmp_query,
- lip->get_ptr() - lip->get_tok_start());
- if (splocal == NULL)
- MYSQL_YYABORT;
-#ifndef DBUG_OFF
- splocal->m_sp= lex->sphead;
-#endif
- lex->safe_to_cache_query=0;
- }
- else
- my_yyabort_error((ER_SP_UNDECLARED_VAR, MYF(0), $1.str));
- if (splocal->type() != Item::INT_ITEM)
- my_yyabort_error((ER_WRONG_SPVAR_TYPE_IN_LIMIT, MYF(0)));
- splocal->limit_clause_param= TRUE;
- $$= splocal;
+ if (!($$= lex->create_item_limit(thd, $1,
+ $1.m_pos -
+ lex->substatement_query(thd),
+ lip->get_tok_end() - $1.m_pos)))
+ MYSQL_YYABORT;
+ }
+ | ident_with_tok_start '.' ident
+ {
+ LEX *lex= thd->lex;
+ Lex_input_stream *lip= & thd->m_parser_state->m_lip;
+ if (!($$= lex->create_item_limit(thd, $1, $3,
+ $1.m_pos -
+ lex->substatement_query(thd),
+ lip->get_ptr() - $1.m_pos)))
+ MYSQL_YYABORT;
}
| param_marker
{
@@ -11750,6 +11813,11 @@ select_outvar:
Lex->sphead)) :
NULL;
}
+ | ident '.' ident
+ {
+ if (!($$= Lex->create_outvar(thd, $1, $3)))
+ MYSQL_YYABORT;
+ }
;
into:
@@ -13820,7 +13888,16 @@ simple_ident:
lip->get_tok_end())))
MYSQL_YYABORT;
}
- | simple_ident_q { $$= $1; }
+ | simple_ident_q2
+ | ident '.' ident
+ {
+ LEX *lex= thd->lex;
+ if (!($$= lex->create_item_ident(thd, $1, $3,
+ $1.m_pos -
+ lex->substatement_query(thd),
+ YYLIP->get_tok_end() - $1.m_pos)))
+ MYSQL_YYABORT;
+ }
;
simple_ident_nospvar:
@@ -13835,45 +13912,14 @@ simple_ident_nospvar:
simple_ident_q:
ident '.' ident
{
- LEX *lex= thd->lex;
-
- /*
- FIXME This will work ok in simple_ident_nospvar case because
- we can't meet simple_ident_nospvar in trigger now. But it
- should be changed in future.
- */
- if (lex->is_trigger_new_or_old_reference($1))
- {
- bool new_row= ($1.str[0]=='N' || $1.str[0]=='n');
-
- if (!($$= lex->create_and_link_Item_trigger_field(thd, $3.str,
- new_row)))
- MYSQL_YYABORT;
- }
- else
- {
- SELECT_LEX *sel= lex->current_select;
- if (sel->no_table_names_allowed)
- {
- my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
- MYF(0), $1.str, thd->where);
- }
- if ((sel->parsing_place != IN_HAVING) ||
- (sel->get_in_sum_expr() > 0))
- {
- $$= new (thd->mem_root) Item_field(thd, Lex->current_context(),
- NullS, $1.str, $3.str);
- }
- else
- {
- $$= new (thd->mem_root) Item_ref(thd, Lex->current_context(),
- NullS, $1.str, $3.str);
- }
- if ($$ == NULL)
- MYSQL_YYABORT;
- }
+ if (!($$= Lex->create_item_ident_nospvar(thd, $1, $3)))
+ MYSQL_YYABORT;
}
- | colon_with_pos ident '.' ident
+ | simple_ident_q2
+ ;
+
+simple_ident_q2:
+ colon_with_pos ident '.' ident
{
LEX *lex= Lex;
if (lex->is_trigger_new_or_old_reference($2))
@@ -14082,16 +14128,35 @@ TEXT_STRING_filesystem:
;
ident:
- IDENT_sys { $$=$1; }
+ IDENT_sys
+ {
+ (LEX_STRING &)$$= $1;
+ $$.m_pos= (char *) YYLIP->get_tok_start_prev();
+ }
| keyword
{
$$.str= thd->strmake($1.str, $1.length);
if ($$.str == NULL)
MYSQL_YYABORT;
$$.length= $1.length;
+ $$.m_pos= (char *) YYLIP->get_tok_start_prev();
}
;
+ident_with_tok_start:
+ IDENT_sys
+ {
+ (LEX_STRING &)$$= $1;
+ $$.m_pos= (char *) YYLIP->get_tok_start();
+ }
+ | keyword
+ {
+ if (!($$.str= thd->strmake($1.str, $1.length)))
+ MYSQL_YYABORT;
+ $$.length= $1.length;
+ $$.m_pos= (char *) YYLIP->get_tok_start();
+ }
+ ;
ident_directly_assignable:
IDENT_sys { $$=$1; }
@@ -14358,6 +14423,7 @@ keyword_sp_data_type:
| POINT_SYM {}
| POLYGON {}
| RAW {} /* Oracle-R */
+ | ROW_SYM {}
| SERIAL_SYM {}
| TEXT_SYM {}
| TIMESTAMP {}
@@ -14593,7 +14659,6 @@ keyword_sp_not_data_type:
| ROWCOUNT_SYM {}
| ROW_COUNT_SYM {}
| ROW_FORMAT_SYM {}
- | ROW_SYM {}
| RTREE_SYM {}
| SCHEDULE_SYM {}
| SCHEMA_NAME_SYM {}
@@ -14711,6 +14776,21 @@ set_assign:
sp_create_assignment_instr(thd, yychar == YYEMPTY))
MYSQL_YYABORT;
}
+ | ident_directly_assignable '.' ident SET_VAR
+ {
+ LEX *lex=Lex;
+ lex->set_stmt_init();
+ lex->var_list.empty();
+ sp_create_assignment_lex(thd, yychar == YYEMPTY);
+ }
+ set_expr_or_default
+ {
+ LEX *lex= Lex;
+ DBUG_ASSERT(lex->var_list.is_empty());
+ if (lex->set_variable($1, $3, $6) ||
+ lex->sphead->restore_lex(thd))
+ MYSQL_YYABORT;
+ }
;
set_stmt_option_value_following_option_type_list:
@@ -14845,11 +14925,26 @@ option_value_following_option_type:
// Option values without preceding option_type.
option_value_no_option_type:
- internal_variable_name equal set_expr_or_default
+ ident equal set_expr_or_default
+ {
+ struct sys_var_with_base var;
+ if (Lex->init_internal_variable(&var, $1) ||
+ Lex->set_variable(&var, $3))
+ MYSQL_YYABORT;
+ }
+ | ident '.' ident equal set_expr_or_default
{
- if (Lex->set_variable(&$1, $3))
+ DBUG_ASSERT(Lex->var_list.is_empty());
+ if (Lex->set_variable($1, $3, $5))
MYSQL_YYABORT;
}
+ | DEFAULT '.' ident equal set_expr_or_default
+ {
+ struct sys_var_with_base var;
+ if (Lex->init_default_internal_variable(&var, $3) ||
+ Lex->set_variable(&var, $5))
+ MYSQL_YYABORT;
+ }
| '@' ident_or_text equal expr
{
Item_func_set_user_var *item;
@@ -14998,11 +15093,6 @@ internal_variable_name_directly_assignable:
if (Lex->init_internal_variable(&$$, $1))
MYSQL_YYABORT;
}
- | ident_directly_assignable '.' ident
- {
- if (Lex->init_internal_variable(&$$, $1, $3))
- MYSQL_YYABORT;
- }
| DEFAULT '.' ident
{
if (Lex->init_default_internal_variable(&$$, $3))
diff --git a/sql/structs.h b/sql/structs.h
index d3ad16592ef..e0fb05f05da 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -693,4 +693,10 @@ public:
};
+struct Lex_string_with_pos_st: public LEX_STRING
+{
+ const char *m_pos;
+};
+
+
#endif /* STRUCTS_INCLUDED */