summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.com>2019-09-04 09:55:59 +0400
committerAlexander Barkov <bar@mariadb.com>2019-09-04 10:19:58 +0400
commit7e08ac0b41b50195aa79f6ac185bc69a91a960ca (patch)
tree3a399827dc8e6bd89bbb6d142f21eda8bd659119
parenta071e0e029cd7c155cff1054d9f7f8a6aa898620 (diff)
parentef00ac4c86daf3294c46a45358da636763fb0049 (diff)
downloadmariadb-git-7e08ac0b41b50195aa79f6ac185bc69a91a960ca.tar.gz
Merge 10.2 (up to commit ef00ac4c86daf3294c46a45358da636763fb0049) into 10.3
-rw-r--r--libmysqld/CMakeLists.txt1
-rw-r--r--mysql-test/main/ssl-big.test1
-rw-r--r--mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYDbin0 -> 60 bytes
-rw-r--r--mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYIbin0 -> 1024 bytes
-rw-r--r--mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_stored.frmbin0 -> 483 bytes
-rw-r--r--mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYDbin0 -> 60 bytes
-rw-r--r--mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYIbin0 -> 2048 bytes
-rw-r--r--mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.frmbin0 -> 972 bytes
-rw-r--r--mysql-test/suite/binlog/t/flashback-largebinlog.test2
-rw-r--r--mysql-test/suite/gcol/r/innodb_virtual_basic.result6
-rw-r--r--mysql-test/suite/gcol/r/innodb_virtual_index.result2
-rw-r--r--mysql-test/suite/gcol/t/innodb_virtual_basic.test6
-rw-r--r--mysql-test/suite/gcol/t/innodb_virtual_index.test2
-rw-r--r--mysql-test/suite/innodb_fts/t/fulltext_table_evict.test1
-rw-r--r--mysql-test/suite/innodb_gis/t/update_root.test2
-rw-r--r--mysql-test/suite/vcol/inc/vcol_trigger_sp.inc2
-rw-r--r--mysql-test/suite/vcol/r/update.result4
-rw-r--r--mysql-test/suite/vcol/r/update_binlog.result8
-rw-r--r--mysql-test/suite/vcol/r/vcol_sql_mode.result438
-rw-r--r--mysql-test/suite/vcol/r/vcol_sql_mode_upgrade.result336
-rw-r--r--mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result2
-rw-r--r--mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result2
-rw-r--r--mysql-test/suite/vcol/t/update.test2
-rw-r--r--mysql-test/suite/vcol/t/vcol_sql_mode.test322
-rw-r--r--mysql-test/suite/vcol/t/vcol_sql_mode_upgrade.test193
-rw-r--r--sql/CMakeLists.txt2
-rw-r--r--sql/field.cc70
-rw-r--r--sql/field.h17
-rw-r--r--sql/item.h35
-rw-r--r--sql/item_cmpfunc.cc40
-rw-r--r--sql/item_cmpfunc.h2
-rw-r--r--sql/item_func.cc16
-rw-r--r--sql/item_func.h5
-rw-r--r--sql/item_strfunc.cc67
-rw-r--r--sql/item_strfunc.h6
-rw-r--r--sql/mysqld.h1
-rw-r--r--sql/set_var.h1
-rw-r--r--sql/sql_insert.cc3
-rw-r--r--sql/sql_mode.cc34
-rw-r--r--sql/sql_mode.h162
-rw-r--r--sql/sql_string.h5
-rw-r--r--sql/sys_vars.cc8
-rw-r--r--sql/table.cc26
-rw-r--r--sql/table.h16
44 files changed, 1825 insertions, 23 deletions
diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt
index 4a508fe22b8..d8d56832be9 100644
--- a/libmysqld/CMakeLists.txt
+++ b/libmysqld/CMakeLists.txt
@@ -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
diff --git a/mysql-test/main/ssl-big.test b/mysql-test/main/ssl-big.test
index 59825a148a4..367cbcba2d7 100644
--- a/mysql-test/main/ssl-big.test
+++ b/mysql-test/main/ssl-big.test
@@ -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
diff --git a/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYD b/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYD
new file mode 100644
index 00000000000..3b511e3b8fa
--- /dev/null
+++ b/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYD
Binary files differ
diff --git a/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYI b/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYI
new file mode 100644
index 00000000000..b039d02f2e0
--- /dev/null
+++ b/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYI
Binary files differ
diff --git a/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_stored.frm b/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_stored.frm
new file mode 100644
index 00000000000..85f142070e9
--- /dev/null
+++ b/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_stored.frm
Binary files differ
diff --git a/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYD b/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYD
new file mode 100644
index 00000000000..e770e42b6bf
--- /dev/null
+++ b/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYD
Binary files differ
diff --git a/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYI b/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYI
new file mode 100644
index 00000000000..aff7d10ce18
--- /dev/null
+++ b/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYI
Binary files differ
diff --git a/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.frm b/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.frm
new file mode 100644
index 00000000000..d7258bc4af3
--- /dev/null
+++ b/mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.frm
Binary files differ
diff --git a/mysql-test/suite/binlog/t/flashback-largebinlog.test b/mysql-test/suite/binlog/t/flashback-largebinlog.test
index 7ee89f43580..fb2703dfac5 100644
--- a/mysql-test/suite/binlog/t/flashback-largebinlog.test
+++ b/mysql-test/suite/binlog/t/flashback-largebinlog.test
@@ -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.
diff --git a/mysql-test/suite/gcol/r/innodb_virtual_basic.result b/mysql-test/suite/gcol/r/innodb_virtual_basic.result
index d4c65f96e59..4e8adbd88e6 100644
--- a/mysql-test/suite/gcol/r/innodb_virtual_basic.result
+++ b/mysql-test/suite/gcol/r/innodb_virtual_basic.result
@@ -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)),
diff --git a/mysql-test/suite/gcol/r/innodb_virtual_index.result b/mysql-test/suite/gcol/r/innodb_virtual_index.result
index 6913ec698b4..3918cf95ae1 100644
--- a/mysql-test/suite/gcol/r/innodb_virtual_index.result
+++ b/mysql-test/suite/gcol/r/innodb_virtual_index.result
@@ -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),
diff --git a/mysql-test/suite/gcol/t/innodb_virtual_basic.test b/mysql-test/suite/gcol/t/innodb_virtual_basic.test
index 72f4c6dc8c4..00b942739b0 100644
--- a/mysql-test/suite/gcol/t/innodb_virtual_basic.test
+++ b/mysql-test/suite/gcol/t/innodb_virtual_basic.test
@@ -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)),
diff --git a/mysql-test/suite/gcol/t/innodb_virtual_index.test b/mysql-test/suite/gcol/t/innodb_virtual_index.test
index a89ae813b05..c2f9cd78fe2 100644
--- a/mysql-test/suite/gcol/t/innodb_virtual_index.test
+++ b/mysql-test/suite/gcol/t/innodb_virtual_index.test
@@ -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),
diff --git a/mysql-test/suite/innodb_fts/t/fulltext_table_evict.test b/mysql-test/suite/innodb_fts/t/fulltext_table_evict.test
index 2e7aa655aa1..eaf50856c55 100644
--- a/mysql-test/suite/innodb_fts/t/fulltext_table_evict.test
+++ b/mysql-test/suite/innodb_fts/t/fulltext_table_evict.test
@@ -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 ]
diff --git a/mysql-test/suite/innodb_gis/t/update_root.test b/mysql-test/suite/innodb_gis/t/update_root.test
index 395fc715f31..c6d3ba60650 100644
--- a/mysql-test/suite/innodb_gis/t/update_root.test
+++ b/mysql-test/suite/innodb_gis/t/update_root.test
@@ -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;
diff --git a/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc b/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc
index f19c0f6d63f..8be139471f1 100644
--- a/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc
+++ b/mysql-test/suite/vcol/inc/vcol_trigger_sp.inc
@@ -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)),
diff --git a/mysql-test/suite/vcol/r/update.result b/mysql-test/suite/vcol/r/update.result
index 2576859b00b..3e8bbc43246 100644
--- a/mysql-test/suite/vcol/r/update.result
+++ b/mysql-test/suite/vcol/r/update.result
@@ -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
diff --git a/mysql-test/suite/vcol/r/update_binlog.result b/mysql-test/suite/vcol/r/update_binlog.result
index 9a22005f062..977037535b4 100644
--- a/mysql-test/suite/vcol/r/update_binlog.result
+++ b/mysql-test/suite/vcol/r/update_binlog.result
@@ -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
diff --git a/mysql-test/suite/vcol/r/vcol_sql_mode.result b/mysql-test/suite/vcol/r/vcol_sql_mode.result
new file mode 100644
index 00000000000..bbc596daa9c
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_sql_mode.result
@@ -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
+#
diff --git a/mysql-test/suite/vcol/r/vcol_sql_mode_upgrade.result b/mysql-test/suite/vcol/r/vcol_sql_mode_upgrade.result
new file mode 100644
index 00000000000..d3954770c7b
--- /dev/null
+++ b/mysql-test/suite/vcol/r/vcol_sql_mode_upgrade.result
@@ -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;
diff --git a/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result b/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result
index de5447e49eb..403515482f0 100644
--- a/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result
+++ b/mysql-test/suite/vcol/r/vcol_trigger_sp_innodb.result
@@ -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)),
diff --git a/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result b/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result
index f5c87838ec9..de605bf8722 100644
--- a/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result
+++ b/mysql-test/suite/vcol/r/vcol_trigger_sp_myisam.result
@@ -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)),
diff --git a/mysql-test/suite/vcol/t/update.test b/mysql-test/suite/vcol/t/update.test
index 53189ee3219..4218f0e3efb 100644
--- a/mysql-test/suite/vcol/t/update.test
+++ b/mysql-test/suite/vcol/t/update.test
@@ -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;
diff --git a/mysql-test/suite/vcol/t/vcol_sql_mode.test b/mysql-test/suite/vcol/t/vcol_sql_mode.test
new file mode 100644
index 00000000000..e4cc6d21718
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_sql_mode.test
@@ -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 #
diff --git a/mysql-test/suite/vcol/t/vcol_sql_mode_upgrade.test b/mysql-test/suite/vcol/t/vcol_sql_mode_upgrade.test
new file mode 100644
index 00000000000..71e34231ac1
--- /dev/null
+++ b/mysql-test/suite/vcol/t/vcol_sql_mode_upgrade.test
@@ -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;
diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt
index c65f78d0593..26ac84a8de8 100644
--- a/sql/CMakeLists.txt
+++ b/sql/CMakeLists.txt
@@ -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
diff --git a/sql/field.cc b/sql/field.cc
index 29446b9378b..75798999cc1 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -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) {
diff --git a/sql/field.h b/sql/field.h
index 3228d51b748..ce6e7e387ed 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -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))
diff --git a/sql/item.h b/sql/item.h
index db3fba15000..694672deabc 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -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;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 49e0a9466c0..fe5ba3b2dad 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -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;
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index f2cf91ffb7e..4bb2e0a5dee 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -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);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 7cab72718c6..6a5cfeac118 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -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);
}
diff --git a/sql/item_func.h b/sql/item_func.h
index 6345dd41f71..088886f9860 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -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 *);
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 74bed5d70ed..4fb83960bc9 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -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);
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 175c76b8f18..a279dd8598f 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -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); }
};
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 2cd61fc91e4..11871155355 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -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 */
diff --git a/sql/set_var.h b/sql/set_var.h
index f9de0236bbf..7530d3eaff5 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -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);
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 5604270ce8f..9669c002731 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -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;
}
diff --git a/sql/sql_mode.cc b/sql/sql_mode.cc
new file mode 100644
index 00000000000..32d19cecbdb
--- /dev/null
+++ b/sql/sql_mode.cc
@@ -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));
+ }
+ }
+}
diff --git a/sql/sql_mode.h b/sql/sql_mode.h
new file mode 100644
index 00000000000..e92848fb6d1
--- /dev/null
+++ b/sql/sql_mode.h
@@ -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
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 9698a47ae0c..f4764211522 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -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);
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index b50f697b489..fd40f9c5f83 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -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)
{
diff --git a/sql/table.cc b/sql/table.cc
index 4e11ce26658..e1dd3f41033 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -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;
diff --git a/sql/table.h b/sql/table.h
index 17c4719a3fa..d5a735de5ed 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -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,