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 ...@@ -162,11 +162,15 @@ INSERT INTO articles (FTS_DOC_ID, title, body) VALUES
(14,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), (14,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
(19, 'MySQL vs. YourSQL','In the following database comparison ...'), (19, 'MySQL vs. YourSQL','In the following database comparison ...'),
(20, 'MySQL Security','When configured properly, MySQL ...'); (20, 'MySQL Security','When configured properly, MySQL ...');
ALTER TABLE articles ADD FULLTEXT INDEX idx3 (title), ALTER TABLE articles ADD FULLTEXT INDEX idx (title),
ADD FULLTEXT INDEX idx5 (title); ADD FULLTEXT INDEX idx3 (title), ALGORITHM=INPLACE;
ERROR HY000: InnoDB presently supports one FULLTEXT index creation at a time ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: InnoDB presently supports one FULLTEXT index creation at a time. Try ALGORITHM=COPY
CREATE FULLTEXT INDEX idx on articles (title); ALTER TABLE articles ADD FULLTEXT INDEX idx (title),
ALTER TABLE articles ADD FULLTEXT INDEX idx3 (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 ADD INDEX t20 (title(20)), LOCK=NONE;
ALTER TABLE articles DROP INDEX t20; ALTER TABLE articles DROP INDEX t20;
INSERT INTO articles (FTS_DOC_ID, title, body) VALUES INSERT INTO articles (FTS_DOC_ID, title, body) VALUES
......
...@@ -195,12 +195,13 @@ 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 ...'), (19, 'MySQL vs. YourSQL','In the following database comparison ...'),
(20, 'MySQL Security','When configured properly, MySQL ...'); (20, 'MySQL Security','When configured properly, MySQL ...');
--error ER_INNODB_FT_LIMIT --error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
ALTER TABLE articles ADD FULLTEXT INDEX idx3 (title), ALTER TABLE articles ADD FULLTEXT INDEX idx (title),
ADD FULLTEXT INDEX idx5 (title); ADD FULLTEXT INDEX idx3 (title), ALGORITHM=INPLACE;
--enable_info
CREATE FULLTEXT INDEX idx on articles (title); ALTER TABLE articles ADD FULLTEXT INDEX idx (title),
ALTER TABLE articles ADD FULLTEXT INDEX idx3 (title); ADD FULLTEXT INDEX idx3 (title);
--disable_info
ALTER TABLE articles ADD INDEX t20 (title(20)), LOCK=NONE; ALTER TABLE articles ADD INDEX t20 (title(20)), LOCK=NONE;
ALTER TABLE articles DROP INDEX t20; ALTER TABLE articles DROP INDEX t20;
......
...@@ -1162,6 +1162,7 @@ ha_innobase::check_if_supported_inplace_alter( ...@@ -1162,6 +1162,7 @@ ha_innobase::check_if_supported_inplace_alter(
/* If the table already contains fulltext indexes, /* If the table already contains fulltext indexes,
refuse to rebuild the table natively altogether. */ refuse to rebuild the table natively altogether. */
if (m_prebuilt->table->fts) { if (m_prebuilt->table->fts) {
cannot_create_many_fulltext_index:
ha_alter_info->unsupported_reason = innobase_get_err_msg( ha_alter_info->unsupported_reason = innobase_get_err_msg(
ER_INNODB_FT_LIMIT); ER_INNODB_FT_LIMIT);
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED); DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
...@@ -1191,6 +1192,7 @@ ha_innobase::check_if_supported_inplace_alter( ...@@ -1191,6 +1192,7 @@ ha_innobase::check_if_supported_inplace_alter(
We could also do ADD SPATIAL INDEX by implementing We could also do ADD SPATIAL INDEX by implementing
row_log_apply() for it. */ row_log_apply() for it. */
bool add_fulltext = false;
for (uint i = 0; i < ha_alter_info->index_add_count; i++) { for (uint i = 0; i < ha_alter_info->index_add_count; i++) {
const KEY* key = const KEY* key =
...@@ -1202,16 +1204,18 @@ ha_innobase::check_if_supported_inplace_alter( ...@@ -1202,16 +1204,18 @@ ha_innobase::check_if_supported_inplace_alter(
| HA_PACK_KEY | HA_PACK_KEY
| HA_GENERATED_KEY | HA_GENERATED_KEY
| HA_BINARY_PACK_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( ha_alter_info->unsupported_reason = innobase_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS); ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS);
online = false; online = false;
break;
} }
if (key->flags & HA_SPATIAL) { if (online && (key->flags & HA_SPATIAL)) {
ha_alter_info->unsupported_reason = innobase_get_err_msg( ha_alter_info->unsupported_reason = innobase_get_err_msg(
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS); ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS);
online = false; online = false;
break;
} }
} }
} }
...@@ -5291,35 +5295,18 @@ prepare_inplace_alter_table_dict( ...@@ -5291,35 +5295,18 @@ prepare_inplace_alter_table_dict(
ctx->prepare_instant(); 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()) { if (ctx->need_rebuild()) {
not_instant_add_column: 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; uint32_t key_id = FIL_DEFAULT_ENCRYPTION_KEY;
fil_encryption_t mode = FIL_ENCRYPTION_DEFAULT; fil_encryption_t mode = FIL_ENCRYPTION_DEFAULT;
...@@ -5419,7 +5406,7 @@ prepare_inplace_alter_table_dict( ...@@ -5419,7 +5406,7 @@ prepare_inplace_alter_table_dict(
ut_ad(index->trx_id == ctx->trx->id); ut_ad(index->trx_id == ctx->trx->id);
if (index->type & DICT_FTS) { if (index->type & DICT_FTS) {
DBUG_ASSERT(num_fts_index); DBUG_ASSERT(num_fts_index == 1);
DBUG_ASSERT(!fts_index); DBUG_ASSERT(!fts_index);
DBUG_ASSERT(index->type == DICT_FTS); DBUG_ASSERT(index->type == DICT_FTS);
fts_index = ctx->add_index[a]; fts_index = ctx->add_index[a];
...@@ -5504,7 +5491,7 @@ prepare_inplace_alter_table_dict( ...@@ -5504,7 +5491,7 @@ prepare_inplace_alter_table_dict(
/* If ADD INDEX with LOCK=NONE has been /* If ADD INDEX with LOCK=NONE has been
requested, allocate a modification log. */ requested, allocate a modification log. */
if (index->type & DICT_FTS) { if (index->type & DICT_FTS) {
DBUG_ASSERT(num_fts_index); DBUG_ASSERT(num_fts_index == 1);
DBUG_ASSERT(!fts_index); DBUG_ASSERT(!fts_index);
DBUG_ASSERT(index->type == DICT_FTS); DBUG_ASSERT(index->type == DICT_FTS);
fts_index = ctx->add_index[a]; 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