summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-11-16 13:28:37 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2018-11-16 13:28:37 +0200
commitf85012246cec2a774c5c1fa895b1e593eaf69081 (patch)
tree5bcf70305f154b14511009732f52b294be14d58a
parent89337d510e9780d6533c3db4d42969b2338a7610 (diff)
downloadmariadb-git-f85012246cec2a774c5c1fa895b1e593eaf69081.tar.gz
MDEV-17735 Assertion failure in row_parse_int() on first ADD/DROP COLUMN
row_ins_clust_index_entry_low(): Do not attempt to read an AUTO_INCREMENT column value from a metadata record, because it does not make any sense. Moreover, the field offset would be off by one in case the AUTO_INCREMENT column is not part of the PRIMARY KEY, because the MDEV-15562 metadata record would contain an extra field at index->first_user_field(). On MariaDB Server 10.3 after MDEV-11369, we would unnecessarily read a dummy AUTO_INCREMENT value from the metadata record, but that value would always be written as NULL or 0, so there is no problem.
-rw-r--r--mysql-test/suite/innodb/r/instant_alter.result35
-rw-r--r--mysql-test/suite/innodb/t/instant_alter.test13
-rw-r--r--storage/innobase/row/row0ins.cc33
3 files changed, 67 insertions, 14 deletions
diff --git a/mysql-test/suite/innodb/r/instant_alter.result b/mysql-test/suite/innodb/r/instant_alter.result
index 5f89b31c142..0fc560b50cb 100644
--- a/mysql-test/suite/innodb/r/instant_alter.result
+++ b/mysql-test/suite/innodb/r/instant_alter.result
@@ -523,6 +523,17 @@ SELECT * FROM t1;
i t
1 NULL
DROP TABLE t1;
+CREATE TABLE t1 (a INT AUTO_INCREMENT, b INT, KEY(a)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
+INSERT INTO t1 SET a=NULL;
+ALTER TABLE t1 DROP COLUMN b;
+ALTER TABLE t1 ADD COLUMN c INT NOT NULL DEFAULT 42;
+INSERT INTO t1 SET a=NULL;
+UPDATE t1 SET a=a+2;
+SELECT * FROM t1;
+a c
+3 42
+4 42
+DROP TABLE t1;
CREATE TABLE t1
(id INT PRIMARY KEY, c2 INT UNIQUE,
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
@@ -992,6 +1003,17 @@ SELECT * FROM t1;
i t
1 NULL
DROP TABLE t1;
+CREATE TABLE t1 (a INT AUTO_INCREMENT, b INT, KEY(a)) ENGINE=InnoDB ROW_FORMAT=COMPACT;
+INSERT INTO t1 SET a=NULL;
+ALTER TABLE t1 DROP COLUMN b;
+ALTER TABLE t1 ADD COLUMN c INT NOT NULL DEFAULT 42;
+INSERT INTO t1 SET a=NULL;
+UPDATE t1 SET a=a+2;
+SELECT * FROM t1;
+a c
+3 42
+4 42
+DROP TABLE t1;
CREATE TABLE t1
(id INT PRIMARY KEY, c2 INT UNIQUE,
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
@@ -1461,10 +1483,21 @@ SELECT * FROM t1;
i t
1 NULL
DROP TABLE t1;
+CREATE TABLE t1 (a INT AUTO_INCREMENT, b INT, KEY(a)) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
+INSERT INTO t1 SET a=NULL;
+ALTER TABLE t1 DROP COLUMN b;
+ALTER TABLE t1 ADD COLUMN c INT NOT NULL DEFAULT 42;
+INSERT INTO t1 SET a=NULL;
+UPDATE t1 SET a=a+2;
+SELECT * FROM t1;
+a c
+3 42
+4 42
+DROP TABLE t1;
disconnect analyze;
SELECT variable_value-@old_instant instants
FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column';
instants
-78
+84
SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency;
diff --git a/mysql-test/suite/innodb/t/instant_alter.test b/mysql-test/suite/innodb/t/instant_alter.test
index fd7fbe94450..243ba333903 100644
--- a/mysql-test/suite/innodb/t/instant_alter.test
+++ b/mysql-test/suite/innodb/t/instant_alter.test
@@ -397,6 +397,19 @@ ALTER TABLE t1 ADD COLUMN t TEXT;
SELECT * FROM t1;
DROP TABLE t1;
+#
+# MDEV-17735 Assertion failure in row_parse_int() on first ADD/DROP COLUMN
+# when an AUTO_INCREMENT column is not in PRIMARY KEY
+#
+eval CREATE TABLE t1 (a INT AUTO_INCREMENT, b INT, KEY(a)) $engine;
+INSERT INTO t1 SET a=NULL;
+ALTER TABLE t1 DROP COLUMN b;
+ALTER TABLE t1 ADD COLUMN c INT NOT NULL DEFAULT 42;
+INSERT INTO t1 SET a=NULL;
+UPDATE t1 SET a=a+2;
+SELECT * FROM t1;
+DROP TABLE t1;
+
dec $format;
}
disconnect analyze;
diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc
index 777d69cf127..1014168d389 100644
--- a/storage/innobase/row/row0ins.cc
+++ b/storage/innobase/row/row0ins.cc
@@ -2597,25 +2597,32 @@ row_ins_clust_index_entry_low(
} else {
index->set_modified(mtr);
- if (mode == BTR_MODIFY_LEAF
- && dict_index_is_online_ddl(index)) {
- mode = BTR_MODIFY_LEAF_ALREADY_S_LATCHED;
- mtr_s_lock(dict_index_get_lock(index), &mtr);
- }
+ if (UNIV_UNLIKELY(entry->is_metadata())) {
+ ut_ad(index->is_instant());
+ ut_ad(!dict_index_is_online_ddl(index));
+ ut_ad(mode == BTR_MODIFY_TREE);
+ } else {
+ if (mode == BTR_MODIFY_LEAF
+ && dict_index_is_online_ddl(index)) {
+ mode = BTR_MODIFY_LEAF_ALREADY_S_LATCHED;
+ mtr_s_lock(dict_index_get_lock(index), &mtr);
+ }
- if (unsigned ai = index->table->persistent_autoinc) {
- /* Prepare to persist the AUTO_INCREMENT value
- from the index entry to PAGE_ROOT_AUTO_INC. */
- const dfield_t* dfield = dtuple_get_nth_field(
- entry, ai - 1);
- auto_inc = dfield_is_null(dfield)
- ? 0
- : row_parse_int(static_cast<const byte*>(
+ if (unsigned ai = index->table->persistent_autoinc) {
+ /* Prepare to persist the AUTO_INCREMENT value
+ from the index entry to PAGE_ROOT_AUTO_INC. */
+ const dfield_t* dfield = dtuple_get_nth_field(
+ entry, ai - 1);
+ if (!dfield_is_null(dfield)) {
+ auto_inc = row_parse_int(
+ static_cast<const byte*>(
dfield->data),
dfield->len,
dfield->type.mtype,
dfield->type.prtype
& DATA_UNSIGNED);
+ }
+ }
}
}