diff --git a/mysql-test/suite/innodb/r/innodb-virtual-columns.result b/mysql-test/suite/innodb/r/innodb-virtual-columns.result index b97eaac75651b..f91c4615af0b7 100644 --- a/mysql-test/suite/innodb/r/innodb-virtual-columns.result +++ b/mysql-test/suite/innodb/r/innodb-virtual-columns.result @@ -351,3 +351,40 @@ SELECT * FROM t1; a b c 1 foo 1 DROP TABLE t1; +CREATE TABLE t1 ( +id int primary key,value varchar(2), +vcomplete int AS (cast(substr(value,1,1) as int)), +va int AS (null),vb int AS (null),vc int AS (null), +vresult char(1) AS (substr(value,2)), +KEY key1(vresult,vcomplete) +) ENGINE=InnoDB; +BEGIN; +INSERT INTO t1(id,value) VALUES (1,'0F'); +UPDATE t1 SET value = '1S'; +UPDATE t1 SET value = '0F'; +COMMIT; +SET GLOBAL innodb_max_purge_lag_wait=0; +SELECT * FROM t1; +id value vcomplete va vb vc vresult +1 0F 0 NULL NULL NULL F +DROP TABLE t1; +CREATE TABLE t1 ( +col1 int primary key, +col2 int, +col3 int, +col4 varchar(5), +v_col1 char(1) AS (substr(col4,1,1)), +v_col2 char(1) AS (substr(col4,2,1)), +v_col3 char(1) AS (substr(col4,3,1)), +v_col4 char(1) AS (substr(col4,4,1)), +v_col5 char(1) AS (substr(col4,5,1)), +KEY key1(v_col2, v_col1, v_col3, v_col4, v_col5), +KEY key2(col2, col3) +) ENGINE=InnoDB; +INSERT INTO t1(col1,col2,col3,col4) VALUES (1,1,1,'ABCDE'); +UPDATE t1 SET col2=2, col4 = 'PQRST'; +SET GLOBAL innodb_max_purge_lag_wait=0; +CHECK TABLE t1 EXTENDED; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/innodb-virtual-columns.test b/mysql-test/suite/innodb/t/innodb-virtual-columns.test index faf542645fb23..6bb9ddc8dc42c 100644 --- a/mysql-test/suite/innodb/t/innodb-virtual-columns.test +++ b/mysql-test/suite/innodb/t/innodb-virtual-columns.test @@ -317,3 +317,49 @@ INSERT INTO t1 (a,b) VALUES (1,'foo'); ALTER TABLE t1 ADD FULLTEXT KEY(b); SELECT * FROM t1; DROP TABLE t1; + +# +# MDEV-38140 : InnoDB index corruption after UPDATE affecting virtual columns +# + +CREATE TABLE t1 ( + id int primary key,value varchar(2), + vcomplete int AS (cast(substr(value,1,1) as int)), + va int AS (null),vb int AS (null),vc int AS (null), + vresult char(1) AS (substr(value,2)), + KEY key1(vresult,vcomplete) +) ENGINE=InnoDB; + +BEGIN; +INSERT INTO t1(id,value) VALUES (1,'0F'); +UPDATE t1 SET value = '1S'; +UPDATE t1 SET value = '0F'; +COMMIT; + +SET GLOBAL innodb_max_purge_lag_wait=0; +SELECT * FROM t1; + +DROP TABLE t1; + +# Test to check if all the stale secondary records are purged +CREATE TABLE t1 ( + col1 int primary key, + col2 int, + col3 int, + col4 varchar(5), + v_col1 char(1) AS (substr(col4,1,1)), + v_col2 char(1) AS (substr(col4,2,1)), + v_col3 char(1) AS (substr(col4,3,1)), + v_col4 char(1) AS (substr(col4,4,1)), + v_col5 char(1) AS (substr(col4,5,1)), + KEY key1(v_col2, v_col1, v_col3, v_col4, v_col5), + KEY key2(col2, col3) +) ENGINE=InnoDB; + + +INSERT INTO t1(col1,col2,col3,col4) VALUES (1,1,1,'ABCDE'); +UPDATE t1 SET col2=2, col4 = 'PQRST'; +SET GLOBAL innodb_max_purge_lag_wait=0; + +CHECK TABLE t1 EXTENDED; +DROP TABLE t1; diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc index 37c64d2153228..5d854ebd5e5e3 100644 --- a/storage/innobase/trx/trx0rec.cc +++ b/storage/innobase/trx/trx0rec.cc @@ -1222,9 +1222,12 @@ trx_undo_page_report_modify( columns that were updated. */ for (i = 0; i < update->n_fields; i++) { + const upd_field_t* fld = + upd_get_nth_field(update, i); + if (upd_fld_is_virtual_col(fld)) + continue; const ulint field_no - = upd_get_nth_field(update, i) - ->field_no; + = fld->field_no; if (field_no >= index->n_fields || dict_index_get_nth_field( index, field_no)->col @@ -1524,7 +1527,7 @@ trx_undo_update_rec_get_update( &field_no); first_v_col = false; /* This column could be dropped or no longer indexed */ - if (field_no >= index->n_fields) { + if (field_no == FIL_NULL) { /* Mark this is no longer needed */ upd_field->field_no = REC_MAX_N_FIELDS;