summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2020-03-03 13:50:33 +0300
committerAleksey Midenkov <midenok@gmail.com>2020-03-03 13:50:33 +0300
commit193725b81ed813d0318c1fa82de284c337246d9e (patch)
tree5491a62650565a58d24cfc629b7466f29b617d18
parentfa8ad7543947f5c74dece982d42bab59b6479449 (diff)
downloadmariadb-git-193725b81ed813d0318c1fa82de284c337246d9e.tar.gz
MDEV-7318 RENAME INDEX
This patch adds support of RENAME INDEX operation to the ALTER TABLE statement. Code which determines if ALTER TABLE can be done in-place for "simple" storage engines like MyISAM, Heap and etc. was updated to handle ALTER TABLE ... RENAME INDEX as an in-place operation. Support for in-place ALTER TABLE ... RENAME INDEX for InnoDB was covered by MDEV-13301. Syntax changes ============== A new type of <alter_specification> is added: <rename index clause> ::= RENAME ( INDEX | KEY ) <oldname> TO <newname> Where <oldname> and <newname> are identifiers for old name and new name of the index. Semantic changes ================ The result of "ALTER TABLE t1 RENAME INDEX a TO b" is a table which contents and structure are identical to the old version of 't1' with the only exception index 'a' being called 'b'. Neither <oldname> nor <newname> can be "primary". The index being renamed should exist and its new name should not be occupied by another index on the same table. Related to: WL#6555, MDEV-13301
-rw-r--r--mysql-test/main/alter_table.result393
-rw-r--r--mysql-test/main/alter_table.test180
-rw-r--r--mysql-test/suite/innodb/r/innodb-alter-debug.result9
-rw-r--r--mysql-test/suite/innodb/r/innodb_rename_index.result989
-rw-r--r--mysql-test/suite/innodb/t/innodb-alter-debug.test12
-rw-r--r--mysql-test/suite/innodb/t/innodb_rename_index.test538
-rw-r--r--sql/handler.cc3
-rw-r--r--sql/sql_alter.cc2
-rw-r--r--sql/sql_alter.h4
-rw-r--r--sql/sql_class.h15
-rw-r--r--sql/sql_table.cc43
-rw-r--r--sql/sql_yacc.yy10
-rw-r--r--storage/innobase/handler/handler0alter.cc8
13 files changed, 2204 insertions, 2 deletions
diff --git a/mysql-test/main/alter_table.result b/mysql-test/main/alter_table.result
index 8a2a9d21f35..c2c5813a100 100644
--- a/mysql-test/main/alter_table.result
+++ b/mysql-test/main/alter_table.result
@@ -2849,5 +2849,398 @@ DROP VIEW v1;
DROP TABLE t3,t1,t2;
SET DEFAULT_STORAGE_ENGINE= @save_default_engine;
#
+# MDEV-7318 RENAME INDEX
+#
+#
+# 1) Tests for syntax and semantics of ALTER TABLE RENAME
+# KEY/INDEX result.
+#
+# 1.a) Both RENAME KEY and RENAME INDEX variants should be
+# allowed and produce expected results.
+create table t1 (pk int primary key, i int, j int, key a(i));
+alter table t1 rename key a to b;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `pk` int(11) NOT NULL,
+ `i` int(11) DEFAULT NULL,
+ `j` int(11) DEFAULT NULL,
+ PRIMARY KEY (`pk`),
+ KEY `b` (`i`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 rename index b to c;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `pk` int(11) NOT NULL,
+ `i` int(11) DEFAULT NULL,
+ `j` int(11) DEFAULT NULL,
+ PRIMARY KEY (`pk`),
+ KEY `c` (`i`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+# 1.b) It should be impossible to rename index that doesn't
+# exists, dropped or added within the same ALTER TABLE.
+alter table t1 rename key d to e;
+ERROR 42000: Key 'd' doesn't exist in table 't1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `pk` int(11) NOT NULL,
+ `i` int(11) DEFAULT NULL,
+ `j` int(11) DEFAULT NULL,
+ PRIMARY KEY (`pk`),
+ KEY `c` (`i`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 drop key c, rename key c to d;
+ERROR 42000: Key 'c' doesn't exist in table 't1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `pk` int(11) NOT NULL,
+ `i` int(11) DEFAULT NULL,
+ `j` int(11) DEFAULT NULL,
+ PRIMARY KEY (`pk`),
+ KEY `c` (`i`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 add key d(j), rename key d to e;
+ERROR 42000: Key 'd' doesn't exist in table 't1'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `pk` int(11) NOT NULL,
+ `i` int(11) DEFAULT NULL,
+ `j` int(11) DEFAULT NULL,
+ PRIMARY KEY (`pk`),
+ KEY `c` (`i`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+# 1.c) It should be impossible to rename index to a name
+# which is already used by another index, or is used
+# by index which is added within the same ALTER TABLE.
+alter table t1 add key d(j);
+alter table t1 rename key c to d;
+ERROR 42000: Duplicate key name 'd'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `pk` int(11) NOT NULL,
+ `i` int(11) DEFAULT NULL,
+ `j` int(11) DEFAULT NULL,
+ PRIMARY KEY (`pk`),
+ KEY `c` (`i`),
+ KEY `d` (`j`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 drop key d;
+alter table t1 add key d(j), rename key c to d;
+ERROR 42000: Duplicate key name 'd'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `pk` int(11) NOT NULL,
+ `i` int(11) DEFAULT NULL,
+ `j` int(11) DEFAULT NULL,
+ PRIMARY KEY (`pk`),
+ KEY `c` (`i`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+# 1.d) It should be possible to rename index to a name
+# which belongs to index which is dropped within the
+# same ALTER TABLE.
+alter table t1 add key d(j);
+alter table t1 drop key c, rename key d to c;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `pk` int(11) NOT NULL,
+ `i` int(11) DEFAULT NULL,
+ `j` int(11) DEFAULT NULL,
+ PRIMARY KEY (`pk`),
+ KEY `c` (`j`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+# 1.e) We disallow renaming from/to PRIMARY as it might
+# lead to some other key becoming "primary" internally,
+# which will be interpreted as dropping/addition of
+# primary key.
+alter table t1 rename key primary to d;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'primary to d' at line 1
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `pk` int(11) NOT NULL,
+ `i` int(11) DEFAULT NULL,
+ `j` int(11) DEFAULT NULL,
+ PRIMARY KEY (`pk`),
+ KEY `c` (`j`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+# Even using 'funny' syntax.
+alter table t1 rename key `primary` to d;
+ERROR 42000: Incorrect index name 'primary'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `pk` int(11) NOT NULL,
+ `i` int(11) DEFAULT NULL,
+ `j` int(11) DEFAULT NULL,
+ PRIMARY KEY (`pk`),
+ KEY `c` (`j`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 rename key c to primary;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'primary' at line 1
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `pk` int(11) NOT NULL,
+ `i` int(11) DEFAULT NULL,
+ `j` int(11) DEFAULT NULL,
+ PRIMARY KEY (`pk`),
+ KEY `c` (`j`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 rename key c to `primary`;
+ERROR 42000: Incorrect index name 'primary'
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `pk` int(11) NOT NULL,
+ `i` int(11) DEFAULT NULL,
+ `j` int(11) DEFAULT NULL,
+ PRIMARY KEY (`pk`),
+ KEY `c` (`j`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+#
+# 2) More complex tests for semantics of ALTER TABLE.
+#
+# 2.a) Check that standalone RENAME KEY works as expected
+# for unique and non-unique indexes.
+create table t1 (a int, unique u(a), b int, key k(b));
+alter table t1 rename key u to uu;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ UNIQUE KEY `uu` (`a`),
+ KEY `k` (`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 rename key k to kk;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ UNIQUE KEY `uu` (`a`),
+ KEY `kk` (`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+# 2.b) Check how that this clause can be mixed with other
+# clauses which don't affect key or its columns.
+alter table t1 rename key kk to kkk, add column c int;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ UNIQUE KEY `uu` (`a`),
+ KEY `kkk` (`b`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 rename key uu to uuu, add key c(c);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ UNIQUE KEY `uuu` (`a`),
+ KEY `kkk` (`b`),
+ KEY `c` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 rename key kkk to k, drop key uuu;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ KEY `k` (`b`),
+ KEY `c` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 rename key k to kk, rename to t2;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) DEFAULT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ KEY `kk` (`b`),
+ KEY `c` (`c`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t2;
+#
+# 3) Test coverage for handling of RENAME INDEX clause in
+# various storage engines and using different ALTER
+# algorithm.
+#
+# 3.a) Test coverage for simple storage engines (MyISAM/Heap).
+create table t1 (i int, key k(i)) engine=myisam;
+insert into t1 values (1);
+create table t2 (i int, key k(i)) engine=memory;
+insert into t2 values (1);
+# MyISAM and Heap should be able to handle key renaming in-place.
+alter table t1 algorithm=inplace, rename key k to kk;
+alter table t2 algorithm=inplace, rename key k to kk;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL,
+ KEY `kk` (`i`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `i` int(11) DEFAULT NULL,
+ KEY `kk` (`i`)
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
+# So by default in-place algorithm should be chosen.
+# (ALTER TABLE should report 0 rows affected).
+alter table t1 rename key kk to kkk;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+alter table t2 rename key kk to kkk;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL,
+ KEY `kkk` (`i`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `i` int(11) DEFAULT NULL,
+ KEY `kkk` (`i`)
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
+# Copy algorithm should work as well.
+alter table t1 algorithm=copy, rename key kkk to kkkk;
+alter table t2 algorithm=copy, rename key kkk to kkkk;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL,
+ KEY `kkkk` (`i`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `i` int(11) DEFAULT NULL,
+ KEY `kkkk` (`i`)
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
+# When renaming is combined with other in-place operation
+# it still works as expected (i.e. works in-place).
+alter table t1 algorithm=inplace, rename key kkkk to k, alter column i set default 100;
+alter table t2 algorithm=inplace, rename key kkkk to k, alter column i set default 100;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT 100,
+ KEY `k` (`i`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `i` int(11) DEFAULT 100,
+ KEY `k` (`i`)
+) ENGINE=MEMORY DEFAULT CHARSET=latin1
+# Combining with non-inplace operation results in the whole ALTER
+# becoming non-inplace.
+alter table t1 algorithm=inplace, rename key k to kk, add column j int;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY
+alter table t2 algorithm=inplace, rename key k to kk, add column j int;
+ERROR 0A000: ALGORITHM=INPLACE is not supported for this operation. Try ALGORITHM=COPY
+drop table t1, t2;
+# 3.b) Basic tests for InnoDB. More tests can be found in
+# innodb.innodb_rename_index*
+create table t1 (i int, key k(i)) engine=innodb;
+insert into t1 values (1);
+# Basic rename, inplace algorithm should be chosen
+alter table t1 algorithm=inplace, rename key k to kk;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL,
+ KEY `kk` (`i`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+# copy algorithm should work as well.
+alter table t1 algorithm=copy, rename key kk to kkk;
+affected rows: 1
+info: Records: 1 Duplicates: 0 Warnings: 0
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `i` int(11) DEFAULT NULL,
+ KEY `kkk` (`i`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+#
+# 4) Additional coverage for complex cases in which code
+# in ALTER TABLE comparing old and new table version
+# got confused.
+#
+# Once InnoDB starts to support in-place index renaming the result
+# of below statements should stay the same. Information about
+# indexes returned by SHOW CREATE TABLE (from .FRM) and by
+# InnoDB (from InnoDB data-dictionary) should be consistent.
+#
+create table t1 ( a int, b int, c int, d int,
+primary key (a), index i1 (b), index i2 (c) ) engine=innodb;
+alter table t1 add index i1 (d), rename index i1 to x;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`),
+ KEY `x` (`b`),
+ KEY `i2` (`c`),
+ KEY `i1` (`d`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+select i.name as k, f.name as c from information_schema.innodb_sys_tables as t,
+information_schema.innodb_sys_indexes as i,
+information_schema.innodb_sys_fields as f
+where t.name='test/t1' and t.table_id = i.table_id and i.index_id = f.index_id
+order by k, c;
+k c
+i1 d
+i2 c
+PRIMARY a
+x b
+drop table t1;
+create table t1 (a int, b int, c int, d int,
+primary key (a), index i1 (b), index i2 (c)) engine=innodb;
+alter table t1 add index i1 (d), rename index i1 to i2, drop index i2;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`),
+ KEY `i2` (`b`),
+ KEY `i1` (`d`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+select i.name as k, f.name as c from information_schema.innodb_sys_tables as t,
+information_schema.innodb_sys_indexes as i,
+information_schema.innodb_sys_fields as f
+where t.name='test/t1' and t.table_id = i.table_id and i.index_id = f.index_id
+order by k, c;
+k c
+i1 d
+i2 b
+PRIMARY a
+drop table t1;
+#
# End of 10.5 tests
#
diff --git a/mysql-test/main/alter_table.test b/mysql-test/main/alter_table.test
index ccd2ee953b1..19f9777d803 100644
--- a/mysql-test/main/alter_table.test
+++ b/mysql-test/main/alter_table.test
@@ -2274,5 +2274,185 @@ DROP TABLE t3,t1,t2;
SET DEFAULT_STORAGE_ENGINE= @save_default_engine;
--echo #
+--echo # MDEV-7318 RENAME INDEX
+--echo #
+
+--echo #
+--echo # 1) Tests for syntax and semantics of ALTER TABLE RENAME
+--echo # KEY/INDEX result.
+--echo #
+--echo # 1.a) Both RENAME KEY and RENAME INDEX variants should be
+--echo # allowed and produce expected results.
+create table t1 (pk int primary key, i int, j int, key a(i));
+alter table t1 rename key a to b;
+show create table t1;
+alter table t1 rename index b to c;
+show create table t1;
+
+--echo # 1.b) It should be impossible to rename index that doesn't
+--echo # exists, dropped or added within the same ALTER TABLE.
+--error ER_KEY_DOES_NOT_EXITS
+alter table t1 rename key d to e;
+show create table t1;
+--error ER_KEY_DOES_NOT_EXITS
+alter table t1 drop key c, rename key c to d;
+show create table t1;
+--error ER_KEY_DOES_NOT_EXITS
+alter table t1 add key d(j), rename key d to e;
+show create table t1;
+
+--echo # 1.c) It should be impossible to rename index to a name
+--echo # which is already used by another index, or is used
+--echo # by index which is added within the same ALTER TABLE.
+alter table t1 add key d(j);
+--error ER_DUP_KEYNAME
+alter table t1 rename key c to d;
+show create table t1;
+alter table t1 drop key d;
+--error ER_DUP_KEYNAME
+alter table t1 add key d(j), rename key c to d;
+show create table t1;
+
+--echo # 1.d) It should be possible to rename index to a name
+--echo # which belongs to index which is dropped within the
+--echo # same ALTER TABLE.
+alter table t1 add key d(j);
+alter table t1 drop key c, rename key d to c;
+show create table t1;
+
+--echo # 1.e) We disallow renaming from/to PRIMARY as it might
+--echo # lead to some other key becoming "primary" internally,
+--echo # which will be interpreted as dropping/addition of
+--echo # primary key.
+--error ER_PARSE_ERROR
+alter table t1 rename key primary to d;
+show create table t1;
+--echo # Even using 'funny' syntax.
+--error ER_WRONG_NAME_FOR_INDEX
+alter table t1 rename key `primary` to d;
+show create table t1;
+--error ER_PARSE_ERROR
+alter table t1 rename key c to primary;
+show create table t1;
+--error ER_WRONG_NAME_FOR_INDEX
+alter table t1 rename key c to `primary`;
+show create table t1;
+drop table t1;
+
+
+--echo #
+--echo # 2) More complex tests for semantics of ALTER TABLE.
+--echo #
+--echo # 2.a) Check that standalone RENAME KEY works as expected
+--echo # for unique and non-unique indexes.
+create table t1 (a int, unique u(a), b int, key k(b));
+alter table t1 rename key u to uu;
+show create table t1;
+alter table t1 rename key k to kk;
+show create table t1;
+
+--echo # 2.b) Check how that this clause can be mixed with other
+--echo # clauses which don't affect key or its columns.
+alter table t1 rename key kk to kkk, add column c int;
+show create table t1;
+alter table t1 rename key uu to uuu, add key c(c);
+show create table t1;
+alter table t1 rename key kkk to k, drop key uuu;
+show create table t1;
+alter table t1 rename key k to kk, rename to t2;
+show create table t2;
+drop table t2;
+
+
+--echo #
+--echo # 3) Test coverage for handling of RENAME INDEX clause in
+--echo # various storage engines and using different ALTER
+--echo # algorithm.
+--echo #
+--echo # 3.a) Test coverage for simple storage engines (MyISAM/Heap).
+create table t1 (i int, key k(i)) engine=myisam;
+insert into t1 values (1);
+create table t2 (i int, key k(i)) engine=memory;
+insert into t2 values (1);
+--echo # MyISAM and Heap should be able to handle key renaming in-place.
+alter table t1 algorithm=inplace, rename key k to kk;
+alter table t2 algorithm=inplace, rename key k to kk;
+show create table t1;
+show create table t2;
+--echo # So by default in-place algorithm should be chosen.
+--echo # (ALTER TABLE should report 0 rows affected).
+--enable_info
+alter table t1 rename key kk to kkk;
+alter table t2 rename key kk to kkk;
+--disable_info
+show create table t1;
+show create table t2;
+--echo # Copy algorithm should work as well.
+alter table t1 algorithm=copy, rename key kkk to kkkk;
+alter table t2 algorithm=copy, rename key kkk to kkkk;
+show create table t1;
+show create table t2;
+--echo # When renaming is combined with other in-place operation
+--echo # it still works as expected (i.e. works in-place).
+alter table t1 algorithm=inplace, rename key kkkk to k, alter column i set default 100;
+alter table t2 algorithm=inplace, rename key kkkk to k, alter column i set default 100;
+show create table t1;
+show create table t2;
+--echo # Combining with non-inplace operation results in the whole ALTER
+--echo # becoming non-inplace.
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+alter table t1 algorithm=inplace, rename key k to kk, add column j int;
+--error ER_ALTER_OPERATION_NOT_SUPPORTED
+alter table t2 algorithm=inplace, rename key k to kk, add column j int;
+drop table t1, t2;
+
+--echo # 3.b) Basic tests for InnoDB. More tests can be found in
+--echo # innodb.innodb_rename_index*
+create table t1 (i int, key k(i)) engine=innodb;
+insert into t1 values (1);
+--echo # Basic rename, inplace algorithm should be chosen
+--enable_info
+alter table t1 algorithm=inplace, rename key k to kk;
+--disable_info
+show create table t1;
+--echo # copy algorithm should work as well.
+--enable_info
+alter table t1 algorithm=copy, rename key kk to kkk;
+--disable_info
+show create table t1;
+drop table t1;
+
+--echo #
+--echo # 4) Additional coverage for complex cases in which code
+--echo # in ALTER TABLE comparing old and new table version
+--echo # got confused.
+--echo #
+--echo # Once InnoDB starts to support in-place index renaming the result
+--echo # of below statements should stay the same. Information about
+--echo # indexes returned by SHOW CREATE TABLE (from .FRM) and by
+--echo # InnoDB (from InnoDB data-dictionary) should be consistent.
+--echo #
+create table t1 ( a int, b int, c int, d int,
+ primary key (a), index i1 (b), index i2 (c) ) engine=innodb;
+alter table t1 add index i1 (d), rename index i1 to x;
+show create table t1;
+select i.name as k, f.name as c from information_schema.innodb_sys_tables as t,
+ information_schema.innodb_sys_indexes as i,
+ information_schema.innodb_sys_fields as f
+where t.name='test/t1' and t.table_id = i.table_id and i.index_id = f.index_id
+order by k, c;
+drop table t1;
+create table t1 (a int, b int, c int, d int,
+ primary key (a), index i1 (b), index i2 (c)) engine=innodb;
+alter table t1 add index i1 (d), rename index i1 to i2, drop index i2;
+show create table t1;
+select i.name as k, f.name as c from information_schema.innodb_sys_tables as t,
+ information_schema.innodb_sys_indexes as i,
+ information_schema.innodb_sys_fields as f
+where t.name='test/t1' and t.table_id = i.table_id and i.index_id = f.index_id
+order by k, c;
+drop table t1;
+
+--echo #
--echo # End of 10.5 tests
--echo #
diff --git a/mysql-test/suite/innodb/r/innodb-alter-debug.result b/mysql-test/suite/innodb/r/innodb-alter-debug.result
index 51ba58aa1ef..48722bbea44 100644
--- a/mysql-test/suite/innodb/r/innodb-alter-debug.result
+++ b/mysql-test/suite/innodb/r/innodb-alter-debug.result
@@ -98,3 +98,12 @@ disconnect con1;
connection default;
UNLOCK TABLES;
DROP TABLE t1;
+#
+# MDEV-7318 RENAME INDEX
+#
+CREATE TABLE t (c1 INT, c2 INT, KEY i2 (c2)) ENGINE=INNODB;
+SET DEBUG_DBUG= '+d,ib_rename_index_fail1';
+ALTER TABLE t RENAME INDEX i2 to x, ALGORITHM=INPLACE;
+ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
+SET DEBUG_DBUG= '-d,ib_rename_index_fail1';
+DROP TABLE t;
diff --git a/mysql-test/suite/innodb/r/innodb_rename_index.result b/mysql-test/suite/innodb/r/innodb_rename_index.result
new file mode 100644
index 00000000000..482070c4ffc
--- /dev/null
+++ b/mysql-test/suite/innodb/r/innodb_rename_index.result
@@ -0,0 +1,989 @@
+CREATE TABLE t (
+a INT,
+b INT,
+c INT,
+d INT,
+e INT,
+f INT,
+PRIMARY KEY (a),
+INDEX i1 (b),
+INDEX i2 (c),
+INDEX i3 (d),
+INDEX i4 (e)
+) ENGINE=INNODB;
+INSERT INTO t SET a = 1;
+ALTER TABLE t RENAME INDEX i1 TO GEN_CLUST_INDEX;
+ERROR 42000: Incorrect index name 'GEN_CLUST_INDEX'
+ALTER TABLE t RENAME INDEX i1 TO i1;
+ALTER TABLE t RENAME INDEX aa TO aa;
+ERROR 42000: Key 'aa' doesn't exist in table 't'
+# combination: aaaa
+ALTER TABLE t ADD INDEX i4(f), DROP INDEX i4, RENAME INDEX i4 TO i4;
+ERROR 42000: Key 'i4' doesn't exist in table 't'
+# combination: aabb
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX aa, RENAME INDEX i2 TO i2;
+ERROR 42000: Can't DROP INDEX `aa`; check that it exists
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX aa, RENAME INDEX bb TO bb;
+ERROR 42000: Can't DROP INDEX `aa`; check that it exists
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i1, RENAME INDEX bb TO bb;
+ERROR 42000: Key 'bb' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i1, RENAME INDEX i2 TO i2;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+SHOW CREATE TABLE t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ `e` int(11) DEFAULT NULL,
+ `f` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`),
+ KEY `i2` (`c`),
+ KEY `i3` (`d`),
+ KEY `i4` (`e`),
+ KEY `i1` (`f`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT
+t.name AS table_name,
+i.name AS index_name,
+f.name AS column_name
+FROM
+information_schema.innodb_sys_tables t,
+information_schema.innodb_sys_indexes i,
+information_schema.innodb_sys_fields f
+WHERE
+t.name LIKE '%/t' AND
+t.table_id = i.table_id AND
+i.index_id = f.index_id
+ORDER BY 1, 2, 3;
+table_name index_name column_name
+test/t i1 f
+test/t i2 c
+test/t i3 d
+test/t i4 e
+test/t PRIMARY a
+DROP TABLE t;
+CREATE TABLE t (
+a INT,
+b INT,
+c INT,
+d INT,
+e INT,
+f INT,
+PRIMARY KEY (a),
+INDEX i1 (b),
+INDEX i2 (c),
+INDEX i3 (d),
+INDEX i4 (e)
+) ENGINE=INNODB;
+INSERT INTO t SET a = 1;
+# combination: abcc
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX bb, RENAME INDEX cc TO cc;
+ERROR 42000: Can't DROP INDEX `bb`; check that it exists
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX bb, RENAME INDEX i3 TO i3;
+ERROR 42000: Can't DROP INDEX `bb`; check that it exists
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i2, RENAME INDEX cc TO cc;
+ERROR 42000: Key 'cc' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i2, RENAME INDEX i3 TO i3;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+SHOW CREATE TABLE t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ `e` int(11) DEFAULT NULL,
+ `f` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`),
+ KEY `i1` (`b`),
+ KEY `i3` (`d`),
+ KEY `i4` (`e`),
+ KEY `aa` (`f`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT
+t.name AS table_name,
+i.name AS index_name,
+f.name AS column_name
+FROM
+information_schema.innodb_sys_tables t,
+information_schema.innodb_sys_indexes i,
+information_schema.innodb_sys_fields f
+WHERE
+t.name LIKE '%/t' AND
+t.table_id = i.table_id AND
+i.index_id = f.index_id
+ORDER BY 1, 2, 3;
+table_name index_name column_name
+test/t aa f
+test/t i1 b
+test/t i3 d
+test/t i4 e
+test/t PRIMARY a
+DROP TABLE t;
+CREATE TABLE t (
+a INT,
+b INT,
+c INT,
+d INT,
+e INT,
+f INT,
+PRIMARY KEY (a),
+INDEX i1 (b),
+INDEX i2 (c),
+INDEX i3 (d),
+INDEX i4 (e)
+) ENGINE=INNODB;
+INSERT INTO t SET a = 1;
+# combination: abaa
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i1, RENAME INDEX aa TO aa;
+ERROR 42000: Key 'aa' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i2, RENAME INDEX i1 TO i1;
+ERROR 42000: Duplicate key name 'i1'
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX bb, RENAME INDEX i1 TO i1;
+ERROR 42000: Can't DROP INDEX `bb`; check that it exists
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX bb, RENAME INDEX aa TO aa;
+ERROR 42000: Can't DROP INDEX `bb`; check that it exists
+# combination: baaa
+ALTER TABLE t ADD INDEX i2(f), DROP INDEX i1, RENAME INDEX i1 TO i1;
+ERROR 42000: Key 'i1' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX bb(f), DROP INDEX i1, RENAME INDEX i1 TO i1;
+ERROR 42000: Key 'i1' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX i2(f), DROP INDEX aa, RENAME INDEX aa TO aa;
+ERROR 42000: Can't DROP INDEX `aa`; check that it exists
+ALTER TABLE t ADD INDEX bb(f), DROP INDEX aa, RENAME INDEX aa TO aa;
+ERROR 42000: Can't DROP INDEX `aa`; check that it exists
+ALTER TABLE t ADD INDEX aa(f), RENAME INDEX aa TO bb;
+ERROR 42000: Key 'aa' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX aa(f), RENAME INDEX bb TO aa;
+ERROR 42000: Key 'bb' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX aa(f), RENAME INDEX i2 TO aa;
+ERROR 42000: Duplicate key name 'aa'
+ALTER TABLE t ADD INDEX i1(f), RENAME INDEX i1 TO bb;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+SHOW CREATE TABLE t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ `e` int(11) DEFAULT NULL,
+ `f` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`),
+ KEY `bb` (`b`),
+ KEY `i2` (`c`),
+ KEY `i3` (`d`),
+ KEY `i4` (`e`),
+ KEY `i1` (`f`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT
+t.name AS table_name,
+i.name AS index_name,
+f.name AS column_name
+FROM
+information_schema.innodb_sys_tables t,
+information_schema.innodb_sys_indexes i,
+information_schema.innodb_sys_fields f
+WHERE
+t.name LIKE '%/t' AND
+t.table_id = i.table_id AND
+i.index_id = f.index_id
+ORDER BY 1, 2, 3;
+table_name index_name column_name
+test/t bb b
+test/t i1 f
+test/t i2 c
+test/t i3 d
+test/t i4 e
+test/t PRIMARY a
+DROP TABLE t;
+CREATE TABLE t (
+a INT,
+b INT,
+c INT,
+d INT,
+e INT,
+f INT,
+PRIMARY KEY (a),
+INDEX i1 (b),
+INDEX i2 (c),
+INDEX i3 (d),
+INDEX i4 (e)
+) ENGINE=INNODB;
+INSERT INTO t SET a = 1;
+# combination: abba
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i2, RENAME INDEX i2 TO i1;
+ERROR 42000: Key 'i2' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i2, RENAME INDEX i2 TO aa;
+ERROR 42000: Key 'i2' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX bb, RENAME INDEX bb TO i1;
+ERROR 42000: Can't DROP INDEX `bb`; check that it exists
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX bb, RENAME INDEX bb TO aa;
+ERROR 42000: Can't DROP INDEX `bb`; check that it exists
+# combination: cabc
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX i1, RENAME INDEX i2 TO i3;
+ERROR 42000: Duplicate key name 'i3'
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX aa, RENAME INDEX i2 TO i3;
+ERROR 42000: Can't DROP INDEX `aa`; check that it exists
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX i1, RENAME INDEX bb TO i3;
+ERROR 42000: Key 'bb' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX aa, RENAME INDEX bb TO i3;
+ERROR 42000: Can't DROP INDEX `aa`; check that it exists
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX i1, RENAME INDEX i2 TO cc;
+ERROR 42000: Duplicate key name 'cc'
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX aa, RENAME INDEX i2 TO cc;
+ERROR 42000: Can't DROP INDEX `aa`; check that it exists
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX i1, RENAME INDEX bb TO cc;
+ERROR 42000: Key 'bb' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX aa, RENAME INDEX bb TO cc;
+ERROR 42000: Can't DROP INDEX `aa`; check that it exists
+ALTER TABLE t DROP INDEX i1, RENAME INDEX i1 TO bb;
+ERROR 42000: Key 'i1' doesn't exist in table 't'
+ALTER TABLE t DROP INDEX aa, RENAME INDEX i2 TO aa;
+ERROR 42000: Can't DROP INDEX `aa`; check that it exists
+ALTER TABLE t DROP INDEX aa, RENAME INDEX aa TO i2;
+ERROR 42000: Can't DROP INDEX `aa`; check that it exists
+ALTER TABLE t DROP INDEX i1, RENAME INDEX i4 TO i1;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+SHOW CREATE TABLE t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ `e` int(11) DEFAULT NULL,
+ `f` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`),
+ KEY `i2` (`c`),
+ KEY `i3` (`d`),
+ KEY `i1` (`e`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT
+t.name AS table_name,
+i.name AS index_name,
+f.name AS column_name
+FROM
+information_schema.innodb_sys_tables t,
+information_schema.innodb_sys_indexes i,
+information_schema.innodb_sys_fields f
+WHERE
+t.name LIKE '%/t' AND
+t.table_id = i.table_id AND
+i.index_id = f.index_id
+ORDER BY 1, 2, 3;
+table_name index_name column_name
+test/t i1 e
+test/t i2 c
+test/t i3 d
+test/t PRIMARY a
+DROP TABLE t;
+CREATE TABLE t (
+a INT,
+b INT,
+c INT,
+d INT,
+e INT,
+f INT,
+PRIMARY KEY (a),
+INDEX i1 (b),
+INDEX i2 (c),
+INDEX i3 (d),
+INDEX i4 (e)
+) ENGINE=INNODB;
+INSERT INTO t SET a = 1;
+# combination: accb
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i3, RENAME INDEX i3 TO i2;
+ERROR 42000: Key 'i3' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i3, RENAME INDEX i3 TO bb;
+ERROR 42000: Key 'i3' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX cc, RENAME INDEX cc TO i2;
+ERROR 42000: Can't DROP INDEX `cc`; check that it exists
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX cc, RENAME INDEX cc TO bb;
+ERROR 42000: Can't DROP INDEX `cc`; check that it exists
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX cc, RENAME INDEX cc TO i2;
+ERROR 42000: Can't DROP INDEX `cc`; check that it exists
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX cc, RENAME INDEX cc TO bb;
+ERROR 42000: Can't DROP INDEX `cc`; check that it exists
+# combination: aaab
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i1, RENAME INDEX i1 TO i2;
+ERROR 42000: Key 'i1' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i1, RENAME INDEX i1 TO bb;
+ERROR 42000: Key 'i1' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i1, RENAME INDEX i1 TO i2;
+ERROR 42000: Key 'i1' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX aa, RENAME INDEX aa TO bb;
+ERROR 42000: Can't DROP INDEX `aa`; check that it exists
+# combination: abcd
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i2, RENAME INDEX cc TO i4;
+ERROR 42000: Key 'cc' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i2, RENAME INDEX cc TO dd;
+ERROR 42000: Key 'cc' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i2, RENAME INDEX cc TO i4;
+ERROR 42000: Key 'cc' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i2, RENAME INDEX cc TO dd;
+ERROR 42000: Key 'cc' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i2, RENAME INDEX i3 TO i4;
+ERROR 42000: Duplicate key name 'i4'
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i2, RENAME INDEX i3 TO dd;
+ERROR 42000: Duplicate key name 'i1'
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i2, RENAME INDEX i3 TO i4;
+ERROR 42000: Duplicate key name 'i4'
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i2, RENAME INDEX i3 TO dd;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+SHOW CREATE TABLE t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ `e` int(11) DEFAULT NULL,
+ `f` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`),
+ KEY `i1` (`b`),
+ KEY `dd` (`d`),
+ KEY `i4` (`e`),
+ KEY `aa` (`f`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT
+t.name AS table_name,
+i.name AS index_name,
+f.name AS column_name
+FROM
+information_schema.innodb_sys_tables t,
+information_schema.innodb_sys_indexes i,
+information_schema.innodb_sys_fields f
+WHERE
+t.name LIKE '%/t' AND
+t.table_id = i.table_id AND
+i.index_id = f.index_id
+ORDER BY 1, 2, 3;
+table_name index_name column_name
+test/t aa f
+test/t dd d
+test/t i1 b
+test/t i4 e
+test/t PRIMARY a
+DROP TABLE t;
+CREATE TABLE t (
+a INT,
+b INT,
+c INT,
+d INT,
+e INT,
+f INT,
+PRIMARY KEY (a),
+INDEX i1 (b),
+INDEX i2 (c),
+INDEX i3 (d),
+INDEX i4 (e)
+) ENGINE=INNODB;
+INSERT INTO t SET a = 1;
+# combination: abab
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i2, RENAME INDEX i1 TO i2;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+SHOW CREATE TABLE t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ `e` int(11) DEFAULT NULL,
+ `f` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`),
+ KEY `i2` (`b`),
+ KEY `i3` (`d`),
+ KEY `i4` (`e`),
+ KEY `i1` (`f`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT
+t.name AS table_name,
+i.name AS index_name,
+f.name AS column_name
+FROM
+information_schema.innodb_sys_tables t,
+information_schema.innodb_sys_indexes i,
+information_schema.innodb_sys_fields f
+WHERE
+t.name LIKE '%/t' AND
+t.table_id = i.table_id AND
+i.index_id = f.index_id
+ORDER BY 1, 2, 3;
+table_name index_name column_name
+test/t i1 f
+test/t i2 b
+test/t i3 d
+test/t i4 e
+test/t PRIMARY a
+DROP TABLE t;
+CREATE TABLE t (
+a INT,
+b INT,
+c INT,
+d INT,
+e INT,
+f INT,
+PRIMARY KEY (a),
+INDEX i1 (b),
+INDEX i2 (c),
+INDEX i3 (d),
+INDEX i4 (e)
+) ENGINE=INNODB;
+INSERT INTO t SET a = 1;
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX bb, RENAME INDEX i1 TO bb;
+ERROR 42000: Can't DROP INDEX `bb`; check that it exists
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i2, RENAME INDEX aa TO i2;
+ERROR 42000: Key 'aa' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX bb, RENAME INDEX aa TO bb;
+ERROR 42000: Can't DROP INDEX `bb`; check that it exists
+# combination: acbc
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX cc, RENAME INDEX i2 TO cc;
+ERROR 42000: Can't DROP INDEX `cc`; check that it exists
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX cc, RENAME INDEX i2 TO cc;
+ERROR 42000: Can't DROP INDEX `cc`; check that it exists
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX cc, RENAME INDEX bb TO cc;
+ERROR 42000: Can't DROP INDEX `cc`; check that it exists
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX cc, RENAME INDEX bb TO cc;
+ERROR 42000: Can't DROP INDEX `cc`; check that it exists
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i3, RENAME INDEX bb TO i3;
+ERROR 42000: Key 'bb' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i3, RENAME INDEX bb TO i3;
+ERROR 42000: Key 'bb' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i3, RENAME INDEX i2 TO i3;
+ERROR 42000: Duplicate key name 'i1'
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i3, RENAME INDEX i2 TO i3;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+SHOW CREATE TABLE t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ `e` int(11) DEFAULT NULL,
+ `f` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`),
+ KEY `i1` (`b`),
+ KEY `i3` (`c`),
+ KEY `i4` (`e`),
+ KEY `aa` (`f`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT
+t.name AS table_name,
+i.name AS index_name,
+f.name AS column_name
+FROM
+information_schema.innodb_sys_tables t,
+information_schema.innodb_sys_indexes i,
+information_schema.innodb_sys_fields f
+WHERE
+t.name LIKE '%/t' AND
+t.table_id = i.table_id AND
+i.index_id = f.index_id
+ORDER BY 1, 2, 3;
+table_name index_name column_name
+test/t aa f
+test/t i1 b
+test/t i3 c
+test/t i4 e
+test/t PRIMARY a
+DROP TABLE t;
+CREATE TABLE t (
+a INT,
+b INT,
+c INT,
+d INT,
+e INT,
+f INT,
+PRIMARY KEY (a),
+INDEX i1 (b),
+INDEX i2 (c),
+INDEX i3 (d),
+INDEX i4 (e)
+) ENGINE=INNODB;
+INSERT INTO t SET a = 1;
+# combination: cacb
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX i1, RENAME INDEX cc TO i2;
+ERROR 42000: Key 'cc' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX aa, RENAME INDEX cc TO i2;
+ERROR 42000: Can't DROP INDEX `aa`; check that it exists
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX aa, RENAME INDEX cc TO bb;
+ERROR 42000: Can't DROP INDEX `aa`; check that it exists
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX i1, RENAME INDEX cc TO bb;
+ERROR 42000: Key 'cc' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX i1, RENAME INDEX i3 TO i2;
+ERROR 42000: Duplicate key name 'i2'
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX aa, RENAME INDEX i3 TO i2;
+ERROR 42000: Can't DROP INDEX `aa`; check that it exists
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX aa, RENAME INDEX i3 TO bb;
+ERROR 42000: Can't DROP INDEX `aa`; check that it exists
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX i1, RENAME INDEX i3 TO bb;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+SHOW CREATE TABLE t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ `e` int(11) DEFAULT NULL,
+ `f` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`),
+ KEY `i2` (`c`),
+ KEY `bb` (`d`),
+ KEY `i4` (`e`),
+ KEY `i3` (`f`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT
+t.name AS table_name,
+i.name AS index_name,
+f.name AS column_name
+FROM
+information_schema.innodb_sys_tables t,
+information_schema.innodb_sys_indexes i,
+information_schema.innodb_sys_fields f
+WHERE
+t.name LIKE '%/t' AND
+t.table_id = i.table_id AND
+i.index_id = f.index_id
+ORDER BY 1, 2, 3;
+table_name index_name column_name
+test/t bb d
+test/t i2 c
+test/t i3 f
+test/t i4 e
+test/t PRIMARY a
+DROP TABLE t;
+CREATE TABLE t (
+a INT,
+b INT,
+c INT,
+d INT,
+e INT,
+f INT,
+PRIMARY KEY (a),
+INDEX i1 (b),
+INDEX i2 (c),
+INDEX i3 (d),
+INDEX i4 (e)
+) ENGINE=INNODB;
+INSERT INTO t SET a = 1;
+# combination: ccab
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX cc, RENAME INDEX i1 TO i2;
+ERROR 42000: Can't DROP INDEX `cc`; check that it exists
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX cc, RENAME INDEX i1 TO bb;
+ERROR 42000: Can't DROP INDEX `cc`; check that it exists
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX cc, RENAME INDEX aa TO i2;
+ERROR 42000: Can't DROP INDEX `cc`; check that it exists
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX cc, RENAME INDEX aa TO bb;
+ERROR 42000: Can't DROP INDEX `cc`; check that it exists
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX cc, RENAME INDEX aa TO i2;
+ERROR 42000: Can't DROP INDEX `cc`; check that it exists
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX cc, RENAME INDEX aa TO bb;
+ERROR 42000: Can't DROP INDEX `cc`; check that it exists
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX i3, RENAME INDEX i1 TO i2;
+ERROR 42000: Duplicate key name 'i2'
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX i3, RENAME INDEX i1 TO bb;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+SHOW CREATE TABLE t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ `e` int(11) DEFAULT NULL,
+ `f` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`),
+ KEY `bb` (`b`),
+ KEY `i2` (`c`),
+ KEY `i4` (`e`),
+ KEY `i3` (`f`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT
+t.name AS table_name,
+i.name AS index_name,
+f.name AS column_name
+FROM
+information_schema.innodb_sys_tables t,
+information_schema.innodb_sys_indexes i,
+information_schema.innodb_sys_fields f
+WHERE
+t.name LIKE '%/t' AND
+t.table_id = i.table_id AND
+i.index_id = f.index_id
+ORDER BY 1, 2, 3;
+table_name index_name column_name
+test/t bb b
+test/t i2 c
+test/t i3 f
+test/t i4 e
+test/t PRIMARY a
+DROP TABLE t;
+CREATE TABLE t (
+a INT,
+b INT,
+c INT,
+d INT,
+e INT,
+f INT,
+PRIMARY KEY (a),
+INDEX i1 (b),
+INDEX i2 (c),
+INDEX i3 (d),
+INDEX i4 (e)
+) ENGINE=INNODB;
+INSERT INTO t SET a = 1;
+ALTER TABLE t RENAME INDEX i1 TO x;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+SHOW CREATE TABLE t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ `e` int(11) DEFAULT NULL,
+ `f` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`),
+ KEY `x` (`b`),
+ KEY `i2` (`c`),
+ KEY `i3` (`d`),
+ KEY `i4` (`e`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT
+t.name AS table_name,
+i.name AS index_name,
+f.name AS column_name
+FROM
+information_schema.innodb_sys_tables t,
+information_schema.innodb_sys_indexes i,
+information_schema.innodb_sys_fields f
+WHERE
+t.name LIKE '%/t' AND
+t.table_id = i.table_id AND
+i.index_id = f.index_id
+ORDER BY 1, 2, 3;
+table_name index_name column_name
+test/t i2 c
+test/t i3 d
+test/t i4 e
+test/t PRIMARY a
+test/t x b
+DROP TABLE t;
+CREATE TABLE t (
+a INT,
+b INT,
+c INT,
+d INT,
+e INT,
+f INT,
+PRIMARY KEY (a),
+INDEX i1 (b),
+INDEX i2 (c),
+INDEX i3 (d),
+INDEX i4 (e)
+) ENGINE=INNODB;
+INSERT INTO t SET a = 1;
+ALTER TABLE t RENAME INDEX i1 TO i2;
+ERROR 42000: Duplicate key name 'i2'
+ALTER TABLE t RENAME INDEX foo TO i1;
+ERROR 42000: Key 'foo' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX i9 (f), RENAME INDEX i1 TO i8;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+SHOW CREATE TABLE t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ `e` int(11) DEFAULT NULL,
+ `f` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`),
+ KEY `i8` (`b`),
+ KEY `i2` (`c`),
+ KEY `i3` (`d`),
+ KEY `i4` (`e`),
+ KEY `i9` (`f`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT
+t.name AS table_name,
+i.name AS index_name,
+f.name AS column_name
+FROM
+information_schema.innodb_sys_tables t,
+information_schema.innodb_sys_indexes i,
+information_schema.innodb_sys_fields f
+WHERE
+t.name LIKE '%/t' AND
+t.table_id = i.table_id AND
+i.index_id = f.index_id
+ORDER BY 1, 2, 3;
+table_name index_name column_name
+test/t i2 c
+test/t i3 d
+test/t i4 e
+test/t i8 b
+test/t i9 f
+test/t PRIMARY a
+DROP TABLE t;
+CREATE TABLE t (
+a INT,
+b INT,
+c INT,
+d INT,
+e INT,
+f INT,
+PRIMARY KEY (a),
+INDEX i1 (b),
+INDEX i2 (c),
+INDEX i3 (d),
+INDEX i4 (e)
+) ENGINE=INNODB;
+INSERT INTO t SET a = 1;
+ALTER TABLE t ADD INDEX i1 (f), RENAME INDEX i1 TO i9;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+SHOW CREATE TABLE t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ `e` int(11) DEFAULT NULL,
+ `f` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`),
+ KEY `i9` (`b`),
+ KEY `i2` (`c`),
+ KEY `i3` (`d`),
+ KEY `i4` (`e`),
+ KEY `i1` (`f`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT
+t.name AS table_name,
+i.name AS index_name,
+f.name AS column_name
+FROM
+information_schema.innodb_sys_tables t,
+information_schema.innodb_sys_indexes i,
+information_schema.innodb_sys_fields f
+WHERE
+t.name LIKE '%/t' AND
+t.table_id = i.table_id AND
+i.index_id = f.index_id
+ORDER BY 1, 2, 3;
+table_name index_name column_name
+test/t i1 f
+test/t i2 c
+test/t i3 d
+test/t i4 e
+test/t i9 b
+test/t PRIMARY a
+DROP TABLE t;
+CREATE TABLE t (
+a INT,
+b INT,
+c INT,
+d INT,
+e INT,
+f INT,
+PRIMARY KEY (a),
+INDEX i1 (b),
+INDEX i2 (c),
+INDEX i3 (d),
+INDEX i4 (e)
+) ENGINE=INNODB;
+INSERT INTO t SET a = 1;
+ALTER TABLE t ADD INDEX foo (f), RENAME INDEX i1 TO foo;
+ERROR 42000: Duplicate key name 'foo'
+ALTER TABLE t ADD INDEX i1 (f), RENAME INDEX i1 TO foo, DROP INDEX i1;
+ERROR 42000: Key 'i1' doesn't exist in table 't'
+ALTER TABLE t ADD INDEX i1 (f), RENAME INDEX i1 TO foo, DROP INDEX foo;
+ERROR 42000: Can't DROP INDEX `foo`; check that it exists
+ALTER TABLE t ADD INDEX foo (f), RENAME INDEX foo TO bar, DROP INDEX foo;
+ERROR 42000: Can't DROP INDEX `foo`; check that it exists
+ALTER TABLE t RENAME INDEX i1 TO x, RENAME INDEX i2 TO x;
+ERROR 42000: Duplicate key name 'x'
+ALTER TABLE t RENAME INDEX i1 TO x, RENAME INDEX i1 TO y;
+ERROR 42000: Key 'i1' doesn't exist in table 't'
+ALTER TABLE t RENAME INDEX i1 TO x, RENAME INDEX i1 TO x;
+ERROR 42000: Key 'i1' doesn't exist in table 't'
+SHOW CREATE TABLE t;
+Table Create Table
+t CREATE TABLE `t` (
+ `a` int(11) NOT NULL,
+ `b` int(11) DEFAULT NULL,
+ `c` int(11) DEFAULT NULL,
+ `d` int(11) DEFAULT NULL,
+ `e` int(11) DEFAULT NULL,
+ `f` int(11) DEFAULT NULL,
+ PRIMARY KEY (`a`),
+ KEY `i1` (`b`),
+ KEY `i2` (`c`),
+ KEY `i3` (`d`),
+ KEY `i4` (`e`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT
+t.name AS table_name,
+i.name AS index_name,
+f.name AS column_name
+FROM
+information_schema.innodb_sys_tables t,
+information_schema.innodb_sys_indexes i,
+information_schema.innodb_sys_fields f
+WHERE
+t.name LIKE '%/t' AND
+t.table_id = i.table_id AND
+i.index_id = f.index_id
+ORDER BY 1, 2, 3;
+table_name index_name column_name
+test/t i1 b
+test/t i2 c
+test/t i3 d
+test/t i4 e
+test/t PRIMARY a
+DROP TABLE t;
+CREATE TABLE t (
+c1 INT NOT NULL,
+c2 INT NOT NULL,
+c3 INT,
+c4 INT,
+PRIMARY KEY (c1),
+INDEX i1 (c3),
+INDEX i2 (c4)
+) ENGINE=INNODB;
+INSERT INTO t SET c1=1, c2=2;
+ALTER TABLE t DROP PRIMARY KEY, ADD PRIMARY KEY (c2), RENAME INDEX i1 TO x;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+SHOW CREATE TABLE t;
+Table Create Table
+t CREATE TABLE `t` (
+ `c1` int(11) NOT NULL,
+ `c2` int(11) NOT NULL,
+ `c3` int(11) DEFAULT NULL,
+ `c4` int(11) DEFAULT NULL,
+ PRIMARY KEY (`c2`),
+ KEY `x` (`c3`),
+ KEY `i2` (`c4`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT
+t.name AS table_name,
+i.name AS index_name,
+f.name AS column_name
+FROM
+information_schema.innodb_sys_tables t,
+information_schema.innodb_sys_indexes i,
+information_schema.innodb_sys_fields f
+WHERE
+t.name LIKE '%/t' AND
+t.table_id = i.table_id AND
+i.index_id = f.index_id
+ORDER BY 1, 2, 3;
+table_name index_name column_name
+test/t i2 c4
+test/t PRIMARY c2
+test/t x c3
+ALTER TABLE t RENAME INDEX i2 TO y, ROW_FORMAT=REDUNDANT;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+SHOW CREATE TABLE t;
+Table Create Table
+t CREATE TABLE `t` (
+ `c1` int(11) NOT NULL,
+ `c2` int(11) NOT NULL,
+ `c3` int(11) DEFAULT NULL,
+ `c4` int(11) DEFAULT NULL,
+ PRIMARY KEY (`c2`),
+ KEY `x` (`c3`),
+ KEY `y` (`c4`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=REDUNDANT
+SELECT
+t.name AS table_name,
+i.name AS index_name,
+f.name AS column_name
+FROM
+information_schema.innodb_sys_tables t,
+information_schema.innodb_sys_indexes i,
+information_schema.innodb_sys_fields f
+WHERE
+t.name LIKE '%/t' AND
+t.table_id = i.table_id AND
+i.index_id = f.index_id
+ORDER BY 1, 2, 3;
+table_name index_name column_name
+test/t PRIMARY c2
+test/t x c3
+test/t y c4
+DROP TABLE t;
+CREATE TABLE t (
+c1 INT NOT NULL,
+c2 INT,
+c3 INT,
+INDEX i1 (c2),
+INDEX i2 (c3)
+) ENGINE=INNODB;
+INSERT INTO t SET c1=1;
+ALTER TABLE t ADD PRIMARY KEY (c1), RENAME INDEX i1 TO x;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+SHOW CREATE TABLE t;
+Table Create Table
+t CREATE TABLE `t` (
+ `c1` int(11) NOT NULL,
+ `c2` int(11) DEFAULT NULL,
+ `c3` int(11) DEFAULT NULL,
+ PRIMARY KEY (`c1`),
+ KEY `x` (`c2`),
+ KEY `i2` (`c3`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+SELECT
+t.name AS table_name,
+i.name AS index_name,
+f.name AS column_name
+FROM
+information_schema.innodb_sys_tables t,
+information_schema.innodb_sys_indexes i,
+information_schema.innodb_sys_fields f
+WHERE
+t.name LIKE '%/t' AND
+t.table_id = i.table_id AND
+i.index_id = f.index_id
+ORDER BY 1, 2, 3;
+table_name index_name column_name
+test/t i2 c3
+test/t PRIMARY c1
+test/t x c2
+DROP TABLE t;
+CREATE TABLE t (a INT, INDEX iiiii (a)) ENGINE=INNODB;
+INSERT INTO t SET a=NULL;
+ALTER TABLE t RENAME INDEX iiiii TO i;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE t RENAME INDEX i TO iiiii;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE t RENAME INDEX iiiii TO i;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+ALTER TABLE t RENAME INDEX i TO iiiii;
+affected rows: 0
+info: Records: 0 Duplicates: 0 Warnings: 0
+DROP TABLE t;
diff --git a/mysql-test/suite/innodb/t/innodb-alter-debug.test b/mysql-test/suite/innodb/t/innodb-alter-debug.test
index 00300bfdccc..792716aeb4e 100644
--- a/mysql-test/suite/innodb/t/innodb-alter-debug.test
+++ b/mysql-test/suite/innodb/t/innodb-alter-debug.test
@@ -132,3 +132,15 @@ DROP TABLE t1;
# Wait till all disconnects are completed
--source include/wait_until_count_sessions.inc
+
+--echo #
+--echo # MDEV-7318 RENAME INDEX
+--echo #
+CREATE TABLE t (c1 INT, c2 INT, KEY i2 (c2)) ENGINE=INNODB;
+
+SET DEBUG_DBUG= '+d,ib_rename_index_fail1';
+-- error ER_LOCK_DEADLOCK
+ALTER TABLE t RENAME INDEX i2 to x, ALGORITHM=INPLACE;
+SET DEBUG_DBUG= '-d,ib_rename_index_fail1';
+
+DROP TABLE t;
diff --git a/mysql-test/suite/innodb/t/innodb_rename_index.test b/mysql-test/suite/innodb/t/innodb_rename_index.test
new file mode 100644
index 00000000000..9236259b279
--- /dev/null
+++ b/mysql-test/suite/innodb/t/innodb_rename_index.test
@@ -0,0 +1,538 @@
+--source include/have_innodb.inc
+
+#
+# Test "ALTER TABLE ... RENAME INDEX" in InnoDB
+#
+
+let create =
+CREATE TABLE t (
+ a INT,
+ b INT,
+ c INT,
+ d INT,
+ e INT,
+ f INT,
+ PRIMARY KEY (a),
+ INDEX i1 (b),
+ INDEX i2 (c),
+ INDEX i3 (d),
+ INDEX i4 (e)
+) ENGINE=INNODB;
+
+let insert = INSERT INTO t SET a = 1;
+
+let show_table =
+SHOW CREATE TABLE t;
+
+let show_sys =
+SELECT
+t.name AS table_name,
+i.name AS index_name,
+f.name AS column_name
+FROM
+information_schema.innodb_sys_tables t,
+information_schema.innodb_sys_indexes i,
+information_schema.innodb_sys_fields f
+WHERE
+t.name LIKE '%/t' AND
+t.table_id = i.table_id AND
+i.index_id = f.index_id
+ORDER BY 1, 2, 3;
+
+-- eval $create
+
+# Add a row, so that affected rows would be nonzero for ALGORITHM=COPY.
+# ALGORITHM=INPLACE will report 0 affected row in the result file.
+# We will have enable_info/disable_info around every successful ALTER
+# to enable the affected rows: output in the result file.
+-- eval $insert
+
+-- error ER_WRONG_NAME_FOR_INDEX
+ALTER TABLE t RENAME INDEX i1 TO GEN_CLUST_INDEX;
+
+# Test all combinations of ADD w, DROP x, RENAME y TO z.
+#
+# Use the following names for wxyz (with 1 to 4 of wxyz being the same):
+# aaaa abcd aabb abab abba abcc acbc accb cacb cabc ccab aaab aaba abaa baaa
+#
+# Some cases should trivially succeed or fail. Test them in isolation:
+# no-op: y=z (RENAME y TO y)
+# rules out the combinations ..\(.\)\1
+# a.k.a. aaaa aabb abcc abaa baaa
+
+# We use the index names i1 to i4 for existing indexes abcd.
+# Non-existing index names will be aa,bb,cc,dd.
+# Index creation on non-existing columns will not be tested.
+
+ALTER TABLE t RENAME INDEX i1 TO i1;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t RENAME INDEX aa TO aa;
+
+-- echo # combination: aaaa
+# drop/add existing, null rename and drop the same
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX i4(f), DROP INDEX i4, RENAME INDEX i4 TO i4;
+
+-- echo # combination: aabb
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX aa, RENAME INDEX i2 TO i2;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX aa, RENAME INDEX bb TO bb;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i1, RENAME INDEX bb TO bb;
+
+-- enable_info
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i1, RENAME INDEX i2 TO i2;
+-- disable_info
+-- eval $show_table
+-- eval $show_sys
+DROP TABLE t;
+-- eval $create
+-- eval $insert
+
+-- echo # combination: abcc
+
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX bb, RENAME INDEX cc TO cc;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX bb, RENAME INDEX i3 TO i3;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i2, RENAME INDEX cc TO cc;
+
+# rename existing (succeeds)
+-- enable_info
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i2, RENAME INDEX i3 TO i3;
+-- disable_info
+-- eval $show_table
+-- eval $show_sys
+DROP TABLE t;
+-- eval $create
+-- eval $insert
+
+-- echo # combination: abaa
+
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i1, RENAME INDEX aa TO aa;
+-- error ER_DUP_KEYNAME
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i2, RENAME INDEX i1 TO i1;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX bb, RENAME INDEX i1 TO i1;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX bb, RENAME INDEX aa TO aa;
+
+-- echo # combination: baaa
+
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX i2(f), DROP INDEX i1, RENAME INDEX i1 TO i1;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX bb(f), DROP INDEX i1, RENAME INDEX i1 TO i1;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX i2(f), DROP INDEX aa, RENAME INDEX aa TO aa;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX bb(f), DROP INDEX aa, RENAME INDEX aa TO aa;
+
+# refuse: w=z (ADD w, RENAME y TO w)
+# rules out the combinations \(.\)..\1
+# a.k.a. aaaa abba cabc aaba abaa
+# the case w=y (ADD w, RENAME w to z) may succeed, as seen below
+
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX aa(f), RENAME INDEX aa TO bb;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX aa(f), RENAME INDEX bb TO aa;
+-- error ER_DUP_KEYNAME
+ALTER TABLE t ADD INDEX aa(f), RENAME INDEX i2 TO aa;
+
+# rename existing, add one with the same name
+-- enable_info
+ALTER TABLE t ADD INDEX i1(f), RENAME INDEX i1 TO bb;
+-- disable_info
+-- eval $show_table
+-- eval $show_sys
+DROP TABLE t;
+-- eval $create
+-- eval $insert
+
+-- echo # combination: abba
+
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i2, RENAME INDEX i2 TO i1;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i2, RENAME INDEX i2 TO aa;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX bb, RENAME INDEX bb TO i1;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX bb, RENAME INDEX bb TO aa;
+
+-- echo # combination: cabc
+
+-- error ER_DUP_KEYNAME
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX i1, RENAME INDEX i2 TO i3;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX aa, RENAME INDEX i2 TO i3;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX i1, RENAME INDEX bb TO i3;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX aa, RENAME INDEX bb TO i3;
+
+-- error ER_DUP_KEYNAME
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX i1, RENAME INDEX i2 TO cc;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX aa, RENAME INDEX i2 TO cc;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX i1, RENAME INDEX bb TO cc;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX aa, RENAME INDEX bb TO cc;
+
+# refuse: x=y (DROP x, RENAME x TO z)
+# rules out the combinations .\(.\)\1.
+# a.k.a. aaaa abba accb aaab baaa
+
+# rename and drop the same
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t DROP INDEX i1, RENAME INDEX i1 TO bb;
+# drop non-existing
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t DROP INDEX aa, RENAME INDEX i2 TO aa;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t DROP INDEX aa, RENAME INDEX aa TO i2;
+
+# this one will succeed (drop, replace with an existing one)
+-- enable_info
+ALTER TABLE t DROP INDEX i1, RENAME INDEX i4 TO i1;
+-- disable_info
+-- eval $show_table
+-- eval $show_sys
+DROP TABLE t;
+-- eval $create
+-- eval $insert
+
+-- echo # combination: accb
+
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i3, RENAME INDEX i3 TO i2;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i3, RENAME INDEX i3 TO bb;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX cc, RENAME INDEX cc TO i2;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX cc, RENAME INDEX cc TO bb;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX cc, RENAME INDEX cc TO i2;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX cc, RENAME INDEX cc TO bb;
+
+-- echo # combination: aaab
+
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i1, RENAME INDEX i1 TO i2;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i1, RENAME INDEX i1 TO bb;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i1, RENAME INDEX i1 TO i2;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX aa, RENAME INDEX aa TO bb;
+
+# Remaining combinations: abcd abab acbc cacb ccab
+
+-- echo # combination: abcd
+
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i2, RENAME INDEX cc TO i4;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i2, RENAME INDEX cc TO dd;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i2, RENAME INDEX cc TO i4;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i2, RENAME INDEX cc TO dd;
+
+# add existing, rename to existing
+-- error ER_DUP_KEYNAME
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i2, RENAME INDEX i3 TO i4;
+# add existing
+-- error ER_DUP_KEYNAME
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i2, RENAME INDEX i3 TO dd;
+# rename to existing
+-- error ER_DUP_KEYNAME
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i2, RENAME INDEX i3 TO i4;
+
+-- enable_info
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i2, RENAME INDEX i3 TO dd;
+-- disable_info
+-- eval $show_table
+-- eval $show_sys
+DROP TABLE t;
+-- eval $create
+-- eval $insert
+
+-- echo # combination: abab
+
+-- enable_info
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i2, RENAME INDEX i1 TO i2;
+-- disable_info
+-- eval $show_table
+-- eval $show_sys
+DROP TABLE t;
+-- eval $create
+-- eval $insert
+
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX bb, RENAME INDEX i1 TO bb;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i2, RENAME INDEX aa TO i2;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX bb, RENAME INDEX aa TO bb;
+
+-- echo # combination: acbc
+
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX cc, RENAME INDEX i2 TO cc;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX cc, RENAME INDEX i2 TO cc;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX cc, RENAME INDEX bb TO cc;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX cc, RENAME INDEX bb TO cc;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i3, RENAME INDEX bb TO i3;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i3, RENAME INDEX bb TO i3;
+
+# add existing
+-- error ER_DUP_KEYNAME
+ALTER TABLE t ADD INDEX i1(f), DROP INDEX i3, RENAME INDEX i2 TO i3;
+
+-- enable_info
+ALTER TABLE t ADD INDEX aa(f), DROP INDEX i3, RENAME INDEX i2 TO i3;
+-- disable_info
+-- eval $show_table
+-- eval $show_sys
+DROP TABLE t;
+-- eval $create
+-- eval $insert
+
+-- echo # combination: cacb
+
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX i1, RENAME INDEX cc TO i2;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX aa, RENAME INDEX cc TO i2;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX aa, RENAME INDEX cc TO bb;
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX i1, RENAME INDEX cc TO bb;
+
+-- error ER_DUP_KEYNAME
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX i1, RENAME INDEX i3 TO i2;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX aa, RENAME INDEX i3 TO i2;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX aa, RENAME INDEX i3 TO bb;
+
+-- enable_info
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX i1, RENAME INDEX i3 TO bb;
+-- disable_info
+-- eval $show_table
+-- eval $show_sys
+DROP TABLE t;
+-- eval $create
+-- eval $insert
+
+-- echo # combination: ccab
+
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX cc, RENAME INDEX i1 TO i2;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX cc, RENAME INDEX i1 TO bb;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX cc, RENAME INDEX aa TO i2;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX cc(f), DROP INDEX cc, RENAME INDEX aa TO bb;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX cc, RENAME INDEX aa TO i2;
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX cc, RENAME INDEX aa TO bb;
+
+-- error ER_DUP_KEYNAME
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX i3, RENAME INDEX i1 TO i2;
+
+-- enable_info
+ALTER TABLE t ADD INDEX i3(f), DROP INDEX i3, RENAME INDEX i1 TO bb;
+-- disable_info
+-- eval $show_table
+-- eval $show_sys
+DROP TABLE t;
+-- eval $create
+-- eval $insert
+
+# A simple successful ALTER
+-- enable_info
+ALTER TABLE t RENAME INDEX i1 TO x;
+-- disable_info
+-- eval $show_table
+-- eval $show_sys
+DROP TABLE t;
+-- eval $create
+-- eval $insert
+
+-- error ER_DUP_KEYNAME
+ALTER TABLE t RENAME INDEX i1 TO i2;
+
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t RENAME INDEX foo TO i1;
+
+# Test ADD INDEX, RENAME INDEX
+
+-- enable_info
+ALTER TABLE t ADD INDEX i9 (f), RENAME INDEX i1 TO i8;
+-- disable_info
+-- eval $show_table
+-- eval $show_sys
+DROP TABLE t;
+-- eval $create
+-- eval $insert
+
+-- enable_info
+ALTER TABLE t ADD INDEX i1 (f), RENAME INDEX i1 TO i9;
+-- disable_info
+-- eval $show_table
+-- eval $show_sys
+DROP TABLE t;
+-- eval $create
+-- eval $insert
+
+-- error ER_DUP_KEYNAME
+ALTER TABLE t ADD INDEX foo (f), RENAME INDEX i1 TO foo;
+
+# Test ADD INDEX, RENAME INDEX, DROP INDEX
+
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t ADD INDEX i1 (f), RENAME INDEX i1 TO foo, DROP INDEX i1;
+
+-- error ER_CANT_DROP_FIELD_OR_KEY
+ALTER TABLE t ADD INDEX i1 (f), RENAME INDEX i1 TO foo, DROP INDEX foo;
+
+-- error ER_CANT_DROP_FIELD_OR_KEY
+# "ALTER TABLE t ADD INDEX foo (d), DROP INDEX foo;" alone fails with the
+# same error code, but we have that test here anyway
+ALTER TABLE t ADD INDEX foo (f), RENAME INDEX foo TO bar, DROP INDEX foo;
+
+# Test RENAME INDEX, RENAME INDEX
+
+-- error ER_DUP_KEYNAME
+ALTER TABLE t RENAME INDEX i1 TO x, RENAME INDEX i2 TO x;
+
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t RENAME INDEX i1 TO x, RENAME INDEX i1 TO y;
+
+-- error ER_KEY_DOES_NOT_EXITS
+ALTER TABLE t RENAME INDEX i1 TO x, RENAME INDEX i1 TO x;
+
+# show that the table did not change after all the erroneous ALTERs
+-- eval $show_table
+-- eval $show_sys
+
+DROP TABLE t;
+
+# now test the rebuild case (new clustered index)
+
+CREATE TABLE t (
+ c1 INT NOT NULL,
+ c2 INT NOT NULL,
+ c3 INT,
+ c4 INT,
+ PRIMARY KEY (c1),
+ INDEX i1 (c3),
+ INDEX i2 (c4)
+) ENGINE=INNODB;
+
+INSERT INTO t SET c1=1, c2=2;
+
+-- enable_info
+ALTER TABLE t DROP PRIMARY KEY, ADD PRIMARY KEY (c2), RENAME INDEX i1 TO x;
+-- disable_info
+
+-- eval $show_table
+-- eval $show_sys
+
+-- enable_info
+ALTER TABLE t RENAME INDEX i2 TO y, ROW_FORMAT=REDUNDANT;
+-- disable_info
+
+-- eval $show_table
+-- eval $show_sys
+
+DROP TABLE t;
+
+# a case where the PK does not exist prior to the ALTER TABLE command
+
+CREATE TABLE t (
+ c1 INT NOT NULL,
+ c2 INT,
+ c3 INT,
+ INDEX i1 (c2),
+ INDEX i2 (c3)
+) ENGINE=INNODB;
+
+INSERT INTO t SET c1=1;
+
+-- enable_info
+ALTER TABLE t ADD PRIMARY KEY (c1), RENAME INDEX i1 TO x;
+-- disable_info
+-- eval $show_table
+-- eval $show_sys
+
+DROP TABLE t;
+
+# Test repeated RENAMEs with alternating names
+
+CREATE TABLE t (a INT, INDEX iiiii (a)) ENGINE=INNODB;
+INSERT INTO t SET a=NULL;
+-- enable_info
+ALTER TABLE t RENAME INDEX iiiii TO i;
+ALTER TABLE t RENAME INDEX i TO iiiii;
+ALTER TABLE t RENAME INDEX iiiii TO i;
+ALTER TABLE t RENAME INDEX i TO iiiii;
+-- disable_info
+DROP TABLE t;
+
+# Below is a shell script to generate the full set of ALTER TABLE
+# DROP/ADD/RENAME combinations. The generated .sql file is 3.3MB and
+# executes in about 7 minutes.
+#
+##!/bin/sh
+#
+#create="
+#CREATE TABLE t (
+# a INT,
+# b INT,
+# c INT,
+# d INT,
+# PRIMARY KEY (a),
+# INDEX i1 (b),
+# INDEX i2 (c)
+#) ENGINE=INNODB;
+#"
+#
+#echo "DROP TABLE IF EXISTS t;"
+#for r in "" ", DROP PRIMARY KEY, ADD PRIMARY KEY (a)" ", ROW_FORMAT=REDUNDANT" ; do
+# for i1 in i1 i1noexist; do
+# for i2 in i2 i2noexist; do
+# for i3 in i3 i3noexist; do
+# for i4 in i4 i4noexist; do
+# for a in $i1 $i2 $i3 $i4; do
+# for b in $i1 $i2 $i3 $i4; do
+# for c in $i1 $i2 $i3 $i4; do
+# for d in $i1 $i2 $i3 $i4; do
+# echo "$create"
+# echo "ALTER TABLE t ADD INDEX $a (d), RENAME INDEX $b TO $c, DROP INDEX $d $r;"
+# echo "DROP TABLE t;"
+# done
+# done
+# done
+# done
+# done
+# done
+# done
+# done
+#done
diff --git a/sql/handler.cc b/sql/handler.cc
index 7d61252eea6..806d91bdbc5 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -4585,7 +4585,8 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
ALTER_DROP_CHECK_CONSTRAINT |
ALTER_PARTITIONED |
ALTER_VIRTUAL_GCOL_EXPR |
- ALTER_RENAME;
+ ALTER_RENAME |
+ ALTER_RENAME_INDEX;
/* Is there at least one operation that requires copy algorithm? */
if (ha_alter_info->handler_flags & ~inplace_offline_operations)
diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc
index 0828e1b7ba8..23e2e3e097f 100644
--- a/sql/sql_alter.cc
+++ b/sql/sql_alter.cc
@@ -25,6 +25,7 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
:drop_list(rhs.drop_list, mem_root),
alter_list(rhs.alter_list, mem_root),
key_list(rhs.key_list, mem_root),
+ alter_rename_key_list(rhs.alter_rename_key_list, mem_root),
create_list(rhs.create_list, mem_root),
check_constraint_list(rhs.check_constraint_list, mem_root),
flags(rhs.flags), partition_flags(rhs.partition_flags),
@@ -46,6 +47,7 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
list_copy_and_replace_each_value(drop_list, mem_root);
list_copy_and_replace_each_value(alter_list, mem_root);
list_copy_and_replace_each_value(key_list, mem_root);
+ list_copy_and_replace_each_value(alter_rename_key_list, mem_root);
list_copy_and_replace_each_value(create_list, mem_root);
/* partition_names are not deeply copied currently */
}
diff --git a/sql/sql_alter.h b/sql/sql_alter.h
index 41408a91836..a553c31346a 100644
--- a/sql/sql_alter.h
+++ b/sql/sql_alter.h
@@ -19,6 +19,7 @@
class Alter_drop;
class Alter_column;
+class Alter_rename_key;
class Key;
/**
@@ -87,6 +88,8 @@ public:
List<Alter_column> alter_list;
// List of keys, used by both CREATE and ALTER TABLE.
List<Key> key_list;
+ // List of keys to be renamed.
+ List<Alter_rename_key> alter_rename_key_list;
// List of columns, used by both CREATE and ALTER TABLE.
List<Create_field> create_list;
@@ -123,6 +126,7 @@ public:
drop_list.empty();
alter_list.empty();
key_list.empty();
+ alter_rename_key_list.empty();
create_list.empty();
check_constraint_list.empty();
flags= 0;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 6a7c0cd4d94..123bf0c0583 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -355,6 +355,21 @@ public:
};
+class Alter_rename_key : public Sql_alloc
+{
+public:
+ LEX_CSTRING old_name;
+ LEX_CSTRING new_name;
+
+ Alter_rename_key(LEX_CSTRING old_name_arg, LEX_CSTRING new_name_arg)
+ : old_name(old_name_arg), new_name(new_name_arg) {}
+
+ Alter_rename_key *clone(MEM_ROOT *mem_root) const
+ { return new (mem_root) Alter_rename_key(*this); }
+
+};
+
+
class Key :public Sql_alloc, public DDL_options {
public:
enum Keytype { PRIMARY, UNIQUE, MULTIPLE, FULLTEXT, SPATIAL, FOREIGN_KEY};
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index b5cc07b1411..3b56a721801 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -6601,7 +6601,7 @@ static int compare_uint(const uint *s, const uint *t)
enum class Compare_keys : uint32_t
{
- Equal,
+ Equal= 0,
EqualButKeyPartLength,
EqualButComment,
NotEqual
@@ -7998,6 +7998,7 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
List<Create_field> new_create_list;
/* New key definitions are added here */
List<Key> new_key_list;
+ List<Alter_rename_key> rename_key_list(alter_info->alter_rename_key_list);
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
List_iterator<Create_field> def_it(alter_info->create_list);
List_iterator<Alter_column> alter_it(alter_info->alter_list);
@@ -8446,6 +8447,39 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
continue;
}
+ /* If this index is to stay in the table check if it has to be renamed. */
+ List_iterator<Alter_rename_key> rename_key_it(rename_key_list);
+ Alter_rename_key *rename_key;
+
+ while ((rename_key= rename_key_it++))
+ {
+ if (!my_strcasecmp(system_charset_info, key_name, rename_key->old_name.str))
+ {
+ if (!my_strcasecmp(system_charset_info, key_name, primary_key_name))
+ {
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), rename_key->old_name.str);
+ goto err;
+ }
+ else if (!my_strcasecmp(system_charset_info, rename_key->new_name.str,
+ primary_key_name))
+ {
+ my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), rename_key->new_name.str);
+ goto err;
+ }
+
+ key_name= rename_key->new_name.str;
+ rename_key_it.remove();
+ /*
+ If the user has explicitly renamed the key, we should no longer
+ treat it as generated. Otherwise this key might be automatically
+ dropped by mysql_prepare_create_table() and this will confuse
+ code in fill_alter_inplace_info().
+ */
+ key_info->flags&= ~HA_GENERATED_KEY;
+ break;
+ }
+ }
+
if (key_info->algorithm == HA_KEY_ALG_LONG_HASH)
{
setup_keyinfo_hash(key_info);
@@ -8772,6 +8806,13 @@ mysql_prepare_alter_table(THD *thd, TABLE *table,
}
}
+ if (rename_key_list.elements)
+ {
+ my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), rename_key_list.head()->old_name.str,
+ table->s->table_name.str);
+ goto err;
+ }
+
if (!create_info->comment.str)
{
create_info->comment.str= table->s->comment.str;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 1d4a8a7e228..b032ce66cc7 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -7732,6 +7732,16 @@ alter_list_item:
if (unlikely(Lex->add_alter_list($3, $5)))
MYSQL_YYABORT;
}
+ | RENAME key_or_index field_ident TO_SYM field_ident
+ {
+ LEX *lex=Lex;
+ Alter_rename_key *ak= new (thd->mem_root)
+ Alter_rename_key($3, $5);
+ if (ak == NULL)
+ MYSQL_YYABORT;
+ lex->alter_info.alter_rename_key_list.push_back(ak);
+ lex->alter_info.flags|= ALTER_RENAME_INDEX;
+ }
| CONVERT_SYM TO_SYM charset charset_name_or_default opt_collate
{
if (!$4)
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index c644ce9593f..3b84a9947b2 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -3330,6 +3330,14 @@ innobase_check_index_keys(
}
}
+ for (const Alter_inplace_info::Rename_key_pair& pair :
+ info->rename_keys) {
+ if (0 == strcmp(key.name.str,
+ pair.old_key->name.str)) {
+ goto name_ok;
+ }
+ }
+
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
key.name.str);
return(ER_WRONG_NAME_FOR_INDEX);