Skip to content

Commit

Permalink
executor: fix wrong result of delete multiple tables using left join (p…
Browse files Browse the repository at this point in the history
  • Loading branch information
ti-srebot authored Jul 5, 2022
1 parent ba76bb4 commit 1baedb9
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 2 deletions.
3 changes: 3 additions & 0 deletions executor/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,9 @@ func (e *DeleteExec) doBatchDelete(ctx context.Context) error {
func (e *DeleteExec) composeTblRowMap(tblRowMap tableRowMapType, colPosInfos []plannercore.TblColPosInfo, joinedRow []types.Datum) error {
// iterate all the joined tables, and got the copresonding rows in joinedRow.
for _, info := range colPosInfos {
if unmatchedOuterRow(info, joinedRow) {
continue
}
if tblRowMap[info.TblID] == nil {
tblRowMap[info.TblID] = kv.NewHandleMap()
}
Expand Down
30 changes: 30 additions & 0 deletions executor/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8453,3 +8453,33 @@ func (s *testSerialSuite) TestIssue30289(c *C) {
err := tk.QueryToErr("select /*+ hash_join(t1) */ * from t t1 join t t2 on t1.a=t2.a")
c.Assert(err.Error(), Matches, "issue30289 build return error")
}

func (s *testSuite) TestDeleteWithMulTbl(c *C) {
tk := testkit.NewTestKit(c, s.store)

// Delete multiple tables from left joined table.
// The result of left join is (3, null, null).
// Because rows in t2 are not matched, so no row will be deleted in t2.
// But row in t1 is matched, so it should be deleted.
tk.MustExec("use test;")
tk.MustExec("drop table if exists t1, t2;")
tk.MustExec("create table t1 (c1 int);")
tk.MustExec("create table t2 (c1 int primary key, c2 int);")
tk.MustExec("insert into t1 values(3);")
tk.MustExec("insert into t2 values(2, 2);")
tk.MustExec("insert into t2 values(0, 0);")
tk.MustExec("delete from t1, t2 using t1 left join t2 on t1.c1 = t2.c2;")
tk.MustQuery("select * from t1 order by c1;").Check(testkit.Rows())
tk.MustQuery("select * from t2 order by c1;").Check(testkit.Rows("0 0", "2 2"))

// Rows in both t1 and t2 are matched, so will be deleted even if it's null.
// NOTE: The null values are not generated by join.
tk.MustExec("drop table if exists t1, t2;")
tk.MustExec("create table t1 (c1 int);")
tk.MustExec("create table t2 (c2 int);")
tk.MustExec("insert into t1 values(null);")
tk.MustExec("insert into t2 values(null);")
tk.MustExec("delete from t1, t2 using t1 join t2 where t1.c1 is null;")
tk.MustQuery("select * from t1;").Check(testkit.Rows())
tk.MustQuery("select * from t2;").Check(testkit.Rows())
}
4 changes: 2 additions & 2 deletions executor/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func (e *UpdateExec) prepare(row []types.Datum) (err error) {
break
}
}
if e.unmatchedOuterRow(content, row) {
if unmatchedOuterRow(content, row) {
updatable = false
}
e.tableUpdatable = append(e.tableUpdatable, updatable)
Expand Down Expand Up @@ -206,7 +206,7 @@ func (e *UpdateExec) exec(ctx context.Context, schema *expression.Schema, row, n
// the inner handle field is filled with a NULL value.
//
// This fixes: https://github.com/pingcap/tidb/issues/7176.
func (e *UpdateExec) unmatchedOuterRow(tblPos plannercore.TblColPosInfo, waitUpdateRow []types.Datum) bool {
func unmatchedOuterRow(tblPos plannercore.TblColPosInfo, waitUpdateRow []types.Datum) bool {
firstHandleIdx := tblPos.HandleCols.GetCol(0)
return waitUpdateRow[firstHandleIdx.Index].IsNull()
}
Expand Down

0 comments on commit 1baedb9

Please sign in to comment.