Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions mysql-test/suite/innodb_fts/r/alter_parser.result
Original file line number Diff line number Diff line change
@@ -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;
43 changes: 43 additions & 0 deletions mysql-test/suite/innodb_fts/t/alter_parser.test
Original file line number Diff line number Diff line change
@@ -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);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional, stylistic, nit: FWIW, these complex tests where one test depends on the result of the other are very hard to maintain and develop further.
I'd keep the individual tests completely separate. E.g. I'd drop the table after the above test and re-recreate it for this one.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done – each case has its own table now.

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;
7 changes: 7 additions & 0 deletions sql/sql_table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down