diff --git a/mysql-test/suite/innodb/include/alter_table_pk_no_sort.inc b/mysql-test/suite/innodb/include/alter_table_pk_no_sort.inc index 6a2fcd15be0..61e304a7626 100644 --- a/mysql-test/suite/innodb/include/alter_table_pk_no_sort.inc +++ b/mysql-test/suite/innodb/include/alter_table_pk_no_sort.inc @@ -263,3 +263,10 @@ create table t1(o1 int, o2 int, o3 int, primary key(o1,o2,o3)) engine = innodb; insert into t1 values(1,1,2),(2,2,1); alter table t1 drop primary key, add primary key(o1), lock=none; drop table t1; + +# pk(o1,o2) to pk(o1,o2,autoinc) must not sort +create table t1(o1 int, o2 int, primary key(o1,o2)) engine = innodb; +insert into t1 values(1,1),(2,1); +alter table t1 drop primary key, add column a int unique auto_increment, +add primary key(o1,o2,a), algorithm=inplace; +drop table t1; diff --git a/mysql-test/suite/innodb/r/alter_table.result b/mysql-test/suite/innodb/r/alter_table.result index e47bfb90152..94262ac29c3 100644 --- a/mysql-test/suite/innodb/r/alter_table.result +++ b/mysql-test/suite/innodb/r/alter_table.result @@ -53,3 +53,10 @@ ALTER TABLE t1 DROP a; ERROR HY000: Cannot drop index 'a': needed in a foreign key constraint ALTER TABLE t1 ADD c INT; DROP TABLE t1, tx; +# +# MDEV-14119 Assertion cmp_rec_rec() on ALTER TABLE +# +CREATE TABLE t1(a INT NOT NULL UNIQUE) ENGINE=InnoDB; +INSERT INTO t1 SELECT * FROM seq_1_to_128; +ALTER TABLE t1 ADD b TINYINT AUTO_INCREMENT PRIMARY KEY, DROP KEY a; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb-index-debug.result b/mysql-test/suite/innodb/r/innodb-index-debug.result index b1f8c9ad3cc..bf2abce989c 100644 --- a/mysql-test/suite/innodb/r/innodb-index-debug.result +++ b/mysql-test/suite/innodb/r/innodb-index-debug.result @@ -323,4 +323,9 @@ create table t1(o1 int, o2 int, o3 int, primary key(o1,o2,o3)) engine = innodb; insert into t1 values(1,1,2),(2,2,1); alter table t1 drop primary key, add primary key(o1), lock=none; drop table t1; +create table t1(o1 int, o2 int, primary key(o1,o2)) engine = innodb; +insert into t1 values(1,1),(2,1); +alter table t1 drop primary key, add column a int unique auto_increment, +add primary key(o1,o2,a), algorithm=inplace; +drop table t1; SET DEBUG_DBUG = @saved_debug_dbug; diff --git a/mysql-test/suite/innodb/r/innodb-index.result b/mysql-test/suite/innodb/r/innodb-index.result index bdc16ad7692..5e91efb7062 100644 --- a/mysql-test/suite/innodb/r/innodb-index.result +++ b/mysql-test/suite/innodb/r/innodb-index.result @@ -1903,6 +1903,11 @@ create table t1(o1 int, o2 int, o3 int, primary key(o1,o2,o3)) engine = innodb; insert into t1 values(1,1,2),(2,2,1); alter table t1 drop primary key, add primary key(o1), lock=none; drop table t1; +create table t1(o1 int, o2 int, primary key(o1,o2)) engine = innodb; +insert into t1 values(1,1),(2,1); +alter table t1 drop primary key, add column a int unique auto_increment, +add primary key(o1,o2,a), algorithm=inplace; +drop table t1; # # MDEV-15325 Incomplete validation of missing tablespace during recovery # diff --git a/mysql-test/suite/innodb/t/alter_table.test b/mysql-test/suite/innodb/t/alter_table.test index d0943e7d407..6bc30d2e8ee 100644 --- a/mysql-test/suite/innodb/t/alter_table.test +++ b/mysql-test/suite/innodb/t/alter_table.test @@ -1,4 +1,5 @@ --source include/have_innodb.inc +--source include/have_sequence.inc # # MDEV-11995 ALTER TABLE proceeds despite reporting ER_TOO_LONG_KEY error # @@ -59,3 +60,11 @@ ALTER TABLE t1 ADD b INT; ALTER TABLE t1 DROP a; ALTER TABLE t1 ADD c INT; DROP TABLE t1, tx; + +--echo # +--echo # MDEV-14119 Assertion cmp_rec_rec() on ALTER TABLE +--echo # +CREATE TABLE t1(a INT NOT NULL UNIQUE) ENGINE=InnoDB; +INSERT INTO t1 SELECT * FROM seq_1_to_128; +ALTER TABLE t1 ADD b TINYINT AUTO_INCREMENT PRIMARY KEY, DROP KEY a; +DROP TABLE t1; diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 782b0d9efb2..0f5ac81f663 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -3362,7 +3362,11 @@ innobase_pk_order_preserved( if (old_pk_column) { new_field_order = old_field; } else if (innobase_pk_col_is_existing(new_col_no, col_map, - old_n_cols)) { + old_n_cols) + || new_clust_index->table->persistent_autoinc + == new_field + 1) { + /* Adding an existing column or an AUTO_INCREMENT + column may change the existing ordering. */ new_field_order = old_n_uniq + existing_field_count++; } else { /* Skip newly added column. */ @@ -4913,12 +4917,6 @@ index_created: user_table); dict_index_t* new_clust_index = dict_table_get_first_index( ctx->new_table); - ctx->skip_pk_sort = innobase_pk_order_preserved( - ctx->col_map, clust_index, new_clust_index); - - DBUG_EXECUTE_IF("innodb_alter_table_pk_assert_no_sort", - DBUG_ASSERT(ctx->skip_pk_sort);); - DBUG_ASSERT(!ctx->new_table->persistent_autoinc); if (const Field* ai = altered_table->found_next_number_field) { const unsigned col_no = innodb_col_no(ai); @@ -4937,6 +4935,12 @@ index_created: } } + ctx->skip_pk_sort = innobase_pk_order_preserved( + ctx->col_map, clust_index, new_clust_index); + + DBUG_EXECUTE_IF("innodb_alter_table_pk_assert_no_sort", + DBUG_ASSERT(ctx->skip_pk_sort);); + if (ctx->online) { /* Allocate a log for online table rebuild. */ rw_lock_x_lock(&clust_index->lock);