From 72f43df623261d5fe579cb355451d84216c8882d Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 2 Feb 2017 22:59:07 +0400 Subject: [PATCH] MDEV-10914 ROW data type for stored routine variables --- mysql-test/r/keywords.result | 2 +- mysql-test/r/sp-row.result | 2122 ++++++++++++++++ mysql-test/r/sp-vars.result | 1 - mysql-test/r/variables.result | 4 +- .../binlog/r/binlog_stm_sp_type_row.result | 179 ++ .../binlog/t/binlog_stm_sp_type_row.test | 81 + .../compat/oracle/r/binlog_stm_sp.result | 179 ++ .../suite/compat/oracle/r/func_concat.result | 2 +- .../suite/compat/oracle/r/sp-code.result | 95 + .../suite/compat/oracle/r/sp-row.result | 2200 +++++++++++++++++ .../suite/compat/oracle/t/binlog_stm_sp.test | 81 + mysql-test/suite/compat/oracle/t/sp-code.test | 85 + .../suite/compat/oracle/t/sp-row-vs-var.inc | 6 + mysql-test/suite/compat/oracle/t/sp-row.test | 1398 +++++++++++ mysql-test/t/keywords.test | 2 +- mysql-test/t/sp-row-vs-var.inc | 6 + mysql-test/t/sp-row.test | 1329 ++++++++++ mysql-test/t/variables.test | 4 +- sql/field.cc | 1 + sql/field.h | 70 +- sql/item.cc | 120 + sql/item.h | 245 +- sql/item_func.cc | 55 +- sql/item_func.h | 8 +- sql/share/errmsg-utf8.txt | 2 + sql/sp_head.cc | 157 +- sql/sp_head.h | 42 +- sql/sp_pcontext.cc | 21 + sql/sp_pcontext.h | 14 + sql/sp_rcontext.cc | 122 +- sql/sp_rcontext.h | 4 +- sql/sql_class.cc | 5 + sql/sql_class.h | 16 + sql/sql_lex.cc | 230 +- sql/sql_lex.h | 130 +- sql/sql_list.h | 12 +- sql/sql_select.cc | 17 + sql/sql_test.cc | 6 +- sql/sql_type.cc | 18 +- sql/sql_yacc.yy | 214 +- sql/sql_yacc_ora.yy | 238 +- sql/structs.h | 6 + 42 files changed, 9226 insertions(+), 303 deletions(-) create mode 100644 mysql-test/r/sp-row.result create mode 100644 mysql-test/suite/binlog/r/binlog_stm_sp_type_row.result create mode 100644 mysql-test/suite/binlog/t/binlog_stm_sp_type_row.test create mode 100644 mysql-test/suite/compat/oracle/r/binlog_stm_sp.result create mode 100644 mysql-test/suite/compat/oracle/r/sp-row.result create mode 100644 mysql-test/suite/compat/oracle/t/binlog_stm_sp.test create mode 100644 mysql-test/suite/compat/oracle/t/sp-row-vs-var.inc create mode 100644 mysql-test/suite/compat/oracle/t/sp-row.test create mode 100644 mysql-test/t/sp-row-vs-var.inc create mode 100644 mysql-test/t/sp-row.test diff --git a/mysql-test/r/keywords.result b/mysql-test/r/keywords.result index 687a122d62808..e2f29f7cfb5eb 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 0000000000000..8c4973ba46c90 --- /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 0a7ea0d68c57e..c2f36437c9daa 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 bca59b5225a69..676432690b409 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 0000000000000..55d0dc13e5696 --- /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 0000000000000..cd0d9111107ba --- /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 0000000000000..55d0dc13e5696 --- /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 5d66fba220f61..d938c013ba7c5 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 5a67e8c3c1d05..8bc940fc15471 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 0000000000000..bffdb7c619fe1 --- /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 0000000000000..cd0d9111107ba --- /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 637251af96c15..5e20db1cedaad 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 0000000000000..14f6f7dfd449b --- /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 0000000000000..b86b087f7b66b --- /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 cf087590df2ce..4ac8f56afc54f 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 0000000000000..54d323f7341f9 --- /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 0000000000000..42fafb750770a --- /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 ed6e92f145ef4..1ba20f0ac9e61 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 40bd6a8a2ddc1..06cf9fbee5843 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 359101530f399..68327159a2242 100644 --- a/sql/field.h +++ b/sql/field.h @@ -3957,12 +3957,48 @@ class Column_definition: public Sql_alloc }; +/** + List of ROW element definitions, e.g.: + DECLARE a ROW(a INT,b VARCHAR(10)) +*/ +class Row_definition_list: public List +{ +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 it(*((List*)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 @@ class Column_definition: public Sql_alloc 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 @@ class Spvar_definition: public Column_definition { 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 9ad54cfad7058..56428fb39bbdd 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 4e737d099523c..01573c9e6ea77 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 &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 &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 *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 @@ class Item_splocal :public Item_sp_variable, { 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 @@ class Item_splocal :public Item_sp_variable, }; +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 @@ class Item_splocal_with_delayed_data_type: public Item_splocal { 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 @@ class Item_field :public Item_ident }; +/** + 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(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 @@ class Item_datetime_literal_for_invalid_dates: public Item_datetime_literal }; -/** - 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 &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 &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 e981722a123c3..7eeb9547c89fe 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 &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 &list) +{ + if (alloc_arguments(thd, list.elements)) + return; List_iterator_fast 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 &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 88fa78cd4a468..5b39c2ef0d86b 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -53,6 +53,7 @@ class Item_func :public Item_func_or_sum 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 @@ class Item_func_sp :public Item_func 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 3f4299e216694..8b0bd18e95abf 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 7fd2624ab7aa9..471e6d46828cf 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 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,9 +384,20 @@ 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. @@ -3184,6 +3228,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 *parameters) diff --git a/sql/sp_head.h b/sql/sp_head.h index ec19058a7f189..fc3dfa49f6374 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -360,9 +360,12 @@ class sp_head :private Query_arena, 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 @@ class sp_instr_set : public sp_instr virtual void print(String *str); -private: +protected: uint m_offset; ///< Frame offset Item *m_value; @@ -1002,6 +1005,36 @@ class sp_instr_set : public sp_instr }; // 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 642f1f16d29fb..06c51642d6832 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 414a3cbc7ccb2..00cc81964ebe7 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -69,6 +69,20 @@ class sp_variable : public Sql_alloc 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 5fcdbf42313e1..17c91b0972744 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 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 *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 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 061f736f6e9e5..78cbfd9ec2622 100644 --- a/sql/sp_rcontext.h +++ b/sql/sp_rcontext.h @@ -187,7 +187,9 @@ class sp_rcontext : public Sql_alloc ///////////////////////////////////////////////////////////////////////// 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 65a4dabb85bc7..5ddb0a865921f 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 &items) { List_iterator_fast var_li(var_list); diff --git a/sql/sql_class.h b/sql/sql_class.h index cac1cdd8fd321..1cc2e22bb1760 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -5522,6 +5522,22 @@ class my_var_sp: public my_var { 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 83983a1a35702..b0647f6b404c3 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 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 c3ef0710112ae..913478b95898a 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 @@ class Lex_input_stream 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 @@ struct LEX: public Query_tables_list 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 @@ struct LEX: public Query_tables_list 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 @@ struct LEX: public Query_tables_list 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 @@ struct LEX: public Query_tables_list 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 8f6f7337f1c32..217cdad5abb4d 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -334,16 +334,15 @@ class base_list :public Sql_alloc 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 @@ class base_list :public Sql_alloc } return data; } -#endif #ifdef LIST_EXTRA_DEBUG /* @@ -546,9 +544,7 @@ template class List :public base_list } 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 ed6a412fdc5bb..d3f2a674664d2 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 e70872af6c5ab..804a6b5c493a6 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:: *dbug_list_item_elem_ptr)(int)= &List::elem; -Item_equal* (List:: *dbug_list_item_equal_elem_ptr)(int)= +Item* (List:: *dbug_list_item_elem_ptr)(uint)= &List::elem; +Item_equal* (List:: *dbug_list_item_equal_elem_ptr)(uint)= &List::elem; -TABLE_LIST* (List:: *dbug_list_table_list_elem_ptr)(int) = +TABLE_LIST* (List:: *dbug_list_table_list_elem_ptr)(uint) = &List::elem; #endif diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 2679795eaa584..055a89697872e 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 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 321e4e58d610d..3115f9603e368 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 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 opt_table_alias +%type + ident ident_with_tok_start + %type 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 condition_information_item_name; %type condition_information; +%type row_field_name row_field_definition +%type row_field_definition_list field_type_row + %type opt_window_clause window_def_list window_def window_spec %type window_name %type 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 de712e33bc388..c652192622ec8 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 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 opt_table_alias +%type + ident ident_with_tok_start + %type
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 condition_information_item_name; %type condition_information; +%type row_field_name row_field_definition +%type row_field_definition_list field_type_row + %type opt_window_clause window_def_list window_def window_spec %type window_name %type 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 d3ad16592ef04..e0fb05f05da87 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -693,4 +693,10 @@ struct Lex_for_loop_st }; +struct Lex_string_with_pos_st: public LEX_STRING +{ + const char *m_pos; +}; + + #endif /* STRUCTS_INCLUDED */