diff --git a/mysql-test/suite/percona_innodb/r/ps_9616.result b/mysql-test/suite/percona_innodb/r/ps_9616.result new file mode 100644 index 000000000000..c8f478ec10e8 --- /dev/null +++ b/mysql-test/suite/percona_innodb/r/ps_9616.result @@ -0,0 +1,109 @@ +# utf8mb4_general_ci ===>>> utf8mb4_0900_ai_ci ### in 2 steps +CREATE TABLE `test_table` +( +`field1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, +`field2` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +ALTER TABLE test_table +MODIFY field1 varchar (10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, +MODIFY field2 text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci, +ALGORITHM=INPLACE; +ALTER TABLE test_table COLLATE=utf8mb4_0900_ai_ci, ALGORITHM=INPLACE; +SHOW CREATE TABLE test_table; +Table Create Table +test_table CREATE TABLE `test_table` ( + `field1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `field2` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE test_table; +# utf8mb4_general_ci ===>>> utf8mb4_0900_ai_ci ### in 1 step +CREATE TABLE `test_table` +( +`field1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, +`field2` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +ALTER TABLE test_table +MODIFY field1 varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, +MODIFY field2 text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci, +COLLATE=utf8mb4_0900_ai_ci, +ALGORITHM=INPLACE; +SHOW CREATE TABLE test_table; +Table Create Table +test_table CREATE TABLE `test_table` ( + `field1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + `field2` text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE test_table; +# with indexed columns +CREATE TABLE `test_table` +( +`field1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, +`field2` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci, +INDEX(`field1`), +INDEX(`field2`(10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +ALTER TABLE test_table +MODIFY field1 varchar (10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, +MODIFY field2 text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci, +ALGORITHM=INPLACE; +ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY. +ALTER TABLE test_table COLLATE=utf8mb4_0900_ai_ci, ALGORITHM=INPLACE; +SHOW CREATE TABLE test_table; +Table Create Table +test_table CREATE TABLE `test_table` ( + `field1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `field2` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci, + KEY `field1` (`field1`), + KEY `field2` (`field2`(10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE test_table; +# utf8mb4_general_ci ===>>> utf8mb4_0900_ai_ci ### in 1 step +CREATE TABLE `test_table` +( +`field1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, +`field2` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci, +INDEX(`field1`), +INDEX(`field2`(10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +ALTER TABLE test_table +MODIFY field1 varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, +MODIFY field2 text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci, +COLLATE=utf8mb4_0900_ai_ci, +ALGORITHM=INPLACE; +ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY. +SHOW CREATE TABLE test_table; +Table Create Table +test_table CREATE TABLE `test_table` ( + `field1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `field2` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci, + KEY `field1` (`field1`), + KEY `field2` (`field2`(10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci +DROP TABLE test_table; +# ADD INDEX + AUTO_INCREMENT= in 1 step +CREATE TABLE test_table (a INT, b INT) ENGINE=InnoDB; +ALTER TABLE test_table ADD INDEX idx_b(b), AUTO_INCREMENT=7, ALGORITHM=INPLACE; +SHOW CREATE TABLE test_table; +Table Create Table +test_table CREATE TABLE `test_table` ( + `a` int DEFAULT NULL, + `b` int DEFAULT NULL, + KEY `idx_b` (`b`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE test_table; +# DROP INDEX + COLLATE= in 1 step +CREATE TABLE `test_table` +( +`field1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, +INDEX(`field1`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +ALTER TABLE test_table +DROP INDEX field1, +COLLATE=utf8mb4_0900_ai_ci, +ALGORITHM=INPLACE; +SHOW CREATE TABLE test_table; +Table Create Table +test_table CREATE TABLE `test_table` ( + `field1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci +DROP TABLE test_table; diff --git a/mysql-test/suite/percona_innodb/t/ps_9616.test b/mysql-test/suite/percona_innodb/t/ps_9616.test new file mode 100644 index 000000000000..83b37e88b880 --- /dev/null +++ b/mysql-test/suite/percona_innodb/t/ps_9616.test @@ -0,0 +1,118 @@ +--echo # utf8mb4_general_ci ===>>> utf8mb4_0900_ai_ci ### in 2 steps +CREATE TABLE `test_table` +( + `field1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `field2` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + + +# ha_alter_info->handler_flags = ALTER_COLUMN_EQUAL_PACK_LENGTH & ALTER_COLUMN_DEFAULT +ALTER TABLE test_table + MODIFY field1 varchar (10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + MODIFY field2 text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci, + ALGORITHM=INPLACE; + +# ha_alter_info->handler_flags = CHANGE_CREATE_OPTION +ALTER TABLE test_table COLLATE=utf8mb4_0900_ai_ci, ALGORITHM=INPLACE; + +SHOW CREATE TABLE test_table; + +DROP TABLE test_table; + + +--echo # utf8mb4_general_ci ===>>> utf8mb4_0900_ai_ci ### in 1 step +# before the patch, this innodb created a new table +# check with SET GLOBAL innodb_print_ddl_logs = ON; SET GLOBAL log_error_verbosity = 3; + +CREATE TABLE `test_table` +( + `field1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `field2` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +# ha_alter_info->handler_flags = ALTER_COLUMN_EQUAL_PACK_LENGTH & ALTER_COLUMN_DEFAULT & CHANGE_CREATE_OPTION +ALTER TABLE test_table + MODIFY field1 varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + MODIFY field2 text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci, + COLLATE=utf8mb4_0900_ai_ci, + ALGORITHM=INPLACE; + +SHOW CREATE TABLE test_table; + +DROP TABLE test_table; + +--echo # with indexed columns +CREATE TABLE `test_table` +( + `field1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `field2` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci, + INDEX(`field1`), + INDEX(`field2`(10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + + +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE test_table + MODIFY field1 varchar (10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + MODIFY field2 text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci, + ALGORITHM=INPLACE; + +ALTER TABLE test_table COLLATE=utf8mb4_0900_ai_ci, ALGORITHM=INPLACE; + +SHOW CREATE TABLE test_table; + +DROP TABLE test_table; + + +--echo # utf8mb4_general_ci ===>>> utf8mb4_0900_ai_ci ### in 1 step +# before the patch, innodb created a new table +# check with SET GLOBAL innodb_print_ddl_logs = ON; SET GLOBAL log_error_verbosity = 3; + +CREATE TABLE `test_table` +( + `field1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + `field2` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci, + INDEX(`field1`), + INDEX(`field2`(10)) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +--error ER_ALTER_OPERATION_NOT_SUPPORTED_REASON +ALTER TABLE test_table + MODIFY field1 varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL, + MODIFY field2 text CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci, + COLLATE=utf8mb4_0900_ai_ci, + ALGORITHM=INPLACE; + +SHOW CREATE TABLE test_table; + +DROP TABLE test_table; + +# Verify that combining ADD INDEX with AUTO_INCREMENT= does not crash the +# server (regression: INNOBASE_INPLACE_NO_REBUILD incorrectly masked ADD_INDEX, +# causing prepare/alter to early-exit while commit tried to find the unbuilt index). +--echo # ADD INDEX + AUTO_INCREMENT= in 1 step +CREATE TABLE test_table (a INT, b INT) ENGINE=InnoDB; + +ALTER TABLE test_table ADD INDEX idx_b(b), AUTO_INCREMENT=7, ALGORITHM=INPLACE; + +SHOW CREATE TABLE test_table; + +DROP TABLE test_table; + +# Verify that combining DROP INDEX with COLLATE= in one INPLACE +# step does not silently discard the index drop. +--echo # DROP INDEX + COLLATE= in 1 step +CREATE TABLE `test_table` +( + `field1` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL, + INDEX(`field1`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +ALTER TABLE test_table + DROP INDEX field1, + COLLATE=utf8mb4_0900_ai_ci, + ALGORITHM=INPLACE; + +SHOW CREATE TABLE test_table; + +DROP TABLE test_table; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 258149ba6009..bad5f4b591ec 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -931,10 +931,12 @@ static inline bool is_instant(const Alter_inplace_info *ha_alter_info) { return (false); } - Alter_inplace_info::HA_ALTER_FLAGS alter_inplace_flags = - ha_alter_info->handler_flags & ~(INNOBASE_INPLACE_IGNORE); + bool has_change_create_option = + (ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE & + ~Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH) == + Alter_inplace_info::CHANGE_CREATE_OPTION; - if (alter_inplace_flags == Alter_inplace_info::CHANGE_CREATE_OPTION && + if (has_change_create_option && !(ha_alter_info->create_info->used_fields & (HA_CREATE_USED_ROW_FORMAT | HA_CREATE_USED_KEY_BLOCK_SIZE | HA_CREATE_USED_TABLESPACE))) { @@ -5960,7 +5962,8 @@ bool ha_innobase::prepare_inplace_alter_table_impl( } if (!(ha_alter_info->handler_flags & INNOBASE_ALTER_DATA) || - ((ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE) == + ((ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE & + ~Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH) == Alter_inplace_info::CHANGE_CREATE_OPTION && !innobase_need_rebuild(ha_alter_info))) { if (heap) { @@ -6002,9 +6005,8 @@ bool ha_innobase::prepare_inplace_alter_table_impl( } return dd_prepare_inplace_alter_table(m_user_thd, ctx->old_table, ctx->new_table, old_dd_tab); - } else { - return false; } + return false; } /* If we are to build a full-text search index, check whether @@ -6215,7 +6217,8 @@ bool ha_innobase::inplace_alter_table_impl(TABLE *altered_table, return all_ok(); } - if (((ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE) == + if (((ha_alter_info->handler_flags & ~INNOBASE_INPLACE_IGNORE & + ~Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH) == Alter_inplace_info::CHANGE_CREATE_OPTION && !innobase_need_rebuild(ha_alter_info))) { return all_ok();