Skip to content

Commit

Permalink
executor: support insert ignore/duplicate replace into with unique mu…
Browse files Browse the repository at this point in the history
…lti-valued index (#40369)

close #40207
  • Loading branch information
xiongjiwei authored Jan 9, 2023
1 parent 408a466 commit 83ec4b0
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 21 deletions.
44 changes: 23 additions & 21 deletions executor/batch_checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,28 +190,30 @@ func getKeysNeedCheckOneRow(ctx sessionctx.Context, t table.Table, row []types.D
}
// Pass handle = 0 to GenIndexKey,
// due to we only care about distinct key.
key, distinct, err1 := v.GenIndexKey(ctx.GetSessionVars().StmtCtx,
colVals, kv.IntHandle(0), nil)
if err1 != nil {
return nil, err1
}
// Skip the non-distinct keys.
if !distinct {
continue
}
// If index is used ingest ways, then we should check key from temp index.
if v.Meta().State != model.StatePublic && v.Meta().BackfillState != model.BackfillStateInapplicable {
_, key, _ = tables.GenTempIdxKeyByState(v.Meta(), key)
}
colValStr, err1 := formatDataForDupError(colVals)
if err1 != nil {
return nil, err1
iter := v.GenIndexKVIter(ctx.GetSessionVars().StmtCtx, colVals, kv.IntHandle(0), nil)
for iter.Valid() {
key, _, distinct, err1 := iter.Next(nil)
if err1 != nil {
return nil, err1
}
// Skip the non-distinct keys.
if !distinct {
continue
}
// If index is used ingest ways, then we should check key from temp index.
if v.Meta().State != model.StatePublic && v.Meta().BackfillState != model.BackfillStateInapplicable {
_, key, _ = tables.GenTempIdxKeyByState(v.Meta(), key)
}
colValStr, err1 := formatDataForDupError(colVals)
if err1 != nil {
return nil, err1
}
uniqueKeys = append(uniqueKeys, &keyValueWithDupInfo{
newKey: key,
dupErr: kv.ErrKeyExists.FastGenByArgs(colValStr, fmt.Sprintf("%s.%s", v.TableMeta().Name.String(), v.Meta().Name.String())),
commonHandle: t.Meta().IsCommonHandle,
})
}
uniqueKeys = append(uniqueKeys, &keyValueWithDupInfo{
newKey: key,
dupErr: kv.ErrKeyExists.FastGenByArgs(colValStr, fmt.Sprintf("%s.%s", v.TableMeta().Name.String(), v.Meta().Name.String())),
commonHandle: t.Meta().IsCommonHandle,
})
}
row = row[:len(row)-extraColumns]
result = append(result, toBeCheckedRow{
Expand Down
28 changes: 28 additions & 0 deletions executor/insert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,34 @@ func TestInsertValueForCastDecimalField(t *testing.T) {
tk.MustQuery(`select cast(a as decimal) from t1;`).Check(testkit.Rows(`9999999999`))
}

func TestInsertForMultiValuedIndex(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec(`drop table if exists t1;`)
tk.MustExec(`create table t1(a json, b int, unique index idx((cast(a as signed array))));`)
tk.MustExec(`insert into t1 values ('[1,11]', 1);`)
tk.MustExec(`insert into t1 values ('[2, 22]', 2);`)
tk.MustQuery(`select * from t1;`).Check(testkit.Rows(`[1, 11] 1`, `[2, 22] 2`))
tk.MustGetErrMsg(`insert into t1 values ('[2, 222]', 2);`, "[kv:1062]Duplicate entry '2' for key 't1.idx'")
tk.MustExec(`replace into t1 values ('[1, 10]', 10)`)
tk.MustQuery(`select * from t1;`).Check(testkit.Rows(`[2, 22] 2`, `[1, 10] 10`))
tk.MustExec(`replace into t1 values ('[1, 2]', 1)`)
tk.MustQuery(`select * from t1;`).Check(testkit.Rows(`[1, 2] 1`))
tk.MustExec(`replace into t1 values ('[1, 11]', 1)`)
tk.MustExec(`insert into t1 values ('[2, 22]', 2);`)
tk.MustQuery(`select * from t1;`).Check(testkit.Rows(`[1, 11] 1`, `[2, 22] 2`))
tk.MustExec(`insert ignore into t1 values ('[1]', 2);`)
tk.MustQuery(`select * from t1;`).Check(testkit.Rows(`[1, 11] 1`, `[2, 22] 2`))
tk.MustExec(`insert ignore into t1 values ('[1, 2]', 2);`)
tk.MustQuery(`select * from t1;`).Check(testkit.Rows(`[1, 11] 1`, `[2, 22] 2`))
tk.MustExec(`insert into t1 values ('[2]', 2) on duplicate key update b = 10;`)
tk.MustQuery(`select * from t1;`).Check(testkit.Rows(`[1, 11] 1`, `[2, 22] 10`))
tk.MustGetErrMsg(`insert into t1 values ('[2, 1]', 2) on duplicate key update a = '[1,2]';`, "[kv:1062]Duplicate entry '[1, 2]' for key 't1.idx'")
tk.MustGetErrMsg(`insert into t1 values ('[1,2]', 2) on duplicate key update a = '[1,2]';`, "[kv:1062]Duplicate entry '[1, 2]' for key 't1.idx'")
tk.MustGetErrMsg(`insert into t1 values ('[11, 22]', 2) on duplicate key update a = '[1,2]';`, "[kv:1062]Duplicate entry '[1, 2]' for key 't1.idx'")
}

func TestInsertDateTimeWithTimeZone(t *testing.T) {
store := testkit.CreateMockStore(t)
tk := testkit.NewTestKit(t, store)
Expand Down

0 comments on commit 83ec4b0

Please sign in to comment.