Merge 10.2 (up to commit ef00ac4c86daf3294c46a45358da636763fb0049) into 10.3

This commit is contained in:
Alexander Barkov 2019-09-04 09:55:59 +04:00
commit 7e08ac0b41
44 changed files with 1825 additions and 23 deletions

View File

@ -109,6 +109,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/sql_analyze_stmt.cc ../sql/sql_analyze_stmt.h
../sql/compat56.cc
../sql/sql_type.cc ../sql/sql_type.h
../sql/sql_mode.cc
../sql/table_cache.cc ../sql/mf_iocache_encr.cc
../sql/item_inetfunc.cc
../sql/wsrep_dummy.cc ../sql/encryption.cc

View File

@ -3,6 +3,7 @@
-- source include/have_ssl_communication.inc
-- source include/big_test.inc
-- source include/have_64bit.inc
# Save the initial number of concurrent sessions
--source include/count_sessions.inc

View File

@ -15,6 +15,8 @@
# This is a big test.
--source include/big_test.inc
# Test needs more than 4G of memory
--source include/have_64bit.inc
--echo #
--echo # Preparatory cleanup.

View File

@ -164,7 +164,7 @@ c
connection default;
disconnect con1;
DROP TABLE t;
CREATE TABLE t (a INT, b INT, c INT GENERATED ALWAYS AS(a+b), h VARCHAR(10), j INT, m INT GENERATED ALWAYS AS(b + x), n VARCHAR(10), p VARCHAR(20) GENERATED ALWAYS AS(CONCAT(n, y)), x INT, y CHAR(20), z INT, INDEX idx1(c), INDEX idx2 (m), INDEX idx3(p));
CREATE TABLE t (a INT, b INT, c INT GENERATED ALWAYS AS(a+b), h VARCHAR(10), j INT, m INT GENERATED ALWAYS AS(b + x), n VARCHAR(10), p VARCHAR(20) GENERATED ALWAYS AS(CONCAT(n, RTRIM(y))), x INT, y CHAR(20), z INT, INDEX idx1(c), INDEX idx2 (m), INDEX idx3(p));
INSERT INTO t VALUES(1, 2, DEFAULT, "hhh", 3, DEFAULT, "nnn", DEFAULT, 4, "yyy", 5);
INSERT INTO t VALUES(2, 3, DEFAULT, "hhha", 4, DEFAULT, "nnna", DEFAULT, 5, "yyya", 6);
INSERT INTO t VALUES(12, 13, DEFAULT, "hhhb", 14, DEFAULT, "nnnb", DEFAULT, 15, "yyyb", 16);
@ -1235,8 +1235,8 @@ c7 TIME GENERATED ALWAYS AS(ADDTIME(c5time_gckey,c6)) VIRTUAL,
c5timek DATE GENERATED ALWAYS AS(ADDTIME(c5time_gckey,c7)) VIRTUAL,
c7k TIME GENERATED ALWAYS AS(ADDTIME(c5time,c6)) VIRTUAL,
c8 CHAR(10),
c9 CHAR(20)GENERATED ALWAYS AS (CONCAT(c8,c8)) VIRTUAL,
c9k CHAR(15)GENERATED ALWAYS AS (CONCAT(c8,0)) VIRTUAL,
c9 CHAR(20)GENERATED ALWAYS AS (CONCAT(RTRIM(c8),RTRIM(c8))) VIRTUAL,
c9k CHAR(15)GENERATED ALWAYS AS (CONCAT(RTRIM(c8),0)) VIRTUAL,
PRIMARY KEY(c1),
KEY(c3),
KEY(c9(10)),

View File

@ -54,7 +54,7 @@ c10 time GENERATED ALWAYS AS(addtime(c7,c8)) VIRTUAL,
c11 DATE GENERATED ALWAYS AS(addtime(c9,c8)) VIRTUAL,
c11a time GENERATED ALWAYS AS(addtime(c7,c10)) VIRTUAL,
c12 CHAR(1),
c13 CHAR(2)GENERATED ALWAYS AS (concat(c12,c12)) VIRTUAL,
c13 CHAR(2)GENERATED ALWAYS AS (concat(RTRIM(c12),RTRIM(c12))) VIRTUAL,
c14 CHAR(4)GENERATED ALWAYS AS (concat(c13,'x')) VIRTUAL,
PRIMARY KEY(c1),
KEY c13(c13),

View File

@ -151,7 +151,7 @@ disconnect con1;
DROP TABLE t;
# CREATE a more complex TABLE
CREATE TABLE t (a INT, b INT, c INT GENERATED ALWAYS AS(a+b), h VARCHAR(10), j INT, m INT GENERATED ALWAYS AS(b + x), n VARCHAR(10), p VARCHAR(20) GENERATED ALWAYS AS(CONCAT(n, y)), x INT, y CHAR(20), z INT, INDEX idx1(c), INDEX idx2 (m), INDEX idx3(p));
CREATE TABLE t (a INT, b INT, c INT GENERATED ALWAYS AS(a+b), h VARCHAR(10), j INT, m INT GENERATED ALWAYS AS(b + x), n VARCHAR(10), p VARCHAR(20) GENERATED ALWAYS AS(CONCAT(n, RTRIM(y))), x INT, y CHAR(20), z INT, INDEX idx1(c), INDEX idx2 (m), INDEX idx3(p));
INSERT INTO t VALUES(1, 2, DEFAULT, "hhh", 3, DEFAULT, "nnn", DEFAULT, 4, "yyy", 5);
@ -1239,8 +1239,8 @@ CREATE TABLE t(
c5timek DATE GENERATED ALWAYS AS(ADDTIME(c5time_gckey,c7)) VIRTUAL,
c7k TIME GENERATED ALWAYS AS(ADDTIME(c5time,c6)) VIRTUAL,
c8 CHAR(10),
c9 CHAR(20)GENERATED ALWAYS AS (CONCAT(c8,c8)) VIRTUAL,
c9k CHAR(15)GENERATED ALWAYS AS (CONCAT(c8,0)) VIRTUAL,
c9 CHAR(20)GENERATED ALWAYS AS (CONCAT(RTRIM(c8),RTRIM(c8))) VIRTUAL,
c9k CHAR(15)GENERATED ALWAYS AS (CONCAT(RTRIM(c8),0)) VIRTUAL,
PRIMARY KEY(c1),
KEY(c3),
KEY(c9(10)),

View File

@ -63,7 +63,7 @@ CREATE TABLE t2(
c11 DATE GENERATED ALWAYS AS(addtime(c9,c8)) VIRTUAL,
c11a time GENERATED ALWAYS AS(addtime(c7,c10)) VIRTUAL,
c12 CHAR(1),
c13 CHAR(2)GENERATED ALWAYS AS (concat(c12,c12)) VIRTUAL,
c13 CHAR(2)GENERATED ALWAYS AS (concat(RTRIM(c12),RTRIM(c12))) VIRTUAL,
c14 CHAR(4)GENERATED ALWAYS AS (concat(c13,'x')) VIRTUAL,
PRIMARY KEY(c1),
KEY c13(c13),

View File

@ -1,6 +1,7 @@
--source include/have_innodb.inc
--source include/have_debug.inc
--source include/big_test.inc
--source include/have_64bit.inc
--echo #
--echo # Bug Bug #27304661 MYSQL CRASH DOING SYNC INDEX ]

View File

@ -8,6 +8,8 @@
--source include/have_debug.inc
--source include/big_test.inc
--source include/not_valgrind.inc
--source include/have_64bit.inc
# Create table with R-tree index.
create table t1 (c1 int, c2 geometry not null, spatial index (c2))engine=innodb;

View File

@ -235,7 +235,7 @@ CREATE TABLE t1 (
b CHAR(10) NULL DEFAULT NULL,
c blob NULL DEFAULT NULL,
blob_a blob GENERATED ALWAYS AS (a) VIRTUAL,
blob_b blob GENERATED ALWAYS AS (b) VIRTUAL,
blob_b blob GENERATED ALWAYS AS (RTRIM(b)) VIRTUAL,
blob_c blob GENERATED ALWAYS AS (c) VIRTUAL,
key (a),
key (blob_a(10)),

View File

@ -8,13 +8,13 @@ select * from t1;
a b c
2 3 4
drop table t1;
create table t1 (a int, c int as(a), p varchar(20) as(y), y char(20), index (p,c));
create table t1 (a int, c int as(a), p varchar(20) as(rtrim(y)), y char(20), index (p,c));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`c` int(11) GENERATED ALWAYS AS (`a`) VIRTUAL,
`p` varchar(20) GENERATED ALWAYS AS (`y`) VIRTUAL,
`p` varchar(20) GENERATED ALWAYS AS (rtrim(`y`)) VIRTUAL,
`y` char(20) DEFAULT NULL,
KEY `p` (`p`,`c`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

View File

@ -10,13 +10,13 @@ select * from t1;
a b c
2 3 4
drop table t1;
create table t1 (a int, c int as(a), p varchar(20) as(y), y char(20), index (p,c));
create table t1 (a int, c int as(a), p varchar(20) as(rtrim(y)), y char(20), index (p,c));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`c` int(11) GENERATED ALWAYS AS (`a`) VIRTUAL,
`p` varchar(20) GENERATED ALWAYS AS (`y`) VIRTUAL,
`p` varchar(20) GENERATED ALWAYS AS (rtrim(`y`)) VIRTUAL,
`y` char(20) DEFAULT NULL,
KEY `p` (`p`,`c`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
@ -190,13 +190,13 @@ select * from t1;
a b c
2 3 4
drop table t1;
create table t1 (a int, c int as(a), p varchar(20) as(y), y char(20), index (p,c));
create table t1 (a int, c int as(a), p varchar(20) as(rtrim(y)), y char(20), index (p,c));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`c` int(11) GENERATED ALWAYS AS (`a`) VIRTUAL,
`p` varchar(20) GENERATED ALWAYS AS (`y`) VIRTUAL,
`p` varchar(20) GENERATED ALWAYS AS (rtrim(`y`)) VIRTUAL,
`y` char(20) DEFAULT NULL,
KEY `p` (`p`,`c`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

View File

@ -0,0 +1,438 @@
#
# Start of 10.2 tests
#
#
# MDEV-18156 Assertion `0' failed or `btr_validate_index(index, 0, false)' in row_upd_sec_index_entry or error code 126: Index is corrupted upon DELETE with PAD_CHAR_TO_FULL_LENGTH
#
#
# PAD_CHAR_TO_FULL_LENGTH + various virtual column data types
#
CREATE TABLE t1 (a CHAR(5), v CHAR(5) AS (a) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` char(5) GENERATED ALWAYS AS (`a`) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v INT AS (a) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` int(11) GENERATED ALWAYS AS (`a`) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v TIME AS (a) VIRTUAL, KEY(v));
DROP TABLE t1;
CREATE TABLE t1 (c CHAR(8), v BINARY(8) AS (c), KEY(v));
ERROR HY000: Function or expression '`c`' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression '`c`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
CREATE TABLE t1 (a CHAR(5), v BIT(64) AS (a) VIRTUAL, KEY(v));
ERROR HY000: Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (a) VIRTUAL, KEY(v));
ERROR HY000: Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
CREATE TABLE t1 (a CHAR(5), v TEXT AS (a) VIRTUAL, KEY(v(100)));
ERROR HY000: Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
# PAD_CHAR_TO_FULL_LENGTH + TRIM resolving dependency
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (RTRIM(a)) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (rtrim(`a`)) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v TEXT AS (RTRIM(a)) VIRTUAL, KEY(v(100)));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` text GENERATED ALWAYS AS (rtrim(`a`)) VIRTUAL,
KEY `v` (`v`(100))
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(TRAILING ' ' FROM a)) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (trim(trailing ' ' from `a`)) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v TEXT AS (TRIM(TRAILING ' ' FROM a)) VIRTUAL, KEY(v(100)));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` text GENERATED ALWAYS AS (trim(trailing ' ' from `a`)) VIRTUAL,
KEY `v` (`v`(100))
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(BOTH ' ' FROM a)) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (trim(both ' ' from `a`)) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v TEXT AS (TRIM(BOTH ' ' FROM a)) VIRTUAL, KEY(v(100)));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` text GENERATED ALWAYS AS (trim(both ' ' from `a`)) VIRTUAL,
KEY `v` (`v`(100))
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(TRAILING NULL FROM a)) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (trim(trailing NULL from `a`)) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(BOTH NULL FROM a)) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (trim(both NULL from `a`)) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
# PAD_CHAR_TO_FULL_LENGTH + TRIM not resolving dependency
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(LEADING ' ' FROM a)) VIRTUAL, KEY(v));
ERROR HY000: Function or expression 'trim(leading ' ' from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression 'trim(leading ' ' from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
CREATE TABLE t1 (a CHAR(5), v TEXT AS (TRIM(LEADING ' ' FROM a)) VIRTUAL, KEY(v(100)));
ERROR HY000: Function or expression 'trim(leading ' ' from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression 'trim(leading ' ' from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(TRAILING '' FROM a)) VIRTUAL, KEY(v));
ERROR HY000: Function or expression 'trim(trailing '' from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression 'trim(trailing '' from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(BOTH '' FROM a)) VIRTUAL, KEY(v));
ERROR HY000: Function or expression 'trim(both '' from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression 'trim(both '' from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(TRAILING 'x' FROM a)) VIRTUAL, KEY(v));
ERROR HY000: Function or expression 'trim(trailing 'x' from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression 'trim(trailing 'x' from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(BOTH 'x' FROM a)) VIRTUAL, KEY(v));
ERROR HY000: Function or expression 'trim(both 'x' from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression 'trim(both 'x' from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
CREATE TABLE t1 (
a CHAR(5),
v VARCHAR(5) AS (TRIM(TRAILING ' ' FROM a)) VIRTUAL, KEY(v));
ERROR HY000: Function or expression 'trim(trailing ' ' from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression 'trim(trailing ' ' from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
CREATE TABLE t1 (
a CHAR(5),
v VARCHAR(5) AS (TRIM(BOTH ' ' FROM a)) VIRTUAL, KEY(v));
ERROR HY000: Function or expression 'trim(both ' ' from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression 'trim(both ' ' from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
# PAD_CHAR_TO_FULL_LENGTH + TRIM(... non_constant FROM a)
CREATE TABLE t1 (
a CHAR(5),
b CHAR(5),
v TEXT AS (TRIM(TRAILING b FROM a)) VIRTUAL, KEY(v(100)));
ERROR HY000: Function or expression 'trim(trailing `b` from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression 'trim(trailing `b` from `a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
# PAD_CHAR_TO_FULL_LENGTH + RPAD resolving dependency
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (RPAD(a,5,' ')) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (rpad(`a`,5,' ')) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (RPAD(a,6,' ')) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (rpad(`a`,6,' ')) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (RPAD(a,6,NULL)) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (rpad(`a`,6,NULL)) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (RPAD(a,NULL,' ')) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (rpad(`a`,NULL,' ')) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
# PAD_CHAR_TO_FULL_LENGTH + RPAD not resolving dependency
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (RPAD(a,4,' ')) VIRTUAL, KEY(v));
ERROR HY000: Function or expression 'rpad(`a`,4,' ')' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression 'rpad(`a`,4,' ')' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
CREATE TABLE t1 (
a CHAR(5),
b CHAR(5),
v VARCHAR(5) AS (RPAD(a,NULL,b)) VIRTUAL,
KEY(v)
);
ERROR HY000: Function or expression 'rpad(`a`,NULL,`b`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression 'rpad(`a`,NULL,`b`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
# PAD_CHAR_TO_FULL_LENGTH + comparison
CREATE TABLE t1 (a CHAR(5), v INT AS (a='a') VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` int(11) GENERATED ALWAYS AS (`a` = 'a') VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (
a CHAR(5) CHARACTER SET latin1 COLLATE latin1_nopad_bin,
v INT AS (a='a') VIRTUAL, KEY(v)
);
ERROR HY000: Function or expression '`a` = 'a'' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression '`a` = 'a'' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
# PAD_CHAR_TO_FULL_LENGTH + LIKE
CREATE TABLE t1 (a CHAR(5), v INT AS (a LIKE 'a%') VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` int(11) GENERATED ALWAYS AS (`a` like 'a%') VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v INT AS (a LIKE NULL) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` int(11) GENERATED ALWAYS AS (`a` like NULL) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v INT AS (a LIKE 'a') VIRTUAL, KEY(v));
ERROR HY000: Function or expression '`a` like 'a'' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression '`a` like 'a'' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
# PAD_CHAR_TO_FULL_LENGTH + LENGTH(char_column) = hard dependency
CREATE TABLE t1 (a CHAR(5), v INT AS (LENGTH(a)) VIRTUAL, KEY(v));
ERROR HY000: Function or expression 'octet_length(`a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression 'octet_length(`a`)' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
#
# Testing NO_UNSIGNED_SUBTRACTION
#
CREATE TABLE t1 (
a INT UNSIGNED,
b INT UNSIGNED,
c INT GENERATED ALWAYS AS (a-b) VIRTUAL,
KEY (c)
);
ERROR HY000: Function or expression '`a` - `b`' cannot be used in the GENERATED ALWAYS AS clause of `c`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression '`a` - `b`' cannot be used in the GENERATED ALWAYS AS clause of `c`
Warning 1105 Expression depends on the @@sql_mode value NO_UNSIGNED_SUBTRACTION
CREATE TABLE t1 (
a INT UNSIGNED,
b INT UNSIGNED,
c INT GENERATED ALWAYS AS (CAST(a AS SIGNED)-b) VIRTUAL,
KEY (c)
);
ERROR HY000: Function or expression 'cast(`a` as signed) - `b`' cannot be used in the GENERATED ALWAYS AS clause of `c`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression 'cast(`a` as signed) - `b`' cannot be used in the GENERATED ALWAYS AS clause of `c`
Warning 1105 Expression depends on the @@sql_mode value NO_UNSIGNED_SUBTRACTION
CREATE TABLE t1 (
a INT UNSIGNED,
b INT UNSIGNED,
c INT GENERATED ALWAYS AS (a-CAST(b AS SIGNED)) VIRTUAL,
KEY (c)
);
ERROR HY000: Function or expression '`a` - cast(`b` as signed)' cannot be used in the GENERATED ALWAYS AS clause of `c`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression '`a` - cast(`b` as signed)' cannot be used in the GENERATED ALWAYS AS clause of `c`
Warning 1105 Expression depends on the @@sql_mode value NO_UNSIGNED_SUBTRACTION
CREATE TABLE t1 (
a INT UNSIGNED,
b INT UNSIGNED,
c INT GENERATED ALWAYS AS (CAST(a AS SIGNED)-CAST(b AS SIGNED)) VIRTUAL,
KEY (c)
);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(10) unsigned DEFAULT NULL,
`b` int(10) unsigned DEFAULT NULL,
`c` int(11) GENERATED ALWAYS AS (cast(`a` as signed) - cast(`b` as signed)) VIRTUAL,
KEY `c` (`c`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
CREATE TABLE t1 (
a INT UNSIGNED,
b INT UNSIGNED,
c INT GENERATED ALWAYS AS (CAST(a AS DECIMAL(20,0))-CAST(b AS DECIMAL(20,0))) VIRTUAL,
KEY (c)
);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(10) unsigned DEFAULT NULL,
`b` int(10) unsigned DEFAULT NULL,
`c` int(11) GENERATED ALWAYS AS (cast(`a` as decimal(20,0)) - cast(`b` as decimal(20,0))) VIRTUAL,
KEY `c` (`c`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# Comnination: PAD_CHAR_TO_FULL_LENGTH + NO_UNSIGNED_SUBTRACTION
#
CREATE TABLE t1 (
a INT UNSIGNED,
b INT UNSIGNED,
c CHAR(5),
v VARCHAR(5) GENERATED ALWAYS AS (RPAD(c,a-b,' ')) VIRTUAL,
KEY (v)
);
ERROR HY000: Function or expression 'rpad(`c`,`a` - `b`,' ')' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression 'rpad(`c`,`a` - `b`,' ')' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value NO_UNSIGNED_SUBTRACTION
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
CREATE TABLE t1 (
a INT UNSIGNED,
b INT UNSIGNED,
c CHAR(5),
v VARCHAR(5) GENERATED ALWAYS AS (RPAD(c,CAST(a AS DECIMAL(20,1))-b,' ')) VIRTUAL,
KEY (v)
);
ERROR HY000: Function or expression 'rpad(`c`,cast(`a` as decimal(20,1)) - `b`,' ')' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression 'rpad(`c`,cast(`a` as decimal(20,1)) - `b`,' ')' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
# ALTER TABLE ADD KEY(vcol_depending_on_sql_mode) --> error
CREATE TABLE t1 (
a INT UNSIGNED,
b INT UNSIGNED,
c CHAR(5),
v VARCHAR(5) GENERATED ALWAYS AS (c) VIRTUAL
);
ALTER TABLE t1 ADD KEY(v);
ERROR HY000: Function or expression '`c`' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Warning 1901 Function or expression '`c`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
Error 1901 Function or expression '`c`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
CREATE INDEX v ON t1 (v);
ERROR HY000: Function or expression '`c`' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Warning 1901 Function or expression '`c`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
Error 1901 Function or expression '`c`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
DROP TABLE t1;
# A virtual column on the second position in an index - cannot depend on sql_mode
CREATE TABLE t1 (id int, a CHAR(5), v TEXT AS (a) VIRTUAL, KEY(id, v(100)));
ERROR HY000: Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
# A persisten virtual column cannot depend on sql_mode
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (a) PERSISTENT);
ERROR HY000: Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW WARNINGS;
Level Code Message
Error 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (RTRIM(a)) PERSISTENT);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (rtrim(`a`)) STORED
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# End of 10.2 tests
#

View File

@ -0,0 +1,336 @@
call mtr.add_suppression("Table rebuild required");
#
# Opening a Maria-10.2.26 table with a stored VARCHAR column
#
# Copying maria100226_char_to_vchar_stored.* to MYSQLD_DATADIR
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (`a`) STORED
) ENGINE=MyISAM DEFAULT CHARSET=latin1
Warnings:
Warning 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (`a`) STORED
) ENGINE=MyISAM DEFAULT CHARSET=latin1
FLUSH TABLES;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (`a`) STORED
) ENGINE=MyISAM DEFAULT CHARSET=latin1
Warnings:
Warning 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
FLUSH TABLES;
SELECT * FROM t1;
a v
1 1
2 2
3 3
Warnings:
Warning 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
SELECT * FROM t1;
a v
1 1
2 2
3 3
FLUSH TABLES;
SELECT * FROM t1;
a v
1 1
2 2
3 3
Warnings:
Warning 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
CREATE TABLE t2 LIKE t1;
ERROR HY000: Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
FLUSH TABLES;
CREATE TABLE t2 LIKE t1;
ERROR HY000: Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (`a`) STORED
) ENGINE=MyISAM DEFAULT CHARSET=latin1
Warnings:
Warning 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
ALTER TABLE t1 ADD b INT DEFAULT a;
ERROR HY000: Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (`a`) STORED
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t1;
a v
1 1
2 2
3 3
FLUSH TABLES;
ALTER TABLE t1 ADD c INT DEFAULT a;
ERROR HY000: Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
SELECT * FROM t1;
a v
1 1
2 2
3 3
DROP TABLE t1;
#
# Fixing a Maria-10.2.26 table with a stored VARCHAR column
#
# Fixing by dropping the generated stored column
# Copying maria100226_char_to_vchar_stored.* to MYSQLD_DATADIR
ALTER TABLE t1 DROP v;
Warnings:
Warning 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
SELECT * FROM t1;
a
1
2
3
DROP TABLE t1;
# Fixing by altering the generation expression of the stored column
# Copying maria100226_char_to_vchar_stored.* to MYSQLD_DATADIR
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (`a`) STORED
) ENGINE=MyISAM DEFAULT CHARSET=latin1
Warnings:
Warning 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
ALTER TABLE t1 MODIFY v VARCHAR(5) AS (RTRIM(a)) PERSISTENT;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (rtrim(`a`)) STORED
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# Opening a Maria-10.2.26 table with a virtual VARCHAR column
#
# Copying maria100226_char_to_vchar_virtual.* to MYSQLD_DATADIR
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (`a`) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
Warnings:
Warning 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (`a`) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
FLUSH TABLES;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (`a`) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
Warnings:
Warning 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
FLUSH TABLES;
SELECT * FROM t1;
a v
1 1
2 2
3 3
Warnings:
Warning 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
SELECT * FROM t1;
a v
1 1
2 2
3 3
FLUSH TABLES;
SELECT * FROM t1;
a v
1 1
2 2
3 3
Warnings:
Warning 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
CREATE TABLE t2 LIKE t1;
ERROR HY000: Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
FLUSH TABLES;
CREATE TABLE t2 LIKE t1;
ERROR HY000: Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (`a`) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
Warnings:
Warning 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
ALTER TABLE t1 ADD b INT DEFAULT a;
ERROR HY000: Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
FLUSH TABLES;
ALTER TABLE t1 ADD c INT DEFAULT a;
ERROR HY000: Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
SELECT * FROM t1;
a v
1 1
2 2
3 3
DROP TABLE t1;
#
# Fixing a Maria-10.2.26 table with a virtual VARCHAR column
#
# Fixing by dropping the virtual column
# Copying maria100226_char_to_vchar_virtual.* to MYSQLD_DATADIR
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (`a`) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
Warnings:
Warning 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
ALTER TABLE t1 DROP v;
SELECT * FROM t1;
a
1
2
3
DROP TABLE t1;
# Fixing by dropping a key on a virtual column, using ALTER TABLE
# Copying maria100226_char_to_vchar_virtual.* to MYSQLD_DATADIR
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (`a`) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
Warnings:
Warning 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
ALTER TABLE t1 DROP KEY v;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (`a`) VIRTUAL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t1;
a v
1 1
2 2
3 3
DROP TABLE t1;
# Fixing by dropping a key on a virtual column, using DROP INDEX
# Copying maria100226_char_to_vchar_virtual.* to MYSQLD_DATADIR
DROP INDEX v ON t1;
Warnings:
Warning 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (`a`) VIRTUAL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t1;
a v
1 1
2 2
3 3
DROP TABLE t1;
# Fixing by altering the generation expression of a virtual column
# Copying maria100226_char_to_vchar_virtual.* to MYSQLD_DATADIR
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (`a`) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
Warnings:
Warning 1901 Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
Warning 1105 Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
ALTER TABLE t1 MODIFY v VARCHAR(5) AS(RTRIM(a)) VIRTUAL;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (rtrim(`a`)) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t1;
a v
1 1
2 2
3 3
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` char(5) DEFAULT NULL,
`v` varchar(5) GENERATED ALWAYS AS (rtrim(`a`)) VIRTUAL,
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t2;
DROP TABLE t1;
#
# Upgrading a Maria-10.2.26 table with a stored column
#
# Copying maria100226_char_to_varchar.* to MYSQLD_DATADIR
CHECK TABLE t1 FOR UPGRADE;
Table Op Msg_type Msg_text
test.t1 check Warning Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
test.t1 check Warning Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
test.t1 check status OK
FLUSH TABLES;
CHECK TABLE t1 FOR UPGRADE;
Table Op Msg_type Msg_text
test.t1 check Warning Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
test.t1 check Warning Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
test.t1 check status OK
DROP TABLE t1;
#
# Upgrading a Maria-10.2.26 table with a virtual column
#
# Copying maria100226_char_to_varchar.* to MYSQLD_DATADIR
CHECK TABLE t1 FOR UPGRADE;
Table Op Msg_type Msg_text
test.t1 check Warning Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
test.t1 check Warning Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
test.t1 check status OK
FLUSH TABLES;
CHECK TABLE t1 FOR UPGRADE;
Table Op Msg_type Msg_text
test.t1 check Warning Function or expression '`a`' cannot be used in the GENERATED ALWAYS AS clause of `v`
test.t1 check Warning Expression depends on the @@sql_mode value PAD_CHAR_TO_FULL_LENGTH
test.t1 check status OK
DROP TABLE t1;

View File

@ -232,7 +232,7 @@ a INTEGER UNSIGNED NULL DEFAULT NULL,
b CHAR(10) NULL DEFAULT NULL,
c blob NULL DEFAULT NULL,
blob_a blob GENERATED ALWAYS AS (a) VIRTUAL,
blob_b blob GENERATED ALWAYS AS (b) VIRTUAL,
blob_b blob GENERATED ALWAYS AS (RTRIM(b)) VIRTUAL,
blob_c blob GENERATED ALWAYS AS (c) VIRTUAL,
key (a),
key (blob_a(10)),

View File

@ -232,7 +232,7 @@ a INTEGER UNSIGNED NULL DEFAULT NULL,
b CHAR(10) NULL DEFAULT NULL,
c blob NULL DEFAULT NULL,
blob_a blob GENERATED ALWAYS AS (a) VIRTUAL,
blob_b blob GENERATED ALWAYS AS (b) VIRTUAL,
blob_b blob GENERATED ALWAYS AS (RTRIM(b)) VIRTUAL,
blob_c blob GENERATED ALWAYS AS (c) VIRTUAL,
key (a),
key (blob_a(10)),

View File

@ -14,7 +14,7 @@ drop table t1;
# one keypart is virtual, the other keypart is updated
# this tests TABLE::mark_columns_needed_for_update()
#
create table t1 (a int, c int as(a), p varchar(20) as(y), y char(20), index (p,c));
create table t1 (a int, c int as(a), p varchar(20) as(rtrim(y)), y char(20), index (p,c));
show create table t1;
insert into t1 (a,y) values(1, "yyy");
update t1 set a = 100 where a = 1;

View File

@ -0,0 +1,322 @@
--echo #
--echo # Start of 10.2 tests
--echo #
--echo #
--echo # MDEV-18156 Assertion `0' failed or `btr_validate_index(index, 0, false)' in row_upd_sec_index_entry or error code 126: Index is corrupted upon DELETE with PAD_CHAR_TO_FULL_LENGTH
--echo #
--echo #
--echo # PAD_CHAR_TO_FULL_LENGTH + various virtual column data types
--echo #
CREATE TABLE t1 (a CHAR(5), v CHAR(5) AS (a) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v INT AS (a) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v TIME AS (a) VIRTUAL, KEY(v));
DROP TABLE t1;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (c CHAR(8), v BINARY(8) AS (c), KEY(v));
SHOW WARNINGS;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (a CHAR(5), v BIT(64) AS (a) VIRTUAL, KEY(v));
SHOW WARNINGS;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (a) VIRTUAL, KEY(v));
SHOW WARNINGS;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (a CHAR(5), v TEXT AS (a) VIRTUAL, KEY(v(100)));
SHOW WARNINGS;
--echo # PAD_CHAR_TO_FULL_LENGTH + TRIM resolving dependency
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (RTRIM(a)) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v TEXT AS (RTRIM(a)) VIRTUAL, KEY(v(100)));
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(TRAILING ' ' FROM a)) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v TEXT AS (TRIM(TRAILING ' ' FROM a)) VIRTUAL, KEY(v(100)));
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(BOTH ' ' FROM a)) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v TEXT AS (TRIM(BOTH ' ' FROM a)) VIRTUAL, KEY(v(100)));
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(TRAILING NULL FROM a)) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(BOTH NULL FROM a)) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo # PAD_CHAR_TO_FULL_LENGTH + TRIM not resolving dependency
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(LEADING ' ' FROM a)) VIRTUAL, KEY(v));
SHOW WARNINGS;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (a CHAR(5), v TEXT AS (TRIM(LEADING ' ' FROM a)) VIRTUAL, KEY(v(100)));
SHOW WARNINGS;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(TRAILING '' FROM a)) VIRTUAL, KEY(v));
SHOW WARNINGS;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(BOTH '' FROM a)) VIRTUAL, KEY(v));
SHOW WARNINGS;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(TRAILING 'x' FROM a)) VIRTUAL, KEY(v));
SHOW WARNINGS;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (TRIM(BOTH 'x' FROM a)) VIRTUAL, KEY(v));
SHOW WARNINGS;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
# more than one space
CREATE TABLE t1 (
a CHAR(5),
v VARCHAR(5) AS (TRIM(TRAILING ' ' FROM a)) VIRTUAL, KEY(v));
SHOW WARNINGS;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
# more than one space
CREATE TABLE t1 (
a CHAR(5),
v VARCHAR(5) AS (TRIM(BOTH ' ' FROM a)) VIRTUAL, KEY(v));
SHOW WARNINGS;
--echo # PAD_CHAR_TO_FULL_LENGTH + TRIM(... non_constant FROM a)
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (
a CHAR(5),
b CHAR(5),
v TEXT AS (TRIM(TRAILING b FROM a)) VIRTUAL, KEY(v(100)));
SHOW WARNINGS;
--echo # PAD_CHAR_TO_FULL_LENGTH + RPAD resolving dependency
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (RPAD(a,5,' ')) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (RPAD(a,6,' ')) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (RPAD(a,6,NULL)) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (RPAD(a,NULL,' ')) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo # PAD_CHAR_TO_FULL_LENGTH + RPAD not resolving dependency
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (RPAD(a,4,' ')) VIRTUAL, KEY(v));
SHOW WARNINGS;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (
a CHAR(5),
b CHAR(5),
v VARCHAR(5) AS (RPAD(a,NULL,b)) VIRTUAL,
KEY(v)
);
SHOW WARNINGS;
--echo # PAD_CHAR_TO_FULL_LENGTH + comparison
CREATE TABLE t1 (a CHAR(5), v INT AS (a='a') VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
DROP TABLE t1;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (
a CHAR(5) CHARACTER SET latin1 COLLATE latin1_nopad_bin,
v INT AS (a='a') VIRTUAL, KEY(v)
);
SHOW WARNINGS;
--echo # PAD_CHAR_TO_FULL_LENGTH + LIKE
CREATE TABLE t1 (a CHAR(5), v INT AS (a LIKE 'a%') VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
DROP TABLE t1;
CREATE TABLE t1 (a CHAR(5), v INT AS (a LIKE NULL) VIRTUAL, KEY(v));
SHOW CREATE TABLE t1;
DROP TABLE t1;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (a CHAR(5), v INT AS (a LIKE 'a') VIRTUAL, KEY(v));
SHOW WARNINGS;
--echo # PAD_CHAR_TO_FULL_LENGTH + LENGTH(char_column) = hard dependency
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (a CHAR(5), v INT AS (LENGTH(a)) VIRTUAL, KEY(v));
SHOW WARNINGS;
--echo #
--echo # Testing NO_UNSIGNED_SUBTRACTION
--echo #
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (
a INT UNSIGNED,
b INT UNSIGNED,
c INT GENERATED ALWAYS AS (a-b) VIRTUAL,
KEY (c)
);
SHOW WARNINGS;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (
a INT UNSIGNED,
b INT UNSIGNED,
c INT GENERATED ALWAYS AS (CAST(a AS SIGNED)-b) VIRTUAL,
KEY (c)
);
SHOW WARNINGS;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (
a INT UNSIGNED,
b INT UNSIGNED,
c INT GENERATED ALWAYS AS (a-CAST(b AS SIGNED)) VIRTUAL,
KEY (c)
);
SHOW WARNINGS;
CREATE TABLE t1 (
a INT UNSIGNED,
b INT UNSIGNED,
c INT GENERATED ALWAYS AS (CAST(a AS SIGNED)-CAST(b AS SIGNED)) VIRTUAL,
KEY (c)
);
SHOW CREATE TABLE t1;
DROP TABLE t1;
# 'CAST(signed AS DECIMAL)' does not copy 'unsigned_flag' from the argument.
# So the below is safe.
CREATE TABLE t1 (
a INT UNSIGNED,
b INT UNSIGNED,
c INT GENERATED ALWAYS AS (CAST(a AS DECIMAL(20,0))-CAST(b AS DECIMAL(20,0))) VIRTUAL,
KEY (c)
);
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo #
--echo # Comnination: PAD_CHAR_TO_FULL_LENGTH + NO_UNSIGNED_SUBTRACTION
--echo #
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (
a INT UNSIGNED,
b INT UNSIGNED,
c CHAR(5),
v VARCHAR(5) GENERATED ALWAYS AS (RPAD(c,a-b,' ')) VIRTUAL,
KEY (v)
);
SHOW WARNINGS;
# The below solves the dependency on NO_UNSIGNED_SUBTRACTION
# but does not solve the dependency on PAD_CHAR_TO_FULL_LENGTH,
# because the 'length' argument to RPAD() is not a constant.
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (
a INT UNSIGNED,
b INT UNSIGNED,
c CHAR(5),
v VARCHAR(5) GENERATED ALWAYS AS (RPAD(c,CAST(a AS DECIMAL(20,1))-b,' ')) VIRTUAL,
KEY (v)
);
SHOW WARNINGS;
--echo # ALTER TABLE ADD KEY(vcol_depending_on_sql_mode) --> error
# This makes sure that QT_ITEM_IDENT_SKIP_DB_NAMES and
# QT_ITEM_IDENT_SKIP_TABLE_NAMES are passed to print()
# to avoid temporary table names like `test`.`#sql-50a6_4`.`c`
# in the error message.
#
CREATE TABLE t1 (
a INT UNSIGNED,
b INT UNSIGNED,
c CHAR(5),
v VARCHAR(5) GENERATED ALWAYS AS (c) VIRTUAL
);
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
ALTER TABLE t1 ADD KEY(v);
SHOW WARNINGS;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE INDEX v ON t1 (v);
SHOW WARNINGS;
DROP TABLE t1;
--echo # A virtual column on the second position in an index - cannot depend on sql_mode
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (id int, a CHAR(5), v TEXT AS (a) VIRTUAL, KEY(id, v(100)));
SHOW WARNINGS;
--echo # A persisten virtual column cannot depend on sql_mode
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (a) PERSISTENT);
SHOW WARNINGS;
CREATE TABLE t1 (a CHAR(5), v VARCHAR(5) AS (RTRIM(a)) PERSISTENT);
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo #
--echo # End of 10.2 tests
--echo #

View File

@ -0,0 +1,193 @@
-- source include/mysql_upgrade_preparation.inc
call mtr.add_suppression("Table rebuild required");
let $MYSQLD_DATADIR= `select @@datadir`;
--enable_prepare_warnings
--echo #
--echo # Opening a Maria-10.2.26 table with a stored VARCHAR column
--echo #
--echo # Copying maria100226_char_to_vchar_stored.* to MYSQLD_DATADIR
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_stored.frm $MYSQLD_DATADIR/test/t1.frm
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYD $MYSQLD_DATADIR/test/t1.MYD
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYI $MYSQLD_DATADIR/test/t1.MYI
SHOW CREATE TABLE t1;
SHOW CREATE TABLE t1;
FLUSH TABLES;
SHOW CREATE TABLE t1;
FLUSH TABLES;
SELECT * FROM t1;
SELECT * FROM t1;
FLUSH TABLES;
SELECT * FROM t1;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t2 LIKE t1;
FLUSH TABLES;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t1;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
ALTER TABLE t1 ADD b INT DEFAULT a;
SHOW CREATE TABLE t1;
SELECT * FROM t1;
FLUSH TABLES;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
ALTER TABLE t1 ADD c INT DEFAULT a;
SELECT * FROM t1;
DROP TABLE t1;
--echo #
--echo # Fixing a Maria-10.2.26 table with a stored VARCHAR column
--echo #
--echo # Fixing by dropping the generated stored column
--echo # Copying maria100226_char_to_vchar_stored.* to MYSQLD_DATADIR
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_stored.frm $MYSQLD_DATADIR/test/t1.frm
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYD $MYSQLD_DATADIR/test/t1.MYD
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYI $MYSQLD_DATADIR/test/t1.MYI
ALTER TABLE t1 DROP v;
SELECT * FROM t1;
DROP TABLE t1;
--echo # Fixing by altering the generation expression of the stored column
--echo # Copying maria100226_char_to_vchar_stored.* to MYSQLD_DATADIR
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_stored.frm $MYSQLD_DATADIR/test/t1.frm
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYD $MYSQLD_DATADIR/test/t1.MYD
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYI $MYSQLD_DATADIR/test/t1.MYI
SHOW CREATE TABLE t1;
ALTER TABLE t1 MODIFY v VARCHAR(5) AS (RTRIM(a)) PERSISTENT;
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo #
--echo # Opening a Maria-10.2.26 table with a virtual VARCHAR column
--echo #
--echo # Copying maria100226_char_to_vchar_virtual.* to MYSQLD_DATADIR
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.frm $MYSQLD_DATADIR/test/t1.frm
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYD $MYSQLD_DATADIR/test/t1.MYD
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYI $MYSQLD_DATADIR/test/t1.MYI
SHOW CREATE TABLE t1;
SHOW CREATE TABLE t1;
FLUSH TABLES;
SHOW CREATE TABLE t1;
FLUSH TABLES;
SELECT * FROM t1;
SELECT * FROM t1;
FLUSH TABLES;
SELECT * FROM t1;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t2 LIKE t1;
FLUSH TABLES;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t1;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
ALTER TABLE t1 ADD b INT DEFAULT a;
FLUSH TABLES;
--error ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED
ALTER TABLE t1 ADD c INT DEFAULT a;
SELECT * FROM t1;
DROP TABLE t1;
--echo #
--echo # Fixing a Maria-10.2.26 table with a virtual VARCHAR column
--echo #
--echo # Fixing by dropping the virtual column
--echo # Copying maria100226_char_to_vchar_virtual.* to MYSQLD_DATADIR
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.frm $MYSQLD_DATADIR/test/t1.frm
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYD $MYSQLD_DATADIR/test/t1.MYD
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYI $MYSQLD_DATADIR/test/t1.MYI
SHOW CREATE TABLE t1;
ALTER TABLE t1 DROP v;
SELECT * FROM t1;
DROP TABLE t1;
--echo # Fixing by dropping a key on a virtual column, using ALTER TABLE
--echo # Copying maria100226_char_to_vchar_virtual.* to MYSQLD_DATADIR
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.frm $MYSQLD_DATADIR/test/t1.frm
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYD $MYSQLD_DATADIR/test/t1.MYD
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYI $MYSQLD_DATADIR/test/t1.MYI
SHOW CREATE TABLE t1;
ALTER TABLE t1 DROP KEY v;
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
--echo # Fixing by dropping a key on a virtual column, using DROP INDEX
--echo # Copying maria100226_char_to_vchar_virtual.* to MYSQLD_DATADIR
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.frm $MYSQLD_DATADIR/test/t1.frm
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYD $MYSQLD_DATADIR/test/t1.MYD
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYI $MYSQLD_DATADIR/test/t1.MYI
DROP INDEX v ON t1;
SHOW CREATE TABLE t1;
SELECT * FROM t1;
DROP TABLE t1;
--echo # Fixing by altering the generation expression of a virtual column
--echo # Copying maria100226_char_to_vchar_virtual.* to MYSQLD_DATADIR
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.frm $MYSQLD_DATADIR/test/t1.frm
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYD $MYSQLD_DATADIR/test/t1.MYD
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYI $MYSQLD_DATADIR/test/t1.MYI
SHOW CREATE TABLE t1;
ALTER TABLE t1 MODIFY v VARCHAR(5) AS(RTRIM(a)) VIRTUAL;
SHOW CREATE TABLE t1;
SELECT * FROM t1;
CREATE TABLE t2 LIKE t1;
SHOW CREATE TABLE t2;
DROP TABLE t2;
DROP TABLE t1;
--echo #
--echo # Upgrading a Maria-10.2.26 table with a stored column
--echo #
--echo # Copying maria100226_char_to_varchar.* to MYSQLD_DATADIR
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_stored.frm $MYSQLD_DATADIR/test/t1.frm
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYD $MYSQLD_DATADIR/test/t1.MYD
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYI $MYSQLD_DATADIR/test/t1.MYI
CHECK TABLE t1 FOR UPGRADE;
FLUSH TABLES;
CHECK TABLE t1 FOR UPGRADE;
DROP TABLE t1;
--echo #
--echo # Upgrading a Maria-10.2.26 table with a virtual column
--echo #
--echo # Copying maria100226_char_to_varchar.* to MYSQLD_DATADIR
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.frm $MYSQLD_DATADIR/test/t1.frm
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYD $MYSQLD_DATADIR/test/t1.MYD
--copy_file std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYI $MYSQLD_DATADIR/test/t1.MYI
CHECK TABLE t1 FOR UPGRADE;
FLUSH TABLES;
CHECK TABLE t1 FOR UPGRADE;
DROP TABLE t1;

View File

@ -127,7 +127,7 @@ SET (SQL_SOURCE
rpl_gtid.cc rpl_parallel.cc
semisync.cc semisync_master.cc semisync_slave.cc
semisync_master_ack_receiver.cc
sql_type.cc
sql_type.cc sql_mode.cc
item_windowfunc.cc sql_window.cc
sql_cte.cc
item_vers.cc

View File

@ -1372,6 +1372,46 @@ error:
}
void Field::error_generated_column_function_is_not_allowed(THD *thd,
bool error) const
{
StringBuffer<64> tmp;
vcol_info->expr->print(&tmp, (enum_query_type)
(QT_TO_SYSTEM_CHARSET |
QT_ITEM_IDENT_SKIP_DB_NAMES |
QT_ITEM_IDENT_SKIP_TABLE_NAMES));
my_error(ER_GENERATED_COLUMN_FUNCTION_IS_NOT_ALLOWED,
MYF(error ? 0 : ME_JUST_WARNING),
tmp.c_ptr(), vcol_info->get_vcol_type_name(),
const_cast<const char*>(field_name.str));
}
/*
Check if an indexed or a persistent virtual column depends on sql_mode flags
that it cannot handle.
See sql_mode.h for details.
*/
bool Field::check_vcol_sql_mode_dependency(THD *thd, vcol_init_mode mode) const
{
DBUG_ASSERT(vcol_info);
if ((flags & PART_KEY_FLAG) != 0 || stored_in_db())
{
Sql_mode_dependency dep=
vcol_info->expr->value_depends_on_sql_mode() &
Sql_mode_dependency(~0, ~can_handle_sql_mode_dependency_on_store());
if (dep)
{
bool error= (mode & VCOL_INIT_DEPENDENCY_FAILURE_IS_ERROR) != 0;
error_generated_column_function_is_not_allowed(thd, error);
dep.push_dependency_warnings(thd);
return error;
}
}
return false;
}
/**
Numeric fields base class constructor.
*/
@ -1408,6 +1448,12 @@ void Field_num::prepend_zeros(String *value) const
}
sql_mode_t Field_num::can_handle_sql_mode_dependency_on_store() const
{
return MODE_PAD_CHAR_TO_FULL_LENGTH;
}
Item *Field_num::get_equal_zerofill_const_item(THD *thd, const Context &ctx,
Item *const_item)
{
@ -5559,6 +5605,12 @@ my_time_t Field_timestampf::get_timestamp(const uchar *pos,
/*************************************************************/
sql_mode_t Field_temporal::can_handle_sql_mode_dependency_on_store() const
{
return MODE_PAD_CHAR_TO_FULL_LENGTH;
}
uint Field_temporal::is_equal(Create_field *new_field)
{
return new_field->type_handler() == type_handler() &&
@ -7187,6 +7239,18 @@ longlong Field_string::val_int(void)
}
sql_mode_t Field_string::value_depends_on_sql_mode() const
{
return has_charset() ? MODE_PAD_CHAR_TO_FULL_LENGTH : sql_mode_t(0);
};
sql_mode_t Field_string::can_handle_sql_mode_dependency_on_store() const
{
return has_charset() ? MODE_PAD_CHAR_TO_FULL_LENGTH : sql_mode_t(0);
}
String *Field_string::val_str(String *val_buffer __attribute__((unused)),
String *val_ptr)
{
@ -9072,6 +9136,12 @@ bool Field_geom::load_data_set_null(THD *thd)
** If one uses this string in a number context one gets the type number.
****************************************************************************/
sql_mode_t Field_enum::can_handle_sql_mode_dependency_on_store() const
{
return MODE_PAD_CHAR_TO_FULL_LENGTH;
}
enum ha_base_keytype Field_enum::key_type() const
{
switch (packlength) {

View File

@ -631,6 +631,8 @@ protected:
val_str(&result);
return to->store(result.ptr(), result.length(), charset());
}
void error_generated_column_function_is_not_allowed(THD *thd, bool error)
const;
static void do_field_int(Copy_field *copy);
static void do_field_real(Copy_field *copy);
static void do_field_string(Copy_field *copy);
@ -1209,6 +1211,16 @@ public:
}
bool stored_in_db() const { return !vcol_info || vcol_info->stored_in_db; }
bool check_vcol_sql_mode_dependency(THD *, vcol_init_mode mode) const;
virtual sql_mode_t value_depends_on_sql_mode() const
{
return 0;
}
virtual sql_mode_t can_handle_sql_mode_dependency_on_store() const
{
return 0;
}
inline THD *get_thd() const
{ return likely(table) ? table->in_use : current_thd; }
@ -1689,6 +1701,7 @@ public:
enum Derivation derivation(void) const { return DERIVATION_NUMERIC; }
uint repertoire(void) const { return MY_REPERTOIRE_NUMERIC; }
CHARSET_INFO *charset(void) const { return &my_charset_numeric; }
sql_mode_t can_handle_sql_mode_dependency_on_store() const;
Item *get_equal_const_item(THD *thd, const Context &ctx, Item *const_item)
{
return (flags & ZEROFILL_FLAG) ?
@ -2559,6 +2572,7 @@ public:
{
return store(str, length, &my_charset_bin);
}
sql_mode_t can_handle_sql_mode_dependency_on_store() const;
Copy_func *get_copy_func(const Field *from) const;
int save_in_field(Field *to)
{
@ -3390,6 +3404,8 @@ public:
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
virtual uint get_key_image(uchar *buff,uint length, imagetype type);
sql_mode_t value_depends_on_sql_mode() const;
sql_mode_t can_handle_sql_mode_dependency_on_store() const;
private:
int save_field_metadata(uchar *first_byte);
};
@ -3981,6 +3997,7 @@ public:
Field *make_new_field(MEM_ROOT *root, TABLE *new_table, bool keep_type);
const Type_handler *type_handler() const { return &type_handler_enum; }
enum ha_base_keytype key_type() const;
sql_mode_t can_handle_sql_mode_dependency_on_store() const;
Copy_func *get_copy_func(const Field *from) const
{
if (eq_def(from))

View File

@ -1252,6 +1252,32 @@ public:
double val_real_from_decimal();
double val_real_from_date();
/*
Returns true if this item can be calculated during
value_depends_on_sql_mode()
*/
bool value_depends_on_sql_mode_const_item()
{
/*
Currently we use value_depends_on_sql_mode() only for virtual
column expressions. They should not contain any expensive items.
If we ever get a crash on the assert below, it means
check_vcol_func_processor() is badly implemented for this item.
*/
DBUG_ASSERT(!is_expensive());
/*
It should return const_item() actually.
But for some reasons Item_field::const_item() returns true
at value_depends_on_sql_mode() call time.
This should be checked and fixed.
*/
return basic_const_item();
}
virtual Sql_mode_dependency value_depends_on_sql_mode() const
{
return Sql_mode_dependency();
}
// Get TIME, DATE or DATETIME using proper sql_mode flags for the field type
bool get_temporal_with_sql_mode(MYSQL_TIME *ltime);
// Check NULL value for a TIME, DATE or DATETIME expression
@ -2289,6 +2315,7 @@ public:
inline Item **arguments() const { return args; }
inline uint argument_count() const { return arg_count; }
inline void remove_arguments() { arg_count=0; }
Sql_mode_dependency value_depends_on_sql_mode_bit_or() const;
};
@ -3029,6 +3056,10 @@ public:
{
return MONOTONIC_STRICT_INCREASING;
}
Sql_mode_dependency value_depends_on_sql_mode() const
{
return Sql_mode_dependency(0, field->value_depends_on_sql_mode());
}
longlong val_int_endpoint(bool left_endp, bool *incl_endp);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
bool get_date_result(MYSQL_TIME *ltime,ulonglong fuzzydate);
@ -4726,6 +4757,10 @@ public:
bool const_item() const { return const_item_cache; }
table_map used_tables() const { return used_tables_cache; }
Item* build_clone(THD *thd);
Sql_mode_dependency value_depends_on_sql_mode() const
{
return Item_args::value_depends_on_sql_mode_bit_or().soft_to_hard();
}
};
class sp_head;

View File

@ -449,6 +449,23 @@ bool Item_func::setup_args_and_comparator(THD *thd, Arg_comparator *cmp)
}
/*
Comparison operators remove arguments' dependency on PAD_CHAR_TO_FULL_LENGTH
in case of PAD SPACE comparison collations: trailing spaces do not affect
the comparison result for such collations.
*/
Sql_mode_dependency
Item_bool_rowready_func2::value_depends_on_sql_mode() const
{
if (compare_collation()->state & MY_CS_NOPAD)
return Item_func::value_depends_on_sql_mode();
return ((args[0]->value_depends_on_sql_mode() |
args[1]->value_depends_on_sql_mode()) &
Sql_mode_dependency(~0, ~MODE_PAD_CHAR_TO_FULL_LENGTH)).
soft_to_hard();
}
bool Item_bool_rowready_func2::fix_length_and_dec()
{
max_length= 1; // Function returns 0 or 1
@ -5274,6 +5291,29 @@ bool Item_func_like::with_sargable_pattern() const
}
/*
subject LIKE pattern
removes subject's dependency on PAD_CHAR_TO_FULL_LENGTH
if pattern ends with the '%' wildcard.
*/
Sql_mode_dependency Item_func_like::value_depends_on_sql_mode() const
{
if (!args[1]->value_depends_on_sql_mode_const_item())
return Item_func::value_depends_on_sql_mode();
StringBuffer<64> patternbuf;
String *pattern= args[1]->val_str_ascii(&patternbuf);
if (!pattern || !pattern->length())
return Sql_mode_dependency(); // Will return NULL or 0
DBUG_ASSERT(pattern->charset()->mbminlen == 1);
if (pattern->ptr()[pattern->length() - 1] != '%')
return Item_func::value_depends_on_sql_mode();
return ((args[0]->value_depends_on_sql_mode() |
args[1]->value_depends_on_sql_mode()) &
Sql_mode_dependency(~0, ~MODE_PAD_CHAR_TO_FULL_LENGTH)).
soft_to_hard();
}
SEL_TREE *Item_func_like::get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
{
MEM_ROOT *tmp_root= param->mem_root;

View File

@ -507,6 +507,7 @@ public:
Item_bool_rowready_func2(THD *thd, Item *a, Item *b):
Item_bool_func2_with_rev(thd, a, b), cmp(tmp_arg, tmp_arg + 1)
{ }
Sql_mode_dependency value_depends_on_sql_mode() const;
void print(String *str, enum_query_type query_type)
{
Item_func::print_op(str, query_type);
@ -2632,6 +2633,7 @@ public:
Item_bool_func2(thd, a, b), canDoTurboBM(FALSE), pattern(0), pattern_len(0),
bmGs(0), bmBc(0), escape_item(escape_arg),
escape_used_in_parsing(escape_used), use_sampling(0), negated(0) {}
Sql_mode_dependency value_depends_on_sql_mode() const;
longlong val_int();
enum Functype functype() const { return LIKE_FUNC; }
void print(String *str, enum_query_type query_type);

View File

@ -562,6 +562,15 @@ void Item_args::propagate_equal_fields(THD *thd,
}
Sql_mode_dependency Item_args::value_depends_on_sql_mode_bit_or() const
{
Sql_mode_dependency res;
for (uint i= 0; i < arg_count; i++)
res|= args[i]->value_depends_on_sql_mode();
return res;
}
/**
See comments in Item_cond::split_sum_func()
*/
@ -1329,6 +1338,13 @@ bool Item_func_minus::fix_length_and_dec()
if (Item_func_minus::type_handler()->Item_func_minus_fix_length_and_dec(this))
DBUG_RETURN(TRUE);
DBUG_PRINT("info", ("Type: %s", type_handler()->name().ptr()));
m_sql_mode_dependency= Item_func::value_depends_on_sql_mode();
if (unsigned_flag)
{
m_sql_mode_dependency|= Sql_mode_dependency(0,MODE_NO_UNSIGNED_SUBTRACTION);
if (current_thd->variables.sql_mode & MODE_NO_UNSIGNED_SUBTRACTION)
unsigned_flag= false;
}
DBUG_RETURN(FALSE);
}

View File

@ -1095,11 +1095,16 @@ public:
class Item_func_minus :public Item_func_additive_op
{
Sql_mode_dependency m_sql_mode_dependency;
public:
Item_func_minus(THD *thd, Item *a, Item *b):
Item_func_additive_op(thd, a, b) {}
const char *func_name() const { return "-"; }
enum precedence precedence() const { return ADD_PRECEDENCE; }
Sql_mode_dependency value_depends_on_sql_mode() const
{
return m_sql_mode_dependency;
}
longlong int_op();
double real_op();
my_decimal *decimal_op(my_decimal *);

View File

@ -2174,6 +2174,41 @@ void Item_func_trim::print(String *str, enum_query_type query_type)
}
/*
RTRIM(expr)
TRIM(TRAILING ' ' FROM expr)
remove argument's soft dependency on PAD_CHAR_TO_FULL_LENGTH:
*/
Sql_mode_dependency Item_func_trim::value_depends_on_sql_mode() const
{
DBUG_ASSERT(fixed);
if (arg_count == 1) // RTRIM(expr)
return (args[0]->value_depends_on_sql_mode() &
Sql_mode_dependency(~0, ~MODE_PAD_CHAR_TO_FULL_LENGTH)).
soft_to_hard();
// TRIM(... FROM expr)
DBUG_ASSERT(arg_count == 2);
if (!args[1]->value_depends_on_sql_mode_const_item())
return Item_func::value_depends_on_sql_mode();
StringBuffer<64> trimstrbuf;
String *trimstr= args[1]->val_str(&trimstrbuf);
if (!trimstr)
return Sql_mode_dependency(); // will return NULL
if (trimstr->length() == 0)
return Item_func::value_depends_on_sql_mode(); // will trim nothing
if (trimstr->lengthsp() != 0)
return Item_func::value_depends_on_sql_mode(); // will trim not only spaces
if (trimstr->length() > trimstr->charset()->mbminlen ||
trimstr->numchars() > 1)
return Item_func::value_depends_on_sql_mode(); // more than one space
// TRIM(TRAILING ' ' FROM expr)
return ((args[0]->value_depends_on_sql_mode() |
args[1]->value_depends_on_sql_mode()) &
Sql_mode_dependency(~0, ~MODE_PAD_CHAR_TO_FULL_LENGTH)).
soft_to_hard();
}
/* Item_func_password */
bool Item_func_password::fix_fields(THD *thd, Item **ref)
@ -3189,6 +3224,38 @@ bool Item_func_pad::fix_length_and_dec()
}
/*
PAD(expr,length,' ')
removes argument's soft dependency on PAD_CHAR_TO_FULL_LENGTH if the result
is longer than the argument's maximim possible length.
*/
Sql_mode_dependency Item_func_rpad::value_depends_on_sql_mode() const
{
DBUG_ASSERT(fixed);
DBUG_ASSERT(arg_count == 3);
if (!args[1]->value_depends_on_sql_mode_const_item() ||
!args[2]->value_depends_on_sql_mode_const_item())
return Item_func::value_depends_on_sql_mode();
Longlong_hybrid len= args[1]->to_longlong_hybrid();
if (args[1]->null_value || len.neg())
return Sql_mode_dependency(); // will return NULL
if (len.abs() > 0 && len.abs() < args[0]->max_char_length())
return Item_func::value_depends_on_sql_mode();
StringBuffer<64> padstrbuf;
String *padstr= args[2]->val_str(&padstrbuf);
if (!padstr || !padstr->length())
return Sql_mode_dependency(); // will return NULL
if (padstr->lengthsp() != 0)
return Item_func::value_depends_on_sql_mode(); // will pad not only spaces
// RPAD(expr, length, ' ') -- with a long enough length
return ((args[0]->value_depends_on_sql_mode() |
args[1]->value_depends_on_sql_mode()) &
Sql_mode_dependency(~0, ~MODE_PAD_CHAR_TO_FULL_LENGTH)).
soft_to_hard();
}
String *Item_func_rpad::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);

View File

@ -563,6 +563,7 @@ protected:
public:
Item_func_trim(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {}
Item_func_trim(THD *thd, Item *a): Item_str_func(thd, a) {}
Sql_mode_dependency value_depends_on_sql_mode() const;
String *val_str(String *);
bool fix_length_and_dec();
const char *func_name() const { return "trim"; }
@ -600,6 +601,10 @@ class Item_func_ltrim :public Item_func_trim
public:
Item_func_ltrim(THD *thd, Item *a, Item *b): Item_func_trim(thd, a, b) {}
Item_func_ltrim(THD *thd, Item *a): Item_func_trim(thd, a) {}
Sql_mode_dependency value_depends_on_sql_mode() const
{
return Item_func::value_depends_on_sql_mode();
}
String *val_str(String *);
const char *func_name() const { return "ltrim"; }
const char *mode_name() const { return "leading"; }
@ -1133,6 +1138,7 @@ public:
Item_func_pad(thd, arg1, arg2) {}
String *val_str(String *);
const char *func_name() const { return "rpad"; }
Sql_mode_dependency value_depends_on_sql_mode() const;
Item *get_copy(THD *thd)
{ return get_item_copy<Item_func_rpad>(thd, this); }
};

View File

@ -18,6 +18,7 @@
#define MYSQLD_INCLUDED
#include "sql_basic_types.h" /* query_id_t */
#include "sql_mode.h" /* Sql_mode_dependency */
#include "sql_plugin.h"
#include "sql_bitmap.h" /* Bitmap */
#include "my_decimal.h" /* my_decimal */

View File

@ -430,6 +430,7 @@ inline bool IS_SYSVAR_AUTOSIZE(void *ptr)
bool fix_delay_key_write(sys_var *self, THD *thd, enum_var_type type);
sql_mode_t expand_sql_mode(sql_mode_t sql_mode);
const char *sql_mode_string_representation(uint bit_number);
bool sql_mode_string_representation(THD *thd, sql_mode_t sql_mode,
LEX_CSTRING *ls);
int default_regex_flags_pcre(const THD *thd);

View File

@ -2624,7 +2624,8 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
sizeof(MY_BITMAP)))))
goto error;
if (unlikely(parse_vcol_defs(client_thd, client_thd->mem_root, copy,
&error_reported)))
&error_reported,
VCOL_INIT_DEPENDENCY_FAILURE_IS_WARNING)))
goto error;
}

34
sql/sql_mode.cc Normal file
View File

@ -0,0 +1,34 @@
/*
Copyright (c) 2019, MariaDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
#include "mariadb.h"
#include "set_var.h"
void Sql_mode_dependency::push_dependency_warnings(THD *thd)
{
sql_mode_t all= m_hard | m_soft;
for (uint i= 0; all ; i++, all >>= 1)
{
if (all & 1)
{
// TODO-10.5: add a new error code
push_warning_printf(thd,
Sql_condition::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
"Expression depends on the @@%s value %s",
"sql_mode", sql_mode_string_representation(i));
}
}
}

162
sql/sql_mode.h Normal file
View File

@ -0,0 +1,162 @@
#ifndef SQL_MODE_H_INCLUDED
#define SQL_MODE_H_INCLUDED
/*
Copyright (c) 2019, MariaDB.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
#include "sql_basic_types.h"
/*
class Sql_mode_dependency
A combination of hard and soft dependency on sql_mode.
Used to watch if a GENERATED ALWAYS AS expression guarantees consitent
data written to its virtual column.
A virtual column can appear in an index if:
- the generation expression does not depend on any sql_mode flags, or
- the generation expression has a soft dependency on an sql_mode flag,
and the column knows how to handle this dependeny.
A virtual column cannot appear in an index if:
- its generation expression has a hard dependency
- its generation expression has a soft dependency, but the column
cannot handle it on store.
An error is reported in such cases.
How dependencies appear:
- When a column return value depends on some sql_mode flag,
its Item_field adds a corresponding bit to m_soft. For example,
Item_field for a CHAR(N) column adds the PAD_CHAR_TO_FULL_LENGTH flag.
- When an SQL function/operator return value depends on some sql_mode flag,
it adds a corresponding bit to m_soft. For example, Item_func_minus
adds the MODE_NO_UNSIGNED_SUBTRACTION in case of unsigned arguments.
How dependency are processed (see examples below):
- All SQL functions/operators bit-OR all hard dependencies from all arguments.
- Some soft dependencies can be handled by the underlying Field on store,
e.g. CHAR(N) can handle PAD_CHAR_TO_FULL_LENGTH.
- Some soft dependencies can be handled by SQL functions and operators,
e.g. RTRIM(expr) removes expr's soft dependency on PAD_CHAR_TO_FULL_LENGTH.
If a function or operator handles a soft dependency on a certain sql_mode
flag, it removes the corresponding bit from m_soft (see below).
Note, m_hard is not touched in such cases.
- When an expression with a soft dependency on a certain sql_mode flag
goes as an argument to an SQL function/operator which cannot handle
this flag, the dependency escalates from soft to hard
(by moving the corresponding bit from m_soft to m_hard) and cannot be
handled any more on the upper level, neither by a Field on store,
nor by another SQL function/operator.
There are four kinds of Items:
1. Items that generate a soft or hard dependency, e.g.
- Item_field for CHAR(N) - generates soft/PAD_CHAR_TO_FULL_LENGTH
- Item_func_minus - generates soft/NO_UNSIGNED_SUBTRACTION
2. Items that convert a soft dependency to a hard dependency.
This happens e.g. when an Item_func instance gets a soft dependency
from its arguments, and it does not know how to handle this dependency.
Most Item_func descendants do this.
3. Items that remove soft dependencies, e.g.:
- Item_func_rtrim - removes soft/PAD_CHAR_TO_FULL_LENGTH
that came from args[0] (under certain conditions)
- Item_func_rpad - removes soft/PAD_CJAR_TO_FULL_LENGTH
that came from args[0] (under certain conditions)
4. Items that repeat soft dependency from its arguments to the caller.
They are not implemented yet. But functions like Item_func_coalesce,
Item_func_case, Item_func_case_abbreviation2 could do this.
Examples:
1. CREATE OR REPLACE TABLE t1 (a CHAR(5), v CHAR(20) AS(a), KEY(v));
Here `v` has a soft dependency on `a`.
The value of `a` depends on PAD_CHAR_TO_FULL_LENGTH, it can return:
- 'a' - if PAD_CHAR_TO_FULL_LENGTH is disabled
- 'a' followed by four spaces - if PAD_CHAR_TO_FULL_LENGTH is enabled
But `v` will pad trailing spaces to the full length on store anyway.
So Field_string handles this soft dependency on store.
This combination of the virtial column data type and its generation
expression is safe and provides consistent data in `v`, which is
'a' followed by four spaces, no matter what PAD_CHAR_TO_FULL_LENGTH is.
2. CREATE OR REPLACE TABLE t1 (a CHAR(5), v VARCHAR(20) AS(a), KEY(v));
Here `v` has a soft dependency on `a`. But Field_varstring does
not pad spaces on store, so it cannot handle this dependency.
This combination of the virtual column data type and its generation
expression is not safe. An error is returned.
3. CREATE OR REPLACE TABLE t1 (a CHAR(5), v INT AS(LENGTH(a)), KEY(v));
Here `v` has a hard dependency on `a`, because the value of `a`
is wrapped to the function LENGTH().
The value of `LENGTH(a)` depends on PAD_CHAR_TO_FULL_LENGTH, it can return:
- 1 - if PAD_CHAR_TO_FULL_LENGTH is disabled
- 4 - if PAD_CHAR_TO_FULL_LENGTH is enabled
This combination cannot provide consistent data stored to `v`,
therefore it's disallowed.
*/
class Sql_mode_dependency
{
sql_mode_t m_hard;
sql_mode_t m_soft;
public:
Sql_mode_dependency()
:m_hard(0), m_soft(0)
{ }
Sql_mode_dependency(sql_mode_t hard, sql_mode_t soft)
:m_hard(hard), m_soft(soft)
{ }
sql_mode_t hard() const { return m_hard; }
sql_mode_t soft() const { return m_soft; }
operator bool () const
{
return m_hard > 0 || m_soft > 0;
}
Sql_mode_dependency operator|(const Sql_mode_dependency &other) const
{
return Sql_mode_dependency(m_hard | other.m_hard, m_soft | other.m_soft);
}
Sql_mode_dependency operator&(const Sql_mode_dependency &other) const
{
return Sql_mode_dependency(m_hard & other.m_hard, m_soft & other.m_soft);
}
Sql_mode_dependency &operator|=(const Sql_mode_dependency &other)
{
m_hard|= other.m_hard;
m_soft|= other.m_soft;
return *this;
}
Sql_mode_dependency &operator&=(const Sql_mode_dependency &other)
{
m_hard&= other.m_hard;
m_soft&= other.m_soft;
return *this;
}
Sql_mode_dependency &soft_to_hard()
{
m_hard|= m_soft;
m_soft= 0;
return *this;
}
void push_dependency_warnings(THD *thd);
};
#endif // SQL_MODE_H_INCLUDED

View File

@ -232,6 +232,11 @@ public:
return skr;
}
size_t lengthsp() const
{
return str_charset->cset->lengthsp(str_charset, Ptr, str_length);
}
void set(String &str,size_t offset,size_t arg_length)
{
DBUG_ASSERT(&str != this);

View File

@ -3416,6 +3416,14 @@ static const char *sql_mode_names[]=
0
};
const char *sql_mode_string_representation(uint bit_number)
{
DBUG_ASSERT(bit_number < array_elements(sql_mode_names));
return sql_mode_names[bit_number];
}
export bool sql_mode_string_representation(THD *thd, sql_mode_t sql_mode,
LEX_CSTRING *ls)
{

View File

@ -992,7 +992,7 @@ static void mysql57_calculate_null_position(TABLE_SHARE *share,
expression
*/
bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
bool *error_reported)
bool *error_reported, vcol_init_mode mode)
{
CHARSET_INFO *save_character_set_client= thd->variables.character_set_client;
CHARSET_INFO *save_collation= thd->variables.collation_connection;
@ -1076,6 +1076,12 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
vcol= unpack_vcol_info_from_frm(thd, mem_root, table, &expr_str,
&((*field_ptr)->vcol_info), error_reported);
*(vfield_ptr++)= *field_ptr;
if (vcol && field_ptr[0]->check_vcol_sql_mode_dependency(thd, mode))
{
DBUG_ASSERT(thd->is_error());
*error_reported= true;
goto end;
}
break;
case VCOL_DEFAULT:
vcol= unpack_vcol_info_from_frm(thd, mem_root, table, &expr_str,
@ -3359,8 +3365,24 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share,
if (share->table_check_constraints || share->field_check_constraints)
outparam->check_constraints= check_constraint_ptr;
vcol_init_mode mode= VCOL_INIT_DEPENDENCY_FAILURE_IS_WARNING;
switch (thd->lex->sql_command)
{
case SQLCOM_CREATE_TABLE:
mode= VCOL_INIT_DEPENDENCY_FAILURE_IS_ERROR;
break;
case SQLCOM_ALTER_TABLE:
case SQLCOM_CREATE_INDEX:
case SQLCOM_DROP_INDEX:
if ((ha_open_flags & HA_OPEN_FOR_ALTER) == 0)
mode= VCOL_INIT_DEPENDENCY_FAILURE_IS_ERROR;
break;
default:
break;
}
if (unlikely(parse_vcol_defs(thd, &outparam->mem_root, outparam,
&error_reported)))
&error_reported, mode)))
{
error= OPEN_FRM_CORRUPTED;
goto err;

View File

@ -326,6 +326,20 @@ enum tmp_table_type
};
enum release_type { RELEASE_NORMAL, RELEASE_WAIT_FOR_DROP };
enum vcol_init_mode
{
VCOL_INIT_DEPENDENCY_FAILURE_IS_WARNING= 1,
VCOL_INIT_DEPENDENCY_FAILURE_IS_ERROR= 2
/*
There may be new flags here.
e.g. to automatically remove sql_mode dependency:
GENERATED ALWAYS AS (char_col) ->
GENERATED ALWAYS AS (RTRIM(char_col))
*/
};
enum enum_vcol_update_mode
{
VCOL_UPDATE_FOR_READ= 0,
@ -2920,7 +2934,7 @@ bool fix_session_vcol_expr(THD *thd, Virtual_column_info *vcol);
bool fix_session_vcol_expr_for_read(THD *thd, Field *field,
Virtual_column_info *vcol);
bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
bool *error_reported);
bool *error_reported, vcol_init_mode expr);
TABLE_SHARE *alloc_table_share(const char *db, const char *table_name,
const char *key, uint key_length);
void init_tmp_table_share(THD *thd, TABLE_SHARE *share, const char *key,