From 4383e16cbe1010c5fbcd61e0b411703a84649ddf Mon Sep 17 00:00:00 2001 From: Aleksey Midenkov Date: Sun, 25 Dec 2016 08:25:17 +0000 Subject: [PATCH] IB: skip check_ref on historical record [fixes #101] --- mysql-test/suite/versioning/r/foreign.result | 27 +++++++++++++++++-- mysql-test/suite/versioning/t/foreign.test | 28 ++++++++++++++++++-- storage/innobase/row/row0ins.cc | 16 +++++++++-- 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/mysql-test/suite/versioning/r/foreign.result b/mysql-test/suite/versioning/r/foreign.result index ee9e726a29a..3903bee2f00 100644 --- a/mysql-test/suite/versioning/r/foreign.result +++ b/mysql-test/suite/versioning/r/foreign.result @@ -80,13 +80,36 @@ on delete cascade on update restrict ) engine innodb; -insert into parent (id) values (1); -insert into child (x, parent_id) values (1, 1); +insert into parent (id) values (2); +insert into child (x, parent_id) values (2, 2); delete from parent; select * from child; x parent_id drop table child; drop table parent; +create or replace table parent ( +id int primary key +) +engine innodb; +create or replace table child ( +id int primary key, +parent_id int not null, +constraint `parent-fk` + foreign key (parent_id) references parent (id) +on delete cascade +on update restrict +) with system versioning +engine innodb; +insert into parent (id) values (3); +insert into child (id, parent_id) values (3, 3); +delete from parent; +select * from child; +id parent_id +select * from child for system_time all; +id parent_id +3 3 +drop table child; +drop table parent; create table parent( id int unique key ) engine innodb; diff --git a/mysql-test/suite/versioning/t/foreign.test b/mysql-test/suite/versioning/t/foreign.test index 2a1bca3af60..ec23abac460 100644 --- a/mysql-test/suite/versioning/t/foreign.test +++ b/mysql-test/suite/versioning/t/foreign.test @@ -102,14 +102,38 @@ create or replace table child ( ) engine innodb; -insert into parent (id) values (1); -insert into child (x, parent_id) values (1, 1); +insert into parent (id) values (2); +insert into child (x, parent_id) values (2, 2); delete from parent; select * from child; drop table child; drop table parent; +create or replace table parent ( + id int primary key +) +engine innodb; + +create or replace table child ( + id int primary key, + parent_id int not null, + constraint `parent-fk` + foreign key (parent_id) references parent (id) + on delete cascade + on update restrict +) with system versioning +engine innodb; + +insert into parent (id) values (3); +insert into child (id, parent_id) values (3, 3); +delete from parent; +select * from child; +select * from child for system_time all; + +drop table child; +drop table parent; + ################# # Test SET NULL # ################# diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index f3fc7422ffe..c107ae6e01b 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -1686,10 +1686,22 @@ row_ins_check_foreign_constraint( /* If any of the foreign key fields in entry is SQL NULL, we suppress the foreign key check: this is compatible with Oracle, for example */ - for (ulint i = 0; i < foreign->n_fields; i++) { - if (dfield_is_null(dtuple_get_nth_field(entry, i))) { + for (ulint i = 0; i < entry->n_fields; i++) { + dfield_t* field = dtuple_get_nth_field(entry, i); + if (i < foreign->n_fields && dfield_is_null(field)) { goto exit_func; } + /* System Versioning: if sys_trx_end != Inf, we + suppress the foreign key check */ + if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_VERSIONED) && + dfield_get_type(field)->prtype & DATA_VERS_ROW_END) + { + byte* data = static_cast(dfield_get_data(field)); + ut_ad(data); + trx_id_t end_trx_id = mach_read_from_8(data); + if (end_trx_id != TRX_ID_MAX) + goto exit_func; + } } if (que_node_get_type(thr->run_node) == QUE_NODE_UPDATE) {