diff --git a/session/pessimistic_test.go b/session/pessimistic_test.go index fd5a59d7dc..11c788e931 100644 --- a/session/pessimistic_test.go +++ b/session/pessimistic_test.go @@ -2649,3 +2649,188 @@ func (s *testPessimisticSuite) TestChangeLockToPut(c *C) { tk.MustExec("admin check table t1") } + +func createTable(part bool, columnNames []string, columnTypes []string) string { + var str string + str = "create table t(" + if part { + str = "create table t_part(" + } + first := true + for i, colName := range columnNames { + if first { + first = false + } else { + str += "," + } + str += fmt.Sprintf("%s %s", colName, columnTypes[i]) + } + str += ", primary key(c_int, c_str)" + str += ")" + if part { + str += "partition by hash(c_int) partitions 8" + } + return str +} + +func (s *testPessimisticSuite) TestAmendForIndexChange(c *C) { + defer config.RestoreFunc()() + config.UpdateGlobal(func(conf *config.Config) { + conf.TiKVClient.AsyncCommit.SafeWindow = 0 + conf.TiKVClient.AsyncCommit.AllowedClockDrift = 0 + }) + tk := testkit.NewTestKitWithInit(c, s.store) + tk.MustExec("set tidb_enable_amend_pessimistic_txn = ON;") + tk.Se.GetSessionVars().EnableAsyncCommit = false + tk.Se.GetSessionVars().Enable1PC = false + tk2 := testkit.NewTestKitWithInit(c, s.store) + tk.MustExec("drop database if exists test_db") + tk.MustExec("create database test_db") + tk.MustExec("use test_db") + tk2.MustExec("use test_db") + tk2.MustExec("drop table if exists t1") + + // Add some different column types. + columnNames := []string{"c_int", "c_str", "c_datetime", "c_timestamp", "c_double", "c_decimal", "c_float"} + columnTypes := []string{"int", "varchar(40)", "datetime", "timestamp", "double", "decimal(12, 6)", "float"} + + addIndexFunc := func(idxName string, part bool, a, b int) string { + var str string + str = "alter table t" + if part { + str = "alter table t_part" + } + str += " add index " + idxName + " (" + str += strings.Join(columnNames[a:b], ",") + str += ")" + return str + } + + for i := 0; i < len(columnTypes); i++ { + for j := i + 1; j <= len(columnTypes); j++ { + // Create table and prepare some data. + tk2.MustExec("drop table if exists t") + tk2.MustExec("drop table if exists t_part") + tk2.MustExec(createTable(false, columnNames, columnTypes)) + tk2.MustExec(createTable(true, columnNames, columnTypes)) + tk2.MustExec(`insert into t values(1, "1", "2000-01-01", "2020-01-01", "1.1", "123.321", 1.1)`) + tk2.MustExec(`insert into t values(2, "2", "2000-01-02", "2020-01-02", "2.2", "223.322", 2.2)`) + tk2.MustExec(`insert into t_part values(1, "1", "2000-01-01", "2020-01-01", "1.1", "123.321", 1.1)`) + tk2.MustExec(`insert into t_part values(2, "2", "2000-01-02", "2020-01-02", "2.2", "223.322", 2.2)`) + + // Start a pessimistic transaction, the amend should succeed for common table. + tk.MustExec("begin pessimistic") + tk.MustExec(`insert into t values(5, "555", "2000-01-05", "2020-01-05", "5.5", "555.555", 5.5)`) + idxName := fmt.Sprintf("index%d%d", i, j) + tk2.MustExec(addIndexFunc(idxName, false, i, j)) + tk.MustExec("commit") + tk2.MustExec("admin check table t") + + tk.MustExec("begin pessimistic") + tk.MustExec(`insert into t values(6, "666", "2000-01-06", "2020-01-06", "6.6", "666.666", 6.6)`) + tk2.MustExec(fmt.Sprintf(`alter table t drop index %s`, idxName)) + tk.MustExec("commit") + tk2.MustExec("admin check table t") + tk2.MustQuery("select count(*) from t").Check(testkit.Rows("4")) + + // Start a pessimistic transaction for partition table, the amend should fail. + tk.MustExec("begin pessimistic") + tk.MustExec(`insert into t_part values(5, "555", "2000-01-05", "2020-01-05", "5.5", "555.555", 5.5)`) + tk2.MustExec(addIndexFunc(idxName, true, i, j)) + c.Assert(tk.ExecToErr("commit"), NotNil) + tk2.MustExec("admin check table t_part") + + tk.MustExec("begin pessimistic") + tk.MustExec(`insert into t_part values(6, "666", "2000-01-06", "2020-01-06", "6.6", "666.666", 6.6)`) + tk2.MustExec(fmt.Sprintf(`alter table t_part drop index %s`, idxName)) + c.Assert(tk.ExecToErr("commit"), NotNil) + tk2.MustExec("admin check table t_part") + tk2.MustQuery("select count(*) from t_part").Check(testkit.Rows("2")) + } + } + + tk2.MustExec("drop database test_db") +} + +func (s *testPessimisticSuite) TestAmendForColumnChange(c *C) { + tk := testkit.NewTestKitWithInit(c, s.store) + tk2 := testkit.NewTestKitWithInit(c, s.store) + tk.MustExec("set tidb_enable_amend_pessimistic_txn = ON;") + tk.MustExec("drop database if exists test_db") + tk.MustExec("create database test_db") + tk.MustExec("use test_db") + tk2.MustExec("use test_db") + tk2.MustExec("drop table if exists t1") + + // Add some different column types. + columnNames := []string{"c_int", "c_str", "c_datetime", "c_timestamp", "c_double", "c_decimal", "c_float"} + columnTypes := []string{"int", "varchar(40)", "datetime", "timestamp", "double", "decimal(12, 6)", "float"} + colChangeDDLs := []string{ + "alter table %s change column c_int c_int bigint", + "alter table %s modify column c_str varchar(55)", + "alter table %s modify column c_datetime datetime", + "alter table %s modify column c_timestamp timestamp", + "alter table %s modify column c_double double default NULL", + "alter table %s modify column c_int bigint(20) default 100", + "alter table %s change column c_float c_float float", + "alter table %s modify column c_int bigint(20)", + } + amendSucc := []bool{ + true, + true, + true, + true, + true, + false, + true, + true, + } + colChangeFunc := func(part bool, i int) string { + var sql string + sql = colChangeDDLs[i] + if part { + sql = fmt.Sprintf(sql, "t_part") + } else { + sql = fmt.Sprintf(sql, "t") + } + return sql + } + + for i := 0; i < len(colChangeDDLs); i++ { + // Create table and prepare some data. + tk2.MustExec("drop table if exists t") + tk2.MustExec("drop table if exists t_part") + tk2.MustExec(createTable(false, columnNames, columnTypes)) + tk2.MustExec(createTable(true, columnNames, columnTypes)) + tk2.MustExec(`insert into t values(1, "1", "2000-01-01", "2020-01-01", "1.1", "123.321", 1.1)`) + tk2.MustExec(`insert into t values(2, "2", "2000-01-02", "2020-01-02", "2.2", "223.322", 2.2)`) + tk2.MustExec(`insert into t_part values(1, "1", "2000-01-01", "2020-01-01", "1.1", "123.321", 1.1)`) + tk2.MustExec(`insert into t_part values(2, "2", "2000-01-02", "2020-01-02", "2.2", "223.322", 2.2)`) + + // Start a pessimistic transaction, the amend should succeed for common table. + tk.MustExec("begin pessimistic") + tk.MustExec(`insert into t values(5, "555", "2000-01-05", "2020-01-05", "5.5", "555.555", 5.5)`) + tk2.MustExec(colChangeFunc(false, i)) + if amendSucc[i] { + tk.MustExec("commit") + } else { + c.Assert(tk.ExecToErr("commit"), NotNil) + } + tk2.MustExec("admin check table t") + if amendSucc[i] { + tk2.MustQuery("select count(*) from t").Check(testkit.Rows("3")) + } else { + tk2.MustQuery("select count(*) from t").Check(testkit.Rows("2")) + } + + // Start a pessimistic transaction for partition table, the amend should fail. + tk.MustExec("begin pessimistic") + tk.MustExec(`insert into t_part values(5, "555", "2000-01-05", "2020-01-05", "5.5", "555.555", 5.5)`) + tk2.MustExec(colChangeFunc(true, i)) + c.Assert(tk.ExecToErr("commit"), NotNil) + tk2.MustExec("admin check table t_part") + tk2.MustQuery("select count(*) from t_part").Check(testkit.Rows("2")) + } + + tk2.MustExec("drop database test_db") +}