Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

executor: fix issue of foreign key cascade don't work cause by untouched index key #39420

Merged
merged 12 commits into from
Nov 28, 2022
26 changes: 26 additions & 0 deletions executor/fktest/foreign_key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2081,3 +2081,29 @@ func TestForeignKeyOnInsertOnDuplicateUpdate(t *testing.T) {
tk.MustQuery("select * from t2").Check(testkit.Rows("1"))
tk.MustQuery("select * from t3").Check(testkit.Rows("1"))
}

func TestForeignKeyIssue39419(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("set @@global.tidb_enable_foreign_key=1")
tk.MustExec("set @@foreign_key_checks=1")
tk.MustExec("use test")
tk.MustExec("create table t1 (id int key);")
tk.MustExec("create table t2 (id int key, a int, b int, " +
"foreign key fk_1 (a) references t1(id) ON DELETE SET NULL ON UPDATE SET NULL, " +
"foreign key fk_2 (b) references t1(id) ON DELETE CASCADE ON UPDATE CASCADE);")
tk.MustExec("insert into t1 values (1), (2), (3);")
tk.MustExec("insert into t2 values (1, 1, 1), (2, 2, 2), (3, 3, 3);")
tk.MustExec("update t1 set id=id+10 where id in (1, 3);")
tk.MustQuery("select * from t1 order by id").Check(testkit.Rows("2", "11", "13"))
tk.MustQuery("select * from t2 order by id").Check(testkit.Rows("1 <nil> 11", "2 2 2", "3 <nil> 13"))
tk.MustExec("delete from t1 where id = 2;")
tk.MustQuery("select * from t1 order by id").Check(testkit.Rows("11", "13"))
tk.MustQuery("select * from t2 order by id").Check(testkit.Rows("1 <nil> 11", "3 <nil> 13"))

tk.MustExec("drop table t1,t2")
tk.MustExec("create table t1 (id int, b int, index(id), foreign key fk_2 (b) references t1(id) ON UPDATE CASCADE);")
tk.MustExec("insert into t1 values (1, 1), (2, 2), (3, 3);")
tk.MustExec("update t1 set id=id+10 where id > 1")
tk.MustQuery("select * from t1 order by id").Check(testkit.Rows("1 1", "12 12", "13 13"))
}
7 changes: 6 additions & 1 deletion table/tables/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,12 @@ func (t *TableCommon) rebuildIndices(ctx sessionctx.Context, txn kv.Transaction,
break
}
// If txn is auto commit and index is untouched, no need to write index value.
if untouched && !ctx.GetSessionVars().InTxn() {
// If InHandleForeignKeyTrigger or ForeignKeyTriggerCtx.HasFKCascades is true indicate we may have
// foreign key cascade need to handle later, then we still need to write index value,
// otherwise, the later foreign cascade executor may see data-index inconsistency in txn-mem-buffer.
sessVars := ctx.GetSessionVars()
if untouched && !sessVars.InTxn() &&
!sessVars.StmtCtx.InHandleForeignKeyTrigger && !sessVars.StmtCtx.ForeignKeyTriggerCtx.HasFKCascades {
continue
}
newVs, err := idx.FetchValues(newData, nil)
Expand Down