From ef00ac4c86daf3294c46a45358da636763fb0049 Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Thu, 29 Aug 2019 12:35:19 +0400 Subject: [PATCH] Part2: 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 This patch allows the server to open old tables that have "bad" generated columns (i.e. indexed virtual generated columns, persistent generated columns) that depend on sql_mode, for general things like SELECT, INSERT, DROP, etc. Warning are issued in such cases. Only these commands are now disallowed and return an error: - CREATE TABLE introducing a "bad" generated column - ALTER TABLE introducing a "bad" generated column - CREATE INDEX introdicing a "bad" generated column (i.e. adding an index on a virtual generated column that depends on sql_mode). Note, these commands are allowed: - ALTER TABLE removing a "bad" generate column - ALTER TABLE removing an index from a "bad" virtual generated column - DROP INDEX removing an index from a "bad" virtual generated column but only if the table does not have any "bad" columns as a result. --- .../maria100226_char_to_vchar_stored.MYD | Bin 0 -> 60 bytes .../maria100226_char_to_vchar_stored.MYI | Bin 0 -> 1024 bytes .../maria100226_char_to_vchar_stored.frm | Bin 0 -> 483 bytes .../maria100226_char_to_vchar_virtual.MYD | Bin 0 -> 60 bytes .../maria100226_char_to_vchar_virtual.MYI | Bin 0 -> 2048 bytes .../maria100226_char_to_vchar_virtual.frm | Bin 0 -> 972 bytes mysql-test/suite/vcol/r/vcol_sql_mode.result | 6 + .../suite/vcol/r/vcol_sql_mode_upgrade.result | 336 ++++++++++++++++++ mysql-test/suite/vcol/t/vcol_sql_mode.test | 3 + .../suite/vcol/t/vcol_sql_mode_upgrade.test | 193 ++++++++++ sql/field.cc | 13 +- sql/field.h | 5 +- sql/sql_insert.cc | 3 +- sql/table.cc | 22 +- sql/table.h | 16 +- 15 files changed, 585 insertions(+), 12 deletions(-) create mode 100644 mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYD create mode 100644 mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_stored.MYI create mode 100644 mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_stored.frm create mode 100644 mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYD create mode 100644 mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.MYI create mode 100644 mysql-test/std_data/vcol_upgrade/maria100226_char_to_vchar_virtual.frm create mode 100644 mysql-test/suite/vcol/r/vcol_sql_mode_upgrade.result create mode 100644 mysql-test/suite/vcol/t/vcol_sql_mode_upgrade.test 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 0000000000000000000000000000000000000000..3b511e3b8fa147bb13ae5c1d0bf882d0934d74d4 GIT binary patch literal 60 jcmZQ(VB=!^!)VB8$N&e-5HTZ0Be)O)RLq#s7$F7#mShBD literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..b039d02f2e06f7f4b3a3b2044bb838fce8e8a2d6 GIT binary patch literal 1024 zcmezOkDZZ$kx`Rj149ZBg8>Jal>86jF)%}E7{&Y_3LpY3FmW3g12?U;94Kc5m1l&h zi%pLehOt33Iv-gM!iL+4DTOM+1LT4*NCQ6*ivTgmKa6Z(63Aj;fOr?ogcD%5F*2}% TXbuK8Cb+~XV>ASYQwRV6jA;=s literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..85f142070e971ef6dcf7ad3bb4d4ccc8446c0e59 GIT binary patch literal 483 zcmeyz$jvFl5XQjB@R*T-L4bjW0S=fr7&sXiSV4Ran4kcV(cI1mR0snCvz0xcostrK z*~2?Q+r;>LcoS5HiQzv?4a0v05P)&n7!)VBW1ehUWMo2;oP%&d=GBO&0 Z86u2~#$blVAb0wx^F~8pGz2IM0RSai8!P|- literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..d7258bc4af38d81a150b616f9e26f04cdaf72566 GIT binary patch literal 972 zcmeyz$jvFl5XQjBaE6(I;U^;x0~|0(GjK96u!8s;Fu|XU3=GZfj0^%W0S1BDDt|3b zNeRB};hmsuV*EWkn~8ye5vYuX!4aq#$Y5YK}E11~;Wc`C=IaUU6)&UCe T0|ovkV$DH}48W|LkeC1fuf!bU literal 0 HcmV?d00001 diff --git a/mysql-test/suite/vcol/r/vcol_sql_mode.result b/mysql-test/suite/vcol/r/vcol_sql_mode.result index 50aec76cb8d..11b3400ee5e 100644 --- a/mysql-test/suite/vcol/r/vcol_sql_mode.result +++ b/mysql-test/suite/vcol/r/vcol_sql_mode.result @@ -400,6 +400,12 @@ 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 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 +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))); 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/t/vcol_sql_mode.test b/mysql-test/suite/vcol/t/vcol_sql_mode.test index 5fb7ec8331d..e4cc6d21718 100644 --- a/mysql-test/suite/vcol/t/vcol_sql_mode.test +++ b/mysql-test/suite/vcol/t/vcol_sql_mode.test @@ -294,6 +294,9 @@ CREATE TABLE t1 ( --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; 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/field.cc b/sql/field.cc index e5359a7520e..30edee0e386 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1428,14 +1428,16 @@ void Field::load_data_set_value(const char *pos, uint length, } -void Field::error_generated_column_function_is_not_allowed(THD *thd) const +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(0), + 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(field_name)); } @@ -1446,7 +1448,7 @@ void Field::error_generated_column_function_is_not_allowed(THD *thd) const that it cannot handle. See sql_mode.h for details. */ -bool Field::check_vcol_sql_mode_dependency(THD *thd) const +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()) @@ -1456,9 +1458,10 @@ bool Field::check_vcol_sql_mode_dependency(THD *thd) const Sql_mode_dependency(~0, ~can_handle_sql_mode_dependency_on_store()); if (dep) { - error_generated_column_function_is_not_allowed(thd); + 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 true; + return error; } } return false; diff --git a/sql/field.h b/sql/field.h index 9333d1492fd..c82febd956e 100644 --- a/sql/field.h +++ b/sql/field.h @@ -697,7 +697,8 @@ protected: val_str(&result); return to->store(result.ptr(), result.length(), charset()); } - void error_generated_column_function_is_not_allowed(THD *thd) const; + 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); @@ -1175,7 +1176,7 @@ public: } bool stored_in_db() const { return !vcol_info || vcol_info->stored_in_db; } - bool check_vcol_sql_mode_dependency(THD *) const; + bool check_vcol_sql_mode_dependency(THD *, vcol_init_mode mode) const; virtual sql_mode_t value_depends_on_sql_mode() const { diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 3169efbefe6..78564f28c31 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2529,7 +2529,8 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) sizeof(MY_BITMAP)))) goto error; - if (parse_vcol_defs(client_thd, client_thd->mem_root, copy, &error_reported)) + if (parse_vcol_defs(client_thd, client_thd->mem_root, copy, &error_reported, + VCOL_INIT_DEPENDENCY_FAILURE_IS_WARNING)) goto error; } diff --git a/sql/table.cc b/sql/table.cc index 62449ebcc06..07858ab270a 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -989,7 +989,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; @@ -1073,7 +1073,7 @@ 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)) + if (vcol && field_ptr[0]->check_vcol_sql_mode_dependency(thd, mode)) { DBUG_ASSERT(thd->is_error()); *error_reported= true; @@ -3223,7 +3223,23 @@ 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; - if (parse_vcol_defs(thd, &outparam->mem_root, outparam, &error_reported)) + 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 (parse_vcol_defs(thd, &outparam->mem_root, outparam, + &error_reported, mode)) { error= OPEN_FRM_CORRUPTED; goto err; diff --git a/sql/table.h b/sql/table.h index 7786679982f..8f6a9e7aa86 100644 --- a/sql/table.h +++ b/sql/table.h @@ -325,6 +325,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, @@ -2736,7 +2750,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,