ddl: migrate test-infra to testify for part of ddl.testSerialDBSuite (#33258)
ref pingcap/tidb#33004
This commit is contained in:
@ -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)
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
|
||||
@ -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;")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user