From cc0dae97570542254af37068661e4fac774dd229 Mon Sep 17 00:00:00 2001 From: lysu Date: Fri, 26 Mar 2021 19:43:23 +0800 Subject: [PATCH] cherry pick #23491 to release-5.0 Signed-off-by: ti-srebot --- ddl/db_change_test.go | 5 +- executor/builder.go | 28 +++++ executor/executor_test.go | 167 +++++++++++++++++++++++++++ executor/update.go | 67 ++++++----- planner/core/common_plans.go | 2 + planner/core/logical_plan_builder.go | 46 ++------ planner/core/point_get_plan.go | 24 ++-- 7 files changed, 260 insertions(+), 79 deletions(-) diff --git a/ddl/db_change_test.go b/ddl/db_change_test.go index 99a2de6ee3ef5..046f6e07b16cb 100644 --- a/ddl/db_change_test.go +++ b/ddl/db_change_test.go @@ -793,9 +793,10 @@ func (s *testStateChangeSuite) TestWriteOnlyForDropColumn(c *C) { c.Assert(err, IsNil) }() - sqls := make([]sqlWithErr, 2) + sqls := make([]sqlWithErr, 3) sqls[0] = sqlWithErr{"update t set c1='5', c3='2020-03-01';", errors.New("[planner:1054]Unknown column 'c3' in 'field list'")} - sqls[1] = sqlWithErr{"update t t1, tt t2 set t1.c1='5', t1.c3='2020-03-01', t2.c1='10' where t1.c4=t2.c4", + sqls[1] = sqlWithErr{"update t set c1='5', c3='2020-03-01' where c4 = 8;", errors.New("[planner:1054]Unknown column 'c3' in 'field list'")} + sqls[2] = sqlWithErr{"update t t1, tt t2 set t1.c1='5', t1.c3='2020-03-01', t2.c1='10' where t1.c4=t2.c4", errors.New("[planner:1054]Unknown column 'c3' in 'field list'")} // TODO: Fix the case of sqls[2]. // sqls[2] = sqlWithErr{"update t set c1='5' where c3='2017-07-01';", errors.New("[planner:1054]Unknown column 'c3' in 'field list'")} diff --git a/executor/builder.go b/executor/builder.go index c40e36797a432..4f374b5881f8a 100644 --- a/executor/builder.go +++ b/executor/builder.go @@ -1842,6 +1842,15 @@ func (b *executorBuilder) buildUpdate(v *plannercore.Update) Executor { } base := newBaseExecutor(b.ctx, v.Schema(), v.ID(), selExec) base.initCap = chunk.ZeroCapacity + var assignFlag []int + assignFlag, b.err = getAssignFlag(b.ctx, v, selExec.Schema().Len()) + if b.err != nil { + return nil + } + b.err = plannercore.CheckUpdateList(assignFlag, v) + if b.err != nil { + return nil + } updateExec := &UpdateExec{ baseExecutor: base, OrderedList: v.OrderedList, @@ -1850,10 +1859,29 @@ func (b *executorBuilder) buildUpdate(v *plannercore.Update) Executor { multiUpdateOnSameTable: multiUpdateOnSameTable, tblID2table: tblID2table, tblColPosInfos: v.TblColPosInfos, + assignFlag: assignFlag, } return updateExec } +func getAssignFlag(ctx sessionctx.Context, v *plannercore.Update, schemaLen int) ([]int, error) { + assignFlag := make([]int, schemaLen) + for i := range assignFlag { + assignFlag[i] = -1 + } + for _, assign := range v.OrderedList { + if !ctx.GetSessionVars().AllowWriteRowID && assign.Col.ID == model.ExtraHandleID { + return nil, errors.Errorf("insert, update and replace statements for _tidb_rowid are not supported.") + } + tblIdx, found := v.TblColPosInfos.FindTblIdx(assign.Col.Index) + if found { + colIdx := assign.Col.Index + assignFlag[colIdx] = tblIdx + } + } + return assignFlag, nil +} + func (b *executorBuilder) buildDelete(v *plannercore.Delete) Executor { tblID2table := make(map[int64]table.Table, len(v.TblColPosInfos)) for _, info := range v.TblColPosInfos { diff --git a/executor/executor_test.go b/executor/executor_test.go index 65e8b076a837d..a51771157b7bd 100644 --- a/executor/executor_test.go +++ b/executor/executor_test.go @@ -4129,6 +4129,173 @@ func (s *testSuiteP1) TestUnionAutoSignedCast(c *C) { Check(testkit.Rows("1 1", "2 -1", "3 -1")) } +func (s *testSuiteP1) TestUpdateClustered(c *C) { + tk := testkit.NewTestKit(c, s.store) + tk.MustExec("use test") + + type resultChecker struct { + check string + assert []string + } + + for _, clustered := range []string{"", "clustered"} { + tests := []struct { + initSchema []string + initData []string + dml string + resultCheck []resultChecker + }{ + { // left join + update both + match & unmatched + pk + []string{ + "drop table if exists a, b", + "create table a (k1 int, k2 int, v int)", + fmt.Sprintf("create table b (a int not null, k1 int, k2 int, v int, primary key(k1, k2) %s)", clustered), + }, + []string{ + "insert into a values (1, 1, 1), (2, 2, 2)", // unmatched + matched + "insert into b values (2, 2, 2, 2)", + }, + "update a left join b on a.k1 = b.k1 and a.k2 = b.k2 set a.v = 20, b.v = 100, a.k1 = a.k1 + 1, b.k1 = b.k1 + 1, a.k2 = a.k2 + 2, b.k2 = b.k2 + 2", + []resultChecker{ + { + "select * from b", + []string{"2 3 4 100"}, + }, + { + "select * from a", + []string{"2 3 20", "3 4 20"}, + }, + }, + }, + { // left join + update both + match & unmatched + pk + []string{ + "drop table if exists a, b", + "create table a (k1 int, k2 int, v int)", + fmt.Sprintf("create table b (a int not null, k1 int, k2 int, v int, primary key(k1, k2) %s)", clustered), + }, + []string{ + "insert into a values (1, 1, 1), (2, 2, 2)", // unmatched + matched + "insert into b values (2, 2, 2, 2)", + }, + "update a left join b on a.k1 = b.k1 and a.k2 = b.k2 set a.k1 = a.k1 + 1, a.k2 = a.k2 + 2, b.k1 = b.k1 + 1, b.k2 = b.k2 + 2, a.v = 20, b.v = 100", + []resultChecker{ + { + "select * from b", + []string{"2 3 4 100"}, + }, + { + "select * from a", + []string{"2 3 20", "3 4 20"}, + }, + }, + }, + { // left join + update both + match & unmatched + prefix pk + []string{ + "drop table if exists a, b", + "create table a (k1 varchar(100), k2 varchar(100), v varchar(100))", + fmt.Sprintf("create table b (a varchar(100) not null, k1 varchar(100), k2 varchar(100), v varchar(100), primary key(k1(1), k2(1)) %s, key kk1(k1(1), v(1)))", clustered), + }, + []string{ + "insert into a values ('11', '11', '11'), ('22', '22', '22')", // unmatched + matched + "insert into b values ('22', '22', '22', '22')", + }, + "update a left join b on a.k1 = b.k1 and a.k2 = b.k2 set a.k1 = a.k1 + 1, a.k2 = a.k2 + 2, b.k1 = b.k1 + 1, b.k2 = b.k2 + 2, a.v = 20, b.v = 100", + []resultChecker{ + { + "select * from b", + []string{"22 23 24 100"}, + }, + { + "select * from a", + []string{"12 13 20", "23 24 20"}, + }, + }, + }, + { // right join + update both + match & unmatched + prefix pk + []string{ + "drop table if exists a, b", + "create table a (k1 varchar(100), k2 varchar(100), v varchar(100))", + fmt.Sprintf("create table b (a varchar(100) not null, k1 varchar(100), k2 varchar(100), v varchar(100), primary key(k1(1), k2(1)) %s, key kk1(k1(1), v(1)))", clustered), + }, + []string{ + "insert into a values ('11', '11', '11'), ('22', '22', '22')", // unmatched + matched + "insert into b values ('22', '22', '22', '22')", + }, + "update b right join a on a.k1 = b.k1 and a.k2 = b.k2 set a.k1 = a.k1 + 1, a.k2 = a.k2 + 2, b.k1 = b.k1 + 1, b.k2 = b.k2 + 2, a.v = 20, b.v = 100", + []resultChecker{ + { + "select * from b", + []string{"22 23 24 100"}, + }, + { + "select * from a", + []string{"12 13 20", "23 24 20"}, + }, + }, + }, + { // inner join + update both + match & unmatched + prefix pk + []string{ + "drop table if exists a, b", + "create table a (k1 varchar(100), k2 varchar(100), v varchar(100))", + fmt.Sprintf("create table b (a varchar(100) not null, k1 varchar(100), k2 varchar(100), v varchar(100), primary key(k1(1), k2(1)) %s, key kk1(k1(1), v(1)))", clustered), + }, + []string{ + "insert into a values ('11', '11', '11'), ('22', '22', '22')", // unmatched + matched + "insert into b values ('22', '22', '22', '22')", + }, + "update b join a on a.k1 = b.k1 and a.k2 = b.k2 set a.k1 = a.k1 + 1, a.k2 = a.k2 + 2, b.k1 = b.k1 + 1, b.k2 = b.k2 + 2, a.v = 20, b.v = 100", + []resultChecker{ + { + "select * from b", + []string{"22 23 24 100"}, + }, + { + "select * from a", + []string{"11 11 11", "23 24 20"}, + }, + }, + }, + { + []string{ + "drop table if exists a, b", + "create table a (k1 varchar(100), k2 varchar(100), v varchar(100))", + fmt.Sprintf("create table b (a varchar(100) not null, k1 varchar(100), k2 varchar(100), v varchar(100), primary key(k1(1), k2(1)) %s, key kk1(k1(1), v(1)))", clustered), + }, + []string{ + "insert into a values ('11', '11', '11'), ('22', '22', '22')", // unmatched + matched + "insert into b values ('22', '22', '22', '22')", + }, + "update a set a.k1 = a.k1 + 1, a.k2 = a.k2 + 2, a.v = 20 where exists (select 1 from b where a.k1 = b.k1 and a.k2 = b.k2)", + []resultChecker{ + { + "select * from b", + []string{"22 22 22 22"}, + }, + { + "select * from a", + []string{"11 11 11", "23 24 20"}, + }, + }, + }, + } + + for _, test := range tests { + for _, s := range test.initSchema { + tk.MustExec(s) + } + for _, s := range test.initData { + tk.MustExec(s) + } + tk.MustExec(test.dml) + for _, checker := range test.resultCheck { + tk.MustQuery(checker.check).Check(testkit.Rows(checker.assert...)) + } + tk.MustExec("admin check table a") + tk.MustExec("admin check table b") + } + } +} + func (s *testSuite6) TestUpdateJoin(c *C) { tk := testkit.NewTestKit(c, s.store) tk.MustExec("use test") diff --git a/executor/update.go b/executor/update.go index 6e27b3fc99f31..7c4b07ab8e6f6 100644 --- a/executor/update.go +++ b/executor/update.go @@ -49,6 +49,7 @@ type UpdateExec struct { // tblColPosInfos stores relationship between column ordinal to its table handle. // the columns ordinals is present in ordinal range format, @see plannercore.TblColPosInfos tblColPosInfos plannercore.TblColPosInfoSlice + assignFlag []int evalBuffer chunk.MutRow allAssignmentsAreConstant bool virtualAssignmentsOffset int @@ -57,24 +58,19 @@ type UpdateExec struct { stats *runtimeStatsWithSnapshot - handles []kv.Handle - updatable []bool - changed []bool - matches []bool - assignFlag []bool + handles []kv.Handle + tableUpdatable []bool + changed []bool + matches []bool } -// prepare `handles`, `updatable`, `changed` and `assignFlag` to avoid re-computations. -func (e *UpdateExec) prepare(ctx context.Context, schema *expression.Schema, row []types.Datum) (err error) { - e.assignFlag, err = plannercore.GetUpdateColumns(e.ctx, e.OrderedList, schema.Len()) - if err != nil { - return err - } +// prepare `handles`, `tableUpdatable`, `changed` to avoid re-computations. +func (e *UpdateExec) prepare(row []types.Datum) (err error) { if e.updatedRowKeys == nil { e.updatedRowKeys = make(map[int]*kv.HandleMap) } e.handles = e.handles[:0] - e.updatable = e.updatable[:0] + e.tableUpdatable = e.tableUpdatable[:0] e.changed = e.changed[:0] e.matches = e.matches[:0] for _, content := range e.tblColPosInfos { @@ -90,12 +86,15 @@ func (e *UpdateExec) prepare(ctx context.Context, schema *expression.Schema, row updatable := false flags := e.assignFlag[content.Start:content.End] for _, flag := range flags { - if flag { + if flag >= 0 { updatable = true break } } - e.updatable = append(e.updatable, updatable) + if e.unmatchedOuterRow(content, row) { + updatable = false + } + e.tableUpdatable = append(e.tableUpdatable, updatable) changed, ok := e.updatedRowKeys[content.Start].Get(handle) if ok { @@ -109,7 +108,7 @@ func (e *UpdateExec) prepare(ctx context.Context, schema *expression.Schema, row return nil } -func (e *UpdateExec) merge(ctx context.Context, row, newData []types.Datum, mergeGenerated bool) error { +func (e *UpdateExec) merge(row, newData []types.Datum, mergeGenerated bool) error { if e.mergedRowData == nil { e.mergedRowData = make(map[int64]*kv.HandleMap) } @@ -120,7 +119,7 @@ func (e *UpdateExec) merge(ctx context.Context, row, newData []types.Datum, merg // No need to merge if not multi-updated continue } - if !e.updatable[i] { + if !e.tableUpdatable[i] { // If there's nothing to update, we can just skip current row continue } @@ -144,7 +143,7 @@ func (e *UpdateExec) merge(ctx context.Context, row, newData []types.Datum, merg continue } mergedData[i].Copy(&oldData[i]) - if flag { + if flag >= 0 { newTableData[i].Copy(&mergedData[i]) } else { mergedData[i].Copy(&newTableData[i]) @@ -160,8 +159,12 @@ func (e *UpdateExec) merge(ctx context.Context, row, newData []types.Datum, merg func (e *UpdateExec) exec(ctx context.Context, schema *expression.Schema, row, newData []types.Datum) error { defer trace.StartRegion(ctx, "UpdateExec").End() + bAssignFlag := make([]bool, len(e.assignFlag)) + for i, flag := range e.assignFlag { + bAssignFlag[i] = flag >= 0 + } for i, content := range e.tblColPosInfos { - if !e.updatable[i] { + if !e.tableUpdatable[i] { // If there's nothing to update, we can just skip current row continue } @@ -178,7 +181,7 @@ func (e *UpdateExec) exec(ctx context.Context, schema *expression.Schema, row, n oldData := row[content.Start:content.End] newTableData := newData[content.Start:content.End] - flags := e.assignFlag[content.Start:content.End] + flags := bAssignFlag[content.Start:content.End] // Update row changed, err1 := updateRecord(ctx, e.ctx, handle, oldData, newTableData, flags, tbl, false, e.memTracker) @@ -197,14 +200,15 @@ func (e *UpdateExec) exec(ctx context.Context, schema *expression.Schema, row, n return nil } -// canNotUpdate checks the handle of a record to decide whether that record +// unmatchedOuterRow checks the tableCols of a record to decide whether that record // can not be updated. The handle is NULL only when it is the inner side of an // outer join: the outer row can not match any inner rows, and in this scenario // the inner handle field is filled with a NULL value. // // This fixes: https://github.com/pingcap/tidb/issues/7176. -func (e *UpdateExec) canNotUpdate(handle types.Datum) bool { - return handle.IsNull() +func (e *UpdateExec) unmatchedOuterRow(tblPos plannercore.TblColPosInfo, waitUpdateRow []types.Datum) bool { + firstHandleIdx := tblPos.HandleCols.GetCol(0) + return waitUpdateRow[firstHandleIdx.Index].IsNull() } // Next implements the Executor Next interface. @@ -263,7 +267,7 @@ func (e *UpdateExec) updateRows(ctx context.Context) (int, error) { chunkRow := chk.GetRow(rowIdx) datumRow := chunkRow.GetDatumRow(fields) // precomputes handles - if err := e.prepare(ctx, e.children[0].Schema(), datumRow); err != nil { + if err := e.prepare(datumRow); err != nil { return 0, err } // compose non-generated columns @@ -272,7 +276,7 @@ func (e *UpdateExec) updateRows(ctx context.Context) (int, error) { return 0, err } // merge non-generated columns - if err := e.merge(ctx, datumRow, newRow, false); err != nil { + if err := e.merge(datumRow, newRow, false); err != nil { return 0, err } if e.virtualAssignmentsOffset < len(e.OrderedList) { @@ -282,7 +286,7 @@ func (e *UpdateExec) updateRows(ctx context.Context) (int, error) { return 0, err } // merge generated columns - if err := e.merge(ctx, datumRow, newRow, true); err != nil { + if err := e.merge(datumRow, newRow, true); err != nil { return 0, err } } @@ -316,11 +320,10 @@ func (e *UpdateExec) handleErr(colName model.CIStr, rowIdx int, err error) error func (e *UpdateExec) fastComposeNewRow(rowIdx int, oldRow []types.Datum, cols []*table.Column) ([]types.Datum, error) { newRowData := types.CloneRow(oldRow) for _, assign := range e.OrderedList { - handleIdx, handleFound := e.tblColPosInfos.FindHandle(assign.Col.Index) - if handleFound && e.canNotUpdate(oldRow[handleIdx]) { + tblIdx := e.assignFlag[assign.Col.Index] + if tblIdx >= 0 && !e.tableUpdatable[tblIdx] { continue } - con := assign.Expr.(*expression.Constant) val, err := con.Eval(emptyRow) if err = e.handleErr(assign.ColName, rowIdx, err); err != nil { @@ -345,8 +348,8 @@ func (e *UpdateExec) composeNewRow(rowIdx int, oldRow []types.Datum, cols []*tab newRowData := types.CloneRow(oldRow) e.evalBuffer.SetDatums(newRowData...) for _, assign := range e.OrderedList[:e.virtualAssignmentsOffset] { - handleIdx, handleFound := e.tblColPosInfos.FindHandle(assign.Col.Index) - if handleFound && e.canNotUpdate(oldRow[handleIdx]) { + tblIdx := e.assignFlag[assign.Col.Index] + if tblIdx >= 0 && !e.tableUpdatable[tblIdx] { continue } val, err := assign.Expr.Eval(e.evalBuffer.ToRow()) @@ -374,8 +377,8 @@ func (e *UpdateExec) composeGeneratedColumns(rowIdx int, newRowData []types.Datu } e.evalBuffer.SetDatums(newRowData...) for _, assign := range e.OrderedList[e.virtualAssignmentsOffset:] { - handleIdx, handleFound := e.tblColPosInfos.FindHandle(assign.Col.Index) - if handleFound && e.canNotUpdate(newRowData[handleIdx]) { + tblIdx := e.assignFlag[assign.Col.Index] + if tblIdx >= 0 && !e.tableUpdatable[tblIdx] { continue } val, err := assign.Expr.Eval(e.evalBuffer.ToRow()) diff --git a/planner/core/common_plans.go b/planner/core/common_plans.go index 63879cbb619da..10d217179d03b 100644 --- a/planner/core/common_plans.go +++ b/planner/core/common_plans.go @@ -754,6 +754,8 @@ type Update struct { // Used when partition sets are given. // e.g. update t partition(p0) set a = 1; PartitionedTable []table.PartitionedTable + + tblID2Table map[int64]table.Table } // Delete represents a delete plan. diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index 971e29d0f1a91..b2da4c7fa18fe 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -4150,8 +4150,7 @@ type TblColPosInfo struct { // Start and End represent the ordinal range [Start, End) of the consecutive columns. Start, End int // HandleOrdinal represents the ordinal of the handle column. - HandleCols HandleCols - IsCommonHandle bool // TODO: fix redesign update join table and remove me! + HandleCols HandleCols } // TblColPosInfoSlice attaches the methods of sort.Interface to []TblColPosInfos sorting in increasing order. @@ -4172,8 +4171,8 @@ func (c TblColPosInfoSlice) Less(i, j int) bool { return c[i].Start < c[j].Start } -// FindHandle finds the ordinal of the corresponding handle column. -func (c TblColPosInfoSlice) FindHandle(colOrdinal int) (int, bool) { +// FindTblIdx finds the ordinal of the corresponding access column. +func (c TblColPosInfoSlice) FindTblIdx(colOrdinal int) (int, bool) { if len(c) == 0 { return 0, false } @@ -4183,11 +4182,7 @@ func (c TblColPosInfoSlice) FindHandle(colOrdinal int) (int, bool) { if rangeBehindOrdinal == 0 { return 0, false } - if c[rangeBehindOrdinal-1].IsCommonHandle { - // TODO: fix redesign update join table to fix me. - return 0, false - } - return c[rangeBehindOrdinal-1].HandleCols.GetCol(0).Index, true + return rangeBehindOrdinal - 1, true } // buildColumns2Handle builds columns to handle mapping. @@ -4212,8 +4207,7 @@ func buildColumns2Handle( return nil, err } end := offset + tblLen - cols2Handles = append(cols2Handles, TblColPosInfo{tblID, offset, end, handleCol, tbl.Meta().IsCommonHandle}) - // TODO: fix me for cluster index + cols2Handles = append(cols2Handles, TblColPosInfo{tblID, offset, end, handleCol}) } } sort.Sort(cols2Handles) @@ -4337,46 +4331,28 @@ func (b *PlanBuilder) buildUpdate(ctx context.Context, update *ast.UpdateStmt) ( tblID2table[id], _ = b.is.TableByID(id) } updt.TblColPosInfos, err = buildColumns2Handle(updt.OutputNames(), tblID2Handle, tblID2table, true) - if err == nil { - err = checkUpdateList(b.ctx, tblID2table, updt) - } updt.PartitionedTable = b.partitionedTable + updt.tblID2Table = tblID2table return updt, err } -// GetUpdateColumns gets the columns of updated lists. -func GetUpdateColumns(ctx sessionctx.Context, orderedList []*expression.Assignment, schemaLen int) ([]bool, error) { - assignFlag := make([]bool, schemaLen) - for _, v := range orderedList { - if !ctx.GetSessionVars().AllowWriteRowID && v.Col.ID == model.ExtraHandleID { - return nil, errors.Errorf("insert, update and replace statements for _tidb_rowid are not supported.") - } - idx := v.Col.Index - assignFlag[idx] = true - } - return assignFlag, nil -} - type tblUpdateInfo struct { name string pkUpdated bool } -func checkUpdateList(ctx sessionctx.Context, tblID2table map[int64]table.Table, updt *Update) error { - assignFlags, err := GetUpdateColumns(ctx, updt.OrderedList, updt.SelectPlan.Schema().Len()) - if err != nil { - return err - } +// CheckUpdateList checks all related columns in updatable state. +func CheckUpdateList(assignFlags []int, updt *Update) error { updateFromOtherAlias := make(map[int64]tblUpdateInfo) for _, content := range updt.TblColPosInfos { - tbl := tblID2table[content.TblID] + tbl := updt.tblID2Table[content.TblID] flags := assignFlags[content.Start:content.End] var update, updatePK bool for i, col := range tbl.WritableCols() { - if flags[i] && col.State != model.StatePublic { + if flags[i] >= 0 && col.State != model.StatePublic { return ErrUnknownColumn.GenWithStackByArgs(col.Name, clauseMsg[fieldList]) } - if flags[i] { + if flags[i] >= 0 { update = true if mysql.HasPriKeyFlag(col.Flag) { updatePK = true diff --git a/planner/core/point_get_plan.go b/planner/core/point_get_plan.go index 0ec72814b934e..aa0b48df459b5 100644 --- a/planner/core/point_get_plan.go +++ b/planner/core/point_get_plan.go @@ -33,6 +33,7 @@ import ( "github.com/pingcap/tidb/privilege" "github.com/pingcap/tidb/sessionctx" "github.com/pingcap/tidb/sessionctx/stmtctx" + "github.com/pingcap/tidb/table" "github.com/pingcap/tidb/table/tables" "github.com/pingcap/tidb/types" driver "github.com/pingcap/tidb/types/parser_driver" @@ -1231,17 +1232,21 @@ func buildPointUpdatePlan(ctx sessionctx.Context, pointPlan PhysicalPlan, dbName OrderedList: orderedList, TblColPosInfos: TblColPosInfoSlice{ TblColPosInfo{ - TblID: tbl.ID, - Start: 0, - End: pointPlan.Schema().Len(), - HandleCols: handleCols, - IsCommonHandle: tbl.IsCommonHandle, + TblID: tbl.ID, + Start: 0, + End: pointPlan.Schema().Len(), + HandleCols: handleCols, }, }, AllAssignmentsAreConstant: allAssignmentsAreConstant, VirtualAssignmentsOffset: len(orderedList), }.Init(ctx) updatePlan.names = pointPlan.OutputNames() + is := infoschema.GetInfoSchema(ctx) + t, _ := is.TableByID(tbl.ID) + updatePlan.tblID2Table = map[int64]table.Table{ + tbl.ID: t, + } return updatePlan } @@ -1318,11 +1323,10 @@ func buildPointDeletePlan(ctx sessionctx.Context, pointPlan PhysicalPlan, dbName SelectPlan: pointPlan, TblColPosInfos: TblColPosInfoSlice{ TblColPosInfo{ - TblID: tbl.ID, - Start: 0, - End: pointPlan.Schema().Len(), - HandleCols: handleCols, - IsCommonHandle: tbl.IsCommonHandle, + TblID: tbl.ID, + Start: 0, + End: pointPlan.Schema().Len(), + HandleCols: handleCols, }, }, }.Init(ctx)