diff --git a/mysql-test/suite/innodb_fts/r/alter_parser.result b/mysql-test/suite/innodb_fts/r/alter_parser.result new file mode 100644 index 0000000000000..7cf8314731e99 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/alter_parser.result @@ -0,0 +1,50 @@ +# +# MDEV-41758 ALTER TABLE ignores a changed fulltext parser of an index +# +INSTALL PLUGIN simple_parser SONAME 'mypluglib'; +# Adding a parser. The index is built with it: simple_parser keeps +# 'abc-def' as one word, so 'abc' does not match. +CREATE TABLE t (id INT PRIMARY KEY, c TEXT, FULLTEXT ft(c)) ENGINE=InnoDB; +INSERT INTO t VALUES (1, 'abc-def'); +ALTER TABLE t DROP INDEX ft, ADD FULLTEXT ft(c) WITH PARSER simple_parser; +SHOW CREATE TABLE t; +Table Create Table +t CREATE TABLE `t` ( + `id` int(11) NOT NULL, + `c` text DEFAULT NULL, + PRIMARY KEY (`id`), + FULLTEXT KEY `ft` (`c`) WITH PARSER `simple_parser` +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +SELECT id FROM t WHERE MATCH(c) AGAINST('abc'); +id +DROP TABLE t; +# Removing it, which cannot be done instantly +CREATE TABLE t (id INT PRIMARY KEY, c TEXT, +FULLTEXT ft(c) WITH PARSER simple_parser) ENGINE=InnoDB; +ALTER TABLE t DROP INDEX ft, ADD FULLTEXT ft(c), ALGORITHM=INSTANT; +ERROR 0A000: ALGORITHM=INSTANT is not supported. Reason: ADD INDEX. Try ALGORITHM=NOCOPY +ALTER TABLE t DROP INDEX ft, ADD FULLTEXT ft(c); +SHOW CREATE TABLE t; +Table Create Table +t CREATE TABLE `t` ( + `id` int(11) NOT NULL, + `c` text DEFAULT NULL, + PRIMARY KEY (`id`), + FULLTEXT KEY `ft` (`c`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_uca1400_ai_ci +DROP TABLE t; +# Adding it under another name: the index is rebuilt, not just renamed, +# so 'abc' does not match. +CREATE TABLE t (id INT PRIMARY KEY, c TEXT, FULLTEXT ft(c)) ENGINE=InnoDB; +INSERT INTO t VALUES (1, 'abc-def'); +ALTER TABLE t DROP INDEX ft, ADD FULLTEXT ft2(c) WITH PARSER simple_parser; +SELECT id FROM t WHERE MATCH(c) AGAINST('abc'); +id +DROP TABLE t; +# The same parser, in any letter case, is no change +CREATE TABLE t (id INT PRIMARY KEY, c TEXT, +FULLTEXT ft(c) WITH PARSER simple_parser) ENGINE=InnoDB; +ALTER TABLE t DROP INDEX ft, +ADD FULLTEXT ft(c) WITH PARSER SIMPLE_PARSER, ALGORITHM=INSTANT; +DROP TABLE t; +UNINSTALL PLUGIN simple_parser; diff --git a/mysql-test/suite/innodb_fts/t/alter_parser.test b/mysql-test/suite/innodb_fts/t/alter_parser.test new file mode 100644 index 0000000000000..f5cc2b277b536 --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/alter_parser.test @@ -0,0 +1,43 @@ +--source include/have_innodb.inc +--source include/have_simple_parser.inc + +--echo # +--echo # MDEV-41758 ALTER TABLE ignores a changed fulltext parser of an index +--echo # + +INSTALL PLUGIN simple_parser SONAME 'mypluglib'; + +--echo # Adding a parser. The index is built with it: simple_parser keeps +--echo # 'abc-def' as one word, so 'abc' does not match. +CREATE TABLE t (id INT PRIMARY KEY, c TEXT, FULLTEXT ft(c)) ENGINE=InnoDB; +INSERT INTO t VALUES (1, 'abc-def'); +ALTER TABLE t DROP INDEX ft, ADD FULLTEXT ft(c) WITH PARSER simple_parser; +SHOW CREATE TABLE t; +SELECT id FROM t WHERE MATCH(c) AGAINST('abc'); +DROP TABLE t; + +--echo # Removing it, which cannot be done instantly +CREATE TABLE t (id INT PRIMARY KEY, c TEXT, + FULLTEXT ft(c) WITH PARSER simple_parser) ENGINE=InnoDB; +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE t DROP INDEX ft, ADD FULLTEXT ft(c), ALGORITHM=INSTANT; +ALTER TABLE t DROP INDEX ft, ADD FULLTEXT ft(c); +SHOW CREATE TABLE t; +DROP TABLE t; + +--echo # Adding it under another name: the index is rebuilt, not just renamed, +--echo # so 'abc' does not match. +CREATE TABLE t (id INT PRIMARY KEY, c TEXT, FULLTEXT ft(c)) ENGINE=InnoDB; +INSERT INTO t VALUES (1, 'abc-def'); +ALTER TABLE t DROP INDEX ft, ADD FULLTEXT ft2(c) WITH PARSER simple_parser; +SELECT id FROM t WHERE MATCH(c) AGAINST('abc'); +DROP TABLE t; + +--echo # The same parser, in any letter case, is no change +CREATE TABLE t (id INT PRIMARY KEY, c TEXT, + FULLTEXT ft(c) WITH PARSER simple_parser) ENGINE=InnoDB; +ALTER TABLE t DROP INDEX ft, + ADD FULLTEXT ft(c) WITH PARSER SIMPLE_PARSER, ALGORITHM=INSTANT; +DROP TABLE t; + +UNINSTALL PLUGIN simple_parser; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index cf987c052702f..fcff6b29f7b88 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6972,6 +6972,13 @@ Compare_keys compare_keys_but_name(const KEY *table_key, const KEY *new_key, (new_key->flags & HA_KEYFLAG_MASK)) return Compare_keys::NotEqual; + /* A fulltext parser added, removed or replaced */ + if (((table_key->flags ^ new_key->flags) & HA_USES_PARSER) || + ((table_key->flags & HA_USES_PARSER) && + !Lex_ident_plugin(*plugin_name(table_key->parser)).streq( + *new_key->parser_name))) + return Compare_keys::NotEqual; + if (table_key->user_defined_key_parts != new_key->user_defined_key_parts) return Compare_keys::NotEqual;