diff --git a/mysql-test/suite/versioning/r/misc.result b/mysql-test/suite/versioning/r/misc.result index fadc896d185..b7eada49aa0 100644 --- a/mysql-test/suite/versioning/r/misc.result +++ b/mysql-test/suite/versioning/r/misc.result @@ -57,6 +57,30 @@ insert into t2 (a) values (now()),(now()); select * from t2 where a in (select row_start from t1); a drop table t1, t2; +# MDEV-30046 wrong row targeted with "insert ... on duplicate" and "replace" +# Don't allow changes from the past +create or replace table t1 (pk int primary key, i int) with system versioning; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `pk` int(11) NOT NULL, + `i` int(11) DEFAULT NULL, + PRIMARY KEY (`pk`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci WITH SYSTEM VERSIONING +set timestamp=12345; +insert t1(pk, i) values(1,3); +set timestamp=12344; +delete from t1; +select pk,i from t1 for system_time all; +pk i +set timestamp=12345; +insert t1(pk, i) values(1,3); +set timestamp=12344; +replace t1(pk, i) values(1,4); +select pk,i from t1 for system_time all; +pk i +1 4 +drop table t1; # # End of 10.11 tests # diff --git a/mysql-test/suite/versioning/t/misc.test b/mysql-test/suite/versioning/t/misc.test index fa5012b6efa..5ec9c964dca 100644 --- a/mysql-test/suite/versioning/t/misc.test +++ b/mysql-test/suite/versioning/t/misc.test @@ -46,6 +46,25 @@ insert into t2 (a) values (now()),(now()); select * from t2 where a in (select row_start from t1); drop table t1, t2; +--echo # MDEV-30046 wrong row targeted with "insert ... on duplicate" and "replace" +--echo # Don't allow changes from the past +create or replace table t1 (pk int primary key, i int) with system versioning; +show create table t1; +set timestamp=12345; +insert t1(pk, i) values(1,3); +set timestamp=12344; +delete from t1; + +select pk,i from t1 for system_time all; + +set timestamp=12345; +insert t1(pk, i) values(1,3); +set timestamp=12344; +replace t1(pk, i) values(1,4); + +select pk,i from t1 for system_time all; +drop table t1; + --echo # --echo # End of 10.11 tests --echo # diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 735c2fd0863..71d354e6423 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -308,6 +308,7 @@ int TABLE::delete_row(bool treat_versioned) { int err= 0; uchar *del_buf= record[replace ? 1 : 0]; + bool delete_row= !treat_versioned || in_use->lex->vers_conditions.delete_history || versioned(VERS_TRX_ID) @@ -325,7 +326,14 @@ int TABLE::delete_row(bool treat_versioned) store_record(this, record[1]); } vers_update_end(); - err= file->ha_update_row(record[1], record[0]); + + Field *row_start= vers_start_field(); + Field *row_end= vers_end_field(); + // Don't make history row with negative lifetime + delete_row= row_start->cmp(row_start->ptr, row_end->ptr) > 0; + + if (likely(!delete_row)) + err= file->ha_update_row(record[1], record[0]); if (unlikely(err)) { /* @@ -342,11 +350,11 @@ int TABLE::delete_row(bool treat_versioned) || err == HA_ERR_FOREIGN_DUPLICATE_KEY; if (!delete_row) return err; - - if (!replace) - del_buf= record[1]; } + if (delete_row) + del_buf= record[1]; + if (replace) restore_record(this, record[2]); }