Skip to content

MDEV-41758 ALTER TABLE ignores a changed fulltext parser of an index - #5978

Open
futureweb wants to merge 1 commit into
MariaDB:11.8from
futureweb:MDEV-41758-alter-parser
Open

futureweb wants to merge 1 commit into
MariaDB:11.8from
futureweb:MDEV-41758-alter-parser

Conversation

@futureweb

@futureweb futureweb commented Oct 24, 2026 •

Copy link
Copy Markdown
  • The Jira issue number for this PR is: MDEV-41758

Description

compare_keys_but_name() does not look at the fulltext parser. Before 062f8eb ("cleanup: key algorithm vs key flags") this did not matter: a FULLTEXT index added by ALTER TABLE had the key algorithm HA_KEY_ALG_UNDEF and the existing one HA_KEY_ALG_FULLTEXT, so they never compared equal, and the index was always rebuilt. Since then both have HA_KEY_ALG_FULLTEXT. So an in-place ALTER TABLE t DROP INDEX ft, ADD FULLTEXT ft(c) WITH PARSER p did nothing, even with ALGORITHM=INSTANT, and with another index name it only renamed the index, whose rows stayed tokenized by the old parser. Removing or replacing the parser was ignored as well. ALGORITHM=COPY and MyISAM are not affected.

Before (InnoDB):

CREATE TABLE t (id INT PRIMARY KEY, c TEXT, FULLTEXT ft(c)) ENGINE=InnoDB;
INSERT INTO t VALUES (1, 'abc-def'), (2, 'xyz');
ALTER TABLE t DROP INDEX ft, ADD FULLTEXT ft(c) WITH PARSER simple_parser;
SHOW CREATE TABLE t;                             -- FULLTEXT KEY `ft` (`c`)
SELECT id FROM t WHERE MATCH(c) AGAINST('abc');  -- 1

After: SHOW CREATE TABLE shows FULLTEXT KEY `ft` (`c`) WITH PARSER `simple_parser`, and the SELECT returns no rows, because simple_parser keeps 'abc-def' as one word.

Fix: an index whose parser is added, removed or replaced is not equal. Parser names are compared case-insensitively, like plugin names, so WITH PARSER SIMPLE_PARSER on an index that has simple_parser is still a no-op.

Notes for reviewers: MySQL has the same problem (Bug #110976). The test cannot replace one plugin parser with another, because only simple_parser is available.

This matters for MDEV-10267 (ngram parser): users who move to the ngram parser may change an existing index this way.

Release Notes

ALTER TABLE ... DROP INDEX, ADD FULLTEXT ... WITH PARSER on an InnoDB table now rebuilds the fulltext index when its parser is added, removed or replaced, instead of silently keeping the old parser.

How can this PR be tested?

New test innodb_fts.alter_parser (uses the simple_parser plugin from mypluglib, skipped if it is not built), four separate cases: adding the parser (SHOW CREATE TABLE, and one search showing that 'abc' no longer matches), removing it (refused with ALGORITHM=INSTANT, then done without it), adding it under another index name (the same search: the index must be rebuilt, not just renamed), and the same parser in upper case with ALGORITHM=INSTANT as a no-op. Without the fix, SHOW CREATE TABLE keeps the old index definition in the first case, MATCH(c) AGAINST('abc') still finds row 1 in the first and third, and ALGORITHM=INSTANT is accepted in the second.

The innodb_fts suite and the main alter tests pass on 11.8 (debug build). On main with all our fixes and the ngram parser of MDEV-10267, the innodb_fts, maria and plugins suites and the main fulltext, plugin and alter tests pass.

Basing the PR against the correct MariaDB version

  • This is a new feature and the PR is based against the latest MariaDB development branch.
  • This is a bug fix and the PR is based against the earliest maintained branch in which the bug can be reproduced. (062f8eb was first released in 11.7.1; 11.4 is not affected.)

PR quality check

  • I checked the CODING_STANDARDS.md file and my PR conforms to this where appropriate.
  • For any trivial modifications to the PR, I am ok with the reviewer making the changes themselves.

🤖 Generated with Claude Code

@futureweb
futureweb marked this pull request as ready for review October 24, 2026 18:59
@gkodinov gkodinov added the External Contribution All PRs from entities outside of MariaDB Foundation, Corporation, Codership agreements. label Oct 26, 2026
@gkodinov gkodinov self-assigned this Oct 26, 2026

@gkodinov gkodinov left a comment

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.

Thank you for your contribution! This is a preliminary review.

The change itself LGTM. I have a few improvement suggestions for the tests though.
As a rule of thumb: we try to keep them as short as possible (by testing only the relevant bits and nothing but) and as isolated from each other as possible.

Please address these before the final review starts.


INSTALL PLUGIN simple_parser SONAME 'mypluglib';

# The built-in parser splits 'abc-def' into two words, simple_parser does not.

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.

Is this something you're altering? I believe it's already been tested someplace else. If you need to test for the parser, I'd do SHOW CREATE TABLE.

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.

You're right – the search before the ALTER only showed what the built-in parser does; it's gone, and the first two cases check the definition with SHOW CREATE TABLE. The case with another index name needs a search, though: without the fix, the index was only renamed, so SHOW CREATE TABLE already showed the new parser while the rows kept the old words. That case and the first one check that 'abc' no longer matches.

SELECT id FROM t WHERE MATCH(c) AGAINST('abc');
SELECT id FROM t WHERE MATCH(c) AGAINST('abc-def');

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.

SELECT id FROM t WHERE MATCH(c) AGAINST('abc');
SELECT id FROM t WHERE MATCH(c) AGAINST('abc-def');

# Instant ADD COLUMN is not supported on tables with FULLTEXT indexes.

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.

is this testing a behavior you're altering? I find it a bit redundant.

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.

Removed – the case with the unchanged parser and ALGORITHM=INSTANT already covers that.

@gkodinov gkodinov assigned sanja-byelkin and unassigned gkodinov Oct 26, 2026
@futureweb
futureweb force-pushed the MDEV-41758-alter-parser branch from 71c0953 to 23c76e4 Compare October 26, 2026 17:30
compare_keys_but_name() does not look at the fulltext parser. Before
062f8eb ("cleanup: key algorithm vs key flags") this did not
matter: a FULLTEXT index added by ALTER TABLE had the key algorithm
HA_KEY_ALG_UNDEF and the existing one HA_KEY_ALG_FULLTEXT, so the two
never compared equal, and the index was always rebuilt. Since then
both have HA_KEY_ALG_FULLTEXT. So an in-place
ALTER TABLE t DROP INDEX ft, ADD FULLTEXT ft(c) WITH PARSER p did
nothing, and with another index name it only renamed the index, whose
rows stayed tokenized by the old parser. Removing or replacing the
parser was ignored as well.

An index whose parser is added, removed or replaced is not equal. Parser
names are compared case-insensitively, like plugin names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@futureweb
futureweb force-pushed the MDEV-41758-alter-parser branch from 23c76e4 to d35bab2 Compare October 26, 2026 17:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

External Contribution All PRs from entities outside of MariaDB Foundation, Corporation, Codership agreements.

Development

Successfully merging this pull request may close these issues.

3 participants