diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2020-02-05 11:12:10 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2020-02-05 11:12:10 +0200 |
commit | 2acc6f2d95d31f4ea82de8a66c5f2f7fd6583a16 (patch) | |
tree | 89a3c4e7ab169f09a478b4e311b9b81f6ac605ed | |
parent | a56f78243ee06167b5baf8255d3866099f3a3936 (diff) | |
download | mariadb-git-2acc6f2d95d31f4ea82de8a66c5f2f7fd6583a16.tar.gz |
MDEV-21658 Error on online ADD PRIMARY KEY after instant DROP/reorder
row_log_table_get_pk_old_col(): For replacing a NULL value for a
column of the being-added primary key, look up the correct
default value, even if columns had been instantly reordered or
dropped earlier. This ought to have been broken ever since
commit 0e5a4ac2532c64a545796c787354dc41d61d0e62 (MDEV-15562).
-rw-r--r-- | mysql-test/suite/innodb/r/instant_alter_debug.result | 24 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/instant_alter_debug.test | 26 | ||||
-rw-r--r-- | storage/innobase/row/row0log.cc | 15 |
3 files changed, 61 insertions, 4 deletions
diff --git a/mysql-test/suite/innodb/r/instant_alter_debug.result b/mysql-test/suite/innodb/r/instant_alter_debug.result index 72c9a85e369..9fcb8b05a34 100644 --- a/mysql-test/suite/innodb/r/instant_alter_debug.result +++ b/mysql-test/suite/innodb/r/instant_alter_debug.result @@ -343,6 +343,30 @@ UPDATE t1 SET b = 1; SET DEBUG_SYNC='now SIGNAL update'; connection con2; connection default; +DROP TABLE t1; +# +# MDEV-21658 Error on online ADD PRIMARY KEY after instant DROP/reorder +# +CREATE TABLE t1 (a INT, b INT, c INT, col INT) ENGINE=InnoDB; +INSERT INTO t1 () VALUES (); +ALTER TABLE t1 DROP b, DROP c, DROP col; +ALTER TABLE t1 ADD COLUMN col INT; +ALTER TABLE t1 DROP a, DROP col, ADD COLUMN b INT; +connection con2; +SET SQL_MODE= ''; +SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL scanned WAIT_FOR dml'; +ALTER TABLE t1 ADD PRIMARY KEY(b); +connection default; +SET DEBUG_SYNC = 'now WAIT_FOR scanned'; +UPDATE t1 SET b = 1; +SET DEBUG_SYNC = 'now SIGNAL dml'; +connection con2; +Warnings: +Warning 1265 Data truncated for column 'b' at row 1 +connection default; +SELECT * FROM t1; +b +1 SET DEBUG_SYNC='RESET'; disconnect con2; DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/instant_alter_debug.test b/mysql-test/suite/innodb/t/instant_alter_debug.test index 22452c78f4d..fe80de2ca51 100644 --- a/mysql-test/suite/innodb/t/instant_alter_debug.test +++ b/mysql-test/suite/innodb/t/instant_alter_debug.test @@ -385,6 +385,32 @@ SET DEBUG_SYNC='now SIGNAL update'; --reap --connection default +DROP TABLE t1; + +--echo # +--echo # MDEV-21658 Error on online ADD PRIMARY KEY after instant DROP/reorder +--echo # + +CREATE TABLE t1 (a INT, b INT, c INT, col INT) ENGINE=InnoDB; +INSERT INTO t1 () VALUES (); +ALTER TABLE t1 DROP b, DROP c, DROP col; +ALTER TABLE t1 ADD COLUMN col INT; +ALTER TABLE t1 DROP a, DROP col, ADD COLUMN b INT; + +--connection con2 +SET SQL_MODE= ''; +SET DEBUG_SYNC = 'row_log_table_apply1_before SIGNAL scanned WAIT_FOR dml'; +send ALTER TABLE t1 ADD PRIMARY KEY(b); + +--connection default +SET DEBUG_SYNC = 'now WAIT_FOR scanned'; +UPDATE t1 SET b = 1; +SET DEBUG_SYNC = 'now SIGNAL dml'; +--connection con2 +reap; +--connection default +SELECT * FROM t1; + SET DEBUG_SYNC='RESET'; --disconnect con2 DROP TABLE t1; diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 91879068c17..0fd3f840fcf 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -1137,6 +1137,7 @@ row_log_table_get_pk_old_col( /** Maps an old table column of a PRIMARY KEY column. @param[in] ifield clustered index field in the new table (after ALTER TABLE) +@param[in] index the clustered index of ifield @param[in,out] dfield clustered index tuple field in the new table @param[in,out] heap memory heap for allocating dfield contents @param[in] rec clustered index leaf page record in the old @@ -1152,6 +1153,7 @@ static dberr_t row_log_table_get_pk_col( const dict_field_t* ifield, + const dict_index_t* index, dfield_t* dfield, mem_heap_t* heap, const rec_t* rec, @@ -1175,14 +1177,19 @@ row_log_table_get_pk_col( return(DB_INVALID_NULL); } - ulint n_default_cols = i - DATA_N_SYS_COLS; + ulint new_i = dict_col_get_clust_pos(ifield->col, index); + + if (UNIV_UNLIKELY(new_i >= log->defaults->n_fields)) { + ut_ad(0); + return DB_INVALID_NULL; + } field = static_cast<const byte*>( - log->defaults->fields[n_default_cols].data); + log->defaults->fields[new_i].data); if (!field) { return(DB_INVALID_NULL); } - len = log->defaults->fields[i - DATA_N_SYS_COLS].len; + len = log->defaults->fields[new_i].len; } if (rec_offs_nth_extern(offsets, i)) { @@ -1341,7 +1348,7 @@ row_log_table_get_pk( } log->error = row_log_table_get_pk_col( - ifield, dfield, *heap, + ifield, new_index, dfield, *heap, rec, offsets, i, zip_size, max_len, log); |