List:Commits« Previous MessageNext Message »
From:marko.makela Date:April 17 2012 8:06pm
Subject:bzr push into mysql-trunk-wl5545 branch (marko.makela:3894 to 3895)
Bug#13972248
View as plain text  
 3895 Marko Mäkelä	2012-04-17
      Bug#13972248 ORPHAN HIDDEN FTS_DOC_ID_INDEX LEFT AFTER DROPPING FULLTEXT INDEX
      
      ha_innobase::prepare_inplace_alter_table(): When the table would
      contain fulltext indexes before dropping indexes, and no fulltext
      indexes thereafter, drop the FTS_DOC_ID_INDEX if it does not exist
      in the MySQL table definition (it had been created internally in InnoDB).

    modified:
      mysql-test/suite/innodb/r/innodb-alter.result
      mysql-test/suite/innodb/t/innodb-alter.test
      storage/innobase/handler/handler0alter.cc
 3894 Marko Mäkelä	2012-04-17
      recv_recovery_from_checkpoint_start_func(): Remove a compiler warning.

    modified:
      storage/innobase/log/log0recv.cc
=== modified file 'mysql-test/suite/innodb/r/innodb-alter.result'
--- a/mysql-test/suite/innodb/r/innodb-alter.result	revid:marko.makela@stripped4xyu89kks7krh21
+++ b/mysql-test/suite/innodb/r/innodb-alter.result	revid:marko.makela@strippedy8df7zgqt1xb3oc
@@ -520,7 +520,6 @@ t1o	CREATE TABLE `t1o` (
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
 ALTER TABLE t1o CHANGE FTS_DOC_ID foo_id BIGINT UNSIGNED NOT NULL,
 DROP INDEX ct, ALGORITHM=INPLACE;
-call mtr.add_suppression("InnoDB: Table test/t1o contains 2 indexes inside InnoDB, which is different from the number of indexes 1 defined in the MySQL");
 SHOW CREATE TABLE t1o;
 Table	Create Table
 t1o	CREATE TABLE `t1o` (
@@ -547,20 +546,38 @@ SELECT si.NAME,i.POS,i.NAME FROM INFORMA
 INNER JOIN sys_indexes si ON i.INDEX_ID=si.INDEX_ID;
 NAME	POS	NAME
 PRIMARY	0	foo_id
-FTS_DOC_ID_INDEX	0	foo_id
 SELECT i.* FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS i
 INNER JOIN sys_foreign sf ON i.ID = sf.ID;
 ID	FOR_COL_NAME	REF_COL_NAME	POS
-ALTER TABLE t1o ADD FULLTEXT INDEX(ct);
-ERROR HY000: Index 'FTS_DOC_ID_INDEX' is of wrong type for an InnoDB FULLTEXT index
-ALTER TABLE t1o ADD FULLTEXT INDEX(ct),
+ALTER TABLE t1o ADD UNIQUE INDEX FTS_DOC_ID_INDEX(FTS_DOC_ID),
+ADD FULLTEXT INDEX(ct),
 CHANGE foo_id FTS_DOC_ID BIGINT UNSIGNED NOT NULL;
 ERROR HY000: Index 'FTS_DOC_ID_INDEX' is of wrong type for an InnoDB FULLTEXT index
+ALTER TABLE t1o ADD UNIQUE INDEX FTS_DOC_ID_INDEX(foo_id);
+ALTER TABLE t1o CHANGE foo_id FTS_DOC_ID BIGINT UNSIGNED NOT NULL,
+ADD FULLTEXT INDEX(ct);
+ERROR HY000: Index 'FTS_DOC_ID_INDEX' is of wrong type for an InnoDB FULLTEXT index
 ALTER TABLE t1o CHANGE foo_id FTS_DOC_ID BIGINT UNSIGNED NOT NULL;
-ALTER TABLE t1o ADD UNIQUE INDEX FTS_DOC_ID_INDEX(FTS_DOC_ID);
-ERROR 42000: Incorrect index name 'FTS_DOC_ID_INDEX'
-ALTER TABLE t1o ADD UNIQUE INDEX FTS_DOC_ID_INDEX(FTS_DOC_ID),
-ALGORITHM=COPY;
-ALTER TABLE t1o ADD UNIQUE INDEX FTS_DOC_ID_INDEX(FTS_DOC_ID);
-ERROR 42000: Duplicate key name 'FTS_DOC_ID_INDEX'
+CREATE FULLTEXT INDEX ct ON t1o (ct);
+ALTER TABLE t1o CHANGE FTS_DOC_ID foo_id BIGINT UNSIGNED NOT NULL;
+ERROR HY000: Column 'foo_id' is of wrong type for an InnoDB FULLTEXT index
+DROP TABLE sys_indexes;
+CREATE TABLE sys_indexes SELECT i.* FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES i
+INNER JOIN sys_tables st ON i.TABLE_ID=st.TABLE_ID;
+SELECT i.NAME,i.POS,i.MTYPE,i.PRTYPE,i.LEN
+FROM INFORMATION_SCHEMA.INNODB_SYS_COLUMNS i
+INNER JOIN sys_tables st ON i.TABLE_ID=st.TABLE_ID;
+NAME	POS	MTYPE	PRTYPE	LEN
+FTS_DOC_ID	0	6	1800	8
+c2	1	6	1027	4
+ct	2	5	524540	10
+SELECT si.NAME,i.POS,i.NAME FROM INFORMATION_SCHEMA.INNODB_SYS_FIELDS i
+INNER JOIN sys_indexes si ON i.INDEX_ID=si.INDEX_ID;
+NAME	POS	NAME
+PRIMARY	0	FTS_DOC_ID
+FTS_DOC_ID_INDEX	0	FTS_DOC_ID
+ct	0	ct
+SELECT i.* FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS i
+INNER JOIN sys_foreign sf ON i.ID = sf.ID;
+ID	FOR_COL_NAME	REF_COL_NAME	POS
 DROP TABLE tt, t1o, sys_tables, sys_indexes, sys_foreign;

=== modified file 'mysql-test/suite/innodb/t/innodb-alter.test'
--- a/mysql-test/suite/innodb/t/innodb-alter.test	revid:marko.makela@stripped21
+++ b/mysql-test/suite/innodb/t/innodb-alter.test	revid:marko.makela@stripped
@@ -241,10 +241,8 @@ WHERE st.NAME='test/t1o' AND sc.NAME='FT
 
 SHOW CREATE TABLE t1o;
 
-# This will leave an orphan FTS_DOC_ID_INDEX inside InnoDB.
 ALTER TABLE t1o CHANGE FTS_DOC_ID foo_id BIGINT UNSIGNED NOT NULL,
 DROP INDEX ct, ALGORITHM=INPLACE;
-call mtr.add_suppression("InnoDB: Table test/t1o contains 2 indexes inside InnoDB, which is different from the number of indexes 1 defined in the MySQL");
 
 SHOW CREATE TABLE t1o;
 
@@ -261,30 +259,31 @@ FROM INFORMATION_SCHEMA.INNODB_SYS_FOREI
 
 -- source suite/innodb/include/innodb_dict.inc
 
-# Now, there exists a hidden FTS_DOC_ID_INDEX on foo_id, not FTS_DOC_ID.
-# We must rename the foo_id to FTS_DOC_ID first.
+# Ensure that there exists no hidden FTS_DOC_ID_INDEX on foo_id.
 
--- error ER_INNODB_FT_WRONG_DOCID_INDEX
-ALTER TABLE t1o ADD FULLTEXT INDEX(ct);
-
-# Ideally, the renaming should work in the same statement with
-# the ADD FULLTEXT INDEX. This is what we get by defining FTS_DOC_ID
-# as a half-hidden column.
--- error ER_INNODB_FT_WRONG_DOCID_INDEX
-ALTER TABLE t1o ADD FULLTEXT INDEX(ct),
+# Renaming the FTS_DOC_ID column and creating a FULLTEXT index
+# does not work in one go.
+--error ER_INNODB_FT_WRONG_DOCID_INDEX
+ALTER TABLE t1o ADD UNIQUE INDEX FTS_DOC_ID_INDEX(FTS_DOC_ID),
+ADD FULLTEXT INDEX(ct),
 CHANGE foo_id FTS_DOC_ID BIGINT UNSIGNED NOT NULL;
 
+ALTER TABLE t1o ADD UNIQUE INDEX FTS_DOC_ID_INDEX(foo_id);
+
+--error ER_INNODB_FT_WRONG_DOCID_INDEX
+ALTER TABLE t1o CHANGE foo_id FTS_DOC_ID BIGINT UNSIGNED NOT NULL,
+ADD FULLTEXT INDEX(ct);
+
 ALTER TABLE t1o CHANGE foo_id FTS_DOC_ID BIGINT UNSIGNED NOT NULL;
+CREATE FULLTEXT INDEX ct ON t1o (ct);
 
-# InnoDB created FTS_DOC_ID_INDEX internally already.
--- error ER_WRONG_NAME_FOR_INDEX
-ALTER TABLE t1o ADD UNIQUE INDEX FTS_DOC_ID_INDEX(FTS_DOC_ID);
+--error ER_INNODB_FT_WRONG_DOCID_COLUMN
+ALTER TABLE t1o CHANGE FTS_DOC_ID foo_id BIGINT UNSIGNED NOT NULL;
 
-# The ALGORITHM=COPY ignores the internally created index. */
-ALTER TABLE t1o ADD UNIQUE INDEX FTS_DOC_ID_INDEX(FTS_DOC_ID),
-ALGORITHM=COPY;
+DROP TABLE sys_indexes;
+CREATE TABLE sys_indexes SELECT i.* FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES i
+INNER JOIN sys_tables st ON i.TABLE_ID=st.TABLE_ID;
 
--- error ER_DUP_KEYNAME
-ALTER TABLE t1o ADD UNIQUE INDEX FTS_DOC_ID_INDEX(FTS_DOC_ID);
+-- source suite/innodb/include/innodb_dict.inc
 
 DROP TABLE tt, t1o, sys_tables, sys_indexes, sys_foreign;

=== modified file 'storage/innobase/handler/handler0alter.cc'
--- a/storage/innobase/handler/handler0alter.cc	revid:marko.makela@stripped0120417140601-q4xyu89kks7krh21
+++ b/storage/innobase/handler/handler0alter.cc	revid:marko.makela@stripped417200539-oy8df7zgqt1xb3oc
@@ -2083,9 +2083,10 @@ found_fk:
 		if (!heap) {
 			heap = mem_heap_create(1024);
 		}
-		drop_index = (dict_index_t**) mem_heap_alloc(
-			heap, ha_alter_info->index_drop_count
-			* sizeof *drop_index);
+		drop_index = static_cast<dict_index_t**>(
+			mem_heap_alloc(
+				heap, (ha_alter_info->index_drop_count + 1)
+				* sizeof *drop_index));
 		for (uint i = 0; i < ha_alter_info->index_drop_count; i++) {
 			const KEY*	key
 				= ha_alter_info->index_drop_buffer[i];
@@ -2108,6 +2109,43 @@ found_fk:
 			}
 		}
 
+		/* If all FULLTEXT indexes were removed, drop an
+		internal FTS_DOC_ID_INDEX as well, unless it exists in
+		the table. */
+
+		if (innobase_fulltext_exist(table->s)
+		    && !innobase_fulltext_exist(altered_table->s)) {
+			dict_index_t*	fts_doc_index
+				= dict_table_get_index_on_name(
+					indexed_table, FTS_DOC_ID_INDEX_NAME);
+
+			/* The FTS_DOC_ID_INDEX should always exist
+			if fulltext indexes exist, unless the MySQL
+			and InnoDB data dictionaries are out of sync. */
+			DBUG_ASSERT(fts_doc_index != NULL);
+
+			// Add some fault tolerance for non-debug builds.
+			if (fts_doc_index == NULL) {
+				goto check_if_can_drop_indexes;
+			}
+
+			for (uint i = 0; i < table->s->keys; i++) {
+				if (!my_strcasecmp(
+					    system_charset_info,
+					    FTS_DOC_ID_INDEX_NAME,
+					    table->s->key_info[i].name)) {
+					/* The index exists in the MySQL
+					data dictionary. Do not drop it,
+					even though it is no longer needed
+					by InnoDB fulltext search. */
+					goto check_if_can_drop_indexes;
+				}
+			}
+
+			drop_index[n_drop_index++] = fts_doc_index;
+		}
+
+check_if_can_drop_indexes:
 		/* Check if the indexes can be dropped */
 
 		if (prebuilt->trx->check_foreigns) {

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk-wl5545 branch (marko.makela:3894 to 3895)Bug#13972248marko.makela20 Apr