github.com/whtcorpsinc/milevadb-prod@v0.0.0-20211104133533-f57f4be3b597/dbs/dbs_worker_test.go (about)

     1  // Copyright 2020 WHTCORPS INC, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package dbs
    15  
    16  import (
    17  	"context"
    18  	"sync"
    19  	"time"
    20  
    21  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    22  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    23  	"github.com/whtcorpsinc/BerolinaSQL/charset"
    24  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    25  	"github.com/whtcorpsinc/BerolinaSQL/terror"
    26  	. "github.com/whtcorpsinc/check"
    27  	"github.com/whtcorpsinc/errors"
    28  	"github.com/whtcorpsinc/failpoint"
    29  	"github.com/whtcorpsinc/milevadb/causet"
    30  	"github.com/whtcorpsinc/milevadb/ekv"
    31  	"github.com/whtcorpsinc/milevadb/soliton/admin"
    32  	"github.com/whtcorpsinc/milevadb/soliton/mock"
    33  	"github.com/whtcorpsinc/milevadb/soliton/solitonutil"
    34  	"github.com/whtcorpsinc/milevadb/soliton/sqlexec"
    35  	"github.com/whtcorpsinc/milevadb/spacetime"
    36  	"github.com/whtcorpsinc/milevadb/stochastikctx"
    37  	"github.com/whtcorpsinc/milevadb/types"
    38  )
    39  
    40  var _ = Suite(&testDBSSuite{})
    41  var _ = SerialSuites(&testDBSSerialSuite{})
    42  
    43  type testDBSSuite struct {
    44  	solitonutil.CommonHandleSuite
    45  }
    46  type testDBSSerialSuite struct{}
    47  
    48  const testLease = 5 * time.Millisecond
    49  
    50  func (s *testDBSSerialSuite) SetUpSuite(c *C) {
    51  	SetWaitTimeWhenErrorOccurred(1 * time.Microsecond)
    52  
    53  	// We hope that this test is serially executed. So put it here.
    54  	s.testRunWorker(c)
    55  }
    56  
    57  func (s *testDBSSuite) TestCheckTenant(c *C) {
    58  	causetstore := testCreateStore(c, "test_tenant")
    59  	defer causetstore.Close()
    60  
    61  	d1 := testNewDBSAndStart(
    62  		context.Background(),
    63  		c,
    64  		WithStore(causetstore),
    65  		WithLease(testLease),
    66  	)
    67  	defer d1.Stop()
    68  	time.Sleep(testLease)
    69  	testCheckTenant(c, d1, true)
    70  
    71  	c.Assert(d1.GetLease(), Equals, testLease)
    72  }
    73  
    74  // testRunWorker tests no job is handled when the value of RunWorker is false.
    75  func (s *testDBSSerialSuite) testRunWorker(c *C) {
    76  	causetstore := testCreateStore(c, "test_run_worker")
    77  	defer causetstore.Close()
    78  
    79  	RunWorker = false
    80  	d := testNewDBSAndStart(
    81  		context.Background(),
    82  		c,
    83  		WithStore(causetstore),
    84  		WithLease(testLease),
    85  	)
    86  	testCheckTenant(c, d, false)
    87  	defer d.Stop()
    88  
    89  	// Make sure the DBS worker is nil.
    90  	worker := d.generalWorker()
    91  	c.Assert(worker, IsNil)
    92  	// Make sure the DBS job can be done and exit that goroutine.
    93  	RunWorker = true
    94  	d1 := testNewDBSAndStart(
    95  		context.Background(),
    96  		c,
    97  		WithStore(causetstore),
    98  		WithLease(testLease),
    99  	)
   100  	testCheckTenant(c, d1, true)
   101  	defer d1.Stop()
   102  	worker = d1.generalWorker()
   103  	c.Assert(worker, NotNil)
   104  }
   105  
   106  func (s *testDBSSuite) TestSchemaError(c *C) {
   107  	causetstore := testCreateStore(c, "test_schema_error")
   108  	defer causetstore.Close()
   109  
   110  	d := testNewDBSAndStart(
   111  		context.Background(),
   112  		c,
   113  		WithStore(causetstore),
   114  		WithLease(testLease),
   115  	)
   116  	defer d.Stop()
   117  	ctx := testNewContext(d)
   118  
   119  	doDBSJobErr(c, 1, 0, perceptron.CausetActionCreateSchema, []interface{}{1}, ctx, d)
   120  }
   121  
   122  func (s *testDBSSuite) TestBlockError(c *C) {
   123  	causetstore := testCreateStore(c, "test_block_error")
   124  	defer causetstore.Close()
   125  
   126  	d := testNewDBSAndStart(
   127  		context.Background(),
   128  		c,
   129  		WithStore(causetstore),
   130  		WithLease(testLease),
   131  	)
   132  	defer d.Stop()
   133  	ctx := testNewContext(d)
   134  
   135  	// Schema ID is wrong, so dropping causet is failed.
   136  	doDBSJobErr(c, -1, 1, perceptron.CausetActionDropBlock, nil, ctx, d)
   137  	// Block ID is wrong, so dropping causet is failed.
   138  	dbInfo := testSchemaInfo(c, d, "test")
   139  	testCreateSchema(c, testNewContext(d), d, dbInfo)
   140  	job := doDBSJobErr(c, dbInfo.ID, -1, perceptron.CausetActionDropBlock, nil, ctx, d)
   141  
   142  	// Block ID or schemaReplicant ID is wrong, so getting causet is failed.
   143  	tblInfo := testBlockInfo(c, d, "t", 3)
   144  	testCreateBlock(c, ctx, d, dbInfo, tblInfo)
   145  	err := ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error {
   146  		job.SchemaID = -1
   147  		job.BlockID = -1
   148  		t := spacetime.NewMeta(txn)
   149  		_, err1 := getBlockInfoAndCancelFaultJob(t, job, job.SchemaID)
   150  		c.Assert(err1, NotNil)
   151  		job.SchemaID = dbInfo.ID
   152  		_, err1 = getBlockInfoAndCancelFaultJob(t, job, job.SchemaID)
   153  		c.Assert(err1, NotNil)
   154  		return nil
   155  	})
   156  	c.Assert(err, IsNil)
   157  
   158  	// Args is wrong, so creating causet is failed.
   159  	doDBSJobErr(c, 1, 1, perceptron.CausetActionCreateBlock, []interface{}{1}, ctx, d)
   160  	// Schema ID is wrong, so creating causet is failed.
   161  	doDBSJobErr(c, -1, tblInfo.ID, perceptron.CausetActionCreateBlock, []interface{}{tblInfo}, ctx, d)
   162  	// Block exists, so creating causet is failed.
   163  	tblInfo.ID = tblInfo.ID + 1
   164  	doDBSJobErr(c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionCreateBlock, []interface{}{tblInfo}, ctx, d)
   165  
   166  }
   167  
   168  func (s *testDBSSuite) TestViewError(c *C) {
   169  	causetstore := testCreateStore(c, "test_view_error")
   170  	defer causetstore.Close()
   171  
   172  	d := testNewDBSAndStart(
   173  		context.Background(),
   174  		c,
   175  		WithStore(causetstore),
   176  		WithLease(testLease),
   177  	)
   178  	defer d.Stop()
   179  	ctx := testNewContext(d)
   180  	dbInfo := testSchemaInfo(c, d, "test")
   181  	testCreateSchema(c, testNewContext(d), d, dbInfo)
   182  
   183  	// Block ID or schemaReplicant ID is wrong, so getting causet is failed.
   184  	tblInfo := testViewInfo(c, d, "t", 3)
   185  	testCreateView(c, ctx, d, dbInfo, tblInfo)
   186  
   187  	// Args is wrong, so creating view is failed.
   188  	doDBSJobErr(c, 1, 1, perceptron.CausetActionCreateView, []interface{}{1}, ctx, d)
   189  	// Schema ID is wrong and orReplace is false, so creating view is failed.
   190  	doDBSJobErr(c, -1, tblInfo.ID, perceptron.CausetActionCreateView, []interface{}{tblInfo, false}, ctx, d)
   191  	// View exists and orReplace is false, so creating view is failed.
   192  	tblInfo.ID = tblInfo.ID + 1
   193  	doDBSJobErr(c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionCreateView, []interface{}{tblInfo, false}, ctx, d)
   194  
   195  }
   196  
   197  func (s *testDBSSuite) TestInvalidDBSJob(c *C) {
   198  	causetstore := testCreateStore(c, "test_invalid_dbs_job_type_error")
   199  	defer causetstore.Close()
   200  	d := testNewDBSAndStart(
   201  		context.Background(),
   202  		c,
   203  		WithStore(causetstore),
   204  		WithLease(testLease),
   205  	)
   206  	defer d.Stop()
   207  	ctx := testNewContext(d)
   208  
   209  	job := &perceptron.Job{
   210  		SchemaID:   0,
   211  		BlockID:    0,
   212  		Type:       perceptron.CausetActionNone,
   213  		BinlogInfo: &perceptron.HistoryInfo{},
   214  		Args:       []interface{}{},
   215  	}
   216  	err := d.doDBSJob(ctx, job)
   217  	c.Assert(err.Error(), Equals, "[dbs:8204]invalid dbs job type: none")
   218  }
   219  
   220  func (s *testDBSSuite) TestForeignKeyError(c *C) {
   221  	causetstore := testCreateStore(c, "test_foreign_key_error")
   222  	defer causetstore.Close()
   223  
   224  	d := testNewDBSAndStart(
   225  		context.Background(),
   226  		c,
   227  		WithStore(causetstore),
   228  		WithLease(testLease),
   229  	)
   230  	defer d.Stop()
   231  	ctx := testNewContext(d)
   232  
   233  	doDBSJobErr(c, -1, 1, perceptron.CausetActionAddForeignKey, nil, ctx, d)
   234  	doDBSJobErr(c, -1, 1, perceptron.CausetActionDropForeignKey, nil, ctx, d)
   235  
   236  	dbInfo := testSchemaInfo(c, d, "test")
   237  	tblInfo := testBlockInfo(c, d, "t", 3)
   238  	testCreateSchema(c, ctx, d, dbInfo)
   239  	testCreateBlock(c, ctx, d, dbInfo, tblInfo)
   240  	doDBSJobErr(c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionDropForeignKey, []interface{}{perceptron.NewCIStr("c1_foreign_key")}, ctx, d)
   241  }
   242  
   243  func (s *testDBSSuite) TestIndexError(c *C) {
   244  	causetstore := testCreateStore(c, "test_index_error")
   245  	defer causetstore.Close()
   246  
   247  	d := testNewDBSAndStart(
   248  		context.Background(),
   249  		c,
   250  		WithStore(causetstore),
   251  		WithLease(testLease),
   252  	)
   253  	defer d.Stop()
   254  	ctx := testNewContext(d)
   255  
   256  	// Schema ID is wrong.
   257  	doDBSJobErr(c, -1, 1, perceptron.CausetActionAddIndex, nil, ctx, d)
   258  	doDBSJobErr(c, -1, 1, perceptron.CausetActionDropIndex, nil, ctx, d)
   259  
   260  	dbInfo := testSchemaInfo(c, d, "test")
   261  	tblInfo := testBlockInfo(c, d, "t", 3)
   262  	testCreateSchema(c, ctx, d, dbInfo)
   263  	testCreateBlock(c, ctx, d, dbInfo, tblInfo)
   264  
   265  	// for adding index
   266  	doDBSJobErr(c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddIndex, []interface{}{1}, ctx, d)
   267  	doDBSJobErr(c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddIndex,
   268  		[]interface{}{false, perceptron.NewCIStr("t"), 1,
   269  			[]*ast.IndexPartSpecification{{DeferredCauset: &ast.DeferredCausetName{Name: perceptron.NewCIStr("c")}, Length: 256}}}, ctx, d)
   270  	doDBSJobErr(c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddIndex,
   271  		[]interface{}{false, perceptron.NewCIStr("c1_index"), 1,
   272  			[]*ast.IndexPartSpecification{{DeferredCauset: &ast.DeferredCausetName{Name: perceptron.NewCIStr("c")}, Length: 256}}}, ctx, d)
   273  	testCreateIndex(c, ctx, d, dbInfo, tblInfo, false, "c1_index", "c1")
   274  	doDBSJobErr(c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddIndex,
   275  		[]interface{}{false, perceptron.NewCIStr("c1_index"), 1,
   276  			[]*ast.IndexPartSpecification{{DeferredCauset: &ast.DeferredCausetName{Name: perceptron.NewCIStr("c1")}, Length: 256}}}, ctx, d)
   277  
   278  	// for dropping index
   279  	doDBSJobErr(c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionDropIndex, []interface{}{1}, ctx, d)
   280  	testDropIndex(c, ctx, d, dbInfo, tblInfo, "c1_index")
   281  	doDBSJobErr(c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionDropIndex, []interface{}{perceptron.NewCIStr("c1_index")}, ctx, d)
   282  }
   283  
   284  func (s *testDBSSuite) TestDeferredCausetError(c *C) {
   285  	causetstore := testCreateStore(c, "test_defCausumn_error")
   286  	defer causetstore.Close()
   287  	d := testNewDBSAndStart(
   288  		context.Background(),
   289  		c,
   290  		WithStore(causetstore),
   291  		WithLease(testLease),
   292  	)
   293  	defer d.Stop()
   294  	ctx := testNewContext(d)
   295  
   296  	dbInfo := testSchemaInfo(c, d, "test")
   297  	tblInfo := testBlockInfo(c, d, "t", 3)
   298  	testCreateSchema(c, ctx, d, dbInfo)
   299  	testCreateBlock(c, ctx, d, dbInfo, tblInfo)
   300  	defCaus := &perceptron.DeferredCausetInfo{
   301  		Name:         perceptron.NewCIStr("c4"),
   302  		Offset:       len(tblInfo.DeferredCausets),
   303  		DefaultValue: 0,
   304  	}
   305  	defCaus.ID = allocateDeferredCausetID(tblInfo)
   306  	defCaus.FieldType = *types.NewFieldType(allegrosql.TypeLong)
   307  	pos := &ast.DeferredCausetPosition{Tp: ast.DeferredCausetPositionAfter, RelativeDeferredCauset: &ast.DeferredCausetName{Name: perceptron.NewCIStr("c5")}}
   308  
   309  	defcaus := &[]*perceptron.DeferredCausetInfo{defCaus}
   310  	positions := &[]*ast.DeferredCausetPosition{pos}
   311  
   312  	// for adding defCausumn
   313  	doDBSJobErr(c, -1, tblInfo.ID, perceptron.CausetActionAddDeferredCauset, []interface{}{defCaus, pos, 0}, ctx, d)
   314  	doDBSJobErr(c, dbInfo.ID, -1, perceptron.CausetActionAddDeferredCauset, []interface{}{defCaus, pos, 0}, ctx, d)
   315  	doDBSJobErr(c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddDeferredCauset, []interface{}{0}, ctx, d)
   316  	doDBSJobErr(c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddDeferredCauset, []interface{}{defCaus, pos, 0}, ctx, d)
   317  
   318  	// for dropping defCausumn
   319  	doDBSJobErr(c, -1, tblInfo.ID, perceptron.CausetActionDropDeferredCauset, []interface{}{defCaus, pos, 0}, ctx, d)
   320  	doDBSJobErr(c, dbInfo.ID, -1, perceptron.CausetActionDropDeferredCauset, []interface{}{defCaus, pos, 0}, ctx, d)
   321  	doDBSJobErr(c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionDropDeferredCauset, []interface{}{0}, ctx, d)
   322  	doDBSJobErr(c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionDropDeferredCauset, []interface{}{perceptron.NewCIStr("c5")}, ctx, d)
   323  
   324  	// for adding defCausumns
   325  	doDBSJobErr(c, -1, tblInfo.ID, perceptron.CausetActionAddDeferredCausets, []interface{}{defcaus, positions, 0}, ctx, d)
   326  	doDBSJobErr(c, dbInfo.ID, -1, perceptron.CausetActionAddDeferredCausets, []interface{}{defcaus, positions, 0}, ctx, d)
   327  	doDBSJobErr(c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddDeferredCausets, []interface{}{0}, ctx, d)
   328  	doDBSJobErr(c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddDeferredCausets, []interface{}{defcaus, positions, 0}, ctx, d)
   329  
   330  	// for dropping defCausumns
   331  	doDBSJobErr(c, -1, tblInfo.ID, perceptron.CausetActionDropDeferredCausets, []interface{}{defCaus, pos, 0}, ctx, d)
   332  	doDBSJobErr(c, dbInfo.ID, -1, perceptron.CausetActionDropDeferredCausets, []interface{}{defCaus, pos, 0}, ctx, d)
   333  	doDBSJobErr(c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionDropDeferredCausets, []interface{}{0}, ctx, d)
   334  	doDBSJobErr(c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionDropDeferredCausets, []interface{}{[]perceptron.CIStr{perceptron.NewCIStr("c5"), perceptron.NewCIStr("c6")}, make([]bool, 2)}, ctx, d)
   335  }
   336  
   337  func testCheckTenant(c *C, d *dbs, expectedVal bool) {
   338  	c.Assert(d.isTenant(), Equals, expectedVal)
   339  }
   340  
   341  func testCheckJobDone(c *C, d *dbs, job *perceptron.Job, isAdd bool) {
   342  	ekv.RunInNewTxn(d.causetstore, false, func(txn ekv.Transaction) error {
   343  		t := spacetime.NewMeta(txn)
   344  		historyJob, err := t.GetHistoryDBSJob(job.ID)
   345  		c.Assert(err, IsNil)
   346  		checkHistoryJob(c, historyJob)
   347  		if isAdd {
   348  			c.Assert(historyJob.SchemaState, Equals, perceptron.StatePublic)
   349  		} else {
   350  			c.Assert(historyJob.SchemaState, Equals, perceptron.StateNone)
   351  		}
   352  
   353  		return nil
   354  	})
   355  }
   356  
   357  func testCheckJobCancelled(c *C, d *dbs, job *perceptron.Job, state *perceptron.SchemaState) {
   358  	ekv.RunInNewTxn(d.causetstore, false, func(txn ekv.Transaction) error {
   359  		t := spacetime.NewMeta(txn)
   360  		historyJob, err := t.GetHistoryDBSJob(job.ID)
   361  		c.Assert(err, IsNil)
   362  		c.Assert(historyJob.IsCancelled() || historyJob.IsRollbackDone(), IsTrue, Commentf("history job %s", historyJob))
   363  		if state != nil {
   364  			c.Assert(historyJob.SchemaState, Equals, *state)
   365  		}
   366  		return nil
   367  	})
   368  }
   369  
   370  func doDBSJobErrWithSchemaState(ctx stochastikctx.Context, d *dbs, c *C, schemaID, blockID int64, tp perceptron.CausetActionType,
   371  	args []interface{}, state *perceptron.SchemaState) *perceptron.Job {
   372  	job := &perceptron.Job{
   373  		SchemaID:   schemaID,
   374  		BlockID:    blockID,
   375  		Type:       tp,
   376  		Args:       args,
   377  		BinlogInfo: &perceptron.HistoryInfo{},
   378  	}
   379  	err := d.doDBSJob(ctx, job)
   380  	// TODO: Add the detail error check.
   381  	c.Assert(err, NotNil, Commentf("err:%v", err))
   382  	testCheckJobCancelled(c, d, job, state)
   383  
   384  	return job
   385  }
   386  
   387  func doDBSJobSuccess(ctx stochastikctx.Context, d *dbs, c *C, schemaID, blockID int64, tp perceptron.CausetActionType,
   388  	args []interface{}) {
   389  	job := &perceptron.Job{
   390  		SchemaID:   schemaID,
   391  		BlockID:    blockID,
   392  		Type:       tp,
   393  		Args:       args,
   394  		BinlogInfo: &perceptron.HistoryInfo{},
   395  	}
   396  	err := d.doDBSJob(ctx, job)
   397  	c.Assert(err, IsNil)
   398  }
   399  
   400  func doDBSJobErr(c *C, schemaID, blockID int64, tp perceptron.CausetActionType, args []interface{},
   401  	ctx stochastikctx.Context, d *dbs) *perceptron.Job {
   402  	return doDBSJobErrWithSchemaState(ctx, d, c, schemaID, blockID, tp, args, nil)
   403  }
   404  
   405  func checkCancelState(txn ekv.Transaction, job *perceptron.Job, test *testCancelJob) error {
   406  	var checkErr error
   407  	addIndexFirstReorg := (test.act == perceptron.CausetActionAddIndex || test.act == perceptron.CausetActionAddPrimaryKey) &&
   408  		job.SchemaState == perceptron.StateWriteReorganization && job.SnapshotVer == 0
   409  	// If the action is adding index and the state is writing reorganization, it wants to test the case of cancelling the job when backfilling indexes.
   410  	// When the job satisfies this case of addIndexFirstReorg, the worker hasn't started to backfill indexes.
   411  	if test.cancelState == job.SchemaState && !addIndexFirstReorg && !job.IsRollingback() {
   412  		errs, err := admin.CancelJobs(txn, test.jobIDs)
   413  		if err != nil {
   414  			checkErr = errors.Trace(err)
   415  			return checkErr
   416  		}
   417  		// It only tests cancel one DBS job.
   418  		if !terror.ErrorEqual(errs[0], test.cancelRetErrs[0]) {
   419  			checkErr = errors.Trace(errs[0])
   420  			return checkErr
   421  		}
   422  	}
   423  	return checkErr
   424  }
   425  
   426  type testCancelJob struct {
   427  	jobIDs        []int64
   428  	cancelRetErrs []error                     // cancelRetErrs is the first return value of CancelJobs.
   429  	act           perceptron.CausetActionType // act is the job action.
   430  	cancelState   perceptron.SchemaState
   431  }
   432  
   433  func buildCancelJobTests(firstID int64) []testCancelJob {
   434  	noErrs := []error{nil}
   435  	tests := []testCancelJob{
   436  		{act: perceptron.CausetActionAddIndex, jobIDs: []int64{firstID + 1}, cancelRetErrs: noErrs, cancelState: perceptron.StateDeleteOnly},
   437  		{act: perceptron.CausetActionAddIndex, jobIDs: []int64{firstID + 2}, cancelRetErrs: noErrs, cancelState: perceptron.StateWriteOnly},
   438  		{act: perceptron.CausetActionAddIndex, jobIDs: []int64{firstID + 3}, cancelRetErrs: noErrs, cancelState: perceptron.StateWriteReorganization},
   439  		{act: perceptron.CausetActionAddIndex, jobIDs: []int64{firstID + 4}, cancelRetErrs: []error{admin.ErrCancelFinishedDBSJob.GenWithStackByArgs(firstID + 4)}, cancelState: perceptron.StatePublic},
   440  
   441  		// Test cancel drop index job , see TestCancelDropIndex.
   442  		{act: perceptron.CausetActionAddDeferredCauset, jobIDs: []int64{firstID + 5}, cancelRetErrs: noErrs, cancelState: perceptron.StateDeleteOnly},
   443  		{act: perceptron.CausetActionAddDeferredCauset, jobIDs: []int64{firstID + 6}, cancelRetErrs: noErrs, cancelState: perceptron.StateWriteOnly},
   444  		{act: perceptron.CausetActionAddDeferredCauset, jobIDs: []int64{firstID + 7}, cancelRetErrs: noErrs, cancelState: perceptron.StateWriteReorganization},
   445  		{act: perceptron.CausetActionAddDeferredCauset, jobIDs: []int64{firstID + 8}, cancelRetErrs: []error{admin.ErrCancelFinishedDBSJob.GenWithStackByArgs(firstID + 8)}, cancelState: perceptron.StatePublic},
   446  
   447  		// Test create causet, watch out, causet id will alloc a globalID.
   448  		{act: perceptron.CausetActionCreateBlock, jobIDs: []int64{firstID + 10}, cancelRetErrs: noErrs, cancelState: perceptron.StateNone},
   449  		// Test create database, watch out, database id will alloc a globalID.
   450  		{act: perceptron.CausetActionCreateSchema, jobIDs: []int64{firstID + 12}, cancelRetErrs: noErrs, cancelState: perceptron.StateNone},
   451  
   452  		{act: perceptron.CausetActionDropDeferredCauset, jobIDs: []int64{firstID + 13}, cancelRetErrs: []error{admin.ErrCannotCancelDBSJob.GenWithStackByArgs(firstID + 13)}, cancelState: perceptron.StateDeleteOnly},
   453  		{act: perceptron.CausetActionDropDeferredCauset, jobIDs: []int64{firstID + 14}, cancelRetErrs: []error{admin.ErrCannotCancelDBSJob.GenWithStackByArgs(firstID + 14)}, cancelState: perceptron.StateWriteOnly},
   454  		{act: perceptron.CausetActionDropDeferredCauset, jobIDs: []int64{firstID + 15}, cancelRetErrs: []error{admin.ErrCannotCancelDBSJob.GenWithStackByArgs(firstID + 15)}, cancelState: perceptron.StateWriteReorganization},
   455  		{act: perceptron.CausetActionRebaseAutoID, jobIDs: []int64{firstID + 16}, cancelRetErrs: noErrs, cancelState: perceptron.StateNone},
   456  		{act: perceptron.CausetActionShardRowID, jobIDs: []int64{firstID + 17}, cancelRetErrs: noErrs, cancelState: perceptron.StateNone},
   457  
   458  		{act: perceptron.CausetActionModifyDeferredCauset, jobIDs: []int64{firstID + 18}, cancelRetErrs: noErrs, cancelState: perceptron.StateNone},
   459  		{act: perceptron.CausetActionModifyDeferredCauset, jobIDs: []int64{firstID + 19}, cancelRetErrs: []error{admin.ErrCancelFinishedDBSJob.GenWithStackByArgs(firstID + 19)}, cancelState: perceptron.StateDeleteOnly},
   460  
   461  		{act: perceptron.CausetActionAddForeignKey, jobIDs: []int64{firstID + 20}, cancelRetErrs: noErrs, cancelState: perceptron.StateNone},
   462  		{act: perceptron.CausetActionAddForeignKey, jobIDs: []int64{firstID + 21}, cancelRetErrs: []error{admin.ErrCancelFinishedDBSJob.GenWithStackByArgs(firstID + 21)}, cancelState: perceptron.StatePublic},
   463  		{act: perceptron.CausetActionDropForeignKey, jobIDs: []int64{firstID + 22}, cancelRetErrs: noErrs, cancelState: perceptron.StateNone},
   464  		{act: perceptron.CausetActionDropForeignKey, jobIDs: []int64{firstID + 23}, cancelRetErrs: []error{admin.ErrCancelFinishedDBSJob.GenWithStackByArgs(firstID + 23)}, cancelState: perceptron.StatePublic},
   465  
   466  		{act: perceptron.CausetActionRenameBlock, jobIDs: []int64{firstID + 24}, cancelRetErrs: noErrs, cancelState: perceptron.StateNone},
   467  		{act: perceptron.CausetActionRenameBlock, jobIDs: []int64{firstID + 25}, cancelRetErrs: []error{admin.ErrCancelFinishedDBSJob.GenWithStackByArgs(firstID + 25)}, cancelState: perceptron.StatePublic},
   468  
   469  		{act: perceptron.CausetActionModifyBlockCharsetAndDefCauslate, jobIDs: []int64{firstID + 26}, cancelRetErrs: noErrs, cancelState: perceptron.StateNone},
   470  		{act: perceptron.CausetActionModifyBlockCharsetAndDefCauslate, jobIDs: []int64{firstID + 27}, cancelRetErrs: []error{admin.ErrCancelFinishedDBSJob.GenWithStackByArgs(firstID + 27)}, cancelState: perceptron.StatePublic},
   471  		{act: perceptron.CausetActionTruncateBlockPartition, jobIDs: []int64{firstID + 28}, cancelRetErrs: noErrs, cancelState: perceptron.StateNone},
   472  		{act: perceptron.CausetActionTruncateBlockPartition, jobIDs: []int64{firstID + 29}, cancelRetErrs: []error{admin.ErrCancelFinishedDBSJob.GenWithStackByArgs(firstID + 29)}, cancelState: perceptron.StatePublic},
   473  		{act: perceptron.CausetActionModifySchemaCharsetAndDefCauslate, jobIDs: []int64{firstID + 31}, cancelRetErrs: noErrs, cancelState: perceptron.StateNone},
   474  		{act: perceptron.CausetActionModifySchemaCharsetAndDefCauslate, jobIDs: []int64{firstID + 32}, cancelRetErrs: []error{admin.ErrCancelFinishedDBSJob.GenWithStackByArgs(firstID + 32)}, cancelState: perceptron.StatePublic},
   475  
   476  		{act: perceptron.CausetActionAddPrimaryKey, jobIDs: []int64{firstID + 33}, cancelRetErrs: noErrs, cancelState: perceptron.StateDeleteOnly},
   477  		{act: perceptron.CausetActionAddPrimaryKey, jobIDs: []int64{firstID + 34}, cancelRetErrs: noErrs, cancelState: perceptron.StateWriteOnly},
   478  		{act: perceptron.CausetActionAddPrimaryKey, jobIDs: []int64{firstID + 35}, cancelRetErrs: noErrs, cancelState: perceptron.StateWriteReorganization},
   479  		{act: perceptron.CausetActionAddPrimaryKey, jobIDs: []int64{firstID + 36}, cancelRetErrs: []error{admin.ErrCancelFinishedDBSJob.GenWithStackByArgs(firstID + 36)}, cancelState: perceptron.StatePublic},
   480  		{act: perceptron.CausetActionDropPrimaryKey, jobIDs: []int64{firstID + 37}, cancelRetErrs: noErrs, cancelState: perceptron.StateWriteOnly},
   481  		{act: perceptron.CausetActionDropPrimaryKey, jobIDs: []int64{firstID + 38}, cancelRetErrs: []error{admin.ErrCannotCancelDBSJob.GenWithStackByArgs(firstID + 38)}, cancelState: perceptron.StateDeleteOnly},
   482  
   483  		{act: perceptron.CausetActionAddDeferredCausets, jobIDs: []int64{firstID + 39}, cancelRetErrs: noErrs, cancelState: perceptron.StateDeleteOnly},
   484  		{act: perceptron.CausetActionAddDeferredCausets, jobIDs: []int64{firstID + 40}, cancelRetErrs: noErrs, cancelState: perceptron.StateWriteOnly},
   485  		{act: perceptron.CausetActionAddDeferredCausets, jobIDs: []int64{firstID + 41}, cancelRetErrs: noErrs, cancelState: perceptron.StateWriteReorganization},
   486  		{act: perceptron.CausetActionAddDeferredCausets, jobIDs: []int64{firstID + 42}, cancelRetErrs: []error{admin.ErrCancelFinishedDBSJob.GenWithStackByArgs(firstID + 42)}, cancelState: perceptron.StatePublic},
   487  
   488  		{act: perceptron.CausetActionDropDeferredCausets, jobIDs: []int64{firstID + 43}, cancelRetErrs: []error{admin.ErrCannotCancelDBSJob.GenWithStackByArgs(firstID + 43)}, cancelState: perceptron.StateDeleteOnly},
   489  		{act: perceptron.CausetActionDropDeferredCausets, jobIDs: []int64{firstID + 44}, cancelRetErrs: []error{admin.ErrCannotCancelDBSJob.GenWithStackByArgs(firstID + 44)}, cancelState: perceptron.StateWriteOnly},
   490  		{act: perceptron.CausetActionDropDeferredCausets, jobIDs: []int64{firstID + 45}, cancelRetErrs: []error{admin.ErrCannotCancelDBSJob.GenWithStackByArgs(firstID + 45)}, cancelState: perceptron.StateWriteReorganization},
   491  
   492  		{act: perceptron.CausetActionAlterIndexVisibility, jobIDs: []int64{firstID + 47}, cancelRetErrs: noErrs, cancelState: perceptron.StateNone},
   493  		{act: perceptron.CausetActionAlterIndexVisibility, jobIDs: []int64{firstID + 48}, cancelRetErrs: []error{admin.ErrCancelFinishedDBSJob.GenWithStackByArgs(firstID + 48)}, cancelState: perceptron.StatePublic},
   494  
   495  		{act: perceptron.CausetActionExchangeBlockPartition, jobIDs: []int64{firstID + 54}, cancelRetErrs: noErrs, cancelState: perceptron.StateNone},
   496  		{act: perceptron.CausetActionExchangeBlockPartition, jobIDs: []int64{firstID + 55}, cancelRetErrs: []error{admin.ErrCancelFinishedDBSJob.GenWithStackByArgs(firstID + 55)}, cancelState: perceptron.StatePublic},
   497  
   498  		{act: perceptron.CausetActionAddBlockPartition, jobIDs: []int64{firstID + 60}, cancelRetErrs: noErrs, cancelState: perceptron.StateNone},
   499  		{act: perceptron.CausetActionAddBlockPartition, jobIDs: []int64{firstID + 61}, cancelRetErrs: noErrs, cancelState: perceptron.StateReplicaOnly},
   500  		{act: perceptron.CausetActionAddBlockPartition, jobIDs: []int64{firstID + 62}, cancelRetErrs: []error{admin.ErrCancelFinishedDBSJob}, cancelState: perceptron.StatePublic},
   501  
   502  		// modify defCausumn has two different types, normal-type and reorg-type. The latter has 5 states and it can be cancelled except the public state.
   503  		{act: perceptron.CausetActionModifyDeferredCauset, jobIDs: []int64{firstID + 65}, cancelRetErrs: noErrs, cancelState: perceptron.StateNone},
   504  		{act: perceptron.CausetActionModifyDeferredCauset, jobIDs: []int64{firstID + 66}, cancelRetErrs: noErrs, cancelState: perceptron.StateDeleteOnly},
   505  		{act: perceptron.CausetActionModifyDeferredCauset, jobIDs: []int64{firstID + 67}, cancelRetErrs: noErrs, cancelState: perceptron.StateWriteOnly},
   506  		{act: perceptron.CausetActionModifyDeferredCauset, jobIDs: []int64{firstID + 68}, cancelRetErrs: noErrs, cancelState: perceptron.StateWriteReorganization},
   507  		{act: perceptron.CausetActionModifyDeferredCauset, jobIDs: []int64{firstID + 69}, cancelRetErrs: []error{admin.ErrCancelFinishedDBSJob}, cancelState: perceptron.StatePublic},
   508  	}
   509  
   510  	return tests
   511  }
   512  
   513  func (s *testDBSSerialSuite) checkDropIdx(c *C, d *dbs, schemaID int64, blockID int64, idxName string, success bool) {
   514  	checkIdxExist(c, d, schemaID, blockID, idxName, !success)
   515  }
   516  
   517  func (s *testDBSSerialSuite) checkAddIdx(c *C, d *dbs, schemaID int64, blockID int64, idxName string, success bool) {
   518  	checkIdxExist(c, d, schemaID, blockID, idxName, success)
   519  }
   520  
   521  func checkIdxExist(c *C, d *dbs, schemaID int64, blockID int64, idxName string, expectedExist bool) {
   522  	changedBlock := testGetBlock(c, d, schemaID, blockID)
   523  	var found bool
   524  	for _, idxInfo := range changedBlock.Meta().Indices {
   525  		if idxInfo.Name.O == idxName {
   526  			found = true
   527  			break
   528  		}
   529  	}
   530  	c.Assert(found, Equals, expectedExist)
   531  }
   532  
   533  func (s *testDBSSerialSuite) checkAddDeferredCausets(c *C, d *dbs, schemaID int64, blockID int64, defCausNames []string, success bool) {
   534  	changedBlock := testGetBlock(c, d, schemaID, blockID)
   535  	found := !checkDeferredCausetsNotFound(changedBlock, defCausNames)
   536  	c.Assert(found, Equals, success)
   537  }
   538  
   539  func (s *testDBSSerialSuite) checkCancelDropDeferredCausets(c *C, d *dbs, schemaID int64, blockID int64, defCausNames []string, success bool) {
   540  	changedBlock := testGetBlock(c, d, schemaID, blockID)
   541  	notFound := checkDeferredCausetsNotFound(changedBlock, defCausNames)
   542  	c.Assert(notFound, Equals, success)
   543  }
   544  
   545  func checkDeferredCausetsNotFound(t causet.Block, defCausNames []string) bool {
   546  	notFound := true
   547  	for _, defCausName := range defCausNames {
   548  		for _, defCausInfo := range t.Meta().DeferredCausets {
   549  			if defCausInfo.Name.O == defCausName {
   550  				notFound = false
   551  			}
   552  		}
   553  	}
   554  	return notFound
   555  }
   556  
   557  func checkIdxVisibility(changedBlock causet.Block, idxName string, expected bool) bool {
   558  	for _, idxInfo := range changedBlock.Meta().Indices {
   559  		if idxInfo.Name.O == idxName && idxInfo.Invisible == expected {
   560  			return true
   561  		}
   562  	}
   563  	return false
   564  }
   565  
   566  func (s *testDBSSerialSuite) TestCancelJob(c *C) {
   567  	causetstore := testCreateStore(c, "test_cancel_job")
   568  	defer causetstore.Close()
   569  	d := testNewDBSAndStart(
   570  		context.Background(),
   571  		c,
   572  		WithStore(causetstore),
   573  		WithLease(testLease),
   574  	)
   575  	defer d.Stop()
   576  	dbInfo := testSchemaInfo(c, d, "test_cancel_job")
   577  	testCreateSchema(c, testNewContext(d), d, dbInfo)
   578  	// create a partition causet.
   579  	partitionTblInfo := testBlockInfoWithPartition(c, d, "t_partition", 5)
   580  	// Skip using sessPool. Make sure adding primary key can be successful.
   581  	partitionTblInfo.DeferredCausets[0].Flag |= allegrosql.NotNullFlag
   582  	// create causet t (c1 int, c2 int, c3 int, c4 int, c5 int);
   583  	tblInfo := testBlockInfo(c, d, "t", 5)
   584  	ctx := testNewContext(d)
   585  	err := ctx.NewTxn(context.Background())
   586  	c.Assert(err, IsNil)
   587  	testCreateBlock(c, ctx, d, dbInfo, partitionTblInfo)
   588  	blockAutoID := int64(100)
   589  	shardRowIDBits := uint64(5)
   590  	tblInfo.AutoIncID = blockAutoID
   591  	tblInfo.ShardRowIDBits = shardRowIDBits
   592  	job := testCreateBlock(c, ctx, d, dbInfo, tblInfo)
   593  	// insert t values (1, 2, 3, 4, 5);
   594  	originBlock := testGetBlock(c, d, dbInfo.ID, tblInfo.ID)
   595  	event := types.MakeCausets(1, 2, 3, 4, 5)
   596  	_, err = originBlock.AddRecord(ctx, event)
   597  	c.Assert(err, IsNil)
   598  	txn, err := ctx.Txn(true)
   599  	c.Assert(err, IsNil)
   600  	err = txn.Commit(context.Background())
   601  	c.Assert(err, IsNil)
   602  
   603  	tc := &TestDBSCallback{}
   604  	// set up hook
   605  	firstJobID := job.ID
   606  	tests := buildCancelJobTests(firstJobID)
   607  	var checkErr error
   608  	var mu sync.Mutex
   609  	var test *testCancelJob
   610  	uFIDelateTest := func(t *testCancelJob) {
   611  		mu.Lock()
   612  		test = t
   613  		mu.Unlock()
   614  	}
   615  	hookCancelFunc := func(job *perceptron.Job) {
   616  		if job.State == perceptron.JobStateSynced || job.State == perceptron.JobStateCancelled || job.State == perceptron.JobStateCancelling {
   617  			return
   618  		}
   619  		// This hook only valid for the related test job.
   620  		// This is use to avoid parallel test fail.
   621  		mu.Lock()
   622  		if len(test.jobIDs) > 0 && test.jobIDs[0] != job.ID {
   623  			mu.Unlock()
   624  			return
   625  		}
   626  		mu.Unlock()
   627  		if checkErr != nil {
   628  			return
   629  		}
   630  
   631  		hookCtx := mock.NewContext()
   632  		hookCtx.CausetStore = causetstore
   633  		err1 := hookCtx.NewTxn(context.Background())
   634  		if err1 != nil {
   635  			checkErr = errors.Trace(err1)
   636  			return
   637  		}
   638  		txn, err1 = hookCtx.Txn(true)
   639  		if err1 != nil {
   640  			checkErr = errors.Trace(err1)
   641  			return
   642  		}
   643  		mu.Lock()
   644  		checkErr = checkCancelState(txn, job, test)
   645  		mu.Unlock()
   646  		if checkErr != nil {
   647  			return
   648  		}
   649  		err1 = txn.Commit(context.Background())
   650  		if err1 != nil {
   651  			checkErr = errors.Trace(err1)
   652  			return
   653  		}
   654  	}
   655  	tc.onJobUFIDelated = hookCancelFunc
   656  	tc.onJobRunBefore = hookCancelFunc
   657  	d.SetHook(tc)
   658  
   659  	// for adding index
   660  	uFIDelateTest(&tests[0])
   661  	idxOrigName := "idx"
   662  	validArgs := []interface{}{false, perceptron.NewCIStr(idxOrigName),
   663  		[]*ast.IndexPartSpecification{{
   664  			DeferredCauset: &ast.DeferredCausetName{Name: perceptron.NewCIStr("c1")},
   665  			Length:         -1,
   666  		}}, nil}
   667  
   668  	// When the job satisfies this test case, the option will be rollback, so the job's schemaReplicant state is none.
   669  	cancelState := perceptron.StateNone
   670  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddIndex, validArgs, &cancelState)
   671  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   672  	s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, false)
   673  	uFIDelateTest(&tests[1])
   674  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddIndex, validArgs, &cancelState)
   675  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   676  	s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, false)
   677  	uFIDelateTest(&tests[2])
   678  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddIndex, validArgs, &cancelState)
   679  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   680  	s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, false)
   681  	uFIDelateTest(&tests[3])
   682  	testCreateIndex(c, ctx, d, dbInfo, tblInfo, false, "idx", "c2")
   683  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   684  	txn, err = ctx.Txn(true)
   685  	c.Assert(err, IsNil)
   686  	c.Assert(txn.Commit(context.Background()), IsNil)
   687  	s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, true)
   688  
   689  	// for add defCausumn
   690  	uFIDelateTest(&tests[4])
   691  	addingDefCausName := "defCausA"
   692  	newDeferredCausetDef := &ast.DeferredCausetDef{
   693  		Name:    &ast.DeferredCausetName{Name: perceptron.NewCIStr(addingDefCausName)},
   694  		Tp:      &types.FieldType{Tp: allegrosql.TypeLonglong},
   695  		Options: []*ast.DeferredCausetOption{},
   696  	}
   697  	chs, defCausl := charset.GetDefaultCharsetAndDefCauslate()
   698  	defCaus, _, err := buildDeferredCausetAndConstraint(ctx, 2, newDeferredCausetDef, nil, chs, defCausl)
   699  	c.Assert(err, IsNil)
   700  
   701  	addDeferredCausetArgs := []interface{}{defCaus, &ast.DeferredCausetPosition{Tp: ast.DeferredCausetPositionNone}, 0}
   702  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddDeferredCauset, addDeferredCausetArgs, &cancelState)
   703  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   704  	s.checkAddDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, []string{addingDefCausName}, false)
   705  
   706  	uFIDelateTest(&tests[5])
   707  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddDeferredCauset, addDeferredCausetArgs, &cancelState)
   708  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   709  	s.checkAddDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, []string{addingDefCausName}, false)
   710  
   711  	uFIDelateTest(&tests[6])
   712  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddDeferredCauset, addDeferredCausetArgs, &cancelState)
   713  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   714  	s.checkAddDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, []string{addingDefCausName}, false)
   715  
   716  	uFIDelateTest(&tests[7])
   717  	testAddDeferredCauset(c, ctx, d, dbInfo, tblInfo, addDeferredCausetArgs)
   718  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   719  	s.checkAddDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, []string{addingDefCausName}, true)
   720  
   721  	// for create causet
   722  	tblInfo1 := testBlockInfo(c, d, "t1", 2)
   723  	uFIDelateTest(&tests[8])
   724  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo1.ID, perceptron.CausetActionCreateBlock, []interface{}{tblInfo1}, &cancelState)
   725  	c.Check(checkErr, IsNil)
   726  	testCheckBlockState(c, d, dbInfo, tblInfo1, perceptron.StateNone)
   727  
   728  	// for create database
   729  	dbInfo1 := testSchemaInfo(c, d, "test_cancel_job1")
   730  	uFIDelateTest(&tests[9])
   731  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo1.ID, 0, perceptron.CausetActionCreateSchema, []interface{}{dbInfo1}, &cancelState)
   732  	c.Check(checkErr, IsNil)
   733  	testCheckSchemaState(c, d, dbInfo1, perceptron.StateNone)
   734  
   735  	// for drop defCausumn.
   736  	uFIDelateTest(&tests[10])
   737  	dropDefCausName := "c3"
   738  	s.checkCancelDropDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, []string{dropDefCausName}, false)
   739  	testDropDeferredCauset(c, ctx, d, dbInfo, tblInfo, dropDefCausName, false)
   740  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   741  	s.checkCancelDropDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, []string{dropDefCausName}, true)
   742  
   743  	uFIDelateTest(&tests[11])
   744  	dropDefCausName = "c4"
   745  	s.checkCancelDropDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, []string{dropDefCausName}, false)
   746  	testDropDeferredCauset(c, ctx, d, dbInfo, tblInfo, dropDefCausName, false)
   747  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   748  	s.checkCancelDropDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, []string{dropDefCausName}, true)
   749  
   750  	uFIDelateTest(&tests[12])
   751  	dropDefCausName = "c5"
   752  	s.checkCancelDropDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, []string{dropDefCausName}, false)
   753  	testDropDeferredCauset(c, ctx, d, dbInfo, tblInfo, dropDefCausName, false)
   754  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   755  	s.checkCancelDropDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, []string{dropDefCausName}, true)
   756  
   757  	// cancel rebase auto id
   758  	uFIDelateTest(&tests[13])
   759  	rebaseIDArgs := []interface{}{int64(200)}
   760  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionRebaseAutoID, rebaseIDArgs, &cancelState)
   761  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   762  	changedBlock := testGetBlock(c, d, dbInfo.ID, tblInfo.ID)
   763  	c.Assert(changedBlock.Meta().AutoIncID, Equals, blockAutoID)
   764  
   765  	// cancel shard bits
   766  	uFIDelateTest(&tests[14])
   767  	shardRowIDArgs := []interface{}{uint64(7)}
   768  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionShardRowID, shardRowIDArgs, &cancelState)
   769  	c.Check(checkErr, IsNil)
   770  	changedBlock = testGetBlock(c, d, dbInfo.ID, tblInfo.ID)
   771  	c.Assert(changedBlock.Meta().ShardRowIDBits, Equals, shardRowIDBits)
   772  
   773  	// modify none-state defCausumn
   774  	defCaus.DefaultValue = "1"
   775  	uFIDelateTest(&tests[15])
   776  	modifyDeferredCausetArgs := []interface{}{defCaus, defCaus.Name, &ast.DeferredCausetPosition{}, byte(0)}
   777  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, modifyDeferredCausetArgs, &test.cancelState)
   778  	c.Check(checkErr, IsNil)
   779  	changedBlock = testGetBlock(c, d, dbInfo.ID, tblInfo.ID)
   780  	changedDefCaus := perceptron.FindDeferredCausetInfo(changedBlock.Meta().DeferredCausets, defCaus.Name.L)
   781  	c.Assert(changedDefCaus.DefaultValue, IsNil)
   782  
   783  	// modify delete-only-state defCausumn,
   784  	defCaus.FieldType.Tp = allegrosql.TypeTiny
   785  	defCaus.FieldType.Flen = defCaus.FieldType.Flen - 1
   786  	uFIDelateTest(&tests[16])
   787  	modifyDeferredCausetArgs = []interface{}{defCaus, defCaus.Name, &ast.DeferredCausetPosition{}, byte(0)}
   788  	doDBSJobSuccess(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, modifyDeferredCausetArgs)
   789  	c.Check(checkErr, IsNil)
   790  	changedBlock = testGetBlock(c, d, dbInfo.ID, tblInfo.ID)
   791  	changedDefCaus = perceptron.FindDeferredCausetInfo(changedBlock.Meta().DeferredCausets, defCaus.Name.L)
   792  	c.Assert(changedDefCaus.FieldType.Tp, Equals, allegrosql.TypeTiny)
   793  	c.Assert(changedDefCaus.FieldType.Flen, Equals, defCaus.FieldType.Flen)
   794  	defCaus.FieldType.Flen++
   795  
   796  	// Test add foreign key failed cause by canceled.
   797  	uFIDelateTest(&tests[17])
   798  	addForeignKeyArgs := []interface{}{perceptron.FKInfo{Name: perceptron.NewCIStr("fk1")}}
   799  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, addForeignKeyArgs, &test.cancelState)
   800  	c.Check(checkErr, IsNil)
   801  	changedBlock = testGetBlock(c, d, dbInfo.ID, tblInfo.ID)
   802  	c.Assert(len(changedBlock.Meta().ForeignKeys), Equals, 0)
   803  
   804  	// Test add foreign key successful.
   805  	uFIDelateTest(&tests[18])
   806  	doDBSJobSuccess(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, addForeignKeyArgs)
   807  	c.Check(checkErr, IsNil)
   808  	changedBlock = testGetBlock(c, d, dbInfo.ID, tblInfo.ID)
   809  	c.Assert(len(changedBlock.Meta().ForeignKeys), Equals, 1)
   810  	c.Assert(changedBlock.Meta().ForeignKeys[0].Name, Equals, addForeignKeyArgs[0].(perceptron.FKInfo).Name)
   811  
   812  	// Test drop foreign key failed cause by canceled.
   813  	uFIDelateTest(&tests[19])
   814  	dropForeignKeyArgs := []interface{}{addForeignKeyArgs[0].(perceptron.FKInfo).Name}
   815  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, dropForeignKeyArgs, &test.cancelState)
   816  	c.Check(checkErr, IsNil)
   817  	changedBlock = testGetBlock(c, d, dbInfo.ID, tblInfo.ID)
   818  	c.Assert(len(changedBlock.Meta().ForeignKeys), Equals, 1)
   819  	c.Assert(changedBlock.Meta().ForeignKeys[0].Name, Equals, dropForeignKeyArgs[0].(perceptron.CIStr))
   820  
   821  	// Test drop foreign key successful.
   822  	uFIDelateTest(&tests[20])
   823  	doDBSJobSuccess(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, dropForeignKeyArgs)
   824  	c.Check(checkErr, IsNil)
   825  	changedBlock = testGetBlock(c, d, dbInfo.ID, tblInfo.ID)
   826  	c.Assert(len(changedBlock.Meta().ForeignKeys), Equals, 0)
   827  
   828  	// test rename causet failed caused by canceled.
   829  	test = &tests[21]
   830  	renameBlockArgs := []interface{}{dbInfo.ID, perceptron.NewCIStr("t2")}
   831  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, renameBlockArgs, &test.cancelState)
   832  	c.Check(checkErr, IsNil)
   833  	changedBlock = testGetBlock(c, d, dbInfo.ID, tblInfo.ID)
   834  	c.Assert(changedBlock.Meta().Name.L, Equals, "t")
   835  
   836  	// test rename causet successful.
   837  	test = &tests[22]
   838  	doDBSJobSuccess(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, renameBlockArgs)
   839  	c.Check(checkErr, IsNil)
   840  	changedBlock = testGetBlock(c, d, dbInfo.ID, tblInfo.ID)
   841  	c.Assert(changedBlock.Meta().Name.L, Equals, "t2")
   842  
   843  	// test modify causet charset failed caused by canceled.
   844  	test = &tests[23]
   845  	modifyBlockCharsetArgs := []interface{}{"utf8mb4", "utf8mb4_bin"}
   846  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, modifyBlockCharsetArgs, &test.cancelState)
   847  	c.Check(checkErr, IsNil)
   848  	changedBlock = testGetBlock(c, d, dbInfo.ID, tblInfo.ID)
   849  	c.Assert(changedBlock.Meta().Charset, Equals, "utf8")
   850  	c.Assert(changedBlock.Meta().DefCauslate, Equals, "utf8_bin")
   851  
   852  	// test modify causet charset successfully.
   853  	test = &tests[24]
   854  	doDBSJobSuccess(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, modifyBlockCharsetArgs)
   855  	c.Check(checkErr, IsNil)
   856  	changedBlock = testGetBlock(c, d, dbInfo.ID, tblInfo.ID)
   857  	c.Assert(changedBlock.Meta().Charset, Equals, "utf8mb4")
   858  	c.Assert(changedBlock.Meta().DefCauslate, Equals, "utf8mb4_bin")
   859  
   860  	// test truncate causet partition failed caused by canceled.
   861  	test = &tests[25]
   862  	truncateTblPartitionArgs := []interface{}{[]int64{partitionTblInfo.Partition.Definitions[0].ID}}
   863  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, partitionTblInfo.ID, test.act, truncateTblPartitionArgs, &test.cancelState)
   864  	c.Check(checkErr, IsNil)
   865  	changedBlock = testGetBlock(c, d, dbInfo.ID, partitionTblInfo.ID)
   866  	c.Assert(changedBlock.Meta().Partition.Definitions[0].ID == partitionTblInfo.Partition.Definitions[0].ID, IsTrue)
   867  
   868  	// test truncate causet partition charset successfully.
   869  	test = &tests[26]
   870  	doDBSJobSuccess(ctx, d, c, dbInfo.ID, partitionTblInfo.ID, test.act, truncateTblPartitionArgs)
   871  	c.Check(checkErr, IsNil)
   872  	changedBlock = testGetBlock(c, d, dbInfo.ID, partitionTblInfo.ID)
   873  	c.Assert(changedBlock.Meta().Partition.Definitions[0].ID == partitionTblInfo.Partition.Definitions[0].ID, IsFalse)
   874  
   875  	// test modify schemaReplicant charset failed caused by canceled.
   876  	test = &tests[27]
   877  	charsetAndDefCauslate := []interface{}{"utf8mb4", "utf8mb4_bin"}
   878  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, charsetAndDefCauslate, &test.cancelState)
   879  	c.Check(checkErr, IsNil)
   880  	dbInfo, err = testGetSchemaInfoWithError(d, dbInfo.ID)
   881  	c.Assert(err, IsNil)
   882  	c.Assert(dbInfo.Charset, Equals, "")
   883  	c.Assert(dbInfo.DefCauslate, Equals, "")
   884  
   885  	// test modify causet charset successfully.
   886  	test = &tests[28]
   887  	doDBSJobSuccess(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, charsetAndDefCauslate)
   888  	c.Check(checkErr, IsNil)
   889  	dbInfo, err = testGetSchemaInfoWithError(d, dbInfo.ID)
   890  	c.Assert(err, IsNil)
   891  	c.Assert(dbInfo.Charset, Equals, "utf8mb4")
   892  	c.Assert(dbInfo.DefCauslate, Equals, "utf8mb4_bin")
   893  
   894  	// for adding primary key
   895  	tblInfo = changedBlock.Meta()
   896  	uFIDelateTest(&tests[29])
   897  	idxOrigName = "primary"
   898  	validArgs = []interface{}{false, perceptron.NewCIStr(idxOrigName),
   899  		[]*ast.IndexPartSpecification{{
   900  			DeferredCauset: &ast.DeferredCausetName{Name: perceptron.NewCIStr("c1")},
   901  			Length:         -1,
   902  		}}, nil}
   903  	cancelState = perceptron.StateNone
   904  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddPrimaryKey, validArgs, &cancelState)
   905  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   906  	s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, false)
   907  	uFIDelateTest(&tests[30])
   908  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddPrimaryKey, validArgs, &cancelState)
   909  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   910  	s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, false)
   911  	uFIDelateTest(&tests[31])
   912  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddPrimaryKey, validArgs, &cancelState)
   913  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   914  	s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, false)
   915  	uFIDelateTest(&tests[32])
   916  	testCreatePrimaryKey(c, ctx, d, dbInfo, tblInfo, "c1")
   917  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   918  	txn, err = ctx.Txn(true)
   919  	c.Assert(err, IsNil)
   920  	c.Assert(txn.Commit(context.Background()), IsNil)
   921  	s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, true)
   922  
   923  	// for dropping primary key
   924  	uFIDelateTest(&tests[33])
   925  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionDropPrimaryKey, validArgs, &cancelState)
   926  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   927  	s.checkDropIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, false)
   928  	uFIDelateTest(&tests[34])
   929  	testDropIndex(c, ctx, d, dbInfo, tblInfo, idxOrigName)
   930  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   931  	s.checkDropIdx(c, d, dbInfo.ID, tblInfo.ID, idxOrigName, true)
   932  
   933  	// for add defCausumns
   934  	uFIDelateTest(&tests[35])
   935  	addingDefCausNames := []string{"defCausA", "defCausB", "defCausC", "defCausD", "defCausE", "defCausF"}
   936  	defcaus := make([]*causet.DeferredCauset, len(addingDefCausNames))
   937  	for i, addingDefCausName := range addingDefCausNames {
   938  		newDeferredCausetDef := &ast.DeferredCausetDef{
   939  			Name:    &ast.DeferredCausetName{Name: perceptron.NewCIStr(addingDefCausName)},
   940  			Tp:      &types.FieldType{Tp: allegrosql.TypeLonglong},
   941  			Options: []*ast.DeferredCausetOption{},
   942  		}
   943  		defCaus, _, err := buildDeferredCausetAndConstraint(ctx, 0, newDeferredCausetDef, nil, allegrosql.DefaultCharset, "")
   944  		c.Assert(err, IsNil)
   945  		defcaus[i] = defCaus
   946  	}
   947  	offsets := make([]int, len(defcaus))
   948  	positions := make([]*ast.DeferredCausetPosition, len(defcaus))
   949  	for i := range positions {
   950  		positions[i] = &ast.DeferredCausetPosition{Tp: ast.DeferredCausetPositionNone}
   951  	}
   952  	ifNotExists := make([]bool, len(defcaus))
   953  
   954  	addDeferredCausetArgs = []interface{}{defcaus, positions, offsets, ifNotExists}
   955  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddDeferredCausets, addDeferredCausetArgs, &cancelState)
   956  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   957  	s.checkAddDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, addingDefCausNames, false)
   958  
   959  	uFIDelateTest(&tests[36])
   960  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddDeferredCausets, addDeferredCausetArgs, &cancelState)
   961  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   962  	s.checkAddDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, addingDefCausNames, false)
   963  
   964  	uFIDelateTest(&tests[37])
   965  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, perceptron.CausetActionAddDeferredCausets, addDeferredCausetArgs, &cancelState)
   966  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   967  	s.checkAddDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, addingDefCausNames, false)
   968  
   969  	uFIDelateTest(&tests[38])
   970  	testAddDeferredCausets(c, ctx, d, dbInfo, tblInfo, addDeferredCausetArgs)
   971  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   972  	s.checkAddDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, addingDefCausNames, true)
   973  
   974  	// for drop defCausumns
   975  	uFIDelateTest(&tests[39])
   976  	dropDefCausNames := []string{"defCausA", "defCausB"}
   977  	s.checkCancelDropDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, dropDefCausNames, false)
   978  	testDropDeferredCausets(c, ctx, d, dbInfo, tblInfo, dropDefCausNames, false)
   979  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   980  	s.checkCancelDropDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, dropDefCausNames, true)
   981  
   982  	uFIDelateTest(&tests[40])
   983  	dropDefCausNames = []string{"defCausC", "defCausD"}
   984  	s.checkCancelDropDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, dropDefCausNames, false)
   985  	testDropDeferredCausets(c, ctx, d, dbInfo, tblInfo, dropDefCausNames, false)
   986  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   987  	s.checkCancelDropDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, dropDefCausNames, true)
   988  
   989  	uFIDelateTest(&tests[41])
   990  	dropDefCausNames = []string{"defCausE", "defCausF"}
   991  	s.checkCancelDropDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, dropDefCausNames, false)
   992  	testDropDeferredCausets(c, ctx, d, dbInfo, tblInfo, dropDefCausNames, false)
   993  	c.Check(errors.ErrorStack(checkErr), Equals, "")
   994  	s.checkCancelDropDeferredCausets(c, d, dbInfo.ID, tblInfo.ID, dropDefCausNames, true)
   995  
   996  	// test alter index visibility failed caused by canceled.
   997  	indexName := "idx_c3"
   998  	testCreateIndex(c, ctx, d, dbInfo, tblInfo, false, indexName, "c3")
   999  	c.Check(errors.ErrorStack(checkErr), Equals, "")
  1000  	txn, err = ctx.Txn(true)
  1001  	c.Assert(err, IsNil)
  1002  	c.Assert(txn.Commit(context.Background()), IsNil)
  1003  	s.checkAddIdx(c, d, dbInfo.ID, tblInfo.ID, indexName, true)
  1004  
  1005  	uFIDelateTest(&tests[42])
  1006  	alterIndexVisibility := []interface{}{perceptron.NewCIStr(indexName), true}
  1007  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, alterIndexVisibility, &test.cancelState)
  1008  	c.Check(checkErr, IsNil)
  1009  	changedBlock = testGetBlock(c, d, dbInfo.ID, tblInfo.ID)
  1010  	c.Assert(checkIdxVisibility(changedBlock, indexName, false), IsTrue)
  1011  
  1012  	// cancel alter index visibility successfully
  1013  	uFIDelateTest(&tests[43])
  1014  	alterIndexVisibility = []interface{}{perceptron.NewCIStr(indexName), true}
  1015  	doDBSJobSuccess(ctx, d, c, dbInfo.ID, tblInfo.ID, test.act, alterIndexVisibility)
  1016  	c.Check(checkErr, IsNil)
  1017  	changedBlock = testGetBlock(c, d, dbInfo.ID, tblInfo.ID)
  1018  	c.Assert(checkIdxVisibility(changedBlock, indexName, true), IsTrue)
  1019  
  1020  	// test exchange partition failed caused by canceled
  1021  	pt := testBlockInfoWithPartition(c, d, "pt", 5)
  1022  	nt := testBlockInfo(c, d, "nt", 5)
  1023  	testCreateBlock(c, ctx, d, dbInfo, pt)
  1024  	testCreateBlock(c, ctx, d, dbInfo, nt)
  1025  
  1026  	uFIDelateTest(&tests[44])
  1027  	defID := pt.Partition.Definitions[0].ID
  1028  	exchangeBlockPartition := []interface{}{defID, dbInfo.ID, pt.ID, "p0", true}
  1029  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, nt.ID, test.act, exchangeBlockPartition, &test.cancelState)
  1030  	c.Check(checkErr, IsNil)
  1031  	changedNtBlock := testGetBlock(c, d, dbInfo.ID, nt.ID)
  1032  	changedPtBlock := testGetBlock(c, d, dbInfo.ID, pt.ID)
  1033  	c.Assert(changedNtBlock.Meta().ID == nt.ID, IsTrue)
  1034  	c.Assert(changedPtBlock.Meta().Partition.Definitions[0].ID == pt.Partition.Definitions[0].ID, IsTrue)
  1035  
  1036  	// cancel exchange partition successfully
  1037  	uFIDelateTest(&tests[45])
  1038  	doDBSJobSuccess(ctx, d, c, dbInfo.ID, nt.ID, test.act, exchangeBlockPartition)
  1039  	c.Check(checkErr, IsNil)
  1040  	changedNtBlock = testGetBlock(c, d, dbInfo.ID, pt.Partition.Definitions[0].ID)
  1041  	changedPtBlock = testGetBlock(c, d, dbInfo.ID, pt.ID)
  1042  	c.Assert(changedNtBlock.Meta().ID == nt.ID, IsFalse)
  1043  	c.Assert(changedPtBlock.Meta().Partition.Definitions[0].ID == nt.ID, IsTrue)
  1044  
  1045  	// Cancel add causet partition.
  1046  	baseBlockInfo := testBlockInfoWithPartitionLessThan(c, d, "empty_block", 5, "1000")
  1047  	testCreateBlock(c, ctx, d, dbInfo, baseBlockInfo)
  1048  
  1049  	cancelState = perceptron.StateNone
  1050  	uFIDelateTest(&tests[46])
  1051  	addedPartInfo := testAddedNewBlockPartitionInfo(c, d, baseBlockInfo, "p1", "maxvalue")
  1052  	addPartitionArgs := []interface{}{addedPartInfo}
  1053  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, baseBlockInfo.ID, test.act, addPartitionArgs, &cancelState)
  1054  	c.Check(checkErr, IsNil)
  1055  	baseBlock := testGetBlock(c, d, dbInfo.ID, baseBlockInfo.ID)
  1056  	c.Assert(len(baseBlock.Meta().Partition.Definitions), Equals, 1)
  1057  
  1058  	uFIDelateTest(&tests[47])
  1059  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, baseBlockInfo.ID, test.act, addPartitionArgs, &cancelState)
  1060  	c.Check(checkErr, IsNil)
  1061  	baseBlock = testGetBlock(c, d, dbInfo.ID, baseBlockInfo.ID)
  1062  	c.Assert(len(baseBlock.Meta().Partition.Definitions), Equals, 1)
  1063  
  1064  	uFIDelateTest(&tests[48])
  1065  	doDBSJobSuccess(ctx, d, c, dbInfo.ID, baseBlockInfo.ID, test.act, addPartitionArgs)
  1066  	c.Check(checkErr, IsNil)
  1067  	baseBlock = testGetBlock(c, d, dbInfo.ID, baseBlockInfo.ID)
  1068  	c.Assert(len(baseBlock.Meta().Partition.Definitions), Equals, 2)
  1069  	c.Assert(baseBlock.Meta().Partition.Definitions[1].ID, Equals, addedPartInfo.Definitions[0].ID)
  1070  	c.Assert(baseBlock.Meta().Partition.Definitions[1].LessThan[0], Equals, addedPartInfo.Definitions[0].LessThan[0])
  1071  
  1072  	// Cancel modify defCausumn which should reorg the data.
  1073  	c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/dbs/skipMockContextDoInterDirc", `return(true)`), IsNil)
  1074  	baseBlockInfo = testBlockInfoWith2IndexOnFirstDeferredCauset(c, d, "modify-causet", 2)
  1075  	// This will cost 2 global id, one for causet id, the other for the job id.
  1076  	testCreateBlock(c, ctx, d, dbInfo, baseBlockInfo)
  1077  
  1078  	cancelState = perceptron.StateNone
  1079  	newDefCaus := baseBlockInfo.DeferredCausets[0].Clone()
  1080  	// change type from long to tinyint.
  1081  	newDefCaus.FieldType = *types.NewFieldType(allegrosql.TypeTiny)
  1082  	// change from null to not null
  1083  	newDefCaus.FieldType.Flag |= allegrosql.NotNullFlag
  1084  	newDefCaus.FieldType.Flen = 2
  1085  
  1086  	originDefCausName := baseBlockInfo.DeferredCausets[0].Name
  1087  	pos := &ast.DeferredCausetPosition{Tp: ast.DeferredCausetPositionNone}
  1088  
  1089  	uFIDelateTest(&tests[49])
  1090  	modifyDeferredCausetArgs = []interface{}{&newDefCaus, originDefCausName, pos, allegrosql.TypeNull, 0}
  1091  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, baseBlockInfo.ID, test.act, modifyDeferredCausetArgs, &cancelState)
  1092  	c.Check(checkErr, IsNil)
  1093  	baseBlock = testGetBlock(c, d, dbInfo.ID, baseBlockInfo.ID)
  1094  	c.Assert(baseBlock.Meta().DeferredCausets[0].FieldType.Tp, Equals, allegrosql.TypeLong)
  1095  	c.Assert(allegrosql.HasNotNullFlag(baseBlock.Meta().DeferredCausets[0].FieldType.Flag), Equals, false)
  1096  
  1097  	uFIDelateTest(&tests[50])
  1098  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, baseBlockInfo.ID, test.act, modifyDeferredCausetArgs, &cancelState)
  1099  	c.Check(checkErr, IsNil)
  1100  	baseBlock = testGetBlock(c, d, dbInfo.ID, baseBlockInfo.ID)
  1101  	c.Assert(baseBlock.Meta().DeferredCausets[0].FieldType.Tp, Equals, allegrosql.TypeLong)
  1102  	c.Assert(baseBlock.Meta().DeferredCausets[0].FieldType.Flag&allegrosql.NotNullFlag, Equals, uint(0))
  1103  
  1104  	uFIDelateTest(&tests[51])
  1105  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, baseBlockInfo.ID, test.act, modifyDeferredCausetArgs, &cancelState)
  1106  	c.Check(checkErr, IsNil)
  1107  	baseBlock = testGetBlock(c, d, dbInfo.ID, baseBlockInfo.ID)
  1108  	c.Assert(baseBlock.Meta().DeferredCausets[0].FieldType.Tp, Equals, allegrosql.TypeLong)
  1109  	c.Assert(baseBlock.Meta().DeferredCausets[0].FieldType.Flag&allegrosql.NotNullFlag, Equals, uint(0))
  1110  
  1111  	uFIDelateTest(&tests[52])
  1112  	doDBSJobErrWithSchemaState(ctx, d, c, dbInfo.ID, baseBlockInfo.ID, test.act, modifyDeferredCausetArgs, &cancelState)
  1113  	c.Check(checkErr, IsNil)
  1114  	baseBlock = testGetBlock(c, d, dbInfo.ID, baseBlockInfo.ID)
  1115  	c.Assert(baseBlock.Meta().DeferredCausets[0].FieldType.Tp, Equals, allegrosql.TypeLong)
  1116  	c.Assert(baseBlock.Meta().DeferredCausets[0].FieldType.Flag&allegrosql.NotNullFlag, Equals, uint(0))
  1117  
  1118  	uFIDelateTest(&tests[53])
  1119  	doDBSJobSuccess(ctx, d, c, dbInfo.ID, baseBlockInfo.ID, test.act, modifyDeferredCausetArgs)
  1120  	c.Check(checkErr, IsNil)
  1121  	baseBlock = testGetBlock(c, d, dbInfo.ID, baseBlockInfo.ID)
  1122  	c.Assert(baseBlock.Meta().DeferredCausets[0].FieldType.Tp, Equals, allegrosql.TypeTiny)
  1123  	c.Assert(baseBlock.Meta().DeferredCausets[0].FieldType.Flag&allegrosql.NotNullFlag, Equals, uint(1))
  1124  	c.Assert(failpoint.Disable("github.com/whtcorpsinc/milevadb/dbs/skipMockContextDoInterDirc"), IsNil)
  1125  }
  1126  
  1127  func (s *testDBSSuite) TestIgnorableSpec(c *C) {
  1128  	specs := []ast.AlterBlockType{
  1129  		ast.AlterBlockOption,
  1130  		ast.AlterBlockAddDeferredCausets,
  1131  		ast.AlterBlockAddConstraint,
  1132  		ast.AlterBlockDropDeferredCauset,
  1133  		ast.AlterBlockDropPrimaryKey,
  1134  		ast.AlterBlockDropIndex,
  1135  		ast.AlterBlockDropForeignKey,
  1136  		ast.AlterBlockModifyDeferredCauset,
  1137  		ast.AlterBlockChangeDeferredCauset,
  1138  		ast.AlterBlockRenameBlock,
  1139  		ast.AlterBlockAlterDeferredCauset,
  1140  	}
  1141  	for _, spec := range specs {
  1142  		c.Assert(isIgnorableSpec(spec), IsFalse)
  1143  	}
  1144  
  1145  	ignorableSpecs := []ast.AlterBlockType{
  1146  		ast.AlterBlockLock,
  1147  		ast.AlterBlockAlgorithm,
  1148  	}
  1149  	for _, spec := range ignorableSpecs {
  1150  		c.Assert(isIgnorableSpec(spec), IsTrue)
  1151  	}
  1152  }
  1153  
  1154  func (s *testDBSSuite) TestBuildJobDependence(c *C) {
  1155  	causetstore := testCreateStore(c, "test_set_job_relation")
  1156  	defer causetstore.Close()
  1157  
  1158  	// Add some non-add-index jobs.
  1159  	job1 := &perceptron.Job{ID: 1, BlockID: 1, Type: perceptron.CausetActionAddDeferredCauset}
  1160  	job2 := &perceptron.Job{ID: 2, BlockID: 1, Type: perceptron.CausetActionCreateBlock}
  1161  	job3 := &perceptron.Job{ID: 3, BlockID: 2, Type: perceptron.CausetActionDropDeferredCauset}
  1162  	job6 := &perceptron.Job{ID: 6, BlockID: 1, Type: perceptron.CausetActionDropBlock}
  1163  	job7 := &perceptron.Job{ID: 7, BlockID: 2, Type: perceptron.CausetActionModifyDeferredCauset}
  1164  	job9 := &perceptron.Job{ID: 9, SchemaID: 111, Type: perceptron.CausetActionDropSchema}
  1165  	job11 := &perceptron.Job{ID: 11, BlockID: 2, Type: perceptron.CausetActionRenameBlock, Args: []interface{}{int64(111), "old EDB name"}}
  1166  	ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error {
  1167  		t := spacetime.NewMeta(txn)
  1168  		err := t.EnQueueDBSJob(job1)
  1169  		c.Assert(err, IsNil)
  1170  		err = t.EnQueueDBSJob(job2)
  1171  		c.Assert(err, IsNil)
  1172  		err = t.EnQueueDBSJob(job3)
  1173  		c.Assert(err, IsNil)
  1174  		err = t.EnQueueDBSJob(job6)
  1175  		c.Assert(err, IsNil)
  1176  		err = t.EnQueueDBSJob(job7)
  1177  		c.Assert(err, IsNil)
  1178  		err = t.EnQueueDBSJob(job9)
  1179  		c.Assert(err, IsNil)
  1180  		err = t.EnQueueDBSJob(job11)
  1181  		c.Assert(err, IsNil)
  1182  		return nil
  1183  	})
  1184  	job4 := &perceptron.Job{ID: 4, BlockID: 1, Type: perceptron.CausetActionAddIndex}
  1185  	ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error {
  1186  		t := spacetime.NewMeta(txn)
  1187  		err := buildJobDependence(t, job4)
  1188  		c.Assert(err, IsNil)
  1189  		c.Assert(job4.DependencyID, Equals, int64(2))
  1190  		return nil
  1191  	})
  1192  	job5 := &perceptron.Job{ID: 5, BlockID: 2, Type: perceptron.CausetActionAddIndex}
  1193  	ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error {
  1194  		t := spacetime.NewMeta(txn)
  1195  		err := buildJobDependence(t, job5)
  1196  		c.Assert(err, IsNil)
  1197  		c.Assert(job5.DependencyID, Equals, int64(3))
  1198  		return nil
  1199  	})
  1200  	job8 := &perceptron.Job{ID: 8, BlockID: 3, Type: perceptron.CausetActionAddIndex}
  1201  	ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error {
  1202  		t := spacetime.NewMeta(txn)
  1203  		err := buildJobDependence(t, job8)
  1204  		c.Assert(err, IsNil)
  1205  		c.Assert(job8.DependencyID, Equals, int64(0))
  1206  		return nil
  1207  	})
  1208  	job10 := &perceptron.Job{ID: 10, SchemaID: 111, BlockID: 3, Type: perceptron.CausetActionAddIndex}
  1209  	ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error {
  1210  		t := spacetime.NewMeta(txn)
  1211  		err := buildJobDependence(t, job10)
  1212  		c.Assert(err, IsNil)
  1213  		c.Assert(job10.DependencyID, Equals, int64(9))
  1214  		return nil
  1215  	})
  1216  	job12 := &perceptron.Job{ID: 12, SchemaID: 112, BlockID: 2, Type: perceptron.CausetActionAddIndex}
  1217  	ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error {
  1218  		t := spacetime.NewMeta(txn)
  1219  		err := buildJobDependence(t, job12)
  1220  		c.Assert(err, IsNil)
  1221  		c.Assert(job12.DependencyID, Equals, int64(11))
  1222  		return nil
  1223  	})
  1224  }
  1225  
  1226  func addDBSJob(c *C, d *dbs, job *perceptron.Job) {
  1227  	task := &limitJobTask{job, make(chan error)}
  1228  	d.limitJobCh <- task
  1229  	err := <-task.err
  1230  	c.Assert(err, IsNil)
  1231  }
  1232  
  1233  func (s *testDBSSuite) TestParallelDBS(c *C) {
  1234  	causetstore := testCreateStore(c, "test_parallel_dbs")
  1235  	defer causetstore.Close()
  1236  	d := testNewDBSAndStart(
  1237  		context.Background(),
  1238  		c,
  1239  		WithStore(causetstore),
  1240  		WithLease(testLease),
  1241  	)
  1242  	defer d.Stop()
  1243  	ctx := testNewContext(d)
  1244  	err := ctx.NewTxn(context.Background())
  1245  	c.Assert(err, IsNil)
  1246  	/*
  1247  		build structure:
  1248  			DBs -> {
  1249  			 db1: test_parallel_dbs_1
  1250  			 db2: test_parallel_dbs_2
  1251  			}
  1252  			Blocks -> {
  1253  			 db1.t1 (c1 int, c2 int)
  1254  			 db1.t2 (c1 int primary key, c2 int, c3 int)
  1255  			 db2.t3 (c1 int, c2 int, c3 int, c4 int)
  1256  			}
  1257  			Data -> {
  1258  			 t1: (10, 10), (20, 20)
  1259  			 t2: (1, 1, 1), (2, 2, 2), (3, 3, 3)
  1260  			 t3: (11, 22, 33, 44)
  1261  			}
  1262  	*/
  1263  	// create database test_parallel_dbs_1;
  1264  	dbInfo1 := testSchemaInfo(c, d, "test_parallel_dbs_1")
  1265  	testCreateSchema(c, ctx, d, dbInfo1)
  1266  	// create causet t1 (c1 int, c2 int);
  1267  	tblInfo1 := testBlockInfo(c, d, "t1", 2)
  1268  	testCreateBlock(c, ctx, d, dbInfo1, tblInfo1)
  1269  	// insert t1 values (10, 10), (20, 20)
  1270  	tbl1 := testGetBlock(c, d, dbInfo1.ID, tblInfo1.ID)
  1271  	_, err = tbl1.AddRecord(ctx, types.MakeCausets(1, 1))
  1272  	c.Assert(err, IsNil)
  1273  	_, err = tbl1.AddRecord(ctx, types.MakeCausets(2, 2))
  1274  	c.Assert(err, IsNil)
  1275  	// create causet t2 (c1 int primary key, c2 int, c3 int);
  1276  	tblInfo2 := testBlockInfo(c, d, "t2", 3)
  1277  	tblInfo2.DeferredCausets[0].Flag = allegrosql.PriKeyFlag | allegrosql.NotNullFlag
  1278  	tblInfo2.PKIsHandle = true
  1279  	testCreateBlock(c, ctx, d, dbInfo1, tblInfo2)
  1280  	// insert t2 values (1, 1), (2, 2), (3, 3)
  1281  	tbl2 := testGetBlock(c, d, dbInfo1.ID, tblInfo2.ID)
  1282  	_, err = tbl2.AddRecord(ctx, types.MakeCausets(1, 1, 1))
  1283  	c.Assert(err, IsNil)
  1284  	_, err = tbl2.AddRecord(ctx, types.MakeCausets(2, 2, 2))
  1285  	c.Assert(err, IsNil)
  1286  	_, err = tbl2.AddRecord(ctx, types.MakeCausets(3, 3, 3))
  1287  	c.Assert(err, IsNil)
  1288  	// create database test_parallel_dbs_2;
  1289  	dbInfo2 := testSchemaInfo(c, d, "test_parallel_dbs_2")
  1290  	testCreateSchema(c, ctx, d, dbInfo2)
  1291  	// create causet t3 (c1 int, c2 int, c3 int, c4 int);
  1292  	tblInfo3 := testBlockInfo(c, d, "t3", 4)
  1293  	testCreateBlock(c, ctx, d, dbInfo2, tblInfo3)
  1294  	// insert t3 values (11, 22, 33, 44)
  1295  	tbl3 := testGetBlock(c, d, dbInfo2.ID, tblInfo3.ID)
  1296  	_, err = tbl3.AddRecord(ctx, types.MakeCausets(11, 22, 33, 44))
  1297  	c.Assert(err, IsNil)
  1298  
  1299  	// set hook to execute jobs after all jobs are in queue.
  1300  	jobCnt := int64(11)
  1301  	tc := &TestDBSCallback{}
  1302  	once := sync.Once{}
  1303  	var checkErr error
  1304  	tc.onJobRunBefore = func(job *perceptron.Job) {
  1305  		// TODO: extract a unified function for other tests.
  1306  		once.Do(func() {
  1307  			qLen1 := int64(0)
  1308  			qLen2 := int64(0)
  1309  			for {
  1310  				checkErr = ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error {
  1311  					m := spacetime.NewMeta(txn)
  1312  					qLen1, err = m.DBSJobQueueLen()
  1313  					if err != nil {
  1314  						return err
  1315  					}
  1316  					qLen2, err = m.DBSJobQueueLen(spacetime.AddIndexJobListKey)
  1317  					if err != nil {
  1318  						return err
  1319  					}
  1320  					return nil
  1321  				})
  1322  				if checkErr != nil {
  1323  					break
  1324  				}
  1325  				if qLen1+qLen2 == jobCnt {
  1326  					if qLen2 != 5 {
  1327  						checkErr = errors.Errorf("add index jobs cnt %v != 5", qLen2)
  1328  					}
  1329  					break
  1330  				}
  1331  				time.Sleep(5 * time.Millisecond)
  1332  			}
  1333  		})
  1334  	}
  1335  	d.SetHook(tc)
  1336  	c.Assert(checkErr, IsNil)
  1337  
  1338  	/*
  1339  		prepare jobs:
  1340  		/	job no.	/	database no.	/	causet no.	/	action type	 /
  1341  		/     1		/	 	1			/		1		/	add index	 /
  1342  		/     2		/	 	1			/		1		/	add defCausumn	 /
  1343  		/     3		/	 	1			/		1		/	add index	 /
  1344  		/     4		/	 	1			/		2		/	drop defCausumn	 /
  1345  		/     5		/	 	1			/		1		/	drop index 	 /
  1346  		/     6		/	 	1			/		2		/	add index	 /
  1347  		/     7		/	 	2			/		3		/	drop defCausumn	 /
  1348  		/     8		/	 	2			/		3		/	rebase autoID/
  1349  		/     9		/	 	1			/		1		/	add index	 /
  1350  		/     10	/	 	2			/		null   	/	drop schemaReplicant  /
  1351  		/     11	/	 	2			/		2		/	add index	 /
  1352  	*/
  1353  	job1 := buildCreateIdxJob(dbInfo1, tblInfo1, false, "db1_idx1", "c1")
  1354  	addDBSJob(c, d, job1)
  1355  	job2 := buildCreateDeferredCausetJob(dbInfo1, tblInfo1, "c3", &ast.DeferredCausetPosition{Tp: ast.DeferredCausetPositionNone}, nil)
  1356  	addDBSJob(c, d, job2)
  1357  	job3 := buildCreateIdxJob(dbInfo1, tblInfo1, false, "db1_idx2", "c3")
  1358  	addDBSJob(c, d, job3)
  1359  	job4 := buildDropDeferredCausetJob(dbInfo1, tblInfo2, "c3")
  1360  	addDBSJob(c, d, job4)
  1361  	job5 := buildDropIdxJob(dbInfo1, tblInfo1, "db1_idx1")
  1362  	addDBSJob(c, d, job5)
  1363  	job6 := buildCreateIdxJob(dbInfo1, tblInfo2, false, "db2_idx1", "c2")
  1364  	addDBSJob(c, d, job6)
  1365  	job7 := buildDropDeferredCausetJob(dbInfo2, tblInfo3, "c4")
  1366  	addDBSJob(c, d, job7)
  1367  	job8 := buildRebaseAutoIDJobJob(dbInfo2, tblInfo3, 1024)
  1368  	addDBSJob(c, d, job8)
  1369  	job9 := buildCreateIdxJob(dbInfo1, tblInfo1, false, "db1_idx3", "c2")
  1370  	addDBSJob(c, d, job9)
  1371  	job10 := buildDropSchemaJob(dbInfo2)
  1372  	addDBSJob(c, d, job10)
  1373  	job11 := buildCreateIdxJob(dbInfo2, tblInfo3, false, "db3_idx1", "c2")
  1374  	addDBSJob(c, d, job11)
  1375  	// TODO: add rename causet job
  1376  
  1377  	// check results.
  1378  	isChecked := false
  1379  	for !isChecked {
  1380  		ekv.RunInNewTxn(causetstore, false, func(txn ekv.Transaction) error {
  1381  			m := spacetime.NewMeta(txn)
  1382  			lastJob, err := m.GetHistoryDBSJob(job11.ID)
  1383  			c.Assert(err, IsNil)
  1384  			// all jobs are finished.
  1385  			if lastJob != nil {
  1386  				finishedJobs, err := m.GetAllHistoryDBSJobs()
  1387  				c.Assert(err, IsNil)
  1388  				// get the last 11 jobs completed.
  1389  				finishedJobs = finishedJobs[len(finishedJobs)-11:]
  1390  				// check some jobs are ordered because of the dependence.
  1391  				c.Assert(finishedJobs[0].ID, Equals, job1.ID)
  1392  				c.Assert(finishedJobs[1].ID, Equals, job2.ID)
  1393  				c.Assert(finishedJobs[2].ID, Equals, job3.ID)
  1394  				c.Assert(finishedJobs[4].ID, Equals, job5.ID)
  1395  				c.Assert(finishedJobs[10].ID, Equals, job11.ID)
  1396  				// check the jobs are ordered in the adding-index-job queue or general-job queue.
  1397  				addIdxJobID := int64(0)
  1398  				generalJobID := int64(0)
  1399  				for _, job := range finishedJobs {
  1400  					// check jobs' order.
  1401  					if job.Type == perceptron.CausetActionAddIndex {
  1402  						c.Assert(job.ID, Greater, addIdxJobID)
  1403  						addIdxJobID = job.ID
  1404  					} else {
  1405  						c.Assert(job.ID, Greater, generalJobID)
  1406  						generalJobID = job.ID
  1407  					}
  1408  					// check jobs' state.
  1409  					if job.ID == lastJob.ID {
  1410  						c.Assert(job.State, Equals, perceptron.JobStateCancelled, Commentf("job: %v", job))
  1411  					} else {
  1412  						c.Assert(job.State, Equals, perceptron.JobStateSynced, Commentf("job: %v", job))
  1413  					}
  1414  				}
  1415  
  1416  				isChecked = true
  1417  			}
  1418  			return nil
  1419  		})
  1420  		time.Sleep(10 * time.Millisecond)
  1421  	}
  1422  
  1423  	tc = &TestDBSCallback{}
  1424  	d.SetHook(tc)
  1425  }
  1426  
  1427  func (s *testDBSSuite) TestDBSPackageInterDircuteALLEGROSQL(c *C) {
  1428  	causetstore := testCreateStore(c, "test_run_sql")
  1429  	defer causetstore.Close()
  1430  
  1431  	d := testNewDBSAndStart(
  1432  		context.Background(),
  1433  		c,
  1434  		WithStore(causetstore),
  1435  		WithLease(testLease),
  1436  	)
  1437  	testCheckTenant(c, d, true)
  1438  	defer d.Stop()
  1439  	worker := d.generalWorker()
  1440  	c.Assert(worker, NotNil)
  1441  
  1442  	// In test environment, worker.ctxPool will be nil, and get will return mock.Context.
  1443  	// We just test that can use it to call sqlexec.ALLEGROSQLInterlockingDirectorate.InterDircute.
  1444  	sess, err := worker.sessPool.get()
  1445  	c.Assert(err, IsNil)
  1446  	defer worker.sessPool.put(sess)
  1447  	se := sess.(sqlexec.ALLEGROSQLInterlockingDirectorate)
  1448  	_, _ = se.InterDircute(context.Background(), "create causet t(a int);")
  1449  }