Skip to content

Commit

Permalink
fix bug: when the updated data does not change, there is no need to c…
Browse files Browse the repository at this point in the history
…heck the constraints (#12753)

…check the constraints (#12732)

fix bug: when the updated data does not change, there is no need to
check the constraints

you can repro like:
```
create table f1 (a int primary key);
create table c1(aa int primary key, bb int, CONSTRAINT `fk_bb` FOREIGN KEY (`bb`) REFERENCES `f1`(`a`));
insert into f1 values (1);
insert into c1 values (1,1);
update f1 set a=a;  //MO throw error.  but MySQL not.      this PR will fix it
```

Approved by: @heni02, @badboynt1, @aunjgr
  • Loading branch information
ouyuanning authored Nov 15, 2023
1 parent efb87f6 commit 79ee4c1
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 5 deletions.
49 changes: 44 additions & 5 deletions pkg/sql/plan/build_dml_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,16 +422,15 @@ func buildDeletePlans(ctx CompilerContext, builder *QueryBuilder, bindCtx *BindC
for _, fk := range childTableDef.Fkeys {
if fk.ForeignTbl == delCtx.tableDef.TblId {
// update stmt: update the columns do not contain ref key, skip
updateRefColumn := make(map[string]int32)
if isUpdate {
updateRefColumn := false
for _, colId := range fk.ForeignCols {
updateName := idNameMap[colId]
if _, ok := delCtx.updateColPosMap[updateName]; ok {
updateRefColumn = true
break
if uIdx, ok := delCtx.updateColPosMap[updateName]; ok {
updateRefColumn[updateName] = int32(uIdx)
}
}
if !updateRefColumn {
if len(updateRefColumn) == 0 {
continue
}
}
Expand Down Expand Up @@ -529,6 +528,46 @@ func buildDeletePlans(ctx CompilerContext, builder *QueryBuilder, bindCtx *BindC
}

lastNodeId = appendSinkScanNode(builder, bindCtx, delCtx.sourceStep)
// deal with case: update t1 set a = a. then do not need to check constraint
if isUpdate {
var filterExpr, tmpExpr *Expr
for updateName, newIdx := range updateRefColumn {
oldIdx := nameIdxMap[updateName]
tmpExpr, err = bindFuncExprImplByPlanExpr(builder.GetContext(), "!=", []*Expr{{
Typ: nameTypMap[updateName],
Expr: &plan.Expr_Col{
Col: &ColRef{
ColPos: oldIdx,
Name: updateName,
},
},
}, {
Typ: nameTypMap[updateName],
Expr: &plan.Expr_Col{
Col: &ColRef{
ColPos: newIdx,
Name: updateName,
},
},
}})
if err != nil {
return nil
}
if filterExpr == nil {
filterExpr = tmpExpr
} else {
filterExpr, err = bindFuncExprImplByPlanExpr(builder.GetContext(), "or", []*Expr{filterExpr, tmpExpr})
if err != nil {
return nil
}
}
}
lastNodeId = builder.appendNode(&plan.Node{
NodeType: plan.Node_FILTER,
Children: []int32{lastNodeId},
FilterList: []*Expr{filterExpr},
}, bindCtx)
}

switch refAction {
case plan.ForeignKeyDef_NO_ACTION, plan.ForeignKeyDef_RESTRICT, plan.ForeignKeyDef_SET_DEFAULT:
Expand Down
22 changes: 22 additions & 0 deletions test/distributed/cases/foreign_key/fk_base.result
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,28 @@ drop table fk_04;
drop table fk_03;
drop table fk_02;
drop table fk_01;
create table f1(a int, b int, primary key (a,b));
create table c1(id int primary key, aa int, bb int, CONSTRAINT `fk_aa` FOREIGN KEY(`aa`) REFERENCES `f1`(`a`));
insert into f1 values (1,1);
insert into c1 values (1,1,1);
update f1 set a=a;
update f1 set a=1;
update f1 set a=a, b=2;
update f1 set a=2;
internal error: Cannot delete or update a parent row: a foreign key constraint fails
drop table c1;
drop table f1;
create table f1(a int, b int, primary key (a,b));
create table c1(id int primary key, aa int, bb int, CONSTRAINT `fk_aa` FOREIGN KEY(`aa`,`bb`) REFERENCES `f1`(`a`,`b`));
insert into f1 values (1,1);
insert into c1 values (1,1,1);
update f1 set a=a;
update f1 set a=a, b=1;
update f1 set b=1, a=a;
update f1 set a=a, b=2;
internal error: Cannot delete or update a parent row: a foreign key constraint fails
drop table c1;
drop table f1;
drop database if exists db1;
create database db1;
use db1;
Expand Down
22 changes: 22 additions & 0 deletions test/distributed/cases/foreign_key/fk_base.sql
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,28 @@ drop table fk_03;
drop table fk_02;
drop table fk_01;

create table f1(a int, b int, primary key (a,b));
create table c1(id int primary key, aa int, bb int, CONSTRAINT `fk_aa` FOREIGN KEY(`aa`) REFERENCES `f1`(`a`));
insert into f1 values (1,1);
insert into c1 values (1,1,1);
update f1 set a=a;
update f1 set a=1;
update f1 set a=a, b=2;
update f1 set a=2;
drop table c1;
drop table f1;

create table f1(a int, b int, primary key (a,b));
create table c1(id int primary key, aa int, bb int, CONSTRAINT `fk_aa` FOREIGN KEY(`aa`,`bb`) REFERENCES `f1`(`a`,`b`));
insert into f1 values (1,1);
insert into c1 values (1,1,1);
update f1 set a=a;
update f1 set a=a, b=1;
update f1 set b=1, a=a;
update f1 set a=a, b=2;
drop table c1;
drop table f1;

drop database if exists db1;
create database db1;
use db1;
Expand Down

0 comments on commit 79ee4c1

Please sign in to comment.