diff --git a/mysql-test/main/long_unique_innodb.result b/mysql-test/main/long_unique_innodb.result index 8c23d61f2bc..d5694d04325 100644 --- a/mysql-test/main/long_unique_innodb.result +++ b/mysql-test/main/long_unique_innodb.result @@ -181,3 +181,78 @@ pk b 1 foo drop table t1; # End of 10.6 tests +# +# MDEV-35026 ALTER TABLE loses USING HASH on a unique key +# +create table t ( +id int(10) unsigned not null auto_increment, +x int(10) unsigned default null, +y int(10) unsigned default null, +primary key (id), +unique key y (y) using hash, +key fk_1 (x), +constraint fk_1 foreign key (x) references t (id) +) engine=innodb; +insert t select seq, seq, seq from seq_1_to_1001; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `x` int(10) unsigned DEFAULT NULL, + `y` int(10) unsigned DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `y` (`y`) USING HASH, + KEY `fk_1` (`x`), + CONSTRAINT `fk_1` FOREIGN KEY (`x`) REFERENCES `t` (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1002 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +alter table t drop foreign key fk_1; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `x` int(10) unsigned DEFAULT NULL, + `y` int(10) unsigned DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `y` (`y`) USING HASH, + KEY `fk_1` (`x`) +) ENGINE=InnoDB AUTO_INCREMENT=1002 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +alter table t drop column x; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `y` int(10) unsigned DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `y` (`y`) USING HASH +) ENGINE=InnoDB AUTO_INCREMENT=1002 DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +drop table t; +# Engine change must not keep the hidden hash column +create table t (a int, unique (a) using hash) engine=innodb; +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + UNIQUE KEY `a` (`a`) USING HASH +) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +alter table t engine=memory; +select engine from information_schema.tables where table_schema=database() and table_name='t'; +engine +MEMORY +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + UNIQUE KEY `a` (`a`) +) ENGINE=MEMORY DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +alter table t engine=myisam; +select engine from information_schema.tables where table_schema=database() and table_name='t'; +engine +MyISAM +show create table t; +Table Create Table +t CREATE TABLE `t` ( + `a` int(11) DEFAULT NULL, + UNIQUE KEY `a` (`a`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci +drop table t; +# End of 10.11 tests diff --git a/mysql-test/main/long_unique_innodb.test b/mysql-test/main/long_unique_innodb.test index fc51817e45a..dfbcc8ed30d 100644 --- a/mysql-test/main/long_unique_innodb.test +++ b/mysql-test/main/long_unique_innodb.test @@ -1,5 +1,6 @@ --source include/have_innodb.inc --source include/have_partition.inc +--source include/have_sequence.inc # # MDEV-371 Unique indexes for blobs @@ -187,3 +188,38 @@ select * from t1; drop table t1; --echo # End of 10.6 tests + +--echo # +--echo # MDEV-35026 ALTER TABLE loses USING HASH on a unique key +--echo # + +create table t ( + id int(10) unsigned not null auto_increment, + x int(10) unsigned default null, + y int(10) unsigned default null, + primary key (id), + unique key y (y) using hash, + key fk_1 (x), + constraint fk_1 foreign key (x) references t (id) +) engine=innodb; + +insert t select seq, seq, seq from seq_1_to_1001; +show create table t; +alter table t drop foreign key fk_1; +show create table t; +alter table t drop column x; +show create table t; +drop table t; + +--echo # Engine change must not keep the hidden hash column +create table t (a int, unique (a) using hash) engine=innodb; +show create table t; +alter table t engine=memory; +select engine from information_schema.tables where table_schema=database() and table_name='t'; +show create table t; +alter table t engine=myisam; +select engine from information_schema.tables where table_schema=database() and table_name='t'; +show create table t; +drop table t; + +--echo # End of 10.11 tests diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f524a52ec2a..a0452039827 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -9265,15 +9265,24 @@ mysql_prepare_alter_table(THD *thd, TABLE *table, enum Key::Keytype key_type; LEX_CSTRING tmp_name; bzero((char*) &key_create_info, sizeof(key_create_info)); - if (key_info->algorithm == HA_KEY_ALG_LONG_HASH) - key_info->algorithm= alter_ctx->fast_alter_partition ? - HA_KEY_ALG_HASH : HA_KEY_ALG_UNDEF; /* - For fast alter partition we set HA_KEY_ALG_HASH above to make sure it - doesn't lose the hash property. - Otherwise we let mysql_prepare_create_table() decide if the hash field - is needed depending on the (possibly changed) data types. + All columns of a long hash key survive here, so the key keeps + HA_KEY_ALG_LONG_HASH unless a column was changed or the storage engine + is changed. + For fast alter partition we set HA_KEY_ALG_HASH + to make sure it doesn't lose the hash property. + Otherwise we let mysql_prepare_create_table() decide + if the hash field is needed depending on the (possibly changed) + data types or engine. */ + if (key_info->algorithm == HA_KEY_ALG_LONG_HASH) + { + if (alter_ctx->fast_alter_partition) + key_info->algorithm= HA_KEY_ALG_HASH; + else if ((alter_info->flags & ALTER_CHANGE_COLUMN) || + create_info->db_type != table->s->db_type()) + key_info->algorithm= HA_KEY_ALG_UNDEF; + } key_create_info.algorithm= key_info->algorithm; /* We copy block size directly as some engines, like Area, sets this