diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2018-11-16 13:28:37 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2018-11-16 13:28:37 +0200 |
commit | f85012246cec2a774c5c1fa895b1e593eaf69081 (patch) | |
tree | 5bcf70305f154b14511009732f52b294be14d58a | |
parent | 89337d510e9780d6533c3db4d42969b2338a7610 (diff) | |
download | mariadb-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.result | 35 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/instant_alter.test | 13 | ||||
-rw-r--r-- | storage/innobase/row/row0ins.cc | 33 |
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); + } + } } } |