github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/defcaus_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  	"reflect"
    19  	"sync"
    20  
    21  	"github.com/whtcorpsinc/BerolinaSQL"
    22  	"github.com/whtcorpsinc/BerolinaSQL/allegrosql"
    23  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    24  	"github.com/whtcorpsinc/BerolinaSQL/charset"
    25  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    26  	"github.com/whtcorpsinc/BerolinaSQL/terror"
    27  	. "github.com/whtcorpsinc/check"
    28  	"github.com/whtcorpsinc/errors"
    29  	"github.com/whtcorpsinc/milevadb/blockcodec"
    30  	"github.com/whtcorpsinc/milevadb/causet"
    31  	"github.com/whtcorpsinc/milevadb/causet/blocks"
    32  	"github.com/whtcorpsinc/milevadb/ekv"
    33  	"github.com/whtcorpsinc/milevadb/schemareplicant"
    34  	"github.com/whtcorpsinc/milevadb/stochastikctx"
    35  	"github.com/whtcorpsinc/milevadb/types"
    36  )
    37  
    38  var _ = Suite(&testDeferredCausetSuite{})
    39  
    40  type testDeferredCausetSuite struct {
    41  	causetstore ekv.CausetStorage
    42  	dbInfo      *perceptron.DBInfo
    43  }
    44  
    45  func (s *testDeferredCausetSuite) SetUpSuite(c *C) {
    46  	s.causetstore = testCreateStore(c, "test_defCausumn")
    47  	d := testNewDBSAndStart(
    48  		context.Background(),
    49  		c,
    50  		WithStore(s.causetstore),
    51  		WithLease(testLease),
    52  	)
    53  
    54  	s.dbInfo = testSchemaInfo(c, d, "test_defCausumn")
    55  	testCreateSchema(c, testNewContext(d), d, s.dbInfo)
    56  	d.Stop()
    57  }
    58  
    59  func (s *testDeferredCausetSuite) TearDownSuite(c *C) {
    60  	err := s.causetstore.Close()
    61  	c.Assert(err, IsNil)
    62  }
    63  
    64  func buildCreateDeferredCausetJob(dbInfo *perceptron.DBInfo, tblInfo *perceptron.BlockInfo, defCausName string,
    65  	pos *ast.DeferredCausetPosition, defaultValue interface{}) *perceptron.Job {
    66  	defCaus := &perceptron.DeferredCausetInfo{
    67  		Name:               perceptron.NewCIStr(defCausName),
    68  		Offset:             len(tblInfo.DeferredCausets),
    69  		DefaultValue:       defaultValue,
    70  		OriginDefaultValue: defaultValue,
    71  	}
    72  	defCaus.ID = allocateDeferredCausetID(tblInfo)
    73  	defCaus.FieldType = *types.NewFieldType(allegrosql.TypeLong)
    74  
    75  	job := &perceptron.Job{
    76  		SchemaID:   dbInfo.ID,
    77  		BlockID:    tblInfo.ID,
    78  		Type:       perceptron.CausetActionAddDeferredCauset,
    79  		BinlogInfo: &perceptron.HistoryInfo{},
    80  		Args:       []interface{}{defCaus, pos, 0},
    81  	}
    82  	return job
    83  }
    84  
    85  func testCreateDeferredCauset(c *C, ctx stochastikctx.Context, d *dbs, dbInfo *perceptron.DBInfo, tblInfo *perceptron.BlockInfo,
    86  	defCausName string, pos *ast.DeferredCausetPosition, defaultValue interface{}) *perceptron.Job {
    87  	job := buildCreateDeferredCausetJob(dbInfo, tblInfo, defCausName, pos, defaultValue)
    88  	err := d.doDBSJob(ctx, job)
    89  	c.Assert(err, IsNil)
    90  	v := getSchemaVer(c, ctx)
    91  	checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo})
    92  	return job
    93  }
    94  
    95  func buildCreateDeferredCausetsJob(dbInfo *perceptron.DBInfo, tblInfo *perceptron.BlockInfo, defCausNames []string,
    96  	positions []*ast.DeferredCausetPosition, defaultValue interface{}) *perceptron.Job {
    97  	defCausInfos := make([]*perceptron.DeferredCausetInfo, len(defCausNames))
    98  	offsets := make([]int, len(defCausNames))
    99  	ifNotExists := make([]bool, len(defCausNames))
   100  	for i, defCausName := range defCausNames {
   101  		defCaus := &perceptron.DeferredCausetInfo{
   102  			Name:               perceptron.NewCIStr(defCausName),
   103  			Offset:             len(tblInfo.DeferredCausets),
   104  			DefaultValue:       defaultValue,
   105  			OriginDefaultValue: defaultValue,
   106  		}
   107  		defCaus.ID = allocateDeferredCausetID(tblInfo)
   108  		defCaus.FieldType = *types.NewFieldType(allegrosql.TypeLong)
   109  		defCausInfos[i] = defCaus
   110  	}
   111  
   112  	job := &perceptron.Job{
   113  		SchemaID:   dbInfo.ID,
   114  		BlockID:    tblInfo.ID,
   115  		Type:       perceptron.CausetActionAddDeferredCausets,
   116  		BinlogInfo: &perceptron.HistoryInfo{},
   117  		Args:       []interface{}{defCausInfos, positions, offsets, ifNotExists},
   118  	}
   119  	return job
   120  }
   121  
   122  func testCreateDeferredCausets(c *C, ctx stochastikctx.Context, d *dbs, dbInfo *perceptron.DBInfo, tblInfo *perceptron.BlockInfo,
   123  	defCausNames []string, positions []*ast.DeferredCausetPosition, defaultValue interface{}) *perceptron.Job {
   124  	job := buildCreateDeferredCausetsJob(dbInfo, tblInfo, defCausNames, positions, defaultValue)
   125  	err := d.doDBSJob(ctx, job)
   126  	c.Assert(err, IsNil)
   127  	v := getSchemaVer(c, ctx)
   128  	checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo})
   129  	return job
   130  }
   131  
   132  func buildDropDeferredCausetJob(dbInfo *perceptron.DBInfo, tblInfo *perceptron.BlockInfo, defCausName string) *perceptron.Job {
   133  	return &perceptron.Job{
   134  		SchemaID:   dbInfo.ID,
   135  		BlockID:    tblInfo.ID,
   136  		Type:       perceptron.CausetActionDropDeferredCauset,
   137  		BinlogInfo: &perceptron.HistoryInfo{},
   138  		Args:       []interface{}{perceptron.NewCIStr(defCausName)},
   139  	}
   140  }
   141  
   142  func testDropDeferredCauset(c *C, ctx stochastikctx.Context, d *dbs, dbInfo *perceptron.DBInfo, tblInfo *perceptron.BlockInfo, defCausName string, isError bool) *perceptron.Job {
   143  	job := buildDropDeferredCausetJob(dbInfo, tblInfo, defCausName)
   144  	err := d.doDBSJob(ctx, job)
   145  	if isError {
   146  		c.Assert(err, NotNil)
   147  		return nil
   148  	}
   149  	c.Assert(errors.ErrorStack(err), Equals, "")
   150  	v := getSchemaVer(c, ctx)
   151  	checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo})
   152  	return job
   153  }
   154  
   155  func buildDropDeferredCausetsJob(dbInfo *perceptron.DBInfo, tblInfo *perceptron.BlockInfo, defCausNames []string) *perceptron.Job {
   156  	defCausumnNames := make([]perceptron.CIStr, len(defCausNames))
   157  	ifExists := make([]bool, len(defCausNames))
   158  	for i, defCausName := range defCausNames {
   159  		defCausumnNames[i] = perceptron.NewCIStr(defCausName)
   160  	}
   161  	job := &perceptron.Job{
   162  		SchemaID:   dbInfo.ID,
   163  		BlockID:    tblInfo.ID,
   164  		Type:       perceptron.CausetActionDropDeferredCausets,
   165  		BinlogInfo: &perceptron.HistoryInfo{},
   166  		Args:       []interface{}{defCausumnNames, ifExists},
   167  	}
   168  	return job
   169  }
   170  
   171  func testDropDeferredCausets(c *C, ctx stochastikctx.Context, d *dbs, dbInfo *perceptron.DBInfo, tblInfo *perceptron.BlockInfo, defCausNames []string, isError bool) *perceptron.Job {
   172  	job := buildDropDeferredCausetsJob(dbInfo, tblInfo, defCausNames)
   173  	err := d.doDBSJob(ctx, job)
   174  	if isError {
   175  		c.Assert(err, NotNil)
   176  		return nil
   177  	}
   178  	c.Assert(errors.ErrorStack(err), Equals, "")
   179  	v := getSchemaVer(c, ctx)
   180  	checkHistoryJobArgs(c, ctx, job.ID, &historyJobArgs{ver: v, tbl: tblInfo})
   181  	return job
   182  }
   183  
   184  func (s *testDeferredCausetSuite) TestDeferredCauset(c *C) {
   185  	d := testNewDBSAndStart(
   186  		context.Background(),
   187  		c,
   188  		WithStore(s.causetstore),
   189  		WithLease(testLease),
   190  	)
   191  	defer d.Stop()
   192  
   193  	tblInfo := testBlockInfo(c, d, "t1", 3)
   194  	ctx := testNewContext(d)
   195  
   196  	testCreateBlock(c, ctx, d, s.dbInfo, tblInfo)
   197  	t := testGetBlock(c, d, s.dbInfo.ID, tblInfo.ID)
   198  
   199  	num := 10
   200  	for i := 0; i < num; i++ {
   201  		_, err := t.AddRecord(ctx, types.MakeCausets(i, 10*i, 100*i))
   202  		c.Assert(err, IsNil)
   203  	}
   204  
   205  	err := ctx.NewTxn(context.Background())
   206  	c.Assert(err, IsNil)
   207  
   208  	i := int64(0)
   209  	err = t.IterRecords(ctx, t.FirstKey(), t.DefCauss(), func(_ ekv.Handle, data []types.Causet, defcaus []*causet.DeferredCauset) (bool, error) {
   210  		c.Assert(data, HasLen, 3)
   211  		c.Assert(data[0].GetInt64(), Equals, i)
   212  		c.Assert(data[1].GetInt64(), Equals, 10*i)
   213  		c.Assert(data[2].GetInt64(), Equals, 100*i)
   214  		i++
   215  		return true, nil
   216  	})
   217  	c.Assert(err, IsNil)
   218  	c.Assert(i, Equals, int64(num))
   219  
   220  	c.Assert(causet.FindDefCaus(t.DefCauss(), "c4"), IsNil)
   221  
   222  	job := testCreateDeferredCauset(c, ctx, d, s.dbInfo, tblInfo, "c4", &ast.DeferredCausetPosition{Tp: ast.DeferredCausetPositionAfter, RelativeDeferredCauset: &ast.DeferredCausetName{Name: perceptron.NewCIStr("c3")}}, 100)
   223  	testCheckJobDone(c, d, job, true)
   224  
   225  	t = testGetBlock(c, d, s.dbInfo.ID, tblInfo.ID)
   226  	c.Assert(causet.FindDefCaus(t.DefCauss(), "c4"), NotNil)
   227  
   228  	i = int64(0)
   229  	err = t.IterRecords(ctx, t.FirstKey(), t.DefCauss(),
   230  		func(_ ekv.Handle, data []types.Causet, defcaus []*causet.DeferredCauset) (bool, error) {
   231  			c.Assert(data, HasLen, 4)
   232  			c.Assert(data[0].GetInt64(), Equals, i)
   233  			c.Assert(data[1].GetInt64(), Equals, 10*i)
   234  			c.Assert(data[2].GetInt64(), Equals, 100*i)
   235  			c.Assert(data[3].GetInt64(), Equals, int64(100))
   236  			i++
   237  			return true, nil
   238  		})
   239  	c.Assert(err, IsNil)
   240  	c.Assert(i, Equals, int64(num))
   241  
   242  	h, err := t.AddRecord(ctx, types.MakeCausets(11, 12, 13, 14))
   243  	c.Assert(err, IsNil)
   244  	err = ctx.NewTxn(context.Background())
   245  	c.Assert(err, IsNil)
   246  	values, err := t.EventWithDefCauss(ctx, h, t.DefCauss())
   247  	c.Assert(err, IsNil)
   248  
   249  	c.Assert(values, HasLen, 4)
   250  	c.Assert(values[3].GetInt64(), Equals, int64(14))
   251  
   252  	job = testDropDeferredCauset(c, ctx, d, s.dbInfo, tblInfo, "c4", false)
   253  	testCheckJobDone(c, d, job, false)
   254  
   255  	t = testGetBlock(c, d, s.dbInfo.ID, tblInfo.ID)
   256  	values, err = t.EventWithDefCauss(ctx, h, t.DefCauss())
   257  	c.Assert(err, IsNil)
   258  
   259  	c.Assert(values, HasLen, 3)
   260  	c.Assert(values[2].GetInt64(), Equals, int64(13))
   261  
   262  	job = testCreateDeferredCauset(c, ctx, d, s.dbInfo, tblInfo, "c4", &ast.DeferredCausetPosition{Tp: ast.DeferredCausetPositionNone}, 111)
   263  	testCheckJobDone(c, d, job, true)
   264  
   265  	t = testGetBlock(c, d, s.dbInfo.ID, tblInfo.ID)
   266  	values, err = t.EventWithDefCauss(ctx, h, t.DefCauss())
   267  	c.Assert(err, IsNil)
   268  
   269  	c.Assert(values, HasLen, 4)
   270  	c.Assert(values[3].GetInt64(), Equals, int64(111))
   271  
   272  	job = testCreateDeferredCauset(c, ctx, d, s.dbInfo, tblInfo, "c5", &ast.DeferredCausetPosition{Tp: ast.DeferredCausetPositionNone}, 101)
   273  	testCheckJobDone(c, d, job, true)
   274  
   275  	t = testGetBlock(c, d, s.dbInfo.ID, tblInfo.ID)
   276  	values, err = t.EventWithDefCauss(ctx, h, t.DefCauss())
   277  	c.Assert(err, IsNil)
   278  
   279  	c.Assert(values, HasLen, 5)
   280  	c.Assert(values[4].GetInt64(), Equals, int64(101))
   281  
   282  	job = testCreateDeferredCauset(c, ctx, d, s.dbInfo, tblInfo, "c6", &ast.DeferredCausetPosition{Tp: ast.DeferredCausetPositionFirst}, 202)
   283  	testCheckJobDone(c, d, job, true)
   284  
   285  	t = testGetBlock(c, d, s.dbInfo.ID, tblInfo.ID)
   286  	defcaus := t.DefCauss()
   287  	c.Assert(defcaus, HasLen, 6)
   288  	c.Assert(defcaus[0].Offset, Equals, 0)
   289  	c.Assert(defcaus[0].Name.L, Equals, "c6")
   290  	c.Assert(defcaus[1].Offset, Equals, 1)
   291  	c.Assert(defcaus[1].Name.L, Equals, "c1")
   292  	c.Assert(defcaus[2].Offset, Equals, 2)
   293  	c.Assert(defcaus[2].Name.L, Equals, "c2")
   294  	c.Assert(defcaus[3].Offset, Equals, 3)
   295  	c.Assert(defcaus[3].Name.L, Equals, "c3")
   296  	c.Assert(defcaus[4].Offset, Equals, 4)
   297  	c.Assert(defcaus[4].Name.L, Equals, "c4")
   298  	c.Assert(defcaus[5].Offset, Equals, 5)
   299  	c.Assert(defcaus[5].Name.L, Equals, "c5")
   300  
   301  	values, err = t.EventWithDefCauss(ctx, h, defcaus)
   302  	c.Assert(err, IsNil)
   303  
   304  	c.Assert(values, HasLen, 6)
   305  	c.Assert(values[0].GetInt64(), Equals, int64(202))
   306  	c.Assert(values[5].GetInt64(), Equals, int64(101))
   307  
   308  	job = testDropDeferredCauset(c, ctx, d, s.dbInfo, tblInfo, "c2", false)
   309  	testCheckJobDone(c, d, job, false)
   310  
   311  	t = testGetBlock(c, d, s.dbInfo.ID, tblInfo.ID)
   312  
   313  	values, err = t.EventWithDefCauss(ctx, h, t.DefCauss())
   314  	c.Assert(err, IsNil)
   315  	c.Assert(values, HasLen, 5)
   316  	c.Assert(values[0].GetInt64(), Equals, int64(202))
   317  	c.Assert(values[4].GetInt64(), Equals, int64(101))
   318  
   319  	job = testDropDeferredCauset(c, ctx, d, s.dbInfo, tblInfo, "c1", false)
   320  	testCheckJobDone(c, d, job, false)
   321  
   322  	job = testDropDeferredCauset(c, ctx, d, s.dbInfo, tblInfo, "c3", false)
   323  	testCheckJobDone(c, d, job, false)
   324  
   325  	job = testDropDeferredCauset(c, ctx, d, s.dbInfo, tblInfo, "c4", false)
   326  	testCheckJobDone(c, d, job, false)
   327  
   328  	job = testCreateIndex(c, ctx, d, s.dbInfo, tblInfo, false, "c5_idx", "c5")
   329  	testCheckJobDone(c, d, job, true)
   330  
   331  	job = testDropDeferredCauset(c, ctx, d, s.dbInfo, tblInfo, "c5", false)
   332  	testCheckJobDone(c, d, job, false)
   333  
   334  	testDropDeferredCauset(c, ctx, d, s.dbInfo, tblInfo, "c6", true)
   335  
   336  	testDropBlock(c, ctx, d, s.dbInfo, tblInfo)
   337  }
   338  
   339  func (s *testDeferredCausetSuite) checkDeferredCausetKVExist(ctx stochastikctx.Context, t causet.Block, handle ekv.Handle, defCaus *causet.DeferredCauset, defCausumnValue interface{}, isExist bool) error {
   340  	err := ctx.NewTxn(context.Background())
   341  	if err != nil {
   342  		return errors.Trace(err)
   343  	}
   344  	defer func() {
   345  		if txn, err1 := ctx.Txn(true); err1 == nil {
   346  			txn.Commit(context.Background())
   347  		}
   348  	}()
   349  	key := t.RecordKey(handle)
   350  	txn, err := ctx.Txn(true)
   351  	if err != nil {
   352  		return errors.Trace(err)
   353  	}
   354  	data, err := txn.Get(context.TODO(), key)
   355  	if !isExist {
   356  		if terror.ErrorEqual(err, ekv.ErrNotExist) {
   357  			return nil
   358  		}
   359  	}
   360  	if err != nil {
   361  		return errors.Trace(err)
   362  	}
   363  	defCausMap := make(map[int64]*types.FieldType)
   364  	defCausMap[defCaus.ID] = &defCaus.FieldType
   365  	rowMap, err := blockcodec.DecodeEventToCausetMap(data, defCausMap, ctx.GetStochastikVars().Location())
   366  	if err != nil {
   367  		return errors.Trace(err)
   368  	}
   369  	val, ok := rowMap[defCaus.ID]
   370  	if isExist {
   371  		if !ok || val.GetValue() != defCausumnValue {
   372  			return errors.Errorf("%v is not equal to %v", val.GetValue(), defCausumnValue)
   373  		}
   374  	} else {
   375  		if ok {
   376  			return errors.Errorf("defCausumn value should not exists")
   377  		}
   378  	}
   379  	return nil
   380  }
   381  
   382  func (s *testDeferredCausetSuite) checkNoneDeferredCauset(ctx stochastikctx.Context, d *dbs, tblInfo *perceptron.BlockInfo, handle ekv.Handle, defCaus *causet.DeferredCauset, defCausumnValue interface{}) error {
   383  	t, err := testGetBlockWithError(d, s.dbInfo.ID, tblInfo.ID)
   384  	if err != nil {
   385  		return errors.Trace(err)
   386  	}
   387  	err = s.checkDeferredCausetKVExist(ctx, t, handle, defCaus, defCausumnValue, false)
   388  	if err != nil {
   389  		return errors.Trace(err)
   390  	}
   391  	err = s.testGetDeferredCauset(t, defCaus.Name.L, false)
   392  	if err != nil {
   393  		return errors.Trace(err)
   394  	}
   395  	return nil
   396  }
   397  
   398  func (s *testDeferredCausetSuite) checkDeleteOnlyDeferredCauset(ctx stochastikctx.Context, d *dbs, tblInfo *perceptron.BlockInfo, handle ekv.Handle, defCaus *causet.DeferredCauset, event []types.Causet, defCausumnValue interface{}) error {
   399  	t, err := testGetBlockWithError(d, s.dbInfo.ID, tblInfo.ID)
   400  	if err != nil {
   401  		return errors.Trace(err)
   402  	}
   403  	err = ctx.NewTxn(context.Background())
   404  	if err != nil {
   405  		return errors.Trace(err)
   406  	}
   407  	i := int64(0)
   408  	err = t.IterRecords(ctx, t.FirstKey(), t.DefCauss(), func(_ ekv.Handle, data []types.Causet, defcaus []*causet.DeferredCauset) (bool, error) {
   409  		if !reflect.DeepEqual(data, event) {
   410  			return false, errors.Errorf("%v not equal to %v", data, event)
   411  		}
   412  		i++
   413  		return true, nil
   414  	})
   415  	if err != nil {
   416  		return errors.Trace(err)
   417  	}
   418  	if i != 1 {
   419  		return errors.Errorf("expect 1, got %v", i)
   420  	}
   421  	err = s.checkDeferredCausetKVExist(ctx, t, handle, defCaus, defCausumnValue, false)
   422  	if err != nil {
   423  		return errors.Trace(err)
   424  	}
   425  	// Test add a new event.
   426  	err = ctx.NewTxn(context.Background())
   427  	if err != nil {
   428  		return errors.Trace(err)
   429  	}
   430  
   431  	newEvent := types.MakeCausets(int64(11), int64(22), int64(33))
   432  	newHandle, err := t.AddRecord(ctx, newEvent)
   433  	if err != nil {
   434  		return errors.Trace(err)
   435  	}
   436  	err = ctx.NewTxn(context.Background())
   437  	if err != nil {
   438  		return errors.Trace(err)
   439  	}
   440  
   441  	rows := [][]types.Causet{event, newEvent}
   442  
   443  	i = int64(0)
   444  	err = t.IterRecords(ctx, t.FirstKey(), t.DefCauss(), func(_ ekv.Handle, data []types.Causet, defcaus []*causet.DeferredCauset) (bool, error) {
   445  		if !reflect.DeepEqual(data, rows[i]) {
   446  			return false, errors.Errorf("%v not equal to %v", data, rows[i])
   447  		}
   448  		i++
   449  		return true, nil
   450  	})
   451  	if err != nil {
   452  		return errors.Trace(err)
   453  	}
   454  	if i != 2 {
   455  		return errors.Errorf("expect 2, got %v", i)
   456  	}
   457  
   458  	err = s.checkDeferredCausetKVExist(ctx, t, handle, defCaus, defCausumnValue, false)
   459  	if err != nil {
   460  		return errors.Trace(err)
   461  	}
   462  	// Test remove a event.
   463  	err = ctx.NewTxn(context.Background())
   464  	if err != nil {
   465  		return errors.Trace(err)
   466  	}
   467  
   468  	err = t.RemoveRecord(ctx, newHandle, newEvent)
   469  	if err != nil {
   470  		return errors.Trace(err)
   471  	}
   472  	err = ctx.NewTxn(context.Background())
   473  	if err != nil {
   474  		return errors.Trace(err)
   475  	}
   476  	i = int64(0)
   477  	err = t.IterRecords(ctx, t.FirstKey(), t.DefCauss(), func(_ ekv.Handle, data []types.Causet, defcaus []*causet.DeferredCauset) (bool, error) {
   478  		i++
   479  		return true, nil
   480  	})
   481  	if err != nil {
   482  		return errors.Trace(err)
   483  	}
   484  
   485  	if i != 1 {
   486  		return errors.Errorf("expect 1, got %v", i)
   487  	}
   488  	err = s.checkDeferredCausetKVExist(ctx, t, newHandle, defCaus, defCausumnValue, false)
   489  	if err != nil {
   490  		return errors.Trace(err)
   491  	}
   492  	err = s.testGetDeferredCauset(t, defCaus.Name.L, false)
   493  	if err != nil {
   494  		return errors.Trace(err)
   495  	}
   496  	return nil
   497  }
   498  
   499  func (s *testDeferredCausetSuite) checkWriteOnlyDeferredCauset(ctx stochastikctx.Context, d *dbs, tblInfo *perceptron.BlockInfo, handle ekv.Handle, defCaus *causet.DeferredCauset, event []types.Causet, defCausumnValue interface{}) error {
   500  	t, err := testGetBlockWithError(d, s.dbInfo.ID, tblInfo.ID)
   501  	if err != nil {
   502  		return errors.Trace(err)
   503  	}
   504  	err = ctx.NewTxn(context.Background())
   505  	if err != nil {
   506  		return errors.Trace(err)
   507  	}
   508  
   509  	i := int64(0)
   510  	err = t.IterRecords(ctx, t.FirstKey(), t.DefCauss(), func(_ ekv.Handle, data []types.Causet, defcaus []*causet.DeferredCauset) (bool, error) {
   511  		if !reflect.DeepEqual(data, event) {
   512  			return false, errors.Errorf("%v not equal to %v", data, event)
   513  		}
   514  		i++
   515  		return true, nil
   516  	})
   517  	if err != nil {
   518  		return errors.Trace(err)
   519  	}
   520  	if i != 1 {
   521  		return errors.Errorf("expect 1, got %v", i)
   522  	}
   523  
   524  	err = s.checkDeferredCausetKVExist(ctx, t, handle, defCaus, defCausumnValue, false)
   525  	if err != nil {
   526  		return errors.Trace(err)
   527  	}
   528  
   529  	// Test add a new event.
   530  	err = ctx.NewTxn(context.Background())
   531  	if err != nil {
   532  		return errors.Trace(err)
   533  	}
   534  
   535  	newEvent := types.MakeCausets(int64(11), int64(22), int64(33))
   536  	newHandle, err := t.AddRecord(ctx, newEvent)
   537  	if err != nil {
   538  		return errors.Trace(err)
   539  	}
   540  	err = ctx.NewTxn(context.Background())
   541  	if err != nil {
   542  		return errors.Trace(err)
   543  	}
   544  
   545  	rows := [][]types.Causet{event, newEvent}
   546  
   547  	i = int64(0)
   548  	err = t.IterRecords(ctx, t.FirstKey(), t.DefCauss(), func(_ ekv.Handle, data []types.Causet, defcaus []*causet.DeferredCauset) (bool, error) {
   549  		if !reflect.DeepEqual(data, rows[i]) {
   550  			return false, errors.Errorf("%v not equal to %v", data, rows[i])
   551  		}
   552  		i++
   553  		return true, nil
   554  	})
   555  	if err != nil {
   556  		return errors.Trace(err)
   557  	}
   558  	if i != 2 {
   559  		return errors.Errorf("expect 2, got %v", i)
   560  	}
   561  
   562  	err = s.checkDeferredCausetKVExist(ctx, t, newHandle, defCaus, defCausumnValue, true)
   563  	if err != nil {
   564  		return errors.Trace(err)
   565  	}
   566  	// Test remove a event.
   567  	err = ctx.NewTxn(context.Background())
   568  	if err != nil {
   569  		return errors.Trace(err)
   570  	}
   571  
   572  	err = t.RemoveRecord(ctx, newHandle, newEvent)
   573  	if err != nil {
   574  		return errors.Trace(err)
   575  	}
   576  	err = ctx.NewTxn(context.Background())
   577  	if err != nil {
   578  		return errors.Trace(err)
   579  	}
   580  
   581  	i = int64(0)
   582  	err = t.IterRecords(ctx, t.FirstKey(), t.DefCauss(), func(_ ekv.Handle, data []types.Causet, defcaus []*causet.DeferredCauset) (bool, error) {
   583  		i++
   584  		return true, nil
   585  	})
   586  	if err != nil {
   587  		return errors.Trace(err)
   588  	}
   589  	if i != 1 {
   590  		return errors.Errorf("expect 1, got %v", i)
   591  	}
   592  
   593  	err = s.checkDeferredCausetKVExist(ctx, t, newHandle, defCaus, defCausumnValue, false)
   594  	if err != nil {
   595  		return errors.Trace(err)
   596  	}
   597  	err = s.testGetDeferredCauset(t, defCaus.Name.L, false)
   598  	if err != nil {
   599  		return errors.Trace(err)
   600  	}
   601  	return nil
   602  }
   603  
   604  func (s *testDeferredCausetSuite) checkReorganizationDeferredCauset(ctx stochastikctx.Context, d *dbs, tblInfo *perceptron.BlockInfo, defCaus *causet.DeferredCauset, event []types.Causet, defCausumnValue interface{}) error {
   605  	t, err := testGetBlockWithError(d, s.dbInfo.ID, tblInfo.ID)
   606  	if err != nil {
   607  		return errors.Trace(err)
   608  	}
   609  	err = ctx.NewTxn(context.Background())
   610  	if err != nil {
   611  		return errors.Trace(err)
   612  	}
   613  
   614  	i := int64(0)
   615  	err = t.IterRecords(ctx, t.FirstKey(), t.DefCauss(), func(_ ekv.Handle, data []types.Causet, defcaus []*causet.DeferredCauset) (bool, error) {
   616  		if !reflect.DeepEqual(data, event) {
   617  			return false, errors.Errorf("%v not equal to %v", data, event)
   618  		}
   619  		i++
   620  		return true, nil
   621  	})
   622  	if err != nil {
   623  		return errors.Trace(err)
   624  	}
   625  	if i != 1 {
   626  		return errors.Errorf("expect 1 got %v", i)
   627  	}
   628  
   629  	// Test add a new event.
   630  	err = ctx.NewTxn(context.Background())
   631  	if err != nil {
   632  		return errors.Trace(err)
   633  	}
   634  
   635  	newEvent := types.MakeCausets(int64(11), int64(22), int64(33))
   636  	newHandle, err := t.AddRecord(ctx, newEvent)
   637  	if err != nil {
   638  		return errors.Trace(err)
   639  	}
   640  	err = ctx.NewTxn(context.Background())
   641  	if err != nil {
   642  		return errors.Trace(err)
   643  	}
   644  
   645  	rows := [][]types.Causet{event, newEvent}
   646  
   647  	i = int64(0)
   648  	err = t.IterRecords(ctx, t.FirstKey(), t.DefCauss(), func(_ ekv.Handle, data []types.Causet, defcaus []*causet.DeferredCauset) (bool, error) {
   649  		if !reflect.DeepEqual(data, rows[i]) {
   650  			return false, errors.Errorf("%v not equal to %v", data, rows[i])
   651  		}
   652  		i++
   653  		return true, nil
   654  	})
   655  	if err != nil {
   656  		return errors.Trace(err)
   657  	}
   658  	if i != 2 {
   659  		return errors.Errorf("expect 2, got %v", i)
   660  	}
   661  
   662  	err = s.checkDeferredCausetKVExist(ctx, t, newHandle, defCaus, defCausumnValue, true)
   663  	if err != nil {
   664  		return errors.Trace(err)
   665  	}
   666  
   667  	// Test remove a event.
   668  	err = ctx.NewTxn(context.Background())
   669  	if err != nil {
   670  		return errors.Trace(err)
   671  	}
   672  
   673  	err = t.RemoveRecord(ctx, newHandle, newEvent)
   674  	if err != nil {
   675  		return errors.Trace(err)
   676  	}
   677  	err = ctx.NewTxn(context.Background())
   678  	if err != nil {
   679  		return errors.Trace(err)
   680  	}
   681  
   682  	i = int64(0)
   683  	err = t.IterRecords(ctx, t.FirstKey(), t.DefCauss(), func(_ ekv.Handle, data []types.Causet, defcaus []*causet.DeferredCauset) (bool, error) {
   684  		i++
   685  		return true, nil
   686  	})
   687  	if err != nil {
   688  		return errors.Trace(err)
   689  	}
   690  	if i != 1 {
   691  		return errors.Errorf("expect 1, got %v", i)
   692  	}
   693  	err = s.testGetDeferredCauset(t, defCaus.Name.L, false)
   694  	if err != nil {
   695  		return errors.Trace(err)
   696  	}
   697  	return nil
   698  }
   699  
   700  func (s *testDeferredCausetSuite) checkPublicDeferredCauset(ctx stochastikctx.Context, d *dbs, tblInfo *perceptron.BlockInfo, newDefCaus *causet.DeferredCauset, oldEvent []types.Causet, defCausumnValue interface{}) error {
   701  	t, err := testGetBlockWithError(d, s.dbInfo.ID, tblInfo.ID)
   702  	if err != nil {
   703  		return errors.Trace(err)
   704  	}
   705  	err = ctx.NewTxn(context.Background())
   706  	if err != nil {
   707  		return errors.Trace(err)
   708  	}
   709  
   710  	i := int64(0)
   711  	uFIDelatedEvent := append(oldEvent, types.NewCauset(defCausumnValue))
   712  	err = t.IterRecords(ctx, t.FirstKey(), t.DefCauss(), func(_ ekv.Handle, data []types.Causet, defcaus []*causet.DeferredCauset) (bool, error) {
   713  		if !reflect.DeepEqual(data, uFIDelatedEvent) {
   714  			return false, errors.Errorf("%v not equal to %v", data, uFIDelatedEvent)
   715  		}
   716  		i++
   717  		return true, nil
   718  	})
   719  	if err != nil {
   720  		return errors.Trace(err)
   721  	}
   722  	if i != 1 {
   723  		return errors.Errorf("expect 1, got %v", i)
   724  	}
   725  
   726  	// Test add a new event.
   727  	err = ctx.NewTxn(context.Background())
   728  	if err != nil {
   729  		return errors.Trace(err)
   730  	}
   731  
   732  	newEvent := types.MakeCausets(int64(11), int64(22), int64(33), int64(44))
   733  	handle, err := t.AddRecord(ctx, newEvent)
   734  	if err != nil {
   735  		return errors.Trace(err)
   736  	}
   737  	err = ctx.NewTxn(context.Background())
   738  	if err != nil {
   739  		return errors.Trace(err)
   740  	}
   741  
   742  	rows := [][]types.Causet{uFIDelatedEvent, newEvent}
   743  
   744  	i = int64(0)
   745  	t.IterRecords(ctx, t.FirstKey(), t.DefCauss(), func(_ ekv.Handle, data []types.Causet, defcaus []*causet.DeferredCauset) (bool, error) {
   746  		if !reflect.DeepEqual(data, rows[i]) {
   747  			return false, errors.Errorf("%v not equal to %v", data, rows[i])
   748  		}
   749  		i++
   750  		return true, nil
   751  	})
   752  	if i != 2 {
   753  		return errors.Errorf("expect 2, got %v", i)
   754  	}
   755  
   756  	// Test remove a event.
   757  	err = ctx.NewTxn(context.Background())
   758  	if err != nil {
   759  		return errors.Trace(err)
   760  	}
   761  
   762  	err = t.RemoveRecord(ctx, handle, newEvent)
   763  	if err != nil {
   764  		return errors.Trace(err)
   765  	}
   766  
   767  	err = ctx.NewTxn(context.Background())
   768  	if err != nil {
   769  		return errors.Trace(err)
   770  	}
   771  
   772  	i = int64(0)
   773  	err = t.IterRecords(ctx, t.FirstKey(), t.DefCauss(), func(_ ekv.Handle, data []types.Causet, defcaus []*causet.DeferredCauset) (bool, error) {
   774  		if !reflect.DeepEqual(data, uFIDelatedEvent) {
   775  			return false, errors.Errorf("%v not equal to %v", data, uFIDelatedEvent)
   776  		}
   777  		i++
   778  		return true, nil
   779  	})
   780  	if err != nil {
   781  		return errors.Trace(err)
   782  	}
   783  	if i != 1 {
   784  		return errors.Errorf("expect 1, got %v", i)
   785  	}
   786  
   787  	err = s.testGetDeferredCauset(t, newDefCaus.Name.L, true)
   788  	if err != nil {
   789  		return errors.Trace(err)
   790  	}
   791  	return nil
   792  }
   793  
   794  func (s *testDeferredCausetSuite) checkAddDeferredCauset(state perceptron.SchemaState, d *dbs, tblInfo *perceptron.BlockInfo, handle ekv.Handle, newDefCaus *causet.DeferredCauset, oldEvent []types.Causet, defCausumnValue interface{}) error {
   795  	ctx := testNewContext(d)
   796  	var err error
   797  	switch state {
   798  	case perceptron.StateNone:
   799  		err = errors.Trace(s.checkNoneDeferredCauset(ctx, d, tblInfo, handle, newDefCaus, defCausumnValue))
   800  	case perceptron.StateDeleteOnly:
   801  		err = errors.Trace(s.checkDeleteOnlyDeferredCauset(ctx, d, tblInfo, handle, newDefCaus, oldEvent, defCausumnValue))
   802  	case perceptron.StateWriteOnly:
   803  		err = errors.Trace(s.checkWriteOnlyDeferredCauset(ctx, d, tblInfo, handle, newDefCaus, oldEvent, defCausumnValue))
   804  	case perceptron.StateWriteReorganization, perceptron.StateDeleteReorganization:
   805  		err = errors.Trace(s.checkReorganizationDeferredCauset(ctx, d, tblInfo, newDefCaus, oldEvent, defCausumnValue))
   806  	case perceptron.StatePublic:
   807  		err = errors.Trace(s.checkPublicDeferredCauset(ctx, d, tblInfo, newDefCaus, oldEvent, defCausumnValue))
   808  	}
   809  	return err
   810  }
   811  
   812  func (s *testDeferredCausetSuite) testGetDeferredCauset(t causet.Block, name string, isExist bool) error {
   813  	defCaus := causet.FindDefCaus(t.DefCauss(), name)
   814  	if isExist {
   815  		if defCaus == nil {
   816  			return errors.Errorf("defCausumn should not be nil")
   817  		}
   818  	} else {
   819  		if defCaus != nil {
   820  			return errors.Errorf("defCausumn should be nil")
   821  		}
   822  	}
   823  	return nil
   824  }
   825  
   826  func (s *testDeferredCausetSuite) TestAddDeferredCauset(c *C) {
   827  	d := testNewDBSAndStart(
   828  		context.Background(),
   829  		c,
   830  		WithStore(s.causetstore),
   831  		WithLease(testLease),
   832  	)
   833  	tblInfo := testBlockInfo(c, d, "t", 3)
   834  	ctx := testNewContext(d)
   835  
   836  	err := ctx.NewTxn(context.Background())
   837  	c.Assert(err, IsNil)
   838  
   839  	testCreateBlock(c, ctx, d, s.dbInfo, tblInfo)
   840  	t := testGetBlock(c, d, s.dbInfo.ID, tblInfo.ID)
   841  
   842  	oldEvent := types.MakeCausets(int64(1), int64(2), int64(3))
   843  	handle, err := t.AddRecord(ctx, oldEvent)
   844  	c.Assert(err, IsNil)
   845  
   846  	txn, err := ctx.Txn(true)
   847  	c.Assert(err, IsNil)
   848  	err = txn.Commit(context.Background())
   849  	c.Assert(err, IsNil)
   850  
   851  	newDefCausName := "c4"
   852  	defaultDefCausValue := int64(4)
   853  
   854  	var mu sync.Mutex
   855  	var hookErr error
   856  	checkOK := false
   857  
   858  	tc := &TestDBSCallback{}
   859  	tc.onJobUFIDelated = func(job *perceptron.Job) {
   860  		mu.Lock()
   861  		defer mu.Unlock()
   862  		if checkOK {
   863  			return
   864  		}
   865  
   866  		t, err1 := testGetBlockWithError(d, s.dbInfo.ID, tblInfo.ID)
   867  		if err1 != nil {
   868  			hookErr = errors.Trace(err1)
   869  			return
   870  		}
   871  		newDefCaus := causet.FindDefCaus(t.(*blocks.BlockCommon).DeferredCausets, newDefCausName)
   872  		if newDefCaus == nil {
   873  			return
   874  		}
   875  
   876  		err1 = s.checkAddDeferredCauset(newDefCaus.State, d, tblInfo, handle, newDefCaus, oldEvent, defaultDefCausValue)
   877  		if err1 != nil {
   878  			hookErr = errors.Trace(err1)
   879  			return
   880  		}
   881  
   882  		if newDefCaus.State == perceptron.StatePublic {
   883  			checkOK = true
   884  		}
   885  	}
   886  
   887  	d.SetHook(tc)
   888  
   889  	job := testCreateDeferredCauset(c, ctx, d, s.dbInfo, tblInfo, newDefCausName, &ast.DeferredCausetPosition{Tp: ast.DeferredCausetPositionNone}, defaultDefCausValue)
   890  
   891  	testCheckJobDone(c, d, job, true)
   892  	mu.Lock()
   893  	hErr := hookErr
   894  	ok := checkOK
   895  	mu.Unlock()
   896  	c.Assert(errors.ErrorStack(hErr), Equals, "")
   897  	c.Assert(ok, IsTrue)
   898  
   899  	err = ctx.NewTxn(context.Background())
   900  	c.Assert(err, IsNil)
   901  
   902  	job = testDropBlock(c, ctx, d, s.dbInfo, tblInfo)
   903  	testCheckJobDone(c, d, job, false)
   904  
   905  	txn, err = ctx.Txn(true)
   906  	c.Assert(err, IsNil)
   907  	err = txn.Commit(context.Background())
   908  	c.Assert(err, IsNil)
   909  
   910  	d.Stop()
   911  }
   912  
   913  func (s *testDeferredCausetSuite) TestAddDeferredCausets(c *C) {
   914  	d := testNewDBSAndStart(
   915  		context.Background(),
   916  		c,
   917  		WithStore(s.causetstore),
   918  		WithLease(testLease),
   919  	)
   920  	tblInfo := testBlockInfo(c, d, "t", 3)
   921  	ctx := testNewContext(d)
   922  
   923  	err := ctx.NewTxn(context.Background())
   924  	c.Assert(err, IsNil)
   925  
   926  	testCreateBlock(c, ctx, d, s.dbInfo, tblInfo)
   927  	t := testGetBlock(c, d, s.dbInfo.ID, tblInfo.ID)
   928  
   929  	oldEvent := types.MakeCausets(int64(1), int64(2), int64(3))
   930  	handle, err := t.AddRecord(ctx, oldEvent)
   931  	c.Assert(err, IsNil)
   932  
   933  	txn, err := ctx.Txn(true)
   934  	c.Assert(err, IsNil)
   935  	err = txn.Commit(context.Background())
   936  	c.Assert(err, IsNil)
   937  
   938  	newDefCausNames := []string{"c4,c5,c6"}
   939  	positions := make([]*ast.DeferredCausetPosition, 3)
   940  	for i := range positions {
   941  		positions[i] = &ast.DeferredCausetPosition{Tp: ast.DeferredCausetPositionNone}
   942  	}
   943  	defaultDefCausValue := int64(4)
   944  
   945  	var mu sync.Mutex
   946  	var hookErr error
   947  	checkOK := false
   948  
   949  	tc := &TestDBSCallback{}
   950  	tc.onJobUFIDelated = func(job *perceptron.Job) {
   951  		mu.Lock()
   952  		defer mu.Unlock()
   953  		if checkOK {
   954  			return
   955  		}
   956  
   957  		t, err1 := testGetBlockWithError(d, s.dbInfo.ID, tblInfo.ID)
   958  		if err1 != nil {
   959  			hookErr = errors.Trace(err1)
   960  			return
   961  		}
   962  		for _, newDefCausName := range newDefCausNames {
   963  			newDefCaus := causet.FindDefCaus(t.(*blocks.BlockCommon).DeferredCausets, newDefCausName)
   964  			if newDefCaus == nil {
   965  				return
   966  			}
   967  
   968  			err1 = s.checkAddDeferredCauset(newDefCaus.State, d, tblInfo, handle, newDefCaus, oldEvent, defaultDefCausValue)
   969  			if err1 != nil {
   970  				hookErr = errors.Trace(err1)
   971  				return
   972  			}
   973  
   974  			if newDefCaus.State == perceptron.StatePublic {
   975  				checkOK = true
   976  			}
   977  		}
   978  	}
   979  
   980  	d.SetHook(tc)
   981  
   982  	job := testCreateDeferredCausets(c, ctx, d, s.dbInfo, tblInfo, newDefCausNames, positions, defaultDefCausValue)
   983  
   984  	testCheckJobDone(c, d, job, true)
   985  	mu.Lock()
   986  	hErr := hookErr
   987  	ok := checkOK
   988  	mu.Unlock()
   989  	c.Assert(errors.ErrorStack(hErr), Equals, "")
   990  	c.Assert(ok, IsTrue)
   991  
   992  	job = testDropBlock(c, ctx, d, s.dbInfo, tblInfo)
   993  	testCheckJobDone(c, d, job, false)
   994  	d.Stop()
   995  }
   996  
   997  func (s *testDeferredCausetSuite) TestDropDeferredCauset(c *C) {
   998  	d := testNewDBSAndStart(
   999  		context.Background(),
  1000  		c,
  1001  		WithStore(s.causetstore),
  1002  		WithLease(testLease),
  1003  	)
  1004  	tblInfo := testBlockInfo(c, d, "t2", 4)
  1005  	ctx := testNewContext(d)
  1006  
  1007  	err := ctx.NewTxn(context.Background())
  1008  	c.Assert(err, IsNil)
  1009  
  1010  	testCreateBlock(c, ctx, d, s.dbInfo, tblInfo)
  1011  	t := testGetBlock(c, d, s.dbInfo.ID, tblInfo.ID)
  1012  
  1013  	defCausName := "c4"
  1014  	defaultDefCausValue := int64(4)
  1015  	event := types.MakeCausets(int64(1), int64(2), int64(3))
  1016  	_, err = t.AddRecord(ctx, append(event, types.NewCauset(defaultDefCausValue)))
  1017  	c.Assert(err, IsNil)
  1018  
  1019  	txn, err := ctx.Txn(true)
  1020  	c.Assert(err, IsNil)
  1021  	err = txn.Commit(context.Background())
  1022  	c.Assert(err, IsNil)
  1023  
  1024  	checkOK := false
  1025  	var hookErr error
  1026  	var mu sync.Mutex
  1027  
  1028  	tc := &TestDBSCallback{}
  1029  	tc.onJobUFIDelated = func(job *perceptron.Job) {
  1030  		mu.Lock()
  1031  		defer mu.Unlock()
  1032  		if checkOK {
  1033  			return
  1034  		}
  1035  		t, err1 := testGetBlockWithError(d, s.dbInfo.ID, tblInfo.ID)
  1036  		if err1 != nil {
  1037  			hookErr = errors.Trace(err1)
  1038  			return
  1039  		}
  1040  		defCaus := causet.FindDefCaus(t.(*blocks.BlockCommon).DeferredCausets, defCausName)
  1041  		if defCaus == nil {
  1042  			checkOK = true
  1043  			return
  1044  		}
  1045  	}
  1046  
  1047  	d.SetHook(tc)
  1048  
  1049  	job := testDropDeferredCauset(c, ctx, d, s.dbInfo, tblInfo, defCausName, false)
  1050  	testCheckJobDone(c, d, job, false)
  1051  	mu.Lock()
  1052  	hErr := hookErr
  1053  	ok := checkOK
  1054  	mu.Unlock()
  1055  	c.Assert(hErr, IsNil)
  1056  	c.Assert(ok, IsTrue)
  1057  
  1058  	err = ctx.NewTxn(context.Background())
  1059  	c.Assert(err, IsNil)
  1060  
  1061  	job = testDropBlock(c, ctx, d, s.dbInfo, tblInfo)
  1062  	testCheckJobDone(c, d, job, false)
  1063  
  1064  	txn, err = ctx.Txn(true)
  1065  	c.Assert(err, IsNil)
  1066  	err = txn.Commit(context.Background())
  1067  	c.Assert(err, IsNil)
  1068  
  1069  	d.Stop()
  1070  }
  1071  
  1072  func (s *testDeferredCausetSuite) TestDropDeferredCausets(c *C) {
  1073  	d := testNewDBSAndStart(
  1074  		context.Background(),
  1075  		c,
  1076  		WithStore(s.causetstore),
  1077  		WithLease(testLease),
  1078  	)
  1079  	tblInfo := testBlockInfo(c, d, "t2", 4)
  1080  	ctx := testNewContext(d)
  1081  
  1082  	err := ctx.NewTxn(context.Background())
  1083  	c.Assert(err, IsNil)
  1084  
  1085  	testCreateBlock(c, ctx, d, s.dbInfo, tblInfo)
  1086  	t := testGetBlock(c, d, s.dbInfo.ID, tblInfo.ID)
  1087  
  1088  	defCausNames := []string{"c3", "c4"}
  1089  	defaultDefCausValue := int64(4)
  1090  	event := types.MakeCausets(int64(1), int64(2), int64(3))
  1091  	_, err = t.AddRecord(ctx, append(event, types.NewCauset(defaultDefCausValue)))
  1092  	c.Assert(err, IsNil)
  1093  
  1094  	txn, err := ctx.Txn(true)
  1095  	c.Assert(err, IsNil)
  1096  	err = txn.Commit(context.Background())
  1097  	c.Assert(err, IsNil)
  1098  
  1099  	checkOK := false
  1100  	var hookErr error
  1101  	var mu sync.Mutex
  1102  
  1103  	tc := &TestDBSCallback{}
  1104  	tc.onJobUFIDelated = func(job *perceptron.Job) {
  1105  		mu.Lock()
  1106  		defer mu.Unlock()
  1107  		if checkOK {
  1108  			return
  1109  		}
  1110  		t, err1 := testGetBlockWithError(d, s.dbInfo.ID, tblInfo.ID)
  1111  		if err1 != nil {
  1112  			hookErr = errors.Trace(err1)
  1113  			return
  1114  		}
  1115  		for _, defCausName := range defCausNames {
  1116  			defCaus := causet.FindDefCaus(t.(*blocks.BlockCommon).DeferredCausets, defCausName)
  1117  			if defCaus == nil {
  1118  				checkOK = true
  1119  				return
  1120  			}
  1121  		}
  1122  	}
  1123  
  1124  	d.SetHook(tc)
  1125  
  1126  	job := testDropDeferredCausets(c, ctx, d, s.dbInfo, tblInfo, defCausNames, false)
  1127  	testCheckJobDone(c, d, job, false)
  1128  	mu.Lock()
  1129  	hErr := hookErr
  1130  	ok := checkOK
  1131  	mu.Unlock()
  1132  	c.Assert(hErr, IsNil)
  1133  	c.Assert(ok, IsTrue)
  1134  
  1135  	job = testDropBlock(c, ctx, d, s.dbInfo, tblInfo)
  1136  	testCheckJobDone(c, d, job, false)
  1137  	d.Stop()
  1138  }
  1139  
  1140  func (s *testDeferredCausetSuite) TestModifyDeferredCauset(c *C) {
  1141  	d := testNewDBSAndStart(
  1142  		context.Background(),
  1143  		c,
  1144  		WithStore(s.causetstore),
  1145  		WithLease(testLease),
  1146  	)
  1147  	ctx := testNewContext(d)
  1148  	defer d.Stop()
  1149  	tests := []struct {
  1150  		origin string
  1151  		to     string
  1152  		err    error
  1153  	}{
  1154  		{"int", "bigint", nil},
  1155  		{"int", "int unsigned", errUnsupportedModifyDeferredCauset.GenWithStackByArgs("length 10 is less than origin 11, and milevadb_enable_change_defCausumn_type is false")},
  1156  		{"varchar(10)", "text", nil},
  1157  		{"varbinary(10)", "blob", nil},
  1158  		{"text", "blob", errUnsupportedModifyCharset.GenWithStackByArgs("charset from utf8mb4 to binary")},
  1159  		{"varchar(10)", "varchar(8)", errUnsupportedModifyDeferredCauset.GenWithStackByArgs("length 8 is less than origin 10")},
  1160  		{"varchar(10)", "varchar(11)", nil},
  1161  		{"varchar(10) character set utf8 defCauslate utf8_bin", "varchar(10) character set utf8", nil},
  1162  		{"decimal(2,1)", "decimal(3,2)", errUnsupportedModifyDeferredCauset.GenWithStackByArgs("can't change decimal defCausumn precision")},
  1163  		{"decimal(2,1)", "decimal(2,2)", errUnsupportedModifyDeferredCauset.GenWithStackByArgs("can't change decimal defCausumn precision")},
  1164  		{"decimal(2,1)", "decimal(2,1)", nil},
  1165  		{"decimal(2,1)", "int", errUnsupportedModifyDeferredCauset.GenWithStackByArgs("type int(11) not match origin decimal(2,1)")},
  1166  		{"decimal", "int", errUnsupportedModifyDeferredCauset.GenWithStackByArgs("type int(11) not match origin decimal(11,0)")},
  1167  		{"decimal(2,1)", "bigint", errUnsupportedModifyDeferredCauset.GenWithStackByArgs("type bigint(20) not match origin decimal(2,1)")},
  1168  	}
  1169  	for _, tt := range tests {
  1170  		ftA := s.defCausDefStrToFieldType(c, tt.origin)
  1171  		ftB := s.defCausDefStrToFieldType(c, tt.to)
  1172  		err := checkModifyTypes(ctx, ftA, ftB, false)
  1173  		if err == nil {
  1174  			c.Assert(tt.err, IsNil, Commentf("origin:%v, to:%v", tt.origin, tt.to))
  1175  		} else {
  1176  			c.Assert(err.Error(), Equals, tt.err.Error())
  1177  		}
  1178  	}
  1179  }
  1180  
  1181  func (s *testDeferredCausetSuite) defCausDefStrToFieldType(c *C, str string) *types.FieldType {
  1182  	sqlA := "alter causet t modify defCausumn a " + str
  1183  	stmt, err := BerolinaSQL.New().ParseOneStmt(sqlA, "", "")
  1184  	c.Assert(err, IsNil)
  1185  	defCausDef := stmt.(*ast.AlterBlockStmt).Specs[0].NewDeferredCausets[0]
  1186  	chs, defCausl := charset.GetDefaultCharsetAndDefCauslate()
  1187  	defCaus, _, err := buildDeferredCausetAndConstraint(nil, 0, defCausDef, nil, chs, defCausl)
  1188  	c.Assert(err, IsNil)
  1189  	return &defCaus.FieldType
  1190  }
  1191  
  1192  func (s *testDeferredCausetSuite) TestFieldCase(c *C) {
  1193  	var fields = []string{"field", "Field"}
  1194  	defCausObjects := make([]*perceptron.DeferredCausetInfo, len(fields))
  1195  	for i, name := range fields {
  1196  		defCausObjects[i] = &perceptron.DeferredCausetInfo{
  1197  			Name: perceptron.NewCIStr(name),
  1198  		}
  1199  	}
  1200  	err := checkDuplicateDeferredCauset(defCausObjects)
  1201  	c.Assert(err.Error(), Equals, schemareplicant.ErrDeferredCausetExists.GenWithStackByArgs("Field").Error())
  1202  }