Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

executor: special handling is required when an "auto id out of range" error occurs in insert ignore into ... on on duplicate ... (#39847) #40286

12 changes: 11 additions & 1 deletion executor/insert_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -745,7 +746,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
}
Expand Down
19 changes: 19 additions & 0 deletions executor/write_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down