mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
MDEV-13301 Optimize DROP INDEX, ADD INDEX into RENAME INDEX
Just rename index in data dictionary and in InnoDB cache when it's possible. Introduce ALTER_INDEX_RENAME for that purpose so that engines can optimize such operation. Unused code between macro MYSQL_RENAME_INDEX was removed. compare_keys_but_name(): compare index definitions except for index names Alter_inplace_info::rename_keys: ha_innobase_inplace_ctx::rename_keys: vector of rename indexes fill_alter_inplace_info():: fills Alter_inplace_info::rename_keys
This commit is contained in:
committed by
Sergei Golubchik
parent
5d8ca98997
commit
3a3d5ba235
@ -2,7 +2,7 @@ CREATE TABLE t1 (x INT NOT NULL UNIQUE KEY) ENGINE=InnoDB;
|
|||||||
INSERT INTO t1 VALUES(5);
|
INSERT INTO t1 VALUES(5);
|
||||||
SET GLOBAL innodb_log_checkpoint_now=TRUE;
|
SET GLOBAL innodb_log_checkpoint_now=TRUE;
|
||||||
SET DEBUG_SYNC='commit_cache_rebuild SIGNAL ready WAIT_FOR finish';
|
SET DEBUG_SYNC='commit_cache_rebuild SIGNAL ready WAIT_FOR finish';
|
||||||
ALTER TABLE t1 ADD PRIMARY KEY(x);
|
ALTER TABLE t1 FORCE;;
|
||||||
connect con1,localhost,root,,;
|
connect con1,localhost,root,,;
|
||||||
SET DEBUG_SYNC='now WAIT_FOR ready';
|
SET DEBUG_SYNC='now WAIT_FOR ready';
|
||||||
SET GLOBAL innodb_log_checkpoint_now=TRUE;
|
SET GLOBAL innodb_log_checkpoint_now=TRUE;
|
||||||
@ -13,7 +13,6 @@ SHOW CREATE TABLE t1;
|
|||||||
Table Create Table
|
Table Create Table
|
||||||
t1 CREATE TABLE `t1` (
|
t1 CREATE TABLE `t1` (
|
||||||
`x` int(11) NOT NULL,
|
`x` int(11) NOT NULL,
|
||||||
PRIMARY KEY (`x`),
|
|
||||||
UNIQUE KEY `x` (`x`)
|
UNIQUE KEY `x` (`x`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
@ -236,8 +236,7 @@ WHERE variable_name = 'innodb_encryption_n_rowlog_blocks_encrypted');
|
|||||||
connection con1;
|
connection con1;
|
||||||
SET DEBUG_SYNC = 'row_log_apply_before SIGNAL c2e_created WAIT_FOR dml2_done';
|
SET DEBUG_SYNC = 'row_log_apply_before SIGNAL c2e_created WAIT_FOR dml2_done';
|
||||||
SET lock_wait_timeout = 10;
|
SET lock_wait_timeout = 10;
|
||||||
ALTER TABLE t1 DROP INDEX c2d, ADD INDEX c2e(c2),
|
ALTER TABLE t1 CHANGE c2 c22 INT, DROP INDEX c2d, ADD INDEX c2e(c22, c3(10)), ALGORITHM = NOCOPY;
|
||||||
ALGORITHM = INPLACE;
|
|
||||||
connection default;
|
connection default;
|
||||||
INSERT INTO t1 SELECT 80 + c1, c2, c3 FROM t1;
|
INSERT INTO t1 SELECT 80 + c1, c2, c3 FROM t1;
|
||||||
INSERT INTO t1 SELECT 160 + c1, c2, c3 FROM t1;
|
INSERT INTO t1 SELECT 160 + c1, c2, c3 FROM t1;
|
||||||
@ -295,6 +294,7 @@ INNER JOIN INFORMATION_SCHEMA.INNODB_SYS_FIELDS sf
|
|||||||
ON si.index_id = sf.index_id WHERE si.name = '?c2e';
|
ON si.index_id = sf.index_id WHERE si.name = '?c2e';
|
||||||
name pos
|
name pos
|
||||||
c2 0
|
c2 0
|
||||||
|
c3 1
|
||||||
SET @merge_encrypt_1=
|
SET @merge_encrypt_1=
|
||||||
(SELECT variable_value FROM information_schema.global_status
|
(SELECT variable_value FROM information_schema.global_status
|
||||||
WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted');
|
WHERE variable_name = 'innodb_encryption_n_merge_blocks_encrypted');
|
||||||
|
178
mysql-test/suite/innodb/r/instant_alter_index_rename.result
Normal file
178
mysql-test/suite/innodb/r/instant_alter_index_rename.result
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
create function get_index_id(tbl_id int, index_name char(100))
|
||||||
|
returns int
|
||||||
|
begin
|
||||||
|
declare res int;
|
||||||
|
select index_id into res from information_schema.innodb_sys_indexes where
|
||||||
|
name=index_name and table_id = tbl_id;
|
||||||
|
return res;
|
||||||
|
end|
|
||||||
|
create table t (
|
||||||
|
pk int primary key,
|
||||||
|
a int,
|
||||||
|
b int,
|
||||||
|
c int,
|
||||||
|
unique index a_key (a),
|
||||||
|
key c_key (c)
|
||||||
|
) engine=innodb stats_persistent=1;
|
||||||
|
insert into t values (1, 1, 1, 1);
|
||||||
|
set @table_id = (select table_id from information_schema.innodb_sys_tables where name='test/t');
|
||||||
|
set @a_key_id = get_index_id(@table_id, 'a_key');
|
||||||
|
set @c_key_id = get_index_id(@table_id, 'c_key');
|
||||||
|
set @primary_id = get_index_id(@table_id, 'primary');
|
||||||
|
select distinct(index_name) from mysql.innodb_index_stats where table_name = 't';
|
||||||
|
index_name
|
||||||
|
PRIMARY
|
||||||
|
a_key
|
||||||
|
c_key
|
||||||
|
alter table t
|
||||||
|
drop index a_key,
|
||||||
|
add unique index a_key_strikes_back (a);
|
||||||
|
select distinct(index_name) from mysql.innodb_index_stats where table_name = 't';
|
||||||
|
index_name
|
||||||
|
PRIMARY
|
||||||
|
a_key_strikes_back
|
||||||
|
c_key
|
||||||
|
check table t;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t check status OK
|
||||||
|
select @a_key_id = get_index_id(@table_id, 'a_key_strikes_back'),
|
||||||
|
@c_key_id = get_index_id(@table_id, 'c_key'),
|
||||||
|
@primary_id = get_index_id(@table_id, 'primary');
|
||||||
|
@a_key_id = get_index_id(@table_id, 'a_key_strikes_back') @c_key_id = get_index_id(@table_id, 'c_key') @primary_id = get_index_id(@table_id, 'primary')
|
||||||
|
1 1 1
|
||||||
|
set @a_key_strikes_back_id = get_index_id(@table_id, 'a_key_strikes_back');
|
||||||
|
set @c_key_id = get_index_id(@table_id, 'c_key');
|
||||||
|
set @primary_id = get_index_id(@table_id, 'primary');
|
||||||
|
alter table t
|
||||||
|
drop index a_key_strikes_back,
|
||||||
|
add unique index a_key_returns (a),
|
||||||
|
drop primary key,
|
||||||
|
add primary key (pk),
|
||||||
|
add unique index b_key (b);
|
||||||
|
check table t;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t check status OK
|
||||||
|
select @a_key_strikes_back_id = get_index_id(@table_id, 'a_key_returns'),
|
||||||
|
@c_key_id = get_index_id(@table_id, 'c_key'),
|
||||||
|
@primary_id = get_index_id(@table_id, 'primary');
|
||||||
|
@a_key_strikes_back_id = get_index_id(@table_id, 'a_key_returns') @c_key_id = get_index_id(@table_id, 'c_key') @primary_id = get_index_id(@table_id, 'primary')
|
||||||
|
1 1 1
|
||||||
|
set @a_key_returns_id = get_index_id(@table_id, 'a_key_returns');
|
||||||
|
set @b_key_id = get_index_id(@table_id, 'b_key');
|
||||||
|
set @c_key_id = get_index_id(@table_id, 'c_key');
|
||||||
|
set @primary_id = get_index_id(@table_id, 'primary');
|
||||||
|
alter table t
|
||||||
|
drop key c_key,
|
||||||
|
add key c_key2 (c);
|
||||||
|
check table t;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t check status OK
|
||||||
|
select @a_key_returns_id = get_index_id(@table_id, 'a_key_returns'),
|
||||||
|
@b_key_id = get_index_id(@table_id, 'b_key'),
|
||||||
|
@c_key_id = get_index_id(@table_id, 'c_key2'),
|
||||||
|
@primary_id = get_index_id(@table_id, 'primary');
|
||||||
|
@a_key_returns_id = get_index_id(@table_id, 'a_key_returns') @b_key_id = get_index_id(@table_id, 'b_key') @c_key_id = get_index_id(@table_id, 'c_key2') @primary_id = get_index_id(@table_id, 'primary')
|
||||||
|
1 1 1 1
|
||||||
|
drop table t;
|
||||||
|
drop function get_index_id;
|
||||||
|
create table errors (
|
||||||
|
a int,
|
||||||
|
unique key a_key (a),
|
||||||
|
b int
|
||||||
|
) engine=innodb;
|
||||||
|
alter table errors
|
||||||
|
drop key a_key,
|
||||||
|
drop key a_key,
|
||||||
|
add unique key a_key2 (a);
|
||||||
|
ERROR 42000: Can't DROP INDEX `a_key`; check that it exists
|
||||||
|
alter table errors
|
||||||
|
drop key a_key,
|
||||||
|
drop key a_key2,
|
||||||
|
add unique key a_key2 (a);
|
||||||
|
ERROR 42000: Can't DROP INDEX `a_key2`; check that it exists
|
||||||
|
alter table errors
|
||||||
|
add key b_key (b),
|
||||||
|
drop key b_key,
|
||||||
|
add key bb_key (b);
|
||||||
|
ERROR 42000: Can't DROP INDEX `b_key`; check that it exists
|
||||||
|
alter table errors
|
||||||
|
drop key a_key,
|
||||||
|
add key a_key2 (a),
|
||||||
|
drop key a_key,
|
||||||
|
add key a_key2 (a);
|
||||||
|
ERROR 42000: Can't DROP INDEX `a_key`; check that it exists
|
||||||
|
drop table errors;
|
||||||
|
create table corrupted (
|
||||||
|
a int,
|
||||||
|
key a_key (a)
|
||||||
|
) engine=innodb;
|
||||||
|
insert into corrupted values (1);
|
||||||
|
select * from corrupted;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
SET @save_dbug = @@SESSION.debug_dbug;
|
||||||
|
SET debug_dbug = '+d,dict_set_index_corrupted';
|
||||||
|
check table corrupted;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.corrupted check Warning InnoDB: Index a_key is marked as corrupted
|
||||||
|
test.corrupted check error Corrupt
|
||||||
|
SET debug_dbug = @save_dbug;
|
||||||
|
select * from corrupted;
|
||||||
|
ERROR HY000: Index corrupted is corrupted
|
||||||
|
alter table corrupted
|
||||||
|
drop key a_key,
|
||||||
|
add key a_key2 (a);
|
||||||
|
ERROR HY000: Index a_key is corrupted
|
||||||
|
alter table corrupted
|
||||||
|
drop key a_key;
|
||||||
|
select * from corrupted;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
check table corrupted;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.corrupted check status OK
|
||||||
|
drop table corrupted;
|
||||||
|
create table t (
|
||||||
|
a int,
|
||||||
|
unique key a_key (a)
|
||||||
|
) engine=innodb stats_persistent=1;
|
||||||
|
SET @save_dbug = @@SESSION.debug_dbug;
|
||||||
|
SET debug_dbug = '+d,ib_rename_index_fail1';
|
||||||
|
alter table t
|
||||||
|
drop key a_key,
|
||||||
|
add unique key a_key2 (a),
|
||||||
|
algorithm=instant;
|
||||||
|
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
|
||||||
|
SET debug_dbug = @save_dbug;
|
||||||
|
alter table t
|
||||||
|
drop key a_key,
|
||||||
|
add unique key `GEN_CLUST_INDEX` (a),
|
||||||
|
algorithm=instant;
|
||||||
|
ERROR 42000: Incorrect index name 'GEN_CLUST_INDEX'
|
||||||
|
show create table t;
|
||||||
|
Table Create Table
|
||||||
|
t CREATE TABLE `t` (
|
||||||
|
`a` int(11) DEFAULT NULL,
|
||||||
|
UNIQUE KEY `a_key` (`a`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=1
|
||||||
|
drop table t;
|
||||||
|
create table rename_column_and_index (
|
||||||
|
a int,
|
||||||
|
unique index a_key(a)
|
||||||
|
) engine=innodb;
|
||||||
|
insert into rename_column_and_index values (1), (3);
|
||||||
|
alter table rename_column_and_index
|
||||||
|
change a aa int,
|
||||||
|
drop key a_key,
|
||||||
|
add unique key aa_key(aa),
|
||||||
|
algorithm=instant;
|
||||||
|
show create table rename_column_and_index;
|
||||||
|
Table Create Table
|
||||||
|
rename_column_and_index CREATE TABLE `rename_column_and_index` (
|
||||||
|
`aa` int(11) DEFAULT NULL,
|
||||||
|
UNIQUE KEY `aa_key` (`aa`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||||
|
check table rename_column_and_index;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.rename_column_and_index check status OK
|
||||||
|
drop table rename_column_and_index;
|
@ -11,7 +11,7 @@ SET GLOBAL innodb_log_checkpoint_now=TRUE;
|
|||||||
# Start an ALTER TABLE and stop it before renaming the files
|
# Start an ALTER TABLE and stop it before renaming the files
|
||||||
SET DEBUG_SYNC='commit_cache_rebuild SIGNAL ready WAIT_FOR finish';
|
SET DEBUG_SYNC='commit_cache_rebuild SIGNAL ready WAIT_FOR finish';
|
||||||
|
|
||||||
--send ALTER TABLE t1 ADD PRIMARY KEY(x)
|
--send ALTER TABLE t1 FORCE;
|
||||||
|
|
||||||
connect (con1,localhost,root,,);
|
connect (con1,localhost,root,,);
|
||||||
|
|
||||||
|
@ -225,10 +225,7 @@ SET DEBUG_SYNC = 'row_log_apply_before SIGNAL c2e_created WAIT_FOR dml2_done';
|
|||||||
# Ensure that the ALTER TABLE will be executed even with some concurrent DML.
|
# Ensure that the ALTER TABLE will be executed even with some concurrent DML.
|
||||||
SET lock_wait_timeout = 10;
|
SET lock_wait_timeout = 10;
|
||||||
--send
|
--send
|
||||||
# FIXME: MDEV-13668
|
ALTER TABLE t1 CHANGE c2 c22 INT, DROP INDEX c2d, ADD INDEX c2e(c22, c3(10)), ALGORITHM = NOCOPY;
|
||||||
#ALTER TABLE t1 CHANGE c2 c22 INT, DROP INDEX c2d, ADD INDEX c2e(c22),
|
|
||||||
ALTER TABLE t1 DROP INDEX c2d, ADD INDEX c2e(c2),
|
|
||||||
ALGORITHM = INPLACE;
|
|
||||||
|
|
||||||
# Generate some log (delete-mark, delete-unmark, insert etc.)
|
# Generate some log (delete-mark, delete-unmark, insert etc.)
|
||||||
# while the index creation is blocked. Some of this may run
|
# while the index creation is blocked. Some of this may run
|
||||||
|
186
mysql-test/suite/innodb/t/instant_alter_index_rename.test
Normal file
186
mysql-test/suite/innodb/t/instant_alter_index_rename.test
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
--source include/have_innodb.inc
|
||||||
|
--source include/have_debug.inc
|
||||||
|
|
||||||
|
delimiter |;
|
||||||
|
create function get_index_id(tbl_id int, index_name char(100))
|
||||||
|
returns int
|
||||||
|
begin
|
||||||
|
declare res int;
|
||||||
|
select index_id into res from information_schema.innodb_sys_indexes where
|
||||||
|
name=index_name and table_id = tbl_id;
|
||||||
|
return res;
|
||||||
|
end|
|
||||||
|
|
||||||
|
delimiter ;|
|
||||||
|
|
||||||
|
create table t (
|
||||||
|
pk int primary key,
|
||||||
|
a int,
|
||||||
|
b int,
|
||||||
|
c int,
|
||||||
|
unique index a_key (a),
|
||||||
|
key c_key (c)
|
||||||
|
) engine=innodb stats_persistent=1;
|
||||||
|
|
||||||
|
insert into t values (1, 1, 1, 1);
|
||||||
|
|
||||||
|
set @table_id = (select table_id from information_schema.innodb_sys_tables where name='test/t');
|
||||||
|
|
||||||
|
set @a_key_id = get_index_id(@table_id, 'a_key');
|
||||||
|
set @c_key_id = get_index_id(@table_id, 'c_key');
|
||||||
|
set @primary_id = get_index_id(@table_id, 'primary');
|
||||||
|
|
||||||
|
select distinct(index_name) from mysql.innodb_index_stats where table_name = 't';
|
||||||
|
alter table t
|
||||||
|
drop index a_key,
|
||||||
|
add unique index a_key_strikes_back (a);
|
||||||
|
select distinct(index_name) from mysql.innodb_index_stats where table_name = 't';
|
||||||
|
|
||||||
|
check table t;
|
||||||
|
select @a_key_id = get_index_id(@table_id, 'a_key_strikes_back'),
|
||||||
|
@c_key_id = get_index_id(@table_id, 'c_key'),
|
||||||
|
@primary_id = get_index_id(@table_id, 'primary');
|
||||||
|
|
||||||
|
set @a_key_strikes_back_id = get_index_id(@table_id, 'a_key_strikes_back');
|
||||||
|
set @c_key_id = get_index_id(@table_id, 'c_key');
|
||||||
|
set @primary_id = get_index_id(@table_id, 'primary');
|
||||||
|
|
||||||
|
alter table t
|
||||||
|
drop index a_key_strikes_back,
|
||||||
|
add unique index a_key_returns (a),
|
||||||
|
drop primary key,
|
||||||
|
add primary key (pk),
|
||||||
|
add unique index b_key (b);
|
||||||
|
|
||||||
|
check table t;
|
||||||
|
select @a_key_strikes_back_id = get_index_id(@table_id, 'a_key_returns'),
|
||||||
|
@c_key_id = get_index_id(@table_id, 'c_key'),
|
||||||
|
@primary_id = get_index_id(@table_id, 'primary');
|
||||||
|
|
||||||
|
set @a_key_returns_id = get_index_id(@table_id, 'a_key_returns');
|
||||||
|
set @b_key_id = get_index_id(@table_id, 'b_key');
|
||||||
|
set @c_key_id = get_index_id(@table_id, 'c_key');
|
||||||
|
set @primary_id = get_index_id(@table_id, 'primary');
|
||||||
|
|
||||||
|
alter table t
|
||||||
|
drop key c_key,
|
||||||
|
add key c_key2 (c);
|
||||||
|
|
||||||
|
check table t;
|
||||||
|
select @a_key_returns_id = get_index_id(@table_id, 'a_key_returns'),
|
||||||
|
@b_key_id = get_index_id(@table_id, 'b_key'),
|
||||||
|
@c_key_id = get_index_id(@table_id, 'c_key2'),
|
||||||
|
@primary_id = get_index_id(@table_id, 'primary');
|
||||||
|
|
||||||
|
drop table t;
|
||||||
|
drop function get_index_id;
|
||||||
|
|
||||||
|
create table errors (
|
||||||
|
a int,
|
||||||
|
unique key a_key (a),
|
||||||
|
b int
|
||||||
|
) engine=innodb;
|
||||||
|
|
||||||
|
--error ER_CANT_DROP_FIELD_OR_KEY
|
||||||
|
alter table errors
|
||||||
|
drop key a_key,
|
||||||
|
drop key a_key,
|
||||||
|
add unique key a_key2 (a);
|
||||||
|
|
||||||
|
--error ER_CANT_DROP_FIELD_OR_KEY
|
||||||
|
alter table errors
|
||||||
|
drop key a_key,
|
||||||
|
drop key a_key2,
|
||||||
|
add unique key a_key2 (a);
|
||||||
|
|
||||||
|
--error ER_CANT_DROP_FIELD_OR_KEY
|
||||||
|
alter table errors
|
||||||
|
add key b_key (b),
|
||||||
|
drop key b_key,
|
||||||
|
add key bb_key (b);
|
||||||
|
|
||||||
|
--error ER_CANT_DROP_FIELD_OR_KEY
|
||||||
|
alter table errors
|
||||||
|
drop key a_key,
|
||||||
|
add key a_key2 (a),
|
||||||
|
drop key a_key,
|
||||||
|
add key a_key2 (a);
|
||||||
|
|
||||||
|
drop table errors;
|
||||||
|
|
||||||
|
--disable_query_log
|
||||||
|
call mtr.add_suppression("Flagged corruption of `a_key` in table `test`.`corrupted` in dict_set_index_corrupted");
|
||||||
|
--enable_query_log
|
||||||
|
|
||||||
|
create table corrupted (
|
||||||
|
a int,
|
||||||
|
key a_key (a)
|
||||||
|
) engine=innodb;
|
||||||
|
|
||||||
|
insert into corrupted values (1);
|
||||||
|
|
||||||
|
select * from corrupted;
|
||||||
|
|
||||||
|
SET @save_dbug = @@SESSION.debug_dbug;
|
||||||
|
SET debug_dbug = '+d,dict_set_index_corrupted';
|
||||||
|
check table corrupted;
|
||||||
|
SET debug_dbug = @save_dbug;
|
||||||
|
|
||||||
|
--error ER_INDEX_CORRUPT
|
||||||
|
select * from corrupted;
|
||||||
|
|
||||||
|
--error ER_INDEX_CORRUPT
|
||||||
|
alter table corrupted
|
||||||
|
drop key a_key,
|
||||||
|
add key a_key2 (a);
|
||||||
|
|
||||||
|
alter table corrupted
|
||||||
|
drop key a_key;
|
||||||
|
|
||||||
|
select * from corrupted;
|
||||||
|
|
||||||
|
check table corrupted;
|
||||||
|
|
||||||
|
drop table corrupted;
|
||||||
|
|
||||||
|
create table t (
|
||||||
|
a int,
|
||||||
|
unique key a_key (a)
|
||||||
|
) engine=innodb stats_persistent=1;
|
||||||
|
|
||||||
|
SET @save_dbug = @@SESSION.debug_dbug;
|
||||||
|
SET debug_dbug = '+d,ib_rename_index_fail1';
|
||||||
|
-- error ER_LOCK_DEADLOCK
|
||||||
|
alter table t
|
||||||
|
drop key a_key,
|
||||||
|
add unique key a_key2 (a),
|
||||||
|
algorithm=instant;
|
||||||
|
SET debug_dbug = @save_dbug;
|
||||||
|
|
||||||
|
--error ER_WRONG_NAME_FOR_INDEX
|
||||||
|
alter table t
|
||||||
|
drop key a_key,
|
||||||
|
add unique key `GEN_CLUST_INDEX` (a),
|
||||||
|
algorithm=instant;
|
||||||
|
|
||||||
|
show create table t;
|
||||||
|
|
||||||
|
drop table t;
|
||||||
|
|
||||||
|
|
||||||
|
create table rename_column_and_index (
|
||||||
|
a int,
|
||||||
|
unique index a_key(a)
|
||||||
|
) engine=innodb;
|
||||||
|
|
||||||
|
insert into rename_column_and_index values (1), (3);
|
||||||
|
|
||||||
|
alter table rename_column_and_index
|
||||||
|
change a aa int,
|
||||||
|
drop key a_key,
|
||||||
|
add unique key aa_key(aa),
|
||||||
|
algorithm=instant;
|
||||||
|
|
||||||
|
show create table rename_column_and_index;
|
||||||
|
check table rename_column_and_index;
|
||||||
|
drop table rename_column_and_index;
|
@ -4775,6 +4775,29 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
|
|||||||
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
|
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Alter_inplace_info::Alter_inplace_info(HA_CREATE_INFO *create_info_arg,
|
||||||
|
Alter_info *alter_info_arg,
|
||||||
|
KEY *key_info_arg, uint key_count_arg,
|
||||||
|
partition_info *modified_part_info_arg,
|
||||||
|
bool ignore_arg)
|
||||||
|
: create_info(create_info_arg),
|
||||||
|
alter_info(alter_info_arg),
|
||||||
|
key_info_buffer(key_info_arg),
|
||||||
|
key_count(key_count_arg),
|
||||||
|
index_drop_count(0),
|
||||||
|
index_drop_buffer(nullptr),
|
||||||
|
index_add_count(0),
|
||||||
|
index_add_buffer(nullptr),
|
||||||
|
rename_keys(current_thd->mem_root),
|
||||||
|
handler_ctx(nullptr),
|
||||||
|
group_commit_ctx(nullptr),
|
||||||
|
handler_flags(0),
|
||||||
|
modified_part_info(modified_part_info_arg),
|
||||||
|
ignore(ignore_arg),
|
||||||
|
online(false),
|
||||||
|
unsupported_reason(nullptr)
|
||||||
|
{}
|
||||||
|
|
||||||
void Alter_inplace_info::report_unsupported_error(const char *not_supported,
|
void Alter_inplace_info::report_unsupported_error(const char *not_supported,
|
||||||
const char *try_instead) const
|
const char *try_instead) const
|
||||||
{
|
{
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include <keycache.h>
|
#include <keycache.h>
|
||||||
#include <mysql/psi/mysql_table.h>
|
#include <mysql/psi/mysql_table.h>
|
||||||
#include "sql_sequence.h"
|
#include "sql_sequence.h"
|
||||||
|
#include "mem_root_array.h"
|
||||||
|
|
||||||
class Alter_info;
|
class Alter_info;
|
||||||
class Virtual_column_info;
|
class Virtual_column_info;
|
||||||
@ -635,6 +636,8 @@ typedef ulonglong alter_table_operations;
|
|||||||
#define ALTER_RECREATE (1ULL << 10)
|
#define ALTER_RECREATE (1ULL << 10)
|
||||||
// Set for CONVERT TO
|
// Set for CONVERT TO
|
||||||
#define ALTER_CONVERT_TO (1ULL << 11)
|
#define ALTER_CONVERT_TO (1ULL << 11)
|
||||||
|
// Set for DROP ... ADD some_index
|
||||||
|
#define ALTER_RENAME_INDEX (1ULL << 12)
|
||||||
// Set for ADD FOREIGN KEY
|
// Set for ADD FOREIGN KEY
|
||||||
#define ALTER_ADD_FOREIGN_KEY (1ULL << 21)
|
#define ALTER_ADD_FOREIGN_KEY (1ULL << 21)
|
||||||
// Set for DROP FOREIGN KEY
|
// Set for DROP FOREIGN KEY
|
||||||
@ -2367,6 +2370,29 @@ public:
|
|||||||
*/
|
*/
|
||||||
uint *index_add_buffer;
|
uint *index_add_buffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Old and new index names. Used for index rename.
|
||||||
|
*/
|
||||||
|
struct Rename_key_pair
|
||||||
|
{
|
||||||
|
Rename_key_pair(const KEY *old_key, const KEY *new_key)
|
||||||
|
: old_key(old_key), new_key(new_key)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
const KEY *old_key;
|
||||||
|
const KEY *new_key;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
Vector of key pairs from DROP/ADD index which can be renamed.
|
||||||
|
*/
|
||||||
|
typedef Mem_root_array<Rename_key_pair, true> Rename_keys_vector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
A list of indexes which should be renamed.
|
||||||
|
Index definitions stays the same.
|
||||||
|
*/
|
||||||
|
Rename_keys_vector rename_keys;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Context information to allow handlers to keep context between in-place
|
Context information to allow handlers to keep context between in-place
|
||||||
alter API calls.
|
alter API calls.
|
||||||
@ -2428,23 +2454,7 @@ public:
|
|||||||
Alter_info *alter_info_arg,
|
Alter_info *alter_info_arg,
|
||||||
KEY *key_info_arg, uint key_count_arg,
|
KEY *key_info_arg, uint key_count_arg,
|
||||||
partition_info *modified_part_info_arg,
|
partition_info *modified_part_info_arg,
|
||||||
bool ignore_arg)
|
bool ignore_arg);
|
||||||
: create_info(create_info_arg),
|
|
||||||
alter_info(alter_info_arg),
|
|
||||||
key_info_buffer(key_info_arg),
|
|
||||||
key_count(key_count_arg),
|
|
||||||
index_drop_count(0),
|
|
||||||
index_drop_buffer(NULL),
|
|
||||||
index_add_count(0),
|
|
||||||
index_add_buffer(NULL),
|
|
||||||
handler_ctx(NULL),
|
|
||||||
group_commit_ctx(NULL),
|
|
||||||
handler_flags(0),
|
|
||||||
modified_part_info(modified_part_info_arg),
|
|
||||||
ignore(ignore_arg),
|
|
||||||
online(false),
|
|
||||||
unsupported_reason(NULL)
|
|
||||||
{}
|
|
||||||
|
|
||||||
~Alter_inplace_info()
|
~Alter_inplace_info()
|
||||||
{
|
{
|
||||||
|
@ -87,9 +87,11 @@ public:
|
|||||||
|
|
||||||
// Returns a pointer to the first element in the array.
|
// Returns a pointer to the first element in the array.
|
||||||
Element_type *begin() { return &m_array[0]; }
|
Element_type *begin() { return &m_array[0]; }
|
||||||
|
const Element_type *begin() const { return &m_array[0]; }
|
||||||
|
|
||||||
// Returns a pointer to the past-the-end element in the array.
|
// Returns a pointer to the past-the-end element in the array.
|
||||||
Element_type *end() { return &m_array[size()]; }
|
Element_type *end() { return &m_array[size()]; }
|
||||||
|
const Element_type *end() const { return &m_array[size()]; }
|
||||||
|
|
||||||
// Erases all of the elements.
|
// Erases all of the elements.
|
||||||
void clear()
|
void clear()
|
||||||
@ -226,6 +228,7 @@ public:
|
|||||||
size_t element_size() const { return sizeof(Element_type); }
|
size_t element_size() const { return sizeof(Element_type); }
|
||||||
bool empty() const { return size() == 0; }
|
bool empty() const { return size() == 0; }
|
||||||
size_t size() const { return m_size; }
|
size_t size() const { return m_size; }
|
||||||
|
const MEM_ROOT *mem_root() const { return m_root; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MEM_ROOT *const m_root;
|
MEM_ROOT *const m_root;
|
||||||
|
241
sql/sql_table.cc
241
sql/sql_table.cc
@ -6502,31 +6502,101 @@ remove_key:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Get Create_field object for newly created table by field index.
|
|
||||||
|
|
||||||
@param alter_info Alter_info describing newly created table.
|
|
||||||
@param idx Field index.
|
|
||||||
*/
|
|
||||||
|
|
||||||
static Create_field *get_field_by_index(Alter_info *alter_info, uint idx)
|
|
||||||
{
|
|
||||||
List_iterator_fast<Create_field> field_it(alter_info->create_list);
|
|
||||||
uint field_idx= 0;
|
|
||||||
Create_field *field;
|
|
||||||
|
|
||||||
while ((field= field_it++) && field_idx < idx)
|
|
||||||
{ field_idx++; }
|
|
||||||
|
|
||||||
return field;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int compare_uint(const uint *s, const uint *t)
|
static int compare_uint(const uint *s, const uint *t)
|
||||||
{
|
{
|
||||||
return (*s < *t) ? -1 : ((*s > *t) ? 1 : 0);
|
return (*s < *t) ? -1 : ((*s > *t) ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class Compare_keys
|
||||||
|
{
|
||||||
|
Equal,
|
||||||
|
EqualButKeyPartLength,
|
||||||
|
NotEqual
|
||||||
|
};
|
||||||
|
|
||||||
|
Compare_keys compare_keys_but_name(const KEY *table_key, const KEY *new_key,
|
||||||
|
Alter_info *alter_info, const TABLE *table,
|
||||||
|
const KEY *const new_pk,
|
||||||
|
const KEY *const old_pk)
|
||||||
|
{
|
||||||
|
Compare_keys result= Compare_keys::Equal;
|
||||||
|
|
||||||
|
if ((table_key->algorithm != new_key->algorithm) ||
|
||||||
|
((table_key->flags & HA_KEYFLAG_MASK) !=
|
||||||
|
(new_key->flags & HA_KEYFLAG_MASK)) ||
|
||||||
|
(table_key->user_defined_key_parts != new_key->user_defined_key_parts))
|
||||||
|
return Compare_keys::NotEqual;
|
||||||
|
|
||||||
|
if (table_key->block_size != new_key->block_size)
|
||||||
|
return Compare_keys::NotEqual;
|
||||||
|
|
||||||
|
if (engine_options_differ(table_key->option_struct, new_key->option_struct,
|
||||||
|
table->file->ht->index_options))
|
||||||
|
return Compare_keys::NotEqual;
|
||||||
|
|
||||||
|
const KEY_PART_INFO *end=
|
||||||
|
table_key->key_part + table_key->user_defined_key_parts;
|
||||||
|
for (const KEY_PART_INFO *key_part= table_key->key_part,
|
||||||
|
*new_part= new_key->key_part;
|
||||||
|
key_part < end; key_part++, new_part++)
|
||||||
|
{
|
||||||
|
Create_field *new_field= alter_info->create_list.elem(new_part->fieldnr);
|
||||||
|
const Field *old_field= table->field[key_part->fieldnr - 1];
|
||||||
|
/*
|
||||||
|
If there is a change in index length due to column expansion
|
||||||
|
like varchar(X) changed to varchar(X + N) and has a compatible
|
||||||
|
packed data representation, we mark it for fast/INPLACE change
|
||||||
|
in index definition. InnoDB supports INPLACE for this cases
|
||||||
|
|
||||||
|
Key definition has changed if we are using a different field or
|
||||||
|
if the user key part length is different.
|
||||||
|
*/
|
||||||
|
auto old_field_len= old_field->pack_length();
|
||||||
|
|
||||||
|
if (old_field->type() == MYSQL_TYPE_VARCHAR)
|
||||||
|
{
|
||||||
|
old_field_len= (old_field->pack_length() -
|
||||||
|
((Field_varstring *) old_field)->length_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_part->length == old_field_len &&
|
||||||
|
key_part->length < new_part->length &&
|
||||||
|
(key_part->field->is_equal((Create_field *) new_field) ==
|
||||||
|
IS_EQUAL_PACK_LENGTH))
|
||||||
|
{
|
||||||
|
result= Compare_keys::EqualButKeyPartLength;
|
||||||
|
}
|
||||||
|
else if (key_part->length != new_part->length)
|
||||||
|
return Compare_keys::NotEqual;
|
||||||
|
|
||||||
|
/*
|
||||||
|
For prefix keys KEY_PART_INFO::field points to cloned Field
|
||||||
|
object with adjusted length. So below we have to check field
|
||||||
|
indexes instead of simply comparing pointers to Field objects.
|
||||||
|
*/
|
||||||
|
if (!new_field->field ||
|
||||||
|
new_field->field->field_index != key_part->fieldnr - 1)
|
||||||
|
return Compare_keys::NotEqual;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Rebuild the index if following condition get satisfied:
|
||||||
|
|
||||||
|
(i) Old table doesn't have primary key, new table has it and vice-versa
|
||||||
|
(ii) Primary key changed to another existing index
|
||||||
|
*/
|
||||||
|
if ((new_key == new_pk) != (table_key == old_pk))
|
||||||
|
return Compare_keys::NotEqual;
|
||||||
|
|
||||||
|
/* Check that key comment is not changed. */
|
||||||
|
if (table_key->comment.length != new_key->comment.length ||
|
||||||
|
(table_key->comment.length &&
|
||||||
|
memcmp(table_key->comment.str, new_key->comment.str,
|
||||||
|
table_key->comment.length) != 0))
|
||||||
|
return Compare_keys::NotEqual;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Compare original and new versions of a table and fill Alter_inplace_info
|
Compare original and new versions of a table and fill Alter_inplace_info
|
||||||
@ -6573,21 +6643,21 @@ static int compare_uint(const uint *s, const uint *t)
|
|||||||
static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar,
|
static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar,
|
||||||
Alter_inplace_info *ha_alter_info)
|
Alter_inplace_info *ha_alter_info)
|
||||||
{
|
{
|
||||||
Field **f_ptr, *field, *old_field;
|
Field **f_ptr, *field;
|
||||||
List_iterator_fast<Create_field> new_field_it;
|
List_iterator_fast<Create_field> new_field_it;
|
||||||
Create_field *new_field;
|
Create_field *new_field;
|
||||||
KEY_PART_INFO *key_part, *new_part;
|
|
||||||
KEY_PART_INFO *end;
|
|
||||||
Alter_info *alter_info= ha_alter_info->alter_info;
|
Alter_info *alter_info= ha_alter_info->alter_info;
|
||||||
DBUG_ENTER("fill_alter_inplace_info");
|
DBUG_ENTER("fill_alter_inplace_info");
|
||||||
DBUG_PRINT("info", ("alter_info->flags: %llu", alter_info->flags));
|
DBUG_PRINT("info", ("alter_info->flags: %llu", alter_info->flags));
|
||||||
|
|
||||||
/* Allocate result buffers. */
|
/* Allocate result buffers. */
|
||||||
|
DBUG_ASSERT(ha_alter_info->rename_keys.mem_root() == thd->mem_root);
|
||||||
if (! (ha_alter_info->index_drop_buffer=
|
if (! (ha_alter_info->index_drop_buffer=
|
||||||
(KEY**) thd->alloc(sizeof(KEY*) * table->s->keys)) ||
|
(KEY**) thd->alloc(sizeof(KEY*) * table->s->keys)) ||
|
||||||
! (ha_alter_info->index_add_buffer=
|
! (ha_alter_info->index_add_buffer=
|
||||||
(uint*) thd->alloc(sizeof(uint) *
|
(uint*) thd->alloc(sizeof(uint) *
|
||||||
alter_info->key_list.elements)))
|
alter_info->key_list.elements)) ||
|
||||||
|
ha_alter_info->rename_keys.reserve(ha_alter_info->index_add_count))
|
||||||
DBUG_RETURN(true);
|
DBUG_RETURN(true);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -6871,7 +6941,6 @@ static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar,
|
|||||||
Go through keys and check if the original ones are compatible
|
Go through keys and check if the original ones are compatible
|
||||||
with new table.
|
with new table.
|
||||||
*/
|
*/
|
||||||
uint old_field_len= 0;
|
|
||||||
KEY *table_key;
|
KEY *table_key;
|
||||||
KEY *table_key_end= table->key_info + table->s->keys;
|
KEY *table_key_end= table->key_info + table->s->keys;
|
||||||
KEY *new_key;
|
KEY *new_key;
|
||||||
@ -6918,88 +6987,18 @@ static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check that the key types are compatible between old and new tables. */
|
switch (compare_keys_but_name(table_key, new_key, alter_info, table, new_pk,
|
||||||
if ((table_key->algorithm != new_key->algorithm) ||
|
old_pk))
|
||||||
((table_key->flags & HA_KEYFLAG_MASK) !=
|
|
||||||
(new_key->flags & HA_KEYFLAG_MASK)) ||
|
|
||||||
(table_key->user_defined_key_parts !=
|
|
||||||
new_key->user_defined_key_parts))
|
|
||||||
goto index_changed;
|
|
||||||
|
|
||||||
if (table_key->block_size != new_key->block_size)
|
|
||||||
goto index_changed;
|
|
||||||
|
|
||||||
if (engine_options_differ(table_key->option_struct, new_key->option_struct,
|
|
||||||
table->file->ht->index_options))
|
|
||||||
goto index_changed;
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check that the key parts remain compatible between the old and
|
|
||||||
new tables.
|
|
||||||
*/
|
|
||||||
end= table_key->key_part + table_key->user_defined_key_parts;
|
|
||||||
for (key_part= table_key->key_part, new_part= new_key->key_part;
|
|
||||||
key_part < end;
|
|
||||||
key_part++, new_part++)
|
|
||||||
{
|
{
|
||||||
new_field= get_field_by_index(alter_info, new_part->fieldnr);
|
case Compare_keys::Equal:
|
||||||
old_field= table->field[key_part->fieldnr - 1];
|
continue;
|
||||||
/*
|
case Compare_keys::EqualButKeyPartLength:
|
||||||
If there is a change in index length due to column expansion
|
ha_alter_info->handler_flags|= ALTER_COLUMN_INDEX_LENGTH;
|
||||||
like varchar(X) changed to varchar(X + N) and has a compatible
|
continue;
|
||||||
packed data representation, we mark it for fast/INPLACE change
|
case Compare_keys::NotEqual:
|
||||||
in index definition. InnoDB supports INPLACE for this cases
|
break;
|
||||||
|
|
||||||
Key definition has changed if we are using a different field or
|
|
||||||
if the user key part length is different.
|
|
||||||
*/
|
|
||||||
old_field_len= old_field->pack_length();
|
|
||||||
|
|
||||||
if (old_field->type() == MYSQL_TYPE_VARCHAR)
|
|
||||||
{
|
|
||||||
old_field_len= (old_field->pack_length()
|
|
||||||
- ((Field_varstring*) old_field)->length_bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key_part->length == old_field_len &&
|
|
||||||
key_part->length < new_part->length &&
|
|
||||||
(key_part->field->is_equal((Create_field*) new_field)
|
|
||||||
== IS_EQUAL_PACK_LENGTH))
|
|
||||||
{
|
|
||||||
ha_alter_info->handler_flags |= ALTER_COLUMN_INDEX_LENGTH;
|
|
||||||
}
|
|
||||||
else if (key_part->length != new_part->length)
|
|
||||||
goto index_changed;
|
|
||||||
|
|
||||||
/*
|
|
||||||
For prefix keys KEY_PART_INFO::field points to cloned Field
|
|
||||||
object with adjusted length. So below we have to check field
|
|
||||||
indexes instead of simply comparing pointers to Field objects.
|
|
||||||
*/
|
|
||||||
if (! new_field->field ||
|
|
||||||
new_field->field->field_index != key_part->fieldnr - 1)
|
|
||||||
goto index_changed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Rebuild the index if following condition get satisfied:
|
|
||||||
|
|
||||||
(i) Old table doesn't have primary key, new table has it and vice-versa
|
|
||||||
(ii) Primary key changed to another existing index
|
|
||||||
*/
|
|
||||||
if ((new_key == new_pk) != (table_key == old_pk))
|
|
||||||
goto index_changed;
|
|
||||||
|
|
||||||
/* Check that key comment is not changed. */
|
|
||||||
if (table_key->comment.length != new_key->comment.length ||
|
|
||||||
(table_key->comment.length &&
|
|
||||||
memcmp(table_key->comment.str, new_key->comment.str,
|
|
||||||
table_key->comment.length) != 0))
|
|
||||||
goto index_changed;
|
|
||||||
|
|
||||||
continue;
|
|
||||||
|
|
||||||
index_changed:
|
|
||||||
/* Key modified. Add the key / key offset to both buffers. */
|
/* Key modified. Add the key / key offset to both buffers. */
|
||||||
ha_alter_info->index_drop_buffer
|
ha_alter_info->index_drop_buffer
|
||||||
[ha_alter_info->index_drop_count++]=
|
[ha_alter_info->index_drop_count++]=
|
||||||
@ -7039,6 +7038,40 @@ static bool fill_alter_inplace_info(THD *thd, TABLE *table, bool varchar,
|
|||||||
new_key->option_struct;
|
new_key->option_struct;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (uint i= 0; i < ha_alter_info->index_add_count; i++)
|
||||||
|
{
|
||||||
|
uint *add_buffer= ha_alter_info->index_add_buffer;
|
||||||
|
const KEY *new_key= ha_alter_info->key_info_buffer + add_buffer[i];
|
||||||
|
|
||||||
|
for (uint j= 0; j < ha_alter_info->index_drop_count; j++)
|
||||||
|
{
|
||||||
|
KEY **drop_buffer= ha_alter_info->index_drop_buffer;
|
||||||
|
const KEY *old_key= drop_buffer[j];
|
||||||
|
|
||||||
|
if (compare_keys_but_name(old_key, new_key, alter_info, table, new_pk,
|
||||||
|
old_pk) != Compare_keys::Equal)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBUG_ASSERT(
|
||||||
|
lex_string_cmp(system_charset_info, &old_key->name, &new_key->name));
|
||||||
|
|
||||||
|
ha_alter_info->handler_flags|= ALTER_RENAME_INDEX;
|
||||||
|
ha_alter_info->rename_keys.push_back(
|
||||||
|
Alter_inplace_info::Rename_key_pair(old_key, new_key));
|
||||||
|
|
||||||
|
--ha_alter_info->index_add_count;
|
||||||
|
--ha_alter_info->index_drop_count;
|
||||||
|
memcpy(add_buffer + i, add_buffer + i + 1,
|
||||||
|
sizeof(add_buffer[0]) * (ha_alter_info->index_add_count - i));
|
||||||
|
memcpy(drop_buffer + j, drop_buffer + j + 1,
|
||||||
|
sizeof(drop_buffer[0]) * (ha_alter_info->index_drop_count - j));
|
||||||
|
--i; // this index once again
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Sort index_add_buffer according to how key_info_buffer is sorted.
|
Sort index_add_buffer according to how key_info_buffer is sorted.
|
||||||
I.e. with primary keys first - see sort_keys().
|
I.e. with primary keys first - see sort_keys().
|
||||||
|
@ -3840,6 +3840,63 @@ dict_stats_rename_table(
|
|||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************//**
|
||||||
|
Renames an index in InnoDB persistent stats storage.
|
||||||
|
This function creates its own transaction and commits it.
|
||||||
|
@return DB_SUCCESS or error code. DB_STATS_DO_NOT_EXIST will be returned
|
||||||
|
if the persistent stats do not exist. */
|
||||||
|
dberr_t
|
||||||
|
dict_stats_rename_index(
|
||||||
|
/*====================*/
|
||||||
|
const dict_table_t* table, /*!< in: table whose index
|
||||||
|
is renamed */
|
||||||
|
const char* old_index_name, /*!< in: old index name */
|
||||||
|
const char* new_index_name) /*!< in: new index name */
|
||||||
|
{
|
||||||
|
rw_lock_x_lock(dict_operation_lock);
|
||||||
|
mutex_enter(&dict_sys->mutex);
|
||||||
|
|
||||||
|
if (!dict_stats_persistent_storage_check(true)) {
|
||||||
|
mutex_exit(&dict_sys->mutex);
|
||||||
|
rw_lock_x_unlock(dict_operation_lock);
|
||||||
|
return(DB_STATS_DO_NOT_EXIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
char dbname_utf8[MAX_DB_UTF8_LEN];
|
||||||
|
char tablename_utf8[MAX_TABLE_UTF8_LEN];
|
||||||
|
|
||||||
|
dict_fs2utf8(table->name.m_name, dbname_utf8, sizeof(dbname_utf8),
|
||||||
|
tablename_utf8, sizeof(tablename_utf8));
|
||||||
|
|
||||||
|
pars_info_t* pinfo;
|
||||||
|
|
||||||
|
pinfo = pars_info_create();
|
||||||
|
|
||||||
|
pars_info_add_str_literal(pinfo, "dbname_utf8", dbname_utf8);
|
||||||
|
pars_info_add_str_literal(pinfo, "tablename_utf8", tablename_utf8);
|
||||||
|
pars_info_add_str_literal(pinfo, "new_index_name", new_index_name);
|
||||||
|
pars_info_add_str_literal(pinfo, "old_index_name", old_index_name);
|
||||||
|
|
||||||
|
dberr_t ret;
|
||||||
|
|
||||||
|
ret = dict_stats_exec_sql(
|
||||||
|
pinfo,
|
||||||
|
"PROCEDURE RENAME_INDEX_IN_INDEX_STATS () IS\n"
|
||||||
|
"BEGIN\n"
|
||||||
|
"UPDATE \"" INDEX_STATS_NAME "\" SET\n"
|
||||||
|
"index_name = :new_index_name\n"
|
||||||
|
"WHERE\n"
|
||||||
|
"database_name = :dbname_utf8 AND\n"
|
||||||
|
"table_name = :tablename_utf8 AND\n"
|
||||||
|
"index_name = :old_index_name;\n"
|
||||||
|
"END;\n", NULL);
|
||||||
|
|
||||||
|
mutex_exit(&dict_sys->mutex);
|
||||||
|
rw_lock_x_unlock(dict_operation_lock);
|
||||||
|
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
/* tests @{ */
|
/* tests @{ */
|
||||||
#ifdef UNIV_ENABLE_UNIT_TEST_DICT_STATS
|
#ifdef UNIV_ENABLE_UNIT_TEST_DICT_STATS
|
||||||
|
|
||||||
|
@ -133,6 +133,7 @@ static const alter_table_operations INNOBASE_ALTER_INSTANT
|
|||||||
| INNOBASE_FOREIGN_OPERATIONS
|
| INNOBASE_FOREIGN_OPERATIONS
|
||||||
| ALTER_COLUMN_EQUAL_PACK_LENGTH
|
| ALTER_COLUMN_EQUAL_PACK_LENGTH
|
||||||
| ALTER_COLUMN_UNVERSIONED
|
| ALTER_COLUMN_UNVERSIONED
|
||||||
|
| ALTER_RENAME_INDEX
|
||||||
| ALTER_DROP_VIRTUAL_COLUMN;
|
| ALTER_DROP_VIRTUAL_COLUMN;
|
||||||
|
|
||||||
/** Acquire a page latch on the possible metadata record,
|
/** Acquire a page latch on the possible metadata record,
|
||||||
@ -863,10 +864,6 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
|
|||||||
dict_index_t** drop_index;
|
dict_index_t** drop_index;
|
||||||
/** number of InnoDB indexes being dropped */
|
/** number of InnoDB indexes being dropped */
|
||||||
const ulint num_to_drop_index;
|
const ulint num_to_drop_index;
|
||||||
/** InnoDB indexes being renamed */
|
|
||||||
dict_index_t** rename;
|
|
||||||
/** number of InnoDB indexes being renamed */
|
|
||||||
const ulint num_to_rename;
|
|
||||||
/** InnoDB foreign key constraints being dropped */
|
/** InnoDB foreign key constraints being dropped */
|
||||||
dict_foreign_t** drop_fk;
|
dict_foreign_t** drop_fk;
|
||||||
/** number of InnoDB foreign key constraints being dropped */
|
/** number of InnoDB foreign key constraints being dropped */
|
||||||
@ -948,8 +945,6 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
|
|||||||
ha_innobase_inplace_ctx(row_prebuilt_t*& prebuilt_arg,
|
ha_innobase_inplace_ctx(row_prebuilt_t*& prebuilt_arg,
|
||||||
dict_index_t** drop_arg,
|
dict_index_t** drop_arg,
|
||||||
ulint num_to_drop_arg,
|
ulint num_to_drop_arg,
|
||||||
dict_index_t** rename_arg,
|
|
||||||
ulint num_to_rename_arg,
|
|
||||||
dict_foreign_t** drop_fk_arg,
|
dict_foreign_t** drop_fk_arg,
|
||||||
ulint num_to_drop_fk_arg,
|
ulint num_to_drop_fk_arg,
|
||||||
dict_foreign_t** add_fk_arg,
|
dict_foreign_t** add_fk_arg,
|
||||||
@ -968,7 +963,6 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
|
|||||||
prebuilt (prebuilt_arg),
|
prebuilt (prebuilt_arg),
|
||||||
add_index (0), add_key_numbers (0), num_to_add_index (0),
|
add_index (0), add_key_numbers (0), num_to_add_index (0),
|
||||||
drop_index (drop_arg), num_to_drop_index (num_to_drop_arg),
|
drop_index (drop_arg), num_to_drop_index (num_to_drop_arg),
|
||||||
rename (rename_arg), num_to_rename (num_to_rename_arg),
|
|
||||||
drop_fk (drop_fk_arg), num_to_drop_fk (num_to_drop_fk_arg),
|
drop_fk (drop_fk_arg), num_to_drop_fk (num_to_drop_fk_arg),
|
||||||
add_fk (add_fk_arg), num_to_add_fk (num_to_add_fk_arg),
|
add_fk (add_fk_arg), num_to_add_fk (num_to_add_fk_arg),
|
||||||
online (online_arg), heap (heap_arg), trx (0),
|
online (online_arg), heap (heap_arg), trx (0),
|
||||||
@ -3258,7 +3252,6 @@ innobase_check_index_keys(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
|
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
|
||||||
key.name.str);
|
key.name.str);
|
||||||
return(ER_WRONG_NAME_FOR_INDEX);
|
return(ER_WRONG_NAME_FOR_INDEX);
|
||||||
@ -7067,6 +7060,120 @@ innobase_check_foreign_key_index(
|
|||||||
return(false);
|
return(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Rename a given index in the InnoDB data dictionary.
|
||||||
|
|
||||||
|
@param index index to rename
|
||||||
|
@param new_name new name of the index
|
||||||
|
@param[in,out] trx dict transaction to use, not going to be committed here
|
||||||
|
|
||||||
|
@retval true Failure
|
||||||
|
@retval false Success */
|
||||||
|
static MY_ATTRIBUTE((warn_unused_result))
|
||||||
|
bool
|
||||||
|
rename_index_try(
|
||||||
|
const dict_index_t* index,
|
||||||
|
const char* new_name,
|
||||||
|
trx_t* trx)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("rename_index_try");
|
||||||
|
|
||||||
|
ut_ad(mutex_own(&dict_sys->mutex));
|
||||||
|
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
|
||||||
|
ut_ad(trx->dict_operation_lock_mode == RW_X_LATCH);
|
||||||
|
|
||||||
|
pars_info_t* pinfo;
|
||||||
|
dberr_t err;
|
||||||
|
|
||||||
|
pinfo = pars_info_create();
|
||||||
|
|
||||||
|
pars_info_add_ull_literal(pinfo, "table_id", index->table->id);
|
||||||
|
pars_info_add_ull_literal(pinfo, "index_id", index->id);
|
||||||
|
pars_info_add_str_literal(pinfo, "new_name", new_name);
|
||||||
|
|
||||||
|
trx->op_info = "Renaming an index in SYS_INDEXES";
|
||||||
|
|
||||||
|
DBUG_EXECUTE_IF(
|
||||||
|
"ib_rename_index_fail1",
|
||||||
|
DBUG_SET("+d,innodb_report_deadlock");
|
||||||
|
);
|
||||||
|
|
||||||
|
err = que_eval_sql(
|
||||||
|
pinfo,
|
||||||
|
"PROCEDURE RENAME_INDEX_IN_SYS_INDEXES () IS\n"
|
||||||
|
"BEGIN\n"
|
||||||
|
"UPDATE SYS_INDEXES SET\n"
|
||||||
|
"NAME = :new_name\n"
|
||||||
|
"WHERE\n"
|
||||||
|
"ID = :index_id AND\n"
|
||||||
|
"TABLE_ID = :table_id;\n"
|
||||||
|
"END;\n",
|
||||||
|
FALSE, trx); /* pinfo is freed by que_eval_sql() */
|
||||||
|
|
||||||
|
DBUG_EXECUTE_IF(
|
||||||
|
"ib_rename_index_fail1",
|
||||||
|
DBUG_SET("-d,innodb_report_deadlock");
|
||||||
|
);
|
||||||
|
|
||||||
|
trx->op_info = "";
|
||||||
|
|
||||||
|
if (err != DB_SUCCESS) {
|
||||||
|
my_error_innodb(err, index->table->name.m_name, 0);
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
DBUG_RETURN(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Rename a given index in the InnoDB data dictionary cache.
|
||||||
|
|
||||||
|
@param[in,out] index index to rename
|
||||||
|
@param new_name new index name
|
||||||
|
*/
|
||||||
|
static
|
||||||
|
void
|
||||||
|
innobase_rename_index_cache(dict_index_t* index, const char* new_name)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("innobase_rename_index_cache");
|
||||||
|
|
||||||
|
ut_ad(mutex_own(&dict_sys->mutex));
|
||||||
|
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
|
||||||
|
|
||||||
|
size_t old_name_len = strlen(index->name);
|
||||||
|
size_t new_name_len = strlen(new_name);
|
||||||
|
|
||||||
|
if (old_name_len < new_name_len) {
|
||||||
|
index->name = static_cast<char*>(
|
||||||
|
mem_heap_alloc(index->heap, new_name_len + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(const_cast<char*>(index->name()), new_name, new_name_len + 1);
|
||||||
|
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Rename the index name in cache.
|
||||||
|
@param[in] ctx alter context
|
||||||
|
@param[in] ha_alter_info Data used during inplace alter. */
|
||||||
|
static void innobase_rename_indexes_cache(
|
||||||
|
const ha_innobase_inplace_ctx* ctx,
|
||||||
|
const Alter_inplace_info* ha_alter_info)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(ha_alter_info->handler_flags & ALTER_RENAME_INDEX);
|
||||||
|
|
||||||
|
for (const Alter_inplace_info::Rename_key_pair& pair :
|
||||||
|
ha_alter_info->rename_keys) {
|
||||||
|
dict_index_t* index = dict_table_get_index_on_name(
|
||||||
|
ctx->old_table, pair.old_key->name.str);
|
||||||
|
ut_ad(index);
|
||||||
|
|
||||||
|
innobase_rename_index_cache(index, pair.new_key->name.str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Fill the stored column information in s_cols list.
|
/** Fill the stored column information in s_cols list.
|
||||||
@param[in] altered_table mysql table object
|
@param[in] altered_table mysql table object
|
||||||
@ -7144,8 +7251,6 @@ ha_innobase::prepare_inplace_alter_table(
|
|||||||
{
|
{
|
||||||
dict_index_t** drop_index; /*!< Index to be dropped */
|
dict_index_t** drop_index; /*!< Index to be dropped */
|
||||||
ulint n_drop_index; /*!< Number of indexes to drop */
|
ulint n_drop_index; /*!< Number of indexes to drop */
|
||||||
dict_index_t** rename_index; /*!< Indexes to be dropped */
|
|
||||||
ulint n_rename_index; /*!< Number of indexes to rename */
|
|
||||||
dict_foreign_t**drop_fk; /*!< Foreign key constraints to drop */
|
dict_foreign_t**drop_fk; /*!< Foreign key constraints to drop */
|
||||||
ulint n_drop_fk; /*!< Number of foreign keys to drop */
|
ulint n_drop_fk; /*!< Number of foreign keys to drop */
|
||||||
dict_foreign_t**add_fk = NULL; /*!< Foreign key constraints to drop */
|
dict_foreign_t**add_fk = NULL; /*!< Foreign key constraints to drop */
|
||||||
@ -7661,9 +7766,6 @@ check_if_can_drop_indexes:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
n_rename_index = 0;
|
|
||||||
rename_index = NULL;
|
|
||||||
|
|
||||||
n_add_fk = 0;
|
n_add_fk = 0;
|
||||||
|
|
||||||
if (ha_alter_info->handler_flags
|
if (ha_alter_info->handler_flags
|
||||||
@ -7717,6 +7819,20 @@ err_exit:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ha_alter_info->handler_flags & ALTER_RENAME_INDEX) {
|
||||||
|
for (const Alter_inplace_info::Rename_key_pair& pair :
|
||||||
|
ha_alter_info->rename_keys) {
|
||||||
|
dict_index_t* index = dict_table_get_index_on_name(
|
||||||
|
indexed_table, pair.old_key->name.str);
|
||||||
|
|
||||||
|
if (!index || index->is_corrupted()) {
|
||||||
|
my_error(ER_INDEX_CORRUPT, MYF(0),
|
||||||
|
index->name());
|
||||||
|
goto err_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const ha_table_option_struct& alt_opt=
|
const ha_table_option_struct& alt_opt=
|
||||||
*ha_alter_info->create_info->option_struct;
|
*ha_alter_info->create_info->option_struct;
|
||||||
|
|
||||||
@ -7732,7 +7848,6 @@ err_exit:
|
|||||||
= new ha_innobase_inplace_ctx(
|
= new ha_innobase_inplace_ctx(
|
||||||
m_prebuilt,
|
m_prebuilt,
|
||||||
drop_index, n_drop_index,
|
drop_index, n_drop_index,
|
||||||
rename_index, n_rename_index,
|
|
||||||
drop_fk, n_drop_fk,
|
drop_fk, n_drop_fk,
|
||||||
add_fk, n_add_fk,
|
add_fk, n_add_fk,
|
||||||
ha_alter_info->online,
|
ha_alter_info->online,
|
||||||
@ -7860,7 +7975,6 @@ found_col:
|
|||||||
ha_alter_info->handler_ctx = new ha_innobase_inplace_ctx(
|
ha_alter_info->handler_ctx = new ha_innobase_inplace_ctx(
|
||||||
m_prebuilt,
|
m_prebuilt,
|
||||||
drop_index, n_drop_index,
|
drop_index, n_drop_index,
|
||||||
rename_index, n_rename_index,
|
|
||||||
drop_fk, n_drop_fk, add_fk, n_add_fk,
|
drop_fk, n_drop_fk, add_fk, n_add_fk,
|
||||||
ha_alter_info->online,
|
ha_alter_info->online,
|
||||||
heap, m_prebuilt->table, col_names,
|
heap, m_prebuilt->table, col_names,
|
||||||
@ -9656,6 +9770,38 @@ commit_try_rebuild(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Rename indexes in dictionary.
|
||||||
|
@param[in] ctx alter info context
|
||||||
|
@param[in] ha_alter_info Operation used during inplace alter
|
||||||
|
@param[out] trx transaction to change the index name
|
||||||
|
in dictionary
|
||||||
|
@return true if it failed to rename
|
||||||
|
@return false if it is success. */
|
||||||
|
static
|
||||||
|
bool
|
||||||
|
rename_indexes_try(
|
||||||
|
const ha_innobase_inplace_ctx* ctx,
|
||||||
|
const Alter_inplace_info* ha_alter_info,
|
||||||
|
trx_t* trx)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(ha_alter_info->handler_flags & ALTER_RENAME_INDEX);
|
||||||
|
|
||||||
|
for (const Alter_inplace_info::Rename_key_pair& pair :
|
||||||
|
ha_alter_info->rename_keys) {
|
||||||
|
dict_index_t* index = dict_table_get_index_on_name(
|
||||||
|
ctx->old_table, pair.old_key->name.str);
|
||||||
|
// This was checked previously in
|
||||||
|
// ha_innobase::prepare_inplace_alter_table()
|
||||||
|
ut_ad(index);
|
||||||
|
|
||||||
|
if (rename_index_try(index, pair.new_key->name.str, trx)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/** Apply the changes made during commit_try_rebuild(),
|
/** Apply the changes made during commit_try_rebuild(),
|
||||||
to the data dictionary cache and the file system.
|
to the data dictionary cache and the file system.
|
||||||
@param ctx In-place ALTER TABLE context */
|
@param ctx In-place ALTER TABLE context */
|
||||||
@ -9913,6 +10059,11 @@ commit_try_norebuild(
|
|||||||
DBUG_RETURN(true);
|
DBUG_RETURN(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((ha_alter_info->handler_flags & ALTER_RENAME_INDEX)
|
||||||
|
&& rename_indexes_try(ctx, ha_alter_info, trx)) {
|
||||||
|
DBUG_RETURN(true);
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->is_instant()) {
|
if (ctx->is_instant()) {
|
||||||
DBUG_RETURN(innobase_instant_try(ha_alter_info, ctx,
|
DBUG_RETURN(innobase_instant_try(ha_alter_info, ctx,
|
||||||
altered_table, old_table,
|
altered_table, old_table,
|
||||||
@ -10165,6 +10316,10 @@ commit_cache_norebuild(
|
|||||||
vers_change_fields_cache(ha_alter_info, ctx, table);
|
vers_change_fields_cache(ha_alter_info, ctx, table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ha_alter_info->handler_flags & ALTER_RENAME_INDEX) {
|
||||||
|
innobase_rename_indexes_cache(ctx, ha_alter_info);
|
||||||
|
}
|
||||||
|
|
||||||
ctx->new_table->fts_doc_id_index
|
ctx->new_table->fts_doc_id_index
|
||||||
= ctx->new_table->fts
|
= ctx->new_table->fts
|
||||||
? dict_table_get_index_on_name(
|
? dict_table_get_index_on_name(
|
||||||
@ -10234,6 +10389,27 @@ alter_stats_norebuild(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const Alter_inplace_info::Rename_key_pair& pair :
|
||||||
|
ha_alter_info->rename_keys) {
|
||||||
|
dberr_t err = dict_stats_rename_index(ctx->new_table,
|
||||||
|
pair.old_key->name.str,
|
||||||
|
pair.new_key->name.str);
|
||||||
|
|
||||||
|
if (err != DB_SUCCESS) {
|
||||||
|
push_warning_printf(
|
||||||
|
thd,
|
||||||
|
Sql_condition::WARN_LEVEL_WARN,
|
||||||
|
ER_ERROR_ON_RENAME,
|
||||||
|
"Error renaming an index of table '%s'"
|
||||||
|
" from '%s' to '%s' in InnoDB persistent"
|
||||||
|
" statistics storage: %s",
|
||||||
|
ctx->new_table->name.m_name,
|
||||||
|
pair.old_key->name.str,
|
||||||
|
pair.new_key->name.str,
|
||||||
|
ut_strerr(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < ctx->num_to_add_index; i++) {
|
for (i = 0; i < ctx->num_to_add_index; i++) {
|
||||||
dict_index_t* index = ctx->add_index[i];
|
dict_index_t* index = ctx->add_index[i];
|
||||||
DBUG_ASSERT(index->table == ctx->new_table);
|
DBUG_ASSERT(index->table == ctx->new_table);
|
||||||
@ -10269,23 +10445,8 @@ alter_stats_rebuild(
|
|||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DBUG_OFF
|
|
||||||
bool file_unreadable_orig = false;
|
|
||||||
#endif /* DBUG_OFF */
|
|
||||||
|
|
||||||
DBUG_EXECUTE_IF(
|
|
||||||
"ib_rename_index_fail2",
|
|
||||||
file_unreadable_orig = table->file_unreadable;
|
|
||||||
table->file_unreadable = true;
|
|
||||||
);
|
|
||||||
|
|
||||||
dberr_t ret = dict_stats_update(table, DICT_STATS_RECALC_PERSISTENT);
|
dberr_t ret = dict_stats_update(table, DICT_STATS_RECALC_PERSISTENT);
|
||||||
|
|
||||||
DBUG_EXECUTE_IF(
|
|
||||||
"ib_rename_index_fail2",
|
|
||||||
table->file_unreadable = file_unreadable_orig;
|
|
||||||
);
|
|
||||||
|
|
||||||
if (ret != DB_SUCCESS) {
|
if (ret != DB_SUCCESS) {
|
||||||
push_warning_printf(
|
push_warning_printf(
|
||||||
thd,
|
thd,
|
||||||
@ -10943,11 +11104,6 @@ foreign_fail:
|
|||||||
DBUG_ASSERT(0 == strcmp(ctx->old_table->name.m_name,
|
DBUG_ASSERT(0 == strcmp(ctx->old_table->name.m_name,
|
||||||
ctx->tmp_name));
|
ctx->tmp_name));
|
||||||
|
|
||||||
DBUG_EXECUTE_IF(
|
|
||||||
"ib_rename_index_fail3",
|
|
||||||
DBUG_SET("+d,innodb_report_deadlock");
|
|
||||||
);
|
|
||||||
|
|
||||||
if (dict_stats_drop_table(
|
if (dict_stats_drop_table(
|
||||||
ctx->new_table->name.m_name,
|
ctx->new_table->name.m_name,
|
||||||
errstr, sizeof(errstr))
|
errstr, sizeof(errstr))
|
||||||
@ -10963,11 +11119,6 @@ foreign_fail:
|
|||||||
errstr);
|
errstr);
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_EXECUTE_IF(
|
|
||||||
"ib_rename_index_fail3",
|
|
||||||
DBUG_SET("-d,innodb_report_deadlock");
|
|
||||||
);
|
|
||||||
|
|
||||||
DBUG_EXECUTE_IF("ib_ddl_crash_before_commit",
|
DBUG_EXECUTE_IF("ib_ddl_crash_before_commit",
|
||||||
DBUG_SUICIDE(););
|
DBUG_SUICIDE(););
|
||||||
|
|
||||||
|
@ -187,6 +187,19 @@ dict_stats_rename_table(
|
|||||||
char* errstr, /*!< out: error string if != DB_SUCCESS
|
char* errstr, /*!< out: error string if != DB_SUCCESS
|
||||||
is returned */
|
is returned */
|
||||||
size_t errstr_sz); /*!< in: errstr size */
|
size_t errstr_sz); /*!< in: errstr size */
|
||||||
|
/*********************************************************************//**
|
||||||
|
Renames an index in InnoDB persistent stats storage.
|
||||||
|
This function creates its own transaction and commits it.
|
||||||
|
@return DB_SUCCESS or error code. DB_STATS_DO_NOT_EXIST will be returned
|
||||||
|
if the persistent stats do not exist. */
|
||||||
|
dberr_t
|
||||||
|
dict_stats_rename_index(
|
||||||
|
/*====================*/
|
||||||
|
const dict_table_t* table, /*!< in: table whose index
|
||||||
|
is renamed */
|
||||||
|
const char* old_index_name, /*!< in: old index name */
|
||||||
|
const char* new_index_name) /*!< in: new index name */
|
||||||
|
__attribute__((warn_unused_result));
|
||||||
|
|
||||||
/** Save an individual index's statistic into the persistent statistics
|
/** Save an individual index's statistic into the persistent statistics
|
||||||
storage.
|
storage.
|
||||||
|
Reference in New Issue
Block a user