ddl: migrate test-infra to testify for part of ddl.testSerialDBSuite (#33258)

ref pingcap/tidb#33004
This commit is contained in:
tison
2022-03-19 23:02:31 +08:00
committed by GitHub
parent c7a3f31d5b
commit 682d8bedaa
3 changed files with 329 additions and 324 deletions

View File

@ -30,6 +30,7 @@ import (
"github.com/pingcap/tidb/errno"
"github.com/pingcap/tidb/infoschema"
"github.com/pingcap/tidb/kv"
"github.com/pingcap/tidb/parser/ast"
"github.com/pingcap/tidb/parser/model"
"github.com/pingcap/tidb/parser/mysql"
"github.com/pingcap/tidb/sessionctx"
@ -1059,3 +1060,245 @@ func TestAddMultiColumnsIndex(t *testing.T) {
tk.MustExec("alter table tidb.test add index idx1 (a, b);")
tk.MustExec("admin check table test")
}
// For issue #31735.
func TestAddGeneratedColumnAndInsert(t *testing.T) {
store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, columnModifyLease)
defer clean()
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t1 (a int, unique kye(a))")
tk.MustExec("insert into t1 value (1), (10)")
tk1 := testkit.NewTestKit(t, store)
tk1.MustExec("use test")
d := dom.DDL()
hook := &ddl.TestDDLCallback{Do: dom}
ctx := mock.NewContext()
ctx.Store = store
times := 0
var checkErr error
hook.OnJobUpdatedExported = func(job *model.Job) {
if checkErr != nil {
return
}
switch job.SchemaState {
case model.StateDeleteOnly:
_, checkErr = tk1.Exec("insert into t1 values (1) on duplicate key update a=a+1")
if checkErr == nil {
_, checkErr = tk1.Exec("replace into t1 values (2)")
}
case model.StateWriteOnly:
_, checkErr = tk1.Exec("insert into t1 values (2) on duplicate key update a=a+1")
if checkErr == nil {
_, checkErr = tk1.Exec("replace into t1 values (3)")
}
case model.StateWriteReorganization:
if checkErr == nil && job.SchemaState == model.StateWriteReorganization && times == 0 {
_, checkErr = tk1.Exec("insert into t1 values (3) on duplicate key update a=a+1")
if checkErr == nil {
_, checkErr = tk1.Exec("replace into t1 values (4)")
}
times++
}
}
}
d.SetHook(hook)
tk.MustExec("alter table t1 add column gc int as ((a+1))")
tk.MustQuery("select * from t1 order by a").Check(testkit.Rows("4 5", "10 11"))
require.NoError(t, checkErr)
}
func TestColumnTypeChangeGenUniqueChangingName(t *testing.T) {
store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, columnModifyLease)
defer clean()
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
hook := &ddl.TestDDLCallback{}
var checkErr error
assertChangingColName := "_col$_c2_0"
assertChangingIdxName := "_idx$_idx_0"
hook.OnJobUpdatedExported = func(job *model.Job) {
if job.SchemaState == model.StateDeleteOnly && job.Type == model.ActionModifyColumn {
var (
newCol *model.ColumnInfo
oldColName *model.CIStr
modifyColumnTp byte
updatedAutoRandomBits uint64
changingCol *model.ColumnInfo
changingIdxs []*model.IndexInfo
)
pos := &ast.ColumnPosition{}
err := job.DecodeArgs(&newCol, &oldColName, pos, &modifyColumnTp, &updatedAutoRandomBits, &changingCol, &changingIdxs)
if err != nil {
checkErr = err
return
}
if changingCol.Name.L != assertChangingColName {
checkErr = errors.New("changing column name is incorrect")
} else if changingIdxs[0].Name.L != assertChangingIdxName {
checkErr = errors.New("changing index name is incorrect")
}
}
}
d := dom.DDL()
d.SetHook(hook)
tk.MustExec("create table if not exists t(c1 varchar(256), c2 bigint, `_col$_c2` varchar(10), unique _idx$_idx(c1), unique idx(c2));")
tk.MustExec("alter table test.t change column c2 cC2 tinyint after `_col$_c2`")
require.NoError(t, checkErr)
tbl := external.GetTableByName(t, tk, "test", "t")
require.Len(t, tbl.Meta().Columns, 3)
require.Equal(t, "c1", tbl.Meta().Columns[0].Name.O)
require.Equal(t, 0, tbl.Meta().Columns[0].Offset)
require.Equal(t, "_col$_c2", tbl.Meta().Columns[1].Name.O)
require.Equal(t, 1, tbl.Meta().Columns[1].Offset)
require.Equal(t, "cC2", tbl.Meta().Columns[2].Name.O)
require.Equal(t, 2, tbl.Meta().Columns[2].Offset)
require.Len(t, tbl.Meta().Indices, 2)
require.Equal(t, "_idx$_idx", tbl.Meta().Indices[0].Name.O)
require.Equal(t, "idx", tbl.Meta().Indices[1].Name.O)
require.Len(t, tbl.Meta().Indices[0].Columns, 1)
require.Equal(t, "c1", tbl.Meta().Indices[0].Columns[0].Name.O)
require.Equal(t, 0, tbl.Meta().Indices[0].Columns[0].Offset)
require.Len(t, tbl.Meta().Indices[1].Columns, 1)
require.Equal(t, "cC2", tbl.Meta().Indices[1].Columns[0].Name.O)
require.Equal(t, 2, tbl.Meta().Indices[1].Columns[0].Offset)
assertChangingColName1 := "_col$__col$_c1_1"
assertChangingColName2 := "_col$__col$__col$_c1_0_1"
query1 := "alter table t modify column _col$_c1 tinyint"
query2 := "alter table t modify column _col$__col$_c1_0 tinyint"
hook.OnJobUpdatedExported = func(job *model.Job) {
if (job.Query == query1 || job.Query == query2) && job.SchemaState == model.StateDeleteOnly && job.Type == model.ActionModifyColumn {
var (
newCol *model.ColumnInfo
oldColName *model.CIStr
modifyColumnTp byte
updatedAutoRandomBits uint64
changingCol *model.ColumnInfo
changingIdxs []*model.IndexInfo
)
pos := &ast.ColumnPosition{}
err := job.DecodeArgs(&newCol, &oldColName, pos, &modifyColumnTp, &updatedAutoRandomBits, &changingCol, &changingIdxs)
if err != nil {
checkErr = err
return
}
if job.Query == query1 && changingCol.Name.L != assertChangingColName1 {
checkErr = errors.New("changing column name is incorrect")
}
if job.Query == query2 && changingCol.Name.L != assertChangingColName2 {
checkErr = errors.New("changing column name is incorrect")
}
}
}
d.SetHook(hook)
tk.MustExec("drop table if exists t")
tk.MustExec("create table if not exists t(c1 bigint, _col$_c1 bigint, _col$__col$_c1_0 bigint, _col$__col$__col$_c1_0_0 bigint)")
tk.MustExec("alter table t modify column c1 tinyint")
tk.MustExec("alter table t modify column _col$_c1 tinyint")
require.NoError(t, checkErr)
tk.MustExec("alter table t modify column _col$__col$_c1_0 tinyint")
require.NoError(t, checkErr)
tk.MustExec("alter table t change column _col$__col$__col$_c1_0_0 _col$__col$__col$_c1_0_0 tinyint")
tbl = external.GetTableByName(t, tk, "test", "t")
require.Len(t, tbl.Meta().Columns, 4)
require.Equal(t, "c1", tbl.Meta().Columns[0].Name.O)
require.Equal(t, mysql.TypeTiny, tbl.Meta().Columns[0].Tp)
require.Equal(t, 0, tbl.Meta().Columns[0].Offset)
require.Equal(t, "_col$_c1", tbl.Meta().Columns[1].Name.O)
require.Equal(t, mysql.TypeTiny, tbl.Meta().Columns[1].Tp)
require.Equal(t, 1, tbl.Meta().Columns[1].Offset)
require.Equal(t, "_col$__col$_c1_0", tbl.Meta().Columns[2].Name.O)
require.Equal(t, mysql.TypeTiny, tbl.Meta().Columns[2].Tp)
require.Equal(t, 2, tbl.Meta().Columns[2].Offset)
require.Equal(t, "_col$__col$__col$_c1_0_0", tbl.Meta().Columns[3].Name.O)
require.Equal(t, mysql.TypeTiny, tbl.Meta().Columns[3].Tp)
require.Equal(t, 3, tbl.Meta().Columns[3].Offset)
tk.MustExec("drop table if exists t")
}
func TestWriteReorgForColumnTypeChangeOnAmendTxn(t *testing.T) {
store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, columnModifyLease)
defer clean()
tk := testkit.NewTestKit(t, store)
tk.MustExec("set global tidb_enable_amend_pessimistic_txn = ON")
defer tk.MustExec("set global tidb_enable_amend_pessimistic_txn = OFF")
d := dom.DDL()
testInsertOnModifyColumn := func(sql string, startColState, commitColState model.SchemaState, retStrs []string, retErr error) {
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1 (c1 int, c2 int, c3 int, unique key(c1))")
tk.MustExec("insert into t1 values (20, 20, 20);")
var checkErr error
tk1 := testkit.NewTestKit(t, store)
defer func() {
if tk1.Session() != nil {
tk1.Session().Close()
}
}()
hook := &ddl.TestDDLCallback{Do: dom}
times := 0
hook.OnJobUpdatedExported = func(job *model.Job) {
if job.Type != model.ActionModifyColumn || checkErr != nil ||
(job.SchemaState != startColState && job.SchemaState != commitColState) {
return
}
if job.SchemaState == startColState {
tk1.MustExec("use test")
tk1.MustExec("begin pessimistic;")
tk1.MustExec("insert into t1 values(101, 102, 103)")
return
}
if times == 0 {
_, checkErr = tk1.Exec("commit;")
}
times++
}
d.SetHook(hook)
tk.MustExec(sql)
if retErr == nil {
require.NoError(t, checkErr)
} else {
require.Error(t, checkErr)
require.Contains(t, checkErr.Error(), retErr.Error())
}
tk.MustQuery("select * from t1").Check(testkit.Rows(retStrs...))
tk.MustExec("admin check table t1")
}
// Testing it needs reorg data.
ddlStatement := "alter table t1 change column c2 cc smallint;"
testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StateWriteReorganization, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)
testInsertOnModifyColumn(ddlStatement, model.StateDeleteOnly, model.StateWriteReorganization, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)
testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StateWriteReorganization, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)
testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StatePublic, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)
testInsertOnModifyColumn(ddlStatement, model.StateDeleteOnly, model.StatePublic, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)
testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StatePublic, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)
// Testing it needs not reorg data. This case only have two states: none, public.
ddlStatement = "alter table t1 change column c2 cc bigint;"
testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StateWriteReorganization, []string{"20 20 20"}, nil)
testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StateWriteReorganization, []string{"20 20 20"}, nil)
testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StatePublic, []string{"20 20 20", "101 102 103"}, nil)
testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StatePublic, []string{"20 20 20"}, nil)
}

View File

@ -31,9 +31,7 @@ import (
"github.com/pingcap/tidb/domain"
"github.com/pingcap/tidb/errno"
"github.com/pingcap/tidb/kv"
"github.com/pingcap/tidb/meta"
"github.com/pingcap/tidb/meta/autoid"
"github.com/pingcap/tidb/parser/ast"
"github.com/pingcap/tidb/parser/auth"
"github.com/pingcap/tidb/parser/model"
"github.com/pingcap/tidb/parser/mysql"
@ -47,7 +45,6 @@ import (
"github.com/pingcap/tidb/table"
"github.com/pingcap/tidb/tablecodec"
"github.com/pingcap/tidb/util/dbterror"
"github.com/pingcap/tidb/util/mock"
"github.com/pingcap/tidb/util/sqlexec"
"github.com/pingcap/tidb/util/testkit"
"github.com/pingcap/tidb/util/testleak"
@ -167,159 +164,6 @@ func backgroundExecT(s kv.Storage, sql string, done chan error) {
done <- errors.Trace(err)
}
func (s *testSerialDBSuite) TestWriteReorgForColumnTypeChangeOnAmendTxn(c *C) {
tk2 := testkit.NewTestKit(c, s.store)
tk2.MustExec("use test_db")
tk2.MustExec("set global tidb_enable_amend_pessimistic_txn = ON;")
defer func() {
tk2.MustExec("set global tidb_enable_amend_pessimistic_txn = OFF;")
}()
d := s.dom.DDL()
originalHook := d.GetHook()
defer d.SetHook(originalHook)
testInsertOnModifyColumn := func(sql string, startColState, commitColState model.SchemaState, retStrs []string, retErr error) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test_db")
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1 (c1 int, c2 int, c3 int, unique key(c1))")
tk.MustExec("insert into t1 values (20, 20, 20);")
var checkErr error
tk1 := testkit.NewTestKit(c, s.store)
defer func() {
if tk1.Se != nil {
tk1.Se.Close()
}
}()
hook := &ddl.TestDDLCallback{Do: s.dom}
times := 0
hook.OnJobUpdatedExported = func(job *model.Job) {
if job.Type != model.ActionModifyColumn || checkErr != nil ||
(job.SchemaState != startColState && job.SchemaState != commitColState) {
return
}
if job.SchemaState == startColState {
tk1.MustExec("use test_db")
tk1.MustExec("begin pessimistic;")
tk1.MustExec("insert into t1 values(101, 102, 103)")
return
}
if times == 0 {
_, checkErr = tk1.Exec("commit;")
}
times++
}
d.SetHook(hook)
tk.MustExec(sql)
if retErr == nil {
c.Assert(checkErr, IsNil)
} else {
c.Assert(strings.Contains(checkErr.Error(), retErr.Error()), IsTrue)
}
tk.MustQuery("select * from t1;").Check(testkit.Rows(retStrs...))
tk.MustExec("admin check table t1")
}
// Testing it needs reorg data.
ddlStatement := "alter table t1 change column c2 cc smallint;"
testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StateWriteReorganization, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)
testInsertOnModifyColumn(ddlStatement, model.StateDeleteOnly, model.StateWriteReorganization, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)
testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StateWriteReorganization, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)
testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StatePublic, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)
testInsertOnModifyColumn(ddlStatement, model.StateDeleteOnly, model.StatePublic, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)
testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StatePublic, []string{"20 20 20"}, domain.ErrInfoSchemaChanged)
// Testing it needs not reorg data. This case only have two state: none, public.
ddlStatement = "alter table t1 change column c2 cc bigint;"
testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StateWriteReorganization, []string{"20 20 20"}, nil)
testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StateWriteReorganization, []string{"20 20 20"}, nil)
testInsertOnModifyColumn(ddlStatement, model.StateNone, model.StatePublic, []string{"20 20 20", "101 102 103"}, nil)
testInsertOnModifyColumn(ddlStatement, model.StateWriteOnly, model.StatePublic, []string{"20 20 20"}, nil)
}
func (s *testSerialDBSuite) TestAddExpressionIndexRollback(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test_db")
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1 (c1 int, c2 int, c3 int, unique key(c1))")
tk.MustExec("insert into t1 values (20, 20, 20), (40, 40, 40), (80, 80, 80), (160, 160, 160);")
var checkErr error
tk1 := testkit.NewTestKit(c, s.store)
_, checkErr = tk1.Exec("use test_db")
d := s.dom.DDL()
hook := &ddl.TestDDLCallback{Do: s.dom}
var currJob *model.Job
ctx := mock.NewContext()
ctx.Store = s.store
times := 0
hook.OnJobUpdatedExported = func(job *model.Job) {
if checkErr != nil {
return
}
switch job.SchemaState {
case model.StateDeleteOnly:
_, checkErr = tk1.Exec("insert into t1 values (6, 3, 3) on duplicate key update c1 = 10")
if checkErr == nil {
_, checkErr = tk1.Exec("update t1 set c1 = 7 where c2=6;")
}
if checkErr == nil {
_, checkErr = tk1.Exec("delete from t1 where c1 = 40;")
}
case model.StateWriteOnly:
_, checkErr = tk1.Exec("insert into t1 values (2, 2, 2)")
if checkErr == nil {
_, checkErr = tk1.Exec("update t1 set c1 = 3 where c2 = 80")
}
case model.StateWriteReorganization:
if checkErr == nil && job.SchemaState == model.StateWriteReorganization && times == 0 {
_, checkErr = tk1.Exec("insert into t1 values (4, 4, 4)")
if checkErr != nil {
return
}
_, checkErr = tk1.Exec("update t1 set c1 = 5 where c2 = 80")
if checkErr != nil {
return
}
currJob = job
times++
}
}
}
d.SetHook(hook)
tk.MustGetErrMsg("alter table t1 add index expr_idx ((pow(c1, c2)));", "[ddl:8202]Cannot decode index value, because [types:1690]DOUBLE value is out of range in 'pow(160, 160)'")
c.Assert(checkErr, IsNil)
tk.MustQuery("select * from t1 order by c1;").Check(testkit.Rows("2 2 2", "4 4 4", "5 80 80", "10 3 3", "20 20 20", "160 160 160"))
// Check whether the reorg information is cleaned up.
err := ctx.NewTxn(context.Background())
c.Assert(err, IsNil)
txn, err := ctx.Txn(true)
c.Assert(err, IsNil)
m := meta.NewMeta(txn)
element, start, end, physicalID, err := m.GetDDLReorgHandle(currJob)
c.Assert(meta.ErrDDLReorgElementNotExist.Equal(err), IsTrue)
c.Assert(element, IsNil)
c.Assert(start, IsNil)
c.Assert(end, IsNil)
c.Assert(physicalID, Equals, int64(0))
}
func (s *testSerialDBSuite) TestDropTableOnTiKVDiskFull(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test_db")
tk.MustExec("create table test_disk_full_drop_table(a int);")
c.Assert(failpoint.Enable("github.com/pingcap/tidb/store/mockstore/unistore/rpcTiKVAllowedOnAlmostFull", `return(true)`), IsNil)
defer failpoint.Disable("github.com/pingcap/tidb/store/mockstore/unistore/rpcTiKVAllowedOnAlmostFull")
tk.MustExec("drop table test_disk_full_drop_table;")
}
func testGetIndexID(t *testing.T, ctx sessionctx.Context, dbName, tblName, idxName string) int64 {
is := domain.GetDomain(ctx).InfoSchema()
tt, err := is.TableByName(model.NewCIStr(dbName), model.NewCIStr(tblName))
@ -1209,125 +1053,6 @@ func (s *testSerialDBSuite) TestCreateTableWithIntegerLengthWaring(c *C) {
tk.MustExec("drop table if exists t")
}
func (s *testSerialDBSuite) TestColumnTypeChangeGenUniqueChangingName(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test")
tk.MustExec("drop table if exists t")
hook := &ddl.TestDDLCallback{}
var checkErr error
assertChangingColName := "_col$_c2_0"
assertChangingIdxName := "_idx$_idx_0"
hook.OnJobUpdatedExported = func(job *model.Job) {
if job.SchemaState == model.StateDeleteOnly && job.Type == model.ActionModifyColumn {
var (
newCol *model.ColumnInfo
oldColName *model.CIStr
modifyColumnTp byte
updatedAutoRandomBits uint64
changingCol *model.ColumnInfo
changingIdxs []*model.IndexInfo
)
pos := &ast.ColumnPosition{}
err := job.DecodeArgs(&newCol, &oldColName, pos, &modifyColumnTp, &updatedAutoRandomBits, &changingCol, &changingIdxs)
if err != nil {
checkErr = err
return
}
if changingCol.Name.L != assertChangingColName {
checkErr = errors.New("changing column name is incorrect")
} else if changingIdxs[0].Name.L != assertChangingIdxName {
checkErr = errors.New("changing index name is incorrect")
}
}
}
d := s.dom.DDL()
originHook := d.GetHook()
d.SetHook(hook)
defer d.SetHook(originHook)
tk.MustExec("create table if not exists t(c1 varchar(256), c2 bigint, `_col$_c2` varchar(10), unique _idx$_idx(c1), unique idx(c2));")
tk.MustExec("alter table test.t change column c2 cC2 tinyint after `_col$_c2`")
c.Assert(checkErr, IsNil)
t := testGetTableByName(c, tk.Se, "test", "t")
c.Assert(len(t.Meta().Columns), Equals, 3)
c.Assert(t.Meta().Columns[0].Name.O, Equals, "c1")
c.Assert(t.Meta().Columns[0].Offset, Equals, 0)
c.Assert(t.Meta().Columns[1].Name.O, Equals, "_col$_c2")
c.Assert(t.Meta().Columns[1].Offset, Equals, 1)
c.Assert(t.Meta().Columns[2].Name.O, Equals, "cC2")
c.Assert(t.Meta().Columns[2].Offset, Equals, 2)
c.Assert(len(t.Meta().Indices), Equals, 2)
c.Assert(t.Meta().Indices[0].Name.O, Equals, "_idx$_idx")
c.Assert(t.Meta().Indices[1].Name.O, Equals, "idx")
c.Assert(len(t.Meta().Indices[0].Columns), Equals, 1)
c.Assert(t.Meta().Indices[0].Columns[0].Name.O, Equals, "c1")
c.Assert(t.Meta().Indices[0].Columns[0].Offset, Equals, 0)
c.Assert(len(t.Meta().Indices[1].Columns), Equals, 1)
c.Assert(t.Meta().Indices[1].Columns[0].Name.O, Equals, "cC2")
c.Assert(t.Meta().Indices[1].Columns[0].Offset, Equals, 2)
assertChangingColName1 := "_col$__col$_c1_1"
assertChangingColName2 := "_col$__col$__col$_c1_0_1"
query1 := "alter table t modify column _col$_c1 tinyint"
query2 := "alter table t modify column _col$__col$_c1_0 tinyint"
hook.OnJobUpdatedExported = func(job *model.Job) {
if (job.Query == query1 || job.Query == query2) && job.SchemaState == model.StateDeleteOnly && job.Type == model.ActionModifyColumn {
var (
newCol *model.ColumnInfo
oldColName *model.CIStr
modifyColumnTp byte
updatedAutoRandomBits uint64
changingCol *model.ColumnInfo
changingIdxs []*model.IndexInfo
)
pos := &ast.ColumnPosition{}
err := job.DecodeArgs(&newCol, &oldColName, pos, &modifyColumnTp, &updatedAutoRandomBits, &changingCol, &changingIdxs)
if err != nil {
checkErr = err
return
}
if job.Query == query1 && changingCol.Name.L != assertChangingColName1 {
checkErr = errors.New("changing column name is incorrect")
}
if job.Query == query2 && changingCol.Name.L != assertChangingColName2 {
checkErr = errors.New("changing column name is incorrect")
}
}
}
d.SetHook(hook)
tk.MustExec("drop table if exists t")
tk.MustExec("create table if not exists t(c1 bigint, _col$_c1 bigint, _col$__col$_c1_0 bigint, _col$__col$__col$_c1_0_0 bigint)")
tk.MustExec("alter table t modify column c1 tinyint")
tk.MustExec("alter table t modify column _col$_c1 tinyint")
c.Assert(checkErr, IsNil)
tk.MustExec("alter table t modify column _col$__col$_c1_0 tinyint")
c.Assert(checkErr, IsNil)
tk.MustExec("alter table t change column _col$__col$__col$_c1_0_0 _col$__col$__col$_c1_0_0 tinyint")
t = testGetTableByName(c, tk.Se, "test", "t")
c.Assert(len(t.Meta().Columns), Equals, 4)
c.Assert(t.Meta().Columns[0].Name.O, Equals, "c1")
c.Assert(t.Meta().Columns[0].Tp, Equals, mysql.TypeTiny)
c.Assert(t.Meta().Columns[0].Offset, Equals, 0)
c.Assert(t.Meta().Columns[1].Name.O, Equals, "_col$_c1")
c.Assert(t.Meta().Columns[1].Tp, Equals, mysql.TypeTiny)
c.Assert(t.Meta().Columns[1].Offset, Equals, 1)
c.Assert(t.Meta().Columns[2].Name.O, Equals, "_col$__col$_c1_0")
c.Assert(t.Meta().Columns[2].Tp, Equals, mysql.TypeTiny)
c.Assert(t.Meta().Columns[2].Offset, Equals, 2)
c.Assert(t.Meta().Columns[3].Name.O, Equals, "_col$__col$__col$_c1_0_0")
c.Assert(t.Meta().Columns[3].Tp, Equals, mysql.TypeTiny)
c.Assert(t.Meta().Columns[3].Offset, Equals, 3)
tk.MustExec("drop table if exists t")
}
// Close issue #24172.
// See https://github.com/pingcap/tidb/issues/24172
func (s *testSerialDBSuite) TestCancelJobWriteConflict(c *C) {
@ -1372,52 +1097,3 @@ func (s *testSerialDBSuite) TestCancelJobWriteConflict(c *C) {
result := tk1.ResultSetToResultWithCtx(context.Background(), rs[0], Commentf("cancel ddl job fails"))
result.Check(testkit.Rows(fmt.Sprintf("%d successful", jobID)))
}
func (s *testSerialDBSuite) TestAddGeneratedColumnAndInsert(c *C) {
// For issue #31735.
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test_db")
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1 (a int, unique kye(a))")
tk.MustExec("insert into t1 value (1), (10)")
var checkErr error
tk1 := testkit.NewTestKit(c, s.store)
_, checkErr = tk1.Exec("use test_db")
d := s.dom.DDL()
hook := &ddl.TestDDLCallback{Do: s.dom}
ctx := mock.NewContext()
ctx.Store = s.store
times := 0
hook.OnJobUpdatedExported = func(job *model.Job) {
if checkErr != nil {
return
}
switch job.SchemaState {
case model.StateDeleteOnly:
_, checkErr = tk1.Exec("insert into t1 values (1) on duplicate key update a=a+1")
if checkErr == nil {
_, checkErr = tk1.Exec("replace into t1 values (2)")
}
case model.StateWriteOnly:
_, checkErr = tk1.Exec("insert into t1 values (2) on duplicate key update a=a+1")
if checkErr == nil {
_, checkErr = tk1.Exec("replace into t1 values (3)")
}
case model.StateWriteReorganization:
if checkErr == nil && job.SchemaState == model.StateWriteReorganization && times == 0 {
_, checkErr = tk1.Exec("insert into t1 values (3) on duplicate key update a=a+1")
if checkErr == nil {
_, checkErr = tk1.Exec("replace into t1 values (4)")
}
times++
}
}
}
d.SetHook(hook)
tk.MustExec("alter table t1 add column gc int as ((a+1))")
tk.MustQuery("select * from t1 order by a").Check(testkit.Rows("4 5", "10 11"))
c.Assert(checkErr, IsNil)
}

View File

@ -23,12 +23,14 @@ import (
"time"
"github.com/pingcap/errors"
"github.com/pingcap/failpoint"
"github.com/pingcap/tidb/ddl"
ddlutil "github.com/pingcap/tidb/ddl/util"
"github.com/pingcap/tidb/domain"
"github.com/pingcap/tidb/errno"
"github.com/pingcap/tidb/executor"
"github.com/pingcap/tidb/kv"
"github.com/pingcap/tidb/meta"
"github.com/pingcap/tidb/parser/model"
"github.com/pingcap/tidb/parser/mysql"
"github.com/pingcap/tidb/sessionctx"
@ -1164,3 +1166,87 @@ func TestCancelTruncateTable(t *testing.T) {
require.NoError(t, checkErr)
require.EqualError(t, err, "[ddl:8214]Cancelled DDL job")
}
func TestAddExpressionIndexRollback(t *testing.T) {
store, dom, clean := testkit.CreateMockStoreAndDomainWithSchemaLease(t, dbTestLease)
defer clean()
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table t1 (c1 int, c2 int, c3 int, unique key(c1))")
tk.MustExec("insert into t1 values (20, 20, 20), (40, 40, 40), (80, 80, 80), (160, 160, 160);")
var checkErr error
tk1 := testkit.NewTestKit(t, store)
tk1.MustExec("use test")
d := dom.DDL()
hook := &ddl.TestDDLCallback{Do: dom}
var currJob *model.Job
ctx := mock.NewContext()
ctx.Store = store
times := 0
hook.OnJobUpdatedExported = func(job *model.Job) {
if checkErr != nil {
return
}
switch job.SchemaState {
case model.StateDeleteOnly:
_, checkErr = tk1.Exec("insert into t1 values (6, 3, 3) on duplicate key update c1 = 10")
if checkErr == nil {
_, checkErr = tk1.Exec("update t1 set c1 = 7 where c2=6;")
}
if checkErr == nil {
_, checkErr = tk1.Exec("delete from t1 where c1 = 40;")
}
case model.StateWriteOnly:
_, checkErr = tk1.Exec("insert into t1 values (2, 2, 2)")
if checkErr == nil {
_, checkErr = tk1.Exec("update t1 set c1 = 3 where c2 = 80")
}
case model.StateWriteReorganization:
if checkErr == nil && job.SchemaState == model.StateWriteReorganization && times == 0 {
_, checkErr = tk1.Exec("insert into t1 values (4, 4, 4)")
if checkErr != nil {
return
}
_, checkErr = tk1.Exec("update t1 set c1 = 5 where c2 = 80")
if checkErr != nil {
return
}
currJob = job
times++
}
}
}
d.SetHook(hook)
tk.MustGetErrMsg("alter table t1 add index expr_idx ((pow(c1, c2)));", "[ddl:8202]Cannot decode index value, because [types:1690]DOUBLE value is out of range in 'pow(160, 160)'")
require.NoError(t, checkErr)
tk.MustQuery("select * from t1 order by c1;").Check(testkit.Rows("2 2 2", "4 4 4", "5 80 80", "10 3 3", "20 20 20", "160 160 160"))
// Check whether the reorg information is cleaned up.
err := ctx.NewTxn(context.Background())
require.NoError(t, err)
txn, err := ctx.Txn(true)
require.NoError(t, err)
m := meta.NewMeta(txn)
element, start, end, physicalID, err := m.GetDDLReorgHandle(currJob)
require.True(t, meta.ErrDDLReorgElementNotExist.Equal(err))
require.Nil(t, element)
require.Nil(t, start)
require.Nil(t, end)
require.Equal(t, int64(0), physicalID)
}
func TestDropTableOnTiKVDiskFull(t *testing.T) {
store, clean := testkit.CreateMockStoreWithSchemaLease(t, dbTestLease)
defer clean()
tk := testkit.NewTestKit(t, store)
tk.MustExec("use test")
tk.MustExec("create table test_disk_full_drop_table(a int);")
require.NoError(t, failpoint.Enable("github.com/pingcap/tidb/store/mockstore/unistore/rpcTiKVAllowedOnAlmostFull", `return(true)`))
defer func() {
require.NoError(t, failpoint.Disable("github.com/pingcap/tidb/store/mockstore/unistore/rpcTiKVAllowedOnAlmostFull"))
}()
tk.MustExec("drop table test_disk_full_drop_table;")
}