Commit 3d798be1 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-14655 Assertion `!fts_index' failed in prepare_inplace_alter_table_dict

MariaDB inherits the MySQL limitation that ALGORITHM=INPLACE cannot
create more than one FULLTEXT INDEX at a time. As part of the MDEV-11369
Instant ADD COLUMN refactoring, MariaDB 10.3.2 accidentally stopped
enforcing the restriction.

Actually, it is a bug in MySQL 5.6 and MariaDB 10.0 that an ALTER TABLE
statement with multiple ADD FULLTEXT INDEX but without explicit
ALGORITHM=INPLACE would return in an error message, rather than
executing the operation with ALGORITHM=COPY.

ha_innobase::check_if_supported_inplace_alter(): Enforce the restriction
on multiple FULLTEXT INDEX.

prepare_inplace_alter_table_dict(): Replace some code with debug
assertions. A "goto error_handled" at this point would result in
another error, because the reference count of ctx->new_table would be 0.
parent 2750a020
......@@ -162,11 +162,15 @@ INSERT INTO articles (FTS_DOC_ID, title, body) VALUES
(14,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
(19, 'MySQL vs. YourSQL','In the following database comparison ...'),
(20, 'MySQL Security','When configured properly, MySQL ...');
ALTER TABLE articles ADD FULLTEXT INDEX idx3 (title),
ADD FULLTEXT INDEX idx5 (title);
ERROR HY000: InnoDB presently supports one FULLTEXT index creation at a time
CREATE FULLTEXT INDEX idx on articles (title);
ALTER TABLE articles ADD FULLTEXT INDEX idx3 (title);
ALTER TABLE articles ADD FULLTEXT INDEX idx (title),
ADD FULLTEXT INDEX idx3 (title), ALGORITHM=INPLACE;
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: InnoDB presently supports one FULLTEXT index creation at a time. Try ALGORITHM=COPY
ALTER TABLE articles ADD FULLTEXT INDEX idx (title),
ADD FULLTEXT INDEX idx3 (title);
affected rows: 6
info: Records: 6 Duplicates: 0 Warnings: 1
Warnings:
Note 1831 Duplicate index `idx3`. This is deprecated and will be disallowed in a future release
ALTER TABLE articles ADD INDEX t20 (title(20)), LOCK=NONE;
ALTER TABLE articles DROP INDEX t20;
INSERT INTO articles (FTS_DOC_ID, title, body) VALUES
......
......@@ -195,12 +195,13 @@ INSERT INTO articles (FTS_DOC_ID, title, body) VALUES
(19, 'MySQL vs. YourSQL','In the following database comparison ...'),
(20, 'MySQL Security','When configured properly, MySQL ...');
--error ER_INNODB_FT_LIMIT
ALTER TABLE articles ADD FULLTEXT INDEX idx3 (title),
ADD FULLTEXT INDEX idx5 (title);
CREATE FULLTEXT INDEX idx on articles (title);
ALTER TABLE articles ADD FULLTEXT INDEX idx3 (title);
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
ALTER TABLE articles ADD FULLTEXT INDEX idx (title),
ADD FULLTEXT INDEX idx3 (title), ALGORITHM=INPLACE;
--enable_info
ALTER TABLE articles ADD FULLTEXT INDEX idx (title),
ADD FULLTEXT INDEX idx3 (title);
--disable_info
ALTER TABLE articles ADD INDEX t20 (title(20)), LOCK=NONE;
ALTER TABLE articles DROP INDEX t20;
......
......@@ -1162,6 +1162,7 @@ ha_innobase::check_if_supported_inplace_alter(
/* If the table already contains fulltext indexes,
refuse to rebuild the table natively altogether. */
if (m_prebuilt->table->fts) {
cannot_create_many_fulltext_index:
ha_alter_info->unsupported_reason = innobase_get_err_msg(
ER_INNODB_FT_LIMIT);
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
......@@ -1191,6 +1192,7 @@ ha_innobase::check_if_supported_inplace_alter(
We could also do ADD SPATIAL INDEX by implementing
row_log_apply() for it. */
bool add_fulltext = false;
for (uint i = 0; i < ha_alter_info->index_add_count; i++) {
const KEY* key =
......@@ -1202,16 +1204,18 @@ ha_innobase::check_if_supported_inplace_alter(
| HA_PACK_KEY
| HA_GENERATED_KEY
| HA_BINARY_PACK_KEY)));
if (add_fulltext) {
goto cannot_create_many_fulltext_index;
}
add_fulltext = true;
ha_alter_info->unsupported_reason = innobase_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS);
online = false;
break;
}
if (key->flags & HA_SPATIAL) {
if (online && (key->flags & HA_SPATIAL)) {
ha_alter_info->unsupported_reason = innobase_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS);
online = false;
break;
}
}
}
......@@ -5291,35 +5295,18 @@ prepare_inplace_alter_table_dict(
ctx->prepare_instant();
}
if (!ctx->is_instant()) {
if (num_fts_index > 1) {
my_error(ER_INNODB_FT_LIMIT, MYF(0));
goto error_handled;
}
if (!ctx->online) {
/* This is not an online operation (LOCK=NONE). */
} else if (ctx->add_autoinc == ULINT_UNDEFINED
&& num_fts_index == 0
&& (!innobase_need_rebuild(ha_alter_info, old_table)
|| !innobase_fulltext_exist(altered_table))) {
/* InnoDB can perform an online operation
(LOCK=NONE). */
} else {
size_t query_length;
/* This should have been blocked in
check_if_supported_inplace_alter(). */
ut_ad(0);
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
innobase_get_stmt_unsafe(
ctx->prebuilt->trx->mysql_thd,
&query_length));
goto error_handled;
}
}
if (ctx->need_rebuild()) {
not_instant_add_column:
DBUG_ASSERT(ctx->need_rebuild());
DBUG_ASSERT(!ctx->is_instant());
DBUG_ASSERT(num_fts_index <= 1);
DBUG_ASSERT(!ctx->online || num_fts_index == 0);
DBUG_ASSERT(!ctx->online
|| ctx->add_autoinc == ULINT_UNDEFINED);
DBUG_ASSERT(!ctx->online
|| !innobase_need_rebuild(ha_alter_info, old_table)
|| !innobase_fulltext_exist(altered_table));
uint32_t key_id = FIL_DEFAULT_ENCRYPTION_KEY;
fil_encryption_t mode = FIL_ENCRYPTION_DEFAULT;
......@@ -5419,7 +5406,7 @@ prepare_inplace_alter_table_dict(
ut_ad(index->trx_id == ctx->trx->id);
if (index->type & DICT_FTS) {
DBUG_ASSERT(num_fts_index);
DBUG_ASSERT(num_fts_index == 1);
DBUG_ASSERT(!fts_index);
DBUG_ASSERT(index->type == DICT_FTS);
fts_index = ctx->add_index[a];
......@@ -5504,7 +5491,7 @@ prepare_inplace_alter_table_dict(
/* If ADD INDEX with LOCK=NONE has been
requested, allocate a modification log. */
if (index->type & DICT_FTS) {
DBUG_ASSERT(num_fts_index);
DBUG_ASSERT(num_fts_index == 1);
DBUG_ASSERT(!fts_index);
DBUG_ASSERT(index->type == DICT_FTS);
fts_index = ctx->add_index[a];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment