executor: special handling is required when an "auto id out of range" error occurs in insert ignore into ... on on duplicate ... (#39847)
close pingcap/tidb#38950
This commit is contained in:
@ -32,6 +32,7 @@ import (
|
||||
"github.com/pingcap/tidb/parser/ast"
|
||||
"github.com/pingcap/tidb/parser/model"
|
||||
"github.com/pingcap/tidb/parser/mysql"
|
||||
"github.com/pingcap/tidb/planner/core"
|
||||
"github.com/pingcap/tidb/sessionctx"
|
||||
"github.com/pingcap/tidb/sessionctx/variable"
|
||||
"github.com/pingcap/tidb/sessiontxn"
|
||||
@ -771,7 +772,16 @@ func setDatumAutoIDAndCast(ctx sessionctx.Context, d *types.Datum, id int64, col
|
||||
var err error
|
||||
*d, err = table.CastValue(ctx, *d, col.ToInfo(), false, false)
|
||||
if err == nil && d.GetInt64() < id {
|
||||
// Auto ID is out of range, the truncated ID is possible to duplicate with an existing ID.
|
||||
// Auto ID is out of range.
|
||||
sc := ctx.GetSessionVars().StmtCtx
|
||||
insertPlan, ok := sc.GetPlan().(*core.Insert)
|
||||
if ok && sc.TruncateAsWarning && len(insertPlan.OnDuplicate) > 0 {
|
||||
// Fix issue #38950: AUTO_INCREMENT is incompatible with mysql
|
||||
// An auto id out of range error occurs in `insert ignore into ... on duplicate ...`.
|
||||
// We should allow the SQL to be executed successfully.
|
||||
return nil
|
||||
}
|
||||
// The truncated ID is possible to duplicate with an existing ID.
|
||||
// To prevent updating unrelated rows in the REPLACE statement, it is better to throw an error.
|
||||
return autoid.ErrAutoincReadFailed
|
||||
}
|
||||
|
||||
@ -592,6 +592,25 @@ commit;`
|
||||
tk.MustQuery("show warnings").Check(testkit.Rows("Warning 1526 Table has no partition for value 3"))
|
||||
}
|
||||
|
||||
func TestIssue38950(t *testing.T) {
|
||||
store := testkit.CreateMockStore(t)
|
||||
var cfg kv.InjectionConfig
|
||||
tk := testkit.NewTestKit(t, kv.NewInjectedStore(store, &cfg))
|
||||
tk.MustExec("use test;")
|
||||
tk.MustExec("drop table if exists t; create table t (id smallint auto_increment primary key);")
|
||||
tk.MustExec("alter table t add column c1 int default 1;")
|
||||
tk.MustExec("insert ignore into t(id) values (194626268);")
|
||||
require.Empty(t, tk.Session().LastMessage())
|
||||
|
||||
tk.MustQuery("select * from t").Check(testkit.Rows("32767 1"))
|
||||
|
||||
tk.MustExec("insert ignore into t(id) values ('*') on duplicate key update c1 = 2;")
|
||||
require.Equal(t, int64(2), int64(tk.Session().AffectedRows()))
|
||||
require.Empty(t, tk.Session().LastMessage())
|
||||
|
||||
tk.MustQuery("select * from t").Check(testkit.Rows("32767 2"))
|
||||
}
|
||||
|
||||
func TestInsertOnDup(t *testing.T) {
|
||||
store := testkit.CreateMockStore(t)
|
||||
var cfg kv.InjectionConfig
|
||||
|
||||
Reference in New Issue
Block a user