mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-18152 Assertion 'num_fts_index <= 1' failed
InnoDB does not allow creating multiple FULLTEXT INDEX in ALGORITHM=INPLACE. This constraint was not being properly enforced after MariaDB started to support ALGORITHM=INSTANT and instant ADD COLUMN. As a side effect of this bug, we again allow ALGORITHM=INPLACE to rebuild a table when one FULLTEXT INDEX survives. Also, we are returning a more accurate reason for refusing LOCK=NONE. innobase_fulltext_exist(): Return the number of fulltext indexes. ha_innobase::check_if_supported_inplace_alter(): If the table needs to be rebuilt, refuse the operation if multiple fulltext indexes would remain.
This commit is contained in:
@ -489,7 +489,9 @@ DROP TABLE t1;
|
||||
SET DEBUG_SYNC= 'alter_table_copy_after_lock_upgrade SIGNAL upgraded';
|
||||
#Setup a table with FULLTEXT index.
|
||||
connection default;
|
||||
CREATE TABLE t1(fld1 CHAR(10), FULLTEXT(fld1)) ENGINE= INNODB;
|
||||
CREATE TABLE t1(fld1 CHAR(10), FULLTEXT(fld1), FULLTEXT(fld1)) ENGINE= INNODB;
|
||||
Warnings:
|
||||
Note 1831 Duplicate index `fld1_2`. This is deprecated and will be disallowed in a future release
|
||||
INSERT INTO t1 VALUES("String1");
|
||||
#OPTIMIZE TABLE operation.
|
||||
OPTIMIZE TABLE t1;
|
||||
|
@ -650,7 +650,7 @@ SET DEBUG_SYNC= 'alter_table_copy_after_lock_upgrade SIGNAL upgraded';
|
||||
|
||||
--echo #Setup a table with FULLTEXT index.
|
||||
--connection default
|
||||
CREATE TABLE t1(fld1 CHAR(10), FULLTEXT(fld1)) ENGINE= INNODB;
|
||||
CREATE TABLE t1(fld1 CHAR(10), FULLTEXT(fld1), FULLTEXT(fld1)) ENGINE= INNODB;
|
||||
INSERT INTO t1 VALUES("String1");
|
||||
|
||||
--echo #OPTIMIZE TABLE operation.
|
||||
|
@ -439,15 +439,15 @@ tt CREATE TABLE `tt` (
|
||||
FULLTEXT KEY `ct` (`ct`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
ALTER TABLE tt ADD COLUMN c CHAR(1) NOT NULL FIRST, LOCK=NONE;
|
||||
ERROR 0A000: LOCK=NONE is not supported. Reason: InnoDB presently supports one FULLTEXT index creation at a time. Try LOCK=SHARED
|
||||
ERROR 0A000: LOCK=NONE is not supported. Reason: Fulltext index creation requires a lock. Try LOCK=SHARED
|
||||
ALTER TABLE tt ADD COLUMN c CHAR(1) NOT NULL, LOCK=NONE;
|
||||
ERROR 0A000: LOCK=NONE is not supported. Reason: InnoDB presently supports one FULLTEXT index creation at a time. Try LOCK=SHARED
|
||||
ERROR 0A000: LOCK=NONE is not supported. Reason: Fulltext index creation requires a lock. Try LOCK=SHARED
|
||||
CREATE TABLE tu (
|
||||
pk INT PRIMARY KEY, FTS_DOC_ID BIGINT UNSIGNED NOT NULL, t TEXT,
|
||||
FULLTEXT INDEX(t)
|
||||
) ENGINE=InnoDB;
|
||||
ALTER TABLE tu ADD COLUMN c CHAR(1) NOT NULL FIRST, LOCK=NONE;
|
||||
ERROR 0A000: LOCK=NONE is not supported. Reason: InnoDB presently supports one FULLTEXT index creation at a time. Try LOCK=SHARED
|
||||
ERROR 0A000: LOCK=NONE is not supported. Reason: Fulltext index creation requires a lock. Try LOCK=SHARED
|
||||
ALTER TABLE tu ADD COLUMN c CHAR(1) NOT NULL, LOCK=NONE;
|
||||
DROP TABLE tu;
|
||||
CREATE TABLE tv (
|
||||
@ -456,7 +456,7 @@ UNIQUE INDEX FTS_DOC_ID_INDEX(FTS_DOC_ID),
|
||||
FULLTEXT INDEX(t)
|
||||
) ENGINE=InnoDB;
|
||||
ALTER TABLE tv ADD COLUMN c CHAR(1) NOT NULL FIRST, LOCK=NONE;
|
||||
ERROR 0A000: LOCK=NONE is not supported. Reason: InnoDB presently supports one FULLTEXT index creation at a time. Try LOCK=SHARED
|
||||
ERROR 0A000: LOCK=NONE is not supported. Reason: Fulltext index creation requires a lock. Try LOCK=SHARED
|
||||
ALTER TABLE tv ADD COLUMN c CHAR(1) NOT NULL, LOCK=NONE;
|
||||
DROP TABLE tv;
|
||||
ALTER TABLE t1o CHANGE c1 dB_row_Id INT, ALGORITHM=COPY;
|
||||
@ -498,8 +498,6 @@ ADD COLUMN FTS_DOC_ID BIGINT UNSIGNED NOT NULL, 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 t1o ADD COLUMN FTS_DOC_ID BIGINT UNSIGNED NOT NULL,
|
||||
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 t1o ADD COLUMN FTS_DOC_ID BIGINT UNSIGNED NOT NULL;
|
||||
ALTER TABLE t1o DROP COLUMN FTS_DOC_ID, ALGORITHM=INPLACE;
|
||||
ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot drop or rename FTS_DOC_ID. Try ALGORITHM=COPY
|
||||
ALTER TABLE t1o DROP COLUMN FTS_DOC_ID;
|
||||
|
@ -272,13 +272,8 @@ ALTER TABLE t1o ADD FULLTEXT INDEX(cu),
|
||||
ADD COLUMN FTS_DOC_ID BIGINT UNSIGNED NOT NULL, ALGORITHM=INPLACE;
|
||||
|
||||
# Replace the hidden FTS_DOC_ID column with a user-visible one.
|
||||
# This used to work if there is at most one fulltext index.
|
||||
# Currently, we disallow native ALTER TABLE if the table
|
||||
# contains any FULLTEXT indexes.
|
||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||
ALTER TABLE t1o ADD COLUMN FTS_DOC_ID BIGINT UNSIGNED NOT NULL,
|
||||
ALGORITHM=INPLACE;
|
||||
ALTER TABLE t1o ADD COLUMN FTS_DOC_ID BIGINT UNSIGNED NOT NULL;
|
||||
# Replace the user-visible FTS_DOC_ID column with a hidden one.
|
||||
# We do not support this in-place.
|
||||
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
|
||||
|
@ -79,7 +79,7 @@ CREATE FULLTEXT INDEX idx on fts_test (title, body) LOCK=NONE;
|
||||
ERROR 0A000: LOCK=NONE is not supported. Reason: Fulltext index creation requires a lock. Try LOCK=SHARED
|
||||
ALTER TABLE fts_test ADD FULLTEXT `idx` (title, body), ALGORITHM=NOCOPY;
|
||||
ALTER TABLE fts_test ROW_FORMAT=REDUNDANT, LOCK=NONE;
|
||||
ERROR 0A000: LOCK=NONE is not supported. Reason: InnoDB presently supports one FULLTEXT index creation at a time. Try LOCK=SHARED
|
||||
ERROR 0A000: LOCK=NONE is not supported. Reason: Fulltext index creation requires a lock. Try LOCK=SHARED
|
||||
ALTER TABLE fts_test ROW_FORMAT=REDUNDANT;
|
||||
SELECT * FROM fts_test WHERE MATCH (title, body)
|
||||
AGAINST ('Tutorial' IN NATURAL LANGUAGE MODE);
|
||||
@ -228,3 +228,12 @@ DROP TABLE articles;
|
||||
CREATE TABLE t1 (a VARCHAR(3)) ENGINE=InnoDB;
|
||||
ALTER TABLE t1 ADD FULLTEXT KEY(a), ADD COLUMN b VARCHAR(3), ADD FULLTEXT KEY(b);
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# MDEV-18152 Assertion 'num_fts_index <= 1' failed
|
||||
# in prepare_inplace_alter_table_dict
|
||||
#
|
||||
CREATE TABLE t1
|
||||
(a VARCHAR(128), b VARCHAR(128), FULLTEXT INDEX(a), FULLTEXT INDEX(b))
|
||||
ENGINE=InnoDB;
|
||||
ALTER TABLE t1 ADD c SERIAL;
|
||||
DROP TABLE t1;
|
||||
|
@ -276,3 +276,13 @@ ALTER TABLE t1 ADD FULLTEXT KEY(a), ADD COLUMN b VARCHAR(3), ADD FULLTEXT KEY(b)
|
||||
|
||||
# Cleanup
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # MDEV-18152 Assertion 'num_fts_index <= 1' failed
|
||||
--echo # in prepare_inplace_alter_table_dict
|
||||
--echo #
|
||||
CREATE TABLE t1
|
||||
(a VARCHAR(128), b VARCHAR(128), FULLTEXT INDEX(a), FULLTEXT INDEX(b))
|
||||
ENGINE=InnoDB;
|
||||
ALTER TABLE t1 ADD c SERIAL;
|
||||
DROP TABLE t1;
|
||||
|
@ -453,20 +453,18 @@ my_error_innodb(
|
||||
|
||||
/** Determine if fulltext indexes exist in a given table.
|
||||
@param table MySQL table
|
||||
@return whether fulltext indexes exist on the table */
|
||||
static
|
||||
bool
|
||||
innobase_fulltext_exist(
|
||||
/*====================*/
|
||||
const TABLE* table)
|
||||
@return number of fulltext indexes */
|
||||
static uint innobase_fulltext_exist(const TABLE* table)
|
||||
{
|
||||
uint count = 0;
|
||||
|
||||
for (uint i = 0; i < table->s->keys; i++) {
|
||||
if (table->key_info[i].flags & HA_FULLTEXT) {
|
||||
return(true);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return(false);
|
||||
return count;
|
||||
}
|
||||
|
||||
/** Determine whether indexed virtual columns exist in a table.
|
||||
@ -925,11 +923,14 @@ ha_innobase::check_if_supported_inplace_alter(
|
||||
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
const char* reason_rebuild = NULL;
|
||||
|
||||
switch (ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE) {
|
||||
case ALTER_OPTIONS:
|
||||
if (alter_options_need_rebuild(ha_alter_info, table)) {
|
||||
ha_alter_info->unsupported_reason = my_get_err_msg(
|
||||
reason_rebuild = my_get_err_msg(
|
||||
ER_ALTER_OPERATION_TABLE_OPTIONS_NEED_REBUILD);
|
||||
ha_alter_info->unsupported_reason = reason_rebuild;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
@ -1056,8 +1057,9 @@ ha_innobase::check_if_supported_inplace_alter(
|
||||
}
|
||||
|
||||
/* We should be able to do the operation in-place.
|
||||
See if we can do it online (LOCK=NONE). */
|
||||
bool online = true;
|
||||
See if we can do it online (LOCK=NONE) or without rebuild. */
|
||||
bool online = true, need_rebuild = false;
|
||||
const uint fulltext_indexes = innobase_fulltext_exist(altered_table);
|
||||
|
||||
List_iterator_fast<Create_field> cf_it(
|
||||
ha_alter_info->alter_info->create_list);
|
||||
@ -1118,8 +1120,7 @@ ha_innobase::check_if_supported_inplace_alter(
|
||||
|
||||
/* We cannot replace a hidden FTS_DOC_ID
|
||||
with a user-visible FTS_DOC_ID. */
|
||||
if (m_prebuilt->table->fts
|
||||
&& innobase_fulltext_exist(altered_table)
|
||||
if (fulltext_indexes && m_prebuilt->table->fts
|
||||
&& !my_strcasecmp(
|
||||
system_charset_info,
|
||||
key_part->field->field_name.str,
|
||||
@ -1135,8 +1136,8 @@ ha_innobase::check_if_supported_inplace_alter(
|
||||
& AUTO_INCREMENT_FLAG));
|
||||
|
||||
if (key_part->field->flags & AUTO_INCREMENT_FLAG) {
|
||||
/* We cannot assign an AUTO_INCREMENT
|
||||
column values during online ALTER. */
|
||||
/* We cannot assign AUTO_INCREMENT values
|
||||
during online or instant ALTER. */
|
||||
DBUG_ASSERT(key_part->field == altered_table
|
||||
-> found_next_number_field);
|
||||
|
||||
@ -1146,6 +1147,7 @@ ha_innobase::check_if_supported_inplace_alter(
|
||||
}
|
||||
|
||||
online = false;
|
||||
need_rebuild = true;
|
||||
}
|
||||
|
||||
if (innobase_is_v_fld(key_part->field)) {
|
||||
@ -1178,7 +1180,7 @@ ha_innobase::check_if_supported_inplace_alter(
|
||||
|| (m_prebuilt->table->fts->doc_col
|
||||
< dict_table_get_n_user_cols(m_prebuilt->table)));
|
||||
|
||||
if (m_prebuilt->table->fts && innobase_fulltext_exist(altered_table)) {
|
||||
if (fulltext_indexes && m_prebuilt->table->fts) {
|
||||
/* FULLTEXT indexes are supposed to remain. */
|
||||
/* Disallow DROP INDEX FTS_DOC_ID_INDEX */
|
||||
|
||||
@ -1308,44 +1310,39 @@ next_column:
|
||||
}
|
||||
|
||||
bool fts_need_rebuild = false;
|
||||
const bool need_rebuild = innobase_need_rebuild(ha_alter_info, table);
|
||||
need_rebuild = need_rebuild
|
||||
|| innobase_need_rebuild(ha_alter_info, table);
|
||||
|
||||
if (!online) {
|
||||
/* We already determined that only a non-locking
|
||||
operation is possible. */
|
||||
} else if ((need_rebuild || (ha_alter_info->handler_flags
|
||||
& ALTER_ADD_PK_INDEX))
|
||||
&& (innobase_fulltext_exist(altered_table)
|
||||
|| innobase_spatial_exist(altered_table)
|
||||
|| innobase_indexed_virtual_exist(altered_table))) {
|
||||
/* Refuse to rebuild the table online, if
|
||||
FULLTEXT OR SPATIAL indexes are to survive the rebuild. */
|
||||
online = false;
|
||||
if (need_rebuild
|
||||
&& (fulltext_indexes
|
||||
|| innobase_spatial_exist(altered_table)
|
||||
|| innobase_indexed_virtual_exist(altered_table))) {
|
||||
/* If the table already contains fulltext indexes,
|
||||
refuse to rebuild the table natively altogether. */
|
||||
if (m_prebuilt->table->fts) {
|
||||
if (fulltext_indexes > 1) {
|
||||
cannot_create_many_fulltext_index:
|
||||
ha_alter_info->unsupported_reason =
|
||||
my_get_err_msg(ER_INNODB_FT_LIMIT);
|
||||
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
if (ha_alter_info->online
|
||||
&& !ha_alter_info->unsupported_reason) {
|
||||
|
||||
if (innobase_spatial_exist(altered_table)) {
|
||||
ha_alter_info->unsupported_reason = my_get_err_msg(
|
||||
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS);
|
||||
} else if (!innobase_fulltext_exist(altered_table)) {
|
||||
/* MDEV-14341 FIXME: Remove this limitation. */
|
||||
ha_alter_info->unsupported_reason =
|
||||
"online rebuild with indexed virtual columns";
|
||||
} else {
|
||||
ha_alter_info->unsupported_reason = my_get_err_msg(
|
||||
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS);
|
||||
}
|
||||
if (!online || !ha_alter_info->online
|
||||
|| ha_alter_info->unsupported_reason != reason_rebuild) {
|
||||
/* Either LOCK=NONE was not requested, or we already
|
||||
gave specific reason to refuse it. */
|
||||
} else if (fulltext_indexes) {
|
||||
ha_alter_info->unsupported_reason = my_get_err_msg(
|
||||
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FTS);
|
||||
} else if (innobase_spatial_exist(altered_table)) {
|
||||
ha_alter_info->unsupported_reason = my_get_err_msg(
|
||||
ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_GIS);
|
||||
} else {
|
||||
/* MDEV-14341 FIXME: Remove this limitation. */
|
||||
ha_alter_info->unsupported_reason =
|
||||
"online rebuild with indexed virtual columns";
|
||||
}
|
||||
|
||||
online = false;
|
||||
}
|
||||
|
||||
if (ha_alter_info->handler_flags
|
||||
|
Reference in New Issue
Block a user