summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-08-11 18:52:38 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2020-08-11 18:52:38 +0300
commitc96be848d3bbb668d27645c36ca66c697fdc2752 (patch)
tree1be5999f130ff13a55a51d3f670899bb1ed3d615
parentde8d57e5220ccfab31db4da86167f441df78869b (diff)
downloadmariadb-git-c96be848d3bbb668d27645c36ca66c697fdc2752.tar.gz
MDEV-14119 Assertion cmp_rec_rec() in ALTER TABLE
innobase_pk_order_preserved(): Treat an added AUTO_INCREMENT column in the same way as an added existing column. In either case, the column values are not guaranteed to be constant, and thus the ordering may change if such a column is added before any existing PRIMARY KEY columns. prepare_inplace_alter_table_dict(): Initialize dict_table_t::persistent_autoinc before invoking innobase_pk_order_preserved().
-rw-r--r--mysql-test/suite/innodb/include/alter_table_pk_no_sort.inc7
-rw-r--r--mysql-test/suite/innodb/r/alter_table.result7
-rw-r--r--mysql-test/suite/innodb/r/innodb-index-debug.result5
-rw-r--r--mysql-test/suite/innodb/r/innodb-index.result5
-rw-r--r--mysql-test/suite/innodb/t/alter_table.test9
-rw-r--r--storage/innobase/handler/handler0alter.cc18
6 files changed, 44 insertions, 7 deletions
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);