Skip to content

Commit

Permalink
executor: do not append extra cols to the old row when updateDupRow (
Browse files Browse the repository at this point in the history
  • Loading branch information
ti-srebot authored Aug 21, 2022
1 parent 68c6754 commit 0f9b69f
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 7 deletions.
16 changes: 9 additions & 7 deletions executor/insert.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,13 +193,13 @@ func (e *InsertExec) updateDupRow(ctx context.Context, idxInBatch int, txn kv.Tr
if err != nil {
return err
}
// get the extra columns from the SELECT clause and get the final `oldRow`.
// get the extra columns from the SELECT clause.
var extraCols []types.Datum
if len(e.ctx.GetSessionVars().CurrInsertBatchExtraCols) > 0 {
extraCols := e.ctx.GetSessionVars().CurrInsertBatchExtraCols[idxInBatch]
oldRow = append(oldRow, extraCols...)
extraCols = e.ctx.GetSessionVars().CurrInsertBatchExtraCols[idxInBatch]
}

err = e.doDupRowUpdate(ctx, handle, oldRow, row.row, e.OnDuplicate, idxInBatch)
err = e.doDupRowUpdate(ctx, handle, oldRow, row.row, extraCols, e.OnDuplicate, idxInBatch)
if e.ctx.GetSessionVars().StmtCtx.DupKeyAsWarning && kv.ErrKeyExists.Equal(err) {
e.ctx.GetSessionVars().StmtCtx.AppendWarning(err)
return nil
Expand Down Expand Up @@ -374,16 +374,18 @@ func (e *InsertExec) initEvalBuffer4Dup() {

// doDupRowUpdate updates the duplicate row.
func (e *InsertExec) doDupRowUpdate(ctx context.Context, handle kv.Handle, oldRow []types.Datum, newRow []types.Datum,
cols []*expression.Assignment, idxInBatch int) error {
extraCols []types.Datum, cols []*expression.Assignment, idxInBatch int) error {
assignFlag := make([]bool, len(e.Table.WritableCols()))
// See http://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html#function_values
e.curInsertVals.SetDatums(newRow...)
e.ctx.GetSessionVars().CurrInsertValues = e.curInsertVals.ToRow()
// NOTE: In order to execute the expression inside the column assignment,
// we have to put the value of "oldRow" before "newRow" in "row4Update" to
// be consistent with "Schema4OnDuplicate" in the "Insert" PhysicalPlan.
// we have to put the value of "oldRow" and "extraCols" before "newRow" in
// "row4Update" to be consistent with "Schema4OnDuplicate" in the "Insert"
// PhysicalPlan.
e.row4Update = e.row4Update[:0]
e.row4Update = append(e.row4Update, oldRow...)
e.row4Update = append(e.row4Update, extraCols...)
e.row4Update = append(e.row4Update, newRow...)

// Update old row when the key is duplicated.
Expand Down
14 changes: 14 additions & 0 deletions executor/insert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"testing"
"time"

"github.com/pingcap/failpoint"
"github.com/pingcap/tidb/errno"
"github.com/pingcap/tidb/executor"
"github.com/pingcap/tidb/meta/autoid"
Expand All @@ -39,6 +40,19 @@ func TestInsertOnDuplicateKey(t *testing.T) {
store, clean := testkit.CreateMockStore(t)
defer clean()
tk := testkit.NewTestKit(t, store)
testInsertOnDuplicateKey(t, tk)
}

func TestInsertOnDuplicateKeyWithBinlog(t *testing.T) {
store, clean := testkit.CreateMockStore(t)
defer clean()
tk := testkit.NewTestKit(t, store)
failpoint.Enable("github.com/pingcap/tidb/table/tables/forceWriteBinlog", "return")
defer failpoint.Disable("github.com/pingcap/tidb/table/tables/forceWriteBinlog")
testInsertOnDuplicateKey(t, tk)
}

func testInsertOnDuplicateKey(t *testing.T, tk *testkit.TestKit) {
tk.MustExec("use test")

tk.MustExec(`drop table if exists t1, t2;`)
Expand Down
5 changes: 5 additions & 0 deletions table/tables/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -1556,6 +1556,11 @@ func (t *TableCommon) Type() table.Type {
}

func shouldWriteBinlog(ctx sessionctx.Context, tblInfo *model.TableInfo) bool {
failpoint.Inject("forceWriteBinlog", func() {
// Just to cover binlog related code in this package, since the `BinlogClient` is
// still nil, mutations won't be written to pump on commit.
failpoint.Return(true)
})
if ctx.GetSessionVars().BinlogClient == nil {
return false
}
Expand Down

0 comments on commit 0f9b69f

Please sign in to comment.