mariadb/mysql-test/suite/innodb/t/innodb-wl5980-alter.test
Marko Mäkelä 1bd681c8b3 MDEV-25506 (3 of 3): Do not delete .ibd files before commit
This is a complete rewrite of DROP TABLE, also as part of other DDL,
such as ALTER TABLE, CREATE TABLE...SELECT, TRUNCATE TABLE.

The background DROP TABLE queue hack is removed.
If a transaction needs to drop and create a table by the same name
(like TRUNCATE TABLE does), it must first rename the table to an
internal #sql-ib name. No committed version of the data dictionary
will include any #sql-ib tables, because whenever a transaction
renames a table to a #sql-ib name, it will also drop that table.
Either the rename will be rolled back, or the drop will be committed.

Data files will be unlinked after the transaction has been committed
and a FILE_RENAME record has been durably written. The file will
actually be deleted when the detached file handle returned by
fil_delete_tablespace() will be closed, after the latches have been
released. It is possible that a purge of the delete of the SYS_INDEXES
record for the clustered index will execute fil_delete_tablespace()
concurrently with the DDL transaction. In that case, the thread that
arrives later will wait for the other thread to finish.

HTON_TRUNCATE_REQUIRES_EXCLUSIVE_USE: A new handler flag.
ha_innobase::truncate() now requires that all other references to
the table be released in advance. This was implemented by Monty.

ha_innobase::delete_table(): If CREATE TABLE..SELECT is detected,
we will "hijack" the current transaction, drop the table in
the current transaction and commit the current transaction.
This essentially fixes MDEV-21602. There is a FIXME comment about
making the check less failure-prone.

ha_innobase::truncate(), ha_innobase::delete_table():
Implement a fast path for temporary tables. We will no longer allow
temporary tables to use the adaptive hash index.

dict_table_t::mdl_name: The original table name for the purpose of
acquiring MDL in purge, to prevent a race condition between a
DDL transaction that is dropping a table, and purge processing
undo log records of DML that had executed before the DDL operation.
For #sql-backup- tables during ALTER TABLE...ALGORITHM=COPY, the
dict_table_t::mdl_name will differ from dict_table_t::name.

dict_table_t::parse_name(): Use mdl_name instead of name.

dict_table_rename_in_cache(): Update mdl_name.

For the internal FTS_ tables of FULLTEXT INDEX, purge would
acquire MDL on the FTS_ table name, but not on the main table,
and therefore it would be able to run concurrently with a
DDL transaction that is dropping the table. Previously, the
DROP TABLE queue hack prevented a race between purge and DDL.
For now, we introduce purge_sys.stop_FTS() to prevent purge from
opening any table, while a DDL transaction that may drop FTS_
tables is in progress. The function fts_lock_table(), which will
be invoked before the dictionary is locked, will wait for
purge to release any table handles.

trx_t::drop_table_statistics(): Drop statistics for the table.
This replaces dict_stats_drop_index(). We will drop or rename
persistent statistics atomically as part of DDL transactions.
On lock conflict for dropping statistics, we will fail instantly
with DB_LOCK_WAIT_TIMEOUT, because we will be holding the
exclusive data dictionary latch.

trx_t::commit_cleanup(): Separated from trx_t::commit_in_memory().
Relax an assertion around fts_commit() and allow DB_LOCK_WAIT_TIMEOUT
in addition to DB_DUPLICATE_KEY. The call to fts_commit() is
entirely misplaced here and may obviously break the consistency
of transactions that affect FULLTEXT INDEX. It needs to be fixed
separately.

dict_table_t::n_foreign_key_checks_running: Remove (MDEV-21175).
The counter was a work-around for missing meta-data locking (MDL)
on the SQL layer, and not really needed in MariaDB.

ER_TABLE_IN_FK_CHECK: Replaced with ER_UNUSED_28.

HA_ERR_TABLE_IN_FK_CHECK: Remove.

row_ins_check_foreign_constraints(): Do not acquire
dict_sys.latch either. The SQL-layer MDL will protect us.

This was reviewed by Thirunarayanan Balathandayuthapani
and tested by Matthias Leich.
2021-06-09 17:06:07 +03:00

709 lines
25 KiB
Text

--echo #
--echo # This is a copy of innodb-alter.test except using remote tablespaces
--echo # and showing those files.
--echo #
--source include/have_innodb.inc
SET @innodb_file_per_table_orig=@@GLOBAL.innodb_file_per_table;
LET $regexp=/FTS_[0-9a-f_]+([A-Z0-9_]+)\.([islbd]{3})/FTS_AUX_\1.\2/;
# Set up some variables
LET $MYSQL_DATA_DIR = `select @@datadir`;
LET $data_directory_clause = DATA DIRECTORY='$MYSQL_TMP_DIR/alt_dir';
SET default_storage_engine=InnoDB;
SET GLOBAL innodb_file_per_table=ON;
SET NAMES utf8mb4;
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
eval CREATE TABLE t1 (
c1 INT PRIMARY KEY, c2 INT DEFAULT 1, ct TEXT,
INDEX(c2))
ENGINE=InnoDB $data_directory_clause;
INSERT INTO t1 SET c1=1;
CREATE TABLE sys_tables SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES
WHERE NAME LIKE 'test/t%';
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;
CREATE TABLE t1p LIKE t1;
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
eval CREATE TABLE t1c (c1 INT PRIMARY KEY, c2 INT, c3 INT, INDEX(c2), INDEX(c3),
CONSTRAINT t1c2 FOREIGN KEY (c2) REFERENCES t1(c2),
CONSTRAINT t1c3 FOREIGN KEY (c3) REFERENCES t1p(c2))
ENGINE=InnoDB $data_directory_clause;
CREATE TABLE sys_foreign SELECT i.*
FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN i
WHERE FOR_NAME LIKE 'test/t%';
SELECT i.* FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS i
INNER JOIN sys_foreign sf ON i.ID = sf.ID;
-- source suite/innodb/include/innodb_dict.inc
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE t1;
ALTER TABLE t1 ALTER c2 DROP DEFAULT;
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE t1;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
-- source suite/innodb/include/innodb_dict.inc
# These should be no-op.
ALTER TABLE t1 CHANGE c2 c2 INT AFTER c1;
ALTER TABLE t1 CHANGE c1 c1 INT FIRST;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
-- source suite/innodb/include/innodb_dict.inc
ALTER TABLE t1 CHANGE C2 c3 INT;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
-- source suite/innodb/include/innodb_dict.inc
ALTER TABLE t1 CHANGE c3 C INT;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
-- source suite/innodb/include/innodb_dict.inc
ALTER TABLE t1 CHANGE C Cöŀumň_TWO INT;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
SELECT i.* FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN_COLS i
INNER JOIN sys_foreign sf ON i.ID = sf.ID;
-- source suite/innodb/include/innodb_dict.inc
-- error ER_BAD_FIELD_ERROR
ALTER TABLE t1 CHANGE cöĿǖmň_two c3 INT;
ALTER TABLE t1 CHANGE cÖĿUMŇ_two c3 INT, RENAME TO t3;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
SELECT st.NAME, i.NAME
FROM sys_tables st INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES i
ON i.TABLE_ID=st.TABLE_ID;
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE t3;
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE t1c;
# The maximum column name length should be 64 characters.
--error ER_TOO_LONG_IDENT
ALTER TABLE t3 CHANGE c3
`12345678901234567890123456789012345678901234567890123456789012345` INT;
ALTER TABLE t3 CHANGE c3
`1234567890123456789012345678901234567890123456789012345678901234` INT;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE t3;
# Test the length limit with non-ASCII utf-8 characters.
--error ER_TOO_LONG_IDENT
ALTER TABLE t3 CHANGE
`1234567890123456789012345678901234567890123456789012345678901234`
`倀倁倂倃倄倅倆倇倈倉倊個倌倍倎倏倐們倒倓倔倕倖倗倘候倚倛倜倝倞借倠倡倢倣値倥倦倧倨倩倪倫倬倭倮倯倰倱倲倳倴倵倶倷倸倹债倻值倽倾倿偀` INT;
--error ER_TOO_LONG_IDENT
ALTER TABLE t3 CHANGE
`1234567890123456789012345678901234567890123456789012345678901234`
`倀倁倂倃倄倅倆倇倈倉倊個倌倍倎倏倐們倒倓倔倕倖倗倘候倚倛倜倝倞借倠倡倢倣値倥倦倧倨倩倪倫倬倭倮倯倰倱倲倳倴倵倶倷倸倹债倻值倽倾倿ä` INT;
ALTER TABLE t3 CHANGE
`1234567890123456789012345678901234567890123456789012345678901234`
`倀倁倂倃倄倅倆倇倈倉倊個倌倍倎倏倐們倒倓倔倕倖倗倘候倚倛倜倝倞借倠倡倢倣値倥倦倧倨倩倪倫倬倭倮倯倰倱倲倳倴倵倶倷倸倹债倻值倽倾ä` INT;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
# check that the rename is case-insensitive (note the upper-case ä at end)
ALTER TABLE t3 CHANGE
`倀倁倂倃倄倅倆倇倈倉倊個倌倍倎倏倐們倒倓倔倕倖倗倘候倚倛倜倝倞借倠倡倢倣値倥倦倧倨倩倪倫倬倭倮倯倰倱倲倳倴倵倶倷倸倹债倻值倽倾Ä`
c3 INT;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
# test with 4-byte UTF-8 (should be disallowed)
--error ER_INVALID_CHARACTER_STRING
ALTER TABLE t3 CHANGE c3 𐌀𐌁𐌂𐌃𐌄𐌅𐌆𐌇𐌈𐌉𐌊𐌋𐌌𐌍𐌎𐌏𐌐𐌑𐌒𐌓𐌔𐌕𐌖𐌗𐌘𐌙𐌚𐌛𐌜 INT;
--error ER_INVALID_CHARACTER_STRING
ALTER TABLE t3 CHANGE c3 😲 INT;
ALTER TABLE t3 RENAME TO t2;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
SELECT st.NAME, i.NAME
FROM sys_tables st INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES i
ON i.TABLE_ID=st.TABLE_ID;
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE t2;
RENAME TABLE t2 TO t1;
SELECT st.NAME, i.NAME
FROM sys_tables st INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLES i
ON i.TABLE_ID=st.TABLE_ID;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
-- source suite/innodb/include/innodb_dict.inc
--error ER_DROP_INDEX_FK
ALTER TABLE t1 DROP INDEX c2;
--error ER_CANT_DROP_FIELD_OR_KEY
ALTER TABLE t1 DROP INDEX c4;
--error ER_CANT_DROP_FIELD_OR_KEY
ALTER TABLE t1c DROP FOREIGN KEY c2;
--error ER_CANT_DROP_FIELD_OR_KEY
ALTER TABLE t1c DROP FOREIGN KEY t1c2, DROP FOREIGN KEY c2;
--error ER_CANT_DROP_FIELD_OR_KEY
ALTER TABLE t1c DROP FOREIGN KEY t1c2, DROP FOREIGN KEY c2, DROP INDEX c2;
--error ER_DROP_INDEX_FK
ALTER TABLE t1c DROP INDEX c2;
--error ER_CANT_DROP_FIELD_OR_KEY
ALTER TABLE t1c DROP FOREIGN KEY ẗ1C2;
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE t1c;
SET foreign_key_checks=0;
DROP TABLE t1p;
SET foreign_key_checks=1;
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE t1c;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
-- source suite/innodb/include/innodb_dict.inc
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
eval CREATE TABLE t1p (c1 INT PRIMARY KEY, c2 INT, INDEX(c2))
ENGINE=InnoDB $data_directory_clause;
--error ER_DROP_INDEX_FK
ALTER TABLE t1c DROP INDEX C2, DROP INDEX C3;
--error ER_DROP_INDEX_FK
ALTER TABLE t1c DROP INDEX C3;
SET foreign_key_checks=0;
ALTER TABLE t1c DROP INDEX C3;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
SET foreign_key_checks=1;
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE t1c;
-- source suite/innodb/include/innodb_dict.inc
ALTER TABLE t1c DROP FOREIGN KEY t1C3;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE t1c;
-- source suite/innodb/include/innodb_dict.inc
ALTER TABLE t1c DROP INDEX c2, DROP FOREIGN KEY t1C2;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE t1c;
-- source suite/innodb/include/innodb_dict.inc
ALTER TABLE t1 DROP INDEX c2, CHANGE c3 c2 INT;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
-- source suite/innodb/include/innodb_dict.inc
CREATE TABLE t1o LIKE t1;
# This will implicitly add a DOC_ID column.
# The LOCK=NONE should thus fail.
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
ALTER TABLE t1 ADD FULLTEXT INDEX (ct),
CHANGE c1 pk INT, ALTER c2 SET DEFAULT 42, RENAME TO tt,
ALGORITHM=INPLACE, LOCK=NONE;
# Retry with LOCK=EXCLUSIVE.
ALTER TABLE t1 ADD FULLTEXT INDEX (ct),
CHANGE c1 pk INT, ALTER c2 SET DEFAULT 42, RENAME TO tt,
ALGORITHM=INPLACE, LOCK=SHARED;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
# The output should be empty, because index->id was reassigned.
-- source suite/innodb/include/innodb_dict.inc
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE tt;
# DB_ROW_ID, DB_TRX_ID, DB_ROLL_PTR are reserved InnoDB system column names.
--error ER_WRONG_COLUMN_NAME
ALTER TABLE t1o CHANGE c1 dB_row_Id INT, ALGORITHM=COPY;
--error ER_WRONG_COLUMN_NAME
ALTER TABLE t1o CHANGE c1 dB_row_Id INT, ALGORITHM=INPLACE;
--error ER_WRONG_COLUMN_NAME
ALTER TABLE t1o CHANGE c1 DB_TRX_ID INT;
--error ER_WRONG_COLUMN_NAME
ALTER TABLE t1o CHANGE c1 db_roll_ptr INT;
# FTS_DOC_ID is the internal row identifier for full-text search.
# It should be of type BIGINT UNSIGNED NOT NULL.
--error ER_WRONG_COLUMN_NAME
ALTER TABLE t1o ADD FULLTEXT INDEX(ct), CHANGE c1 FTS_DOC_ID INT,
ALGORITHM=COPY;
--error ER_INNODB_FT_WRONG_DOCID_COLUMN
ALTER TABLE t1o ADD FULLTEXT INDEX(ct), CHANGE c1 FTS_DOC_ID INT,
ALGORITHM=INPLACE;
--error ER_WRONG_COLUMN_NAME
ALTER TABLE t1o ADD FULLTEXT INDEX(ct), CHANGE c1 FTS_Doc_ID INT,
ALGORITHM=INPLACE;
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
ALTER TABLE t1o ADD FULLTEXT INDEX(ct),
CHANGE c1 FTS_DOC_ID BIGINT UNSIGNED NOT NULL,
ALGORITHM=INPLACE;
CREATE TABLE t1n LIKE t1o;
ALTER TABLE t1n ADD FULLTEXT INDEX(ct);
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--error ER_WRONG_COLUMN_NAME
ALTER TABLE t1n CHANGE c1 Fts_DOC_ID INT, ALGORITHM=INPLACE;
--error ER_WRONG_COLUMN_NAME
ALTER TABLE t1n CHANGE c1 Fts_DOC_ID INT, ALGORITHM=COPY;
--error ER_BAD_FIELD_ERROR
ALTER TABLE t1n CHANGE FTS_DOC_ID c11 INT, ALGORITHM=INPLACE;
ALTER TABLE t1n CHANGE c1 FTS_DOC_ïD INT, ALGORITHM=INPLACE;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
ALTER TABLE t1n CHANGE FTS_DOC_ÏD c1 INT, ALGORITHM=INPLACE;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
ALTER TABLE t1n CHANGE c1 c2 INT, CHANGE c2 ct INT, CHANGE ct c1 TEXT,
ALGORITHM=INPLACE;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE t1n;
ALTER TABLE t1n CHANGE c2 c1 INT, CHANGE ct c2 INT, CHANGE c1 ct TEXT,
ALGORITHM=COPY;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE t1n;
--error ER_KEY_COLUMN_DOES_NOT_EXITS
ALTER TABLE t1n ADD INDEX(c2), CHANGE c2 c4 INT, ALGORITHM=INPLACE;
--error ER_KEY_COLUMN_DOES_NOT_EXITS
ALTER TABLE t1n ADD INDEX(c2), CHANGE c2 c4 INT, ALGORITHM=COPY;
ALTER TABLE t1n ADD INDEX(c4), CHANGE c2 c4 INT, ALGORITHM=INPLACE;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE t1n;
ALTER TABLE t1n DROP INDEX c4;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--error ER_DUP_FIELDNAME
ALTER TABLE t1n CHANGE c4 c1 INT, ADD INDEX(c1), ALGORITHM=INPLACE;
ALTER TABLE t1n CHANGE c4 c11 INT, ADD INDEX(c11), ALGORITHM=INPLACE;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE t1n;
DROP TABLE t1n;
ALTER TABLE t1o MODIFY c1 BIGINT UNSIGNED NOT NULL;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
ALTER TABLE t1o ADD FULLTEXT INDEX(ct),
CHANGE c1 FTS_DOC_ID BIGINT UNSIGNED NOT NULL,
ALGORITHM=INPLACE;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
# This would create a hidden FTS_DOC_ID column, which cannot be done online.
--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON
ALTER TABLE t1o CHANGE FTS_DOC_ID foo_id BIGINT UNSIGNED NOT NULL,
LOCK=NONE;
# This should not show duplicates.
SELECT sc.pos FROM information_schema.innodb_sys_columns sc
INNER JOIN information_schema.innodb_sys_tables st
ON sc.TABLE_ID=st.TABLE_ID
WHERE st.NAME='test/t1o' AND sc.NAME='FTS_DOC_ID';
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE t1o;
ALTER TABLE t1o CHANGE FTS_DOC_ID foo_id BIGINT UNSIGNED NOT NULL,
DROP INDEX ct, LOCK=NONE;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--replace_result $MYSQL_TMP_DIR MYSQL_TMP_DIR
SHOW CREATE TABLE t1o;
DROP TABLE t1c, t1p, sys_tables, sys_indexes, sys_foreign;
# Check the internal schemata of tt, t1o.
CREATE TABLE sys_tables SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES
WHERE NAME='test/t1o';
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;
CREATE TABLE sys_foreign SELECT i.*
FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN i WHERE FOR_NAME='test/t1o';
-- source suite/innodb/include/innodb_dict.inc
# Ensure that there exists no hidden FTS_DOC_ID_INDEX on foo_id.
ALTER TABLE t1o ADD UNIQUE INDEX FTS_DOC_ID_INDEX(foo_id);
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
ALTER TABLE t1o CHANGE foo_id FTS_DOC_ID BIGINT UNSIGNED NOT NULL,
ADD FULLTEXT INDEX(ct);
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--error ER_INNODB_FT_WRONG_DOCID_INDEX
ALTER TABLE t1o CHANGE FTS_DOC_ID foo_id BIGINT UNSIGNED NOT NULL;
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;
-- source suite/innodb/include/innodb_dict.inc
--echo #
--echo # Cleanup
--echo #
DROP TABLE tt, t1o, sys_tables, sys_indexes, sys_foreign;
--echo ### files in MYSQL_DATA_DIR/test
--list_files_write_file $MYSQL_DATA_DIR.files.txt $MYSQL_DATA_DIR/test
--replace_regex $regexp
--cat_file $MYSQL_DATA_DIR.files.txt
--remove_file $MYSQL_DATA_DIR.files.txt
--echo ### files in MYSQL_TMP_DIR/alt_dir/test
--replace_regex $regexp
--list_files $MYSQL_TMP_DIR/alt_dir/test
--rmdir $MYSQL_TMP_DIR/alt_dir/test
--rmdir $MYSQL_TMP_DIR/alt_dir
SET GLOBAL innodb_file_per_table = @innodb_file_per_table_orig;