diff --git a/mysql-test/main/innodb_mysql_sync.result b/mysql-test/main/innodb_mysql_sync.result index a8a264d6580..3f284edde86 100644 --- a/mysql-test/main/innodb_mysql_sync.result +++ b/mysql-test/main/innodb_mysql_sync.result @@ -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; diff --git a/mysql-test/main/innodb_mysql_sync.test b/mysql-test/main/innodb_mysql_sync.test index 66935f811d7..4026080c4b4 100644 --- a/mysql-test/main/innodb_mysql_sync.test +++ b/mysql-test/main/innodb_mysql_sync.test @@ -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. diff --git a/mysql-test/suite/innodb/r/innodb-alter.result b/mysql-test/suite/innodb/r/innodb-alter.result index 528cd07770b..c596dbb497d 100644 --- a/mysql-test/suite/innodb/r/innodb-alter.result +++ b/mysql-test/suite/innodb/r/innodb-alter.result @@ -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; diff --git a/mysql-test/suite/innodb/t/innodb-alter.test b/mysql-test/suite/innodb/t/innodb-alter.test index 28ff110fc01..14f90dec43c 100644 --- a/mysql-test/suite/innodb/t/innodb-alter.test +++ b/mysql-test/suite/innodb/t/innodb-alter.test @@ -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 diff --git a/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result b/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result index 6ee5f9f4322..1382457debf 100644 --- a/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result +++ b/mysql-test/suite/innodb_fts/r/innodb-fts-ddl.result @@ -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; diff --git a/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test b/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test index ddd92556772..c81ec18a4e6 100644 --- a/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test +++ b/mysql-test/suite/innodb_fts/t/innodb-fts-ddl.test @@ -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; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index a1ec47d17dc..7bea19bc4ad 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -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 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