Skip to content

Commit

Permalink
IB: FK cascade delete when parent versioned [fixes #101]
Browse files Browse the repository at this point in the history
  • Loading branch information
midenok committed May 5, 2017
1 parent 412dd1e commit 46badf1
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 15 deletions.
26 changes: 23 additions & 3 deletions mysql-test/suite/versioning/r/foreign.result
Original file line number Diff line number Diff line change
Expand Up @@ -52,21 +52,41 @@ insert into child values(1);
delete from parent where id = 1;
select * from child;
parent_id
select * from child for system_time from timestamp '1-1-1' to timestamp now(6);
select * from child for system_time all;
parent_id
1
insert into parent values(1);
insert into child values(1);
update parent set id=id+1;
update parent set id = id + 1;
select * from child;
parent_id
2
select * from child for system_time from timestamp '1-1-1' to timestamp now(6);
select * from child for system_time all;
parent_id
1
2
drop table child;
drop table parent;
create or replace table parent (
id int primary key
) with system versioning
engine innodb;
create or replace table child (
x int,
parent_id int not null,
constraint `parent-fk`
foreign key (parent_id) references parent (id)
on delete cascade
on update restrict
)
engine innodb;
insert into parent (id) values (1);
insert into child (x, parent_id) values (1, 1);
delete from parent;
select * from child;
x parent_id
drop table child;
drop table parent;
create table parent(
id int unique key
) engine innodb;
Expand Down
29 changes: 26 additions & 3 deletions mysql-test/suite/versioning/t/foreign.test
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,36 @@ insert into child values(1);

delete from parent where id = 1;
select * from child;
select * from child for system_time from timestamp '1-1-1' to timestamp now(6);
select * from child for system_time all;

insert into parent values(1);
insert into child values(1);
update parent set id=id+1;
update parent set id = id + 1;
select * from child;
select * from child for system_time all;

drop table child;
drop table parent;

create or replace table parent (
id int primary key
) with system versioning
engine innodb;

create or replace table child (
x int,
parent_id int not null,
constraint `parent-fk`
foreign key (parent_id) references parent (id)
on delete cascade
on update restrict
)
engine innodb;

insert into parent (id) values (1);
insert into child (x, parent_id) values (1, 1);
delete from parent;
select * from child;
select * from child for system_time from timestamp '1-1-1' to timestamp now(6);

drop table child;
drop table parent;
Expand Down
23 changes: 14 additions & 9 deletions storage/innobase/row/row0ins.cc
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,8 @@ row_ins_cascade_ancestor_updates_table(

upd_node = static_cast<upd_node_t*>(parent);

if (upd_node->table == table && upd_node->is_delete == FALSE) {
if (upd_node->table == table && upd_node->is_delete == FALSE
&& !upd_node->vers_delete) {

return(TRUE);
}
Expand Down Expand Up @@ -977,6 +978,8 @@ row_ins_foreign_fill_virtual(
innobase_init_vc_templ(index->table);
}

bool is_delete = node->is_delete || node->vers_delete;

for (ulint i = 0; i < n_v_fld; i++) {

dict_v_col_t* col = dict_table_get_nth_v_col(
Expand Down Expand Up @@ -1008,14 +1011,14 @@ row_ins_foreign_fill_virtual(

upd_field_set_v_field_no(upd_field, i, index);

if (node->is_delete
if (is_delete
? (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
: (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)) {

dfield_set_null(&upd_field->new_val);
}

if (!node->is_delete
if (!is_delete
&& (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)) {

dfield_t* new_vfield = innobase_get_computed_value(
Expand Down Expand Up @@ -1108,7 +1111,9 @@ row_ins_foreign_check_on_constraint(

node = static_cast<upd_node_t*>(thr->run_node);

if (node->is_delete && 0 == (foreign->type
bool is_delete = node->is_delete || node->vers_delete;

if (is_delete && 0 == (foreign->type
& (DICT_FOREIGN_ON_DELETE_CASCADE
| DICT_FOREIGN_ON_DELETE_SET_NULL))) {

Expand All @@ -1119,7 +1124,7 @@ row_ins_foreign_check_on_constraint(
DBUG_RETURN(DB_ROW_IS_REFERENCED);
}

if (!node->is_delete && 0 == (foreign->type
if (!is_delete && 0 == (foreign->type
& (DICT_FOREIGN_ON_UPDATE_CASCADE
| DICT_FOREIGN_ON_UPDATE_SET_NULL))) {

Expand Down Expand Up @@ -1148,7 +1153,7 @@ row_ins_foreign_check_on_constraint(

cascade->foreign = foreign;

if (node->is_delete
if (is_delete
&& (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)) {
cascade->is_delete = TRUE;
} else {
Expand Down Expand Up @@ -1285,7 +1290,7 @@ row_ins_foreign_check_on_constraint(
clust_index, tmp_heap);
}

if (node->is_delete
if (is_delete
? (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL)
: (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)) {

Expand Down Expand Up @@ -1365,7 +1370,7 @@ row_ins_foreign_check_on_constraint(
}
}

if (!node->is_delete
if (!is_delete
&& (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE)) {

/* Build the appropriate update vector which sets changing
Expand Down Expand Up @@ -1690,7 +1695,7 @@ row_ins_check_foreign_constraint(
if (que_node_get_type(thr->run_node) == QUE_NODE_UPDATE) {
upd_node = static_cast<upd_node_t*>(thr->run_node);

if (!(upd_node->is_delete) && upd_node->foreign == foreign) {
if (!(upd_node->is_delete) && !(upd_node->vers_delete) && upd_node->foreign == foreign) {
/* If a cascaded update is done as defined by a
foreign key constraint, do not check that
constraint for the child row. In ON UPDATE CASCADE
Expand Down

0 comments on commit 46badf1

Please sign in to comment.