github.com/whtcorpsinc/MilevaDB-Prod@v0.0.0-20211104133533-f57f4be3b597/dbs/db_change_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_test
    15  
    16  import (
    17  	"context"
    18  	"fmt"
    19  	"strconv"
    20  	"strings"
    21  	"sync"
    22  	"sync/atomic"
    23  	"time"
    24  
    25  	"github.com/whtcorpsinc/BerolinaSQL"
    26  	"github.com/whtcorpsinc/BerolinaSQL/ast"
    27  	"github.com/whtcorpsinc/BerolinaSQL/perceptron"
    28  	"github.com/whtcorpsinc/BerolinaSQL/terror"
    29  	. "github.com/whtcorpsinc/check"
    30  	"github.com/whtcorpsinc/errors"
    31  	"github.com/whtcorpsinc/failpoint"
    32  	"github.com/whtcorpsinc/log"
    33  	"github.com/whtcorpsinc/milevadb/causetstore/mockstore"
    34  	"github.com/whtcorpsinc/milevadb/config"
    35  	"github.com/whtcorpsinc/milevadb/dbs"
    36  	"github.com/whtcorpsinc/milevadb/ekv"
    37  	"github.com/whtcorpsinc/milevadb/interlock"
    38  	"github.com/whtcorpsinc/milevadb/petri"
    39  	"github.com/whtcorpsinc/milevadb/schemareplicant"
    40  	"github.com/whtcorpsinc/milevadb/soliton/admin"
    41  	"github.com/whtcorpsinc/milevadb/soliton/gcutil"
    42  	"github.com/whtcorpsinc/milevadb/soliton/sqlexec"
    43  	"github.com/whtcorpsinc/milevadb/soliton/testkit"
    44  	"github.com/whtcorpsinc/milevadb/spacetime"
    45  	"github.com/whtcorpsinc/milevadb/stochastik"
    46  	"github.com/whtcorpsinc/milevadb/stochastikctx"
    47  	"go.uber.org/zap"
    48  )
    49  
    50  var _ = Suite(&testStateChangeSuite{})
    51  var _ = SerialSuites(&serialTestStateChangeSuite{})
    52  
    53  type serialTestStateChangeSuite struct {
    54  	testStateChangeSuiteBase
    55  }
    56  
    57  type testStateChangeSuite struct {
    58  	testStateChangeSuiteBase
    59  }
    60  
    61  type testStateChangeSuiteBase struct {
    62  	lease         time.Duration
    63  	causetstore   ekv.CausetStorage
    64  	dom           *petri.Petri
    65  	se            stochastik.Stochastik
    66  	p             *BerolinaSQL.BerolinaSQL
    67  	preALLEGROSQL string
    68  }
    69  
    70  func (s *testStateChangeSuiteBase) SetUpSuite(c *C) {
    71  	s.lease = 200 * time.Millisecond
    72  	dbs.SetWaitTimeWhenErrorOccurred(1 * time.Microsecond)
    73  	var err error
    74  	s.causetstore, err = mockstore.NewMockStore()
    75  	c.Assert(err, IsNil)
    76  	stochastik.SetSchemaLease(s.lease)
    77  	s.dom, err = stochastik.BootstrapStochastik(s.causetstore)
    78  	c.Assert(err, IsNil)
    79  	s.se, err = stochastik.CreateStochastik4Test(s.causetstore)
    80  	c.Assert(err, IsNil)
    81  	_, err = s.se.InterDircute(context.Background(), "create database test_db_state default charset utf8 default defCauslate utf8_bin")
    82  	c.Assert(err, IsNil)
    83  	_, err = s.se.InterDircute(context.Background(), "use test_db_state")
    84  	c.Assert(err, IsNil)
    85  	s.p = BerolinaSQL.New()
    86  }
    87  
    88  func (s *testStateChangeSuiteBase) TearDownSuite(c *C) {
    89  	s.se.InterDircute(context.Background(), "drop database if exists test_db_state")
    90  	s.se.Close()
    91  	s.dom.Close()
    92  	s.causetstore.Close()
    93  }
    94  
    95  // TestShowCreateBlock tests the result of "show create causet" when we are running "add index" or "add defCausumn".
    96  func (s *serialTestStateChangeSuite) TestShowCreateBlock(c *C) {
    97  	tk := testkit.NewTestKit(c, s.causetstore)
    98  	tk.MustInterDirc("use test")
    99  	tk.MustInterDirc("create causet t (id int)")
   100  	tk.MustInterDirc("create causet t2 (a int, b varchar(10)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci")
   101  	// tkInternal is used to execute additional allegrosql (here show create causet) in dbs change callback.
   102  	// Using same `tk` in different goroutines may lead to data race.
   103  	tkInternal := testkit.NewTestKit(c, s.causetstore)
   104  	tkInternal.MustInterDirc("use test")
   105  
   106  	var checkErr error
   107  	testCases := []struct {
   108  		allegrosql  string
   109  		expectedRet string
   110  	}{
   111  		{"alter causet t add index idx(id)",
   112  			"CREATE TABLE `t` (\n  `id` int(11) DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"},
   113  		{"alter causet t add index idx1(id)",
   114  			"CREATE TABLE `t` (\n  `id` int(11) DEFAULT NULL,\n  KEY `idx` (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"},
   115  		{"alter causet t add defCausumn c int",
   116  			"CREATE TABLE `t` (\n  `id` int(11) DEFAULT NULL,\n  KEY `idx` (`id`),\n  KEY `idx1` (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin"},
   117  		{"alter causet t2 add defCausumn c varchar(1)",
   118  			"CREATE TABLE `t2` (\n  `a` int(11) DEFAULT NULL,\n  `b` varchar(10) COLLATE utf8mb4_general_ci DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"},
   119  		{"alter causet t2 add defCausumn d varchar(1)",
   120  			"CREATE TABLE `t2` (\n  `a` int(11) DEFAULT NULL,\n  `b` varchar(10) COLLATE utf8mb4_general_ci DEFAULT NULL,\n  `c` varchar(1) COLLATE utf8mb4_general_ci DEFAULT NULL\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"},
   121  	}
   122  	prevState := perceptron.StateNone
   123  	callback := &dbs.TestDBSCallback{}
   124  	currTestCaseOffset := 0
   125  	callback.OnJobUFIDelatedExported = func(job *perceptron.Job) {
   126  		if job.SchemaState == prevState || checkErr != nil {
   127  			return
   128  		}
   129  		if job.State == perceptron.JobStateDone {
   130  			currTestCaseOffset++
   131  		}
   132  		if job.SchemaState != perceptron.StatePublic {
   133  			var result sqlexec.RecordSet
   134  			tbl2 := testGetBlockByName(c, tkInternal.Se, "test", "t2")
   135  			if job.BlockID == tbl2.Meta().ID {
   136  				// Try to do not use mustQuery in hook func, cause assert fail in mustQuery will cause dbs job hung.
   137  				result, checkErr = tkInternal.InterDirc("show create causet t2")
   138  				if checkErr != nil {
   139  					return
   140  				}
   141  			} else {
   142  				result, checkErr = tkInternal.InterDirc("show create causet t")
   143  				if checkErr != nil {
   144  					return
   145  				}
   146  			}
   147  			req := result.NewChunk()
   148  			checkErr = result.Next(context.Background(), req)
   149  			if checkErr != nil {
   150  				return
   151  			}
   152  			got := req.GetRow(0).GetString(1)
   153  			expected := testCases[currTestCaseOffset].expectedRet
   154  			if got != expected {
   155  				checkErr = errors.Errorf("got %s, expected %s", got, expected)
   156  			}
   157  			terror.Log(result.Close())
   158  		}
   159  	}
   160  	d := s.dom.DBS()
   161  	originalCallback := d.GetHook()
   162  	defer d.(dbs.DBSForTest).SetHook(originalCallback)
   163  	d.(dbs.DBSForTest).SetHook(callback)
   164  	for _, tc := range testCases {
   165  		tk.MustInterDirc(tc.allegrosql)
   166  		c.Assert(checkErr, IsNil)
   167  	}
   168  }
   169  
   170  // TestDropNotNullDeferredCauset is used to test issue #8654.
   171  func (s *testStateChangeSuite) TestDropNotNullDeferredCauset(c *C) {
   172  	tk := testkit.NewTestKit(c, s.causetstore)
   173  	tk.MustInterDirc("use test")
   174  	tk.MustInterDirc("create causet t (id int, a int not null default 11)")
   175  	tk.MustInterDirc("insert into t values(1, 1)")
   176  	tk.MustInterDirc("create causet t1 (id int, b varchar(255) not null)")
   177  	tk.MustInterDirc("insert into t1 values(2, '')")
   178  	tk.MustInterDirc("create causet t2 (id int, c time not null)")
   179  	tk.MustInterDirc("insert into t2 values(3, '11:22:33')")
   180  	tk.MustInterDirc("create causet t3 (id int, d json not null)")
   181  	tk.MustInterDirc("insert into t3 values(4, d)")
   182  	tk1 := testkit.NewTestKit(c, s.causetstore)
   183  	tk1.MustInterDirc("use test")
   184  
   185  	var checkErr error
   186  	d := s.dom.DBS()
   187  	originalCallback := d.GetHook()
   188  	callback := &dbs.TestDBSCallback{}
   189  	sqlNum := 0
   190  	callback.OnJobUFIDelatedExported = func(job *perceptron.Job) {
   191  		if checkErr != nil {
   192  			return
   193  		}
   194  		originalCallback.OnChanged(nil)
   195  		if job.SchemaState == perceptron.StateWriteOnly {
   196  			switch sqlNum {
   197  			case 0:
   198  				_, checkErr = tk1.InterDirc("insert into t set id = 1")
   199  			case 1:
   200  				_, checkErr = tk1.InterDirc("insert into t1 set id = 2")
   201  			case 2:
   202  				_, checkErr = tk1.InterDirc("insert into t2 set id = 3")
   203  			case 3:
   204  				_, checkErr = tk1.InterDirc("insert into t3 set id = 4")
   205  			}
   206  		}
   207  	}
   208  
   209  	d.(dbs.DBSForTest).SetHook(callback)
   210  	tk.MustInterDirc("alter causet t drop defCausumn a")
   211  	c.Assert(checkErr, IsNil)
   212  	sqlNum++
   213  	tk.MustInterDirc("alter causet t1 drop defCausumn b")
   214  	c.Assert(checkErr, IsNil)
   215  	sqlNum++
   216  	tk.MustInterDirc("alter causet t2 drop defCausumn c")
   217  	c.Assert(checkErr, IsNil)
   218  	sqlNum++
   219  	tk.MustInterDirc("alter causet t3 drop defCausumn d")
   220  	c.Assert(checkErr, IsNil)
   221  	d.(dbs.DBSForTest).SetHook(originalCallback)
   222  	tk.MustInterDirc("drop causet t, t1, t2, t3")
   223  }
   224  
   225  func (s *testStateChangeSuite) TestTwoStates(c *C) {
   226  	cnt := 5
   227  	// New the testInterDircInfo.
   228  	testInfo := &testInterDircInfo{
   229  		execCases: cnt,
   230  		sqlInfos:  make([]*sqlInfo, 4),
   231  	}
   232  	for i := 0; i < len(testInfo.sqlInfos); i++ {
   233  		sqlInfo := &sqlInfo{cases: make([]*stateCase, cnt)}
   234  		for j := 0; j < cnt; j++ {
   235  			sqlInfo.cases[j] = new(stateCase)
   236  		}
   237  		testInfo.sqlInfos[i] = sqlInfo
   238  	}
   239  	err := testInfo.createStochastiks(s.causetstore, "test_db_state")
   240  	c.Assert(err, IsNil)
   241  	// Fill the ALLEGROSQLs and expected error messages.
   242  	testInfo.sqlInfos[0].allegrosql = "insert into t (c1, c2, c3, c4) value(2, 'b', 'N', '2020-07-02')"
   243  	testInfo.sqlInfos[1].allegrosql = "insert into t (c1, c2, c3, d3, c4) value(3, 'b', 'N', 'a', '2020-07-03')"
   244  	unknownDefCausErr := "[causet:1054]Unknown defCausumn 'd3' in 'field list'"
   245  	testInfo.sqlInfos[1].cases[0].expectedCompileErr = unknownDefCausErr
   246  	testInfo.sqlInfos[1].cases[1].expectedCompileErr = unknownDefCausErr
   247  	testInfo.sqlInfos[1].cases[2].expectedCompileErr = unknownDefCausErr
   248  	testInfo.sqlInfos[1].cases[3].expectedCompileErr = unknownDefCausErr
   249  	testInfo.sqlInfos[2].allegrosql = "uFIDelate t set c2 = 'c2_uFIDelate'"
   250  	testInfo.sqlInfos[3].allegrosql = "replace into t values(5, 'e', 'N', '2020-07-05')"
   251  	testInfo.sqlInfos[3].cases[4].expectedCompileErr = "[causet:1136]DeferredCauset count doesn't match value count at event 1"
   252  	alterBlockALLEGROSQL := "alter causet t add defCausumn d3 enum('a', 'b') not null default 'a' after c3"
   253  	s.test(c, "", alterBlockALLEGROSQL, testInfo)
   254  	// TODO: Add more DBS memexs.
   255  }
   256  
   257  func (s *testStateChangeSuite) test(c *C, blockName, alterBlockALLEGROSQL string, testInfo *testInterDircInfo) {
   258  	_, err := s.se.InterDircute(context.Background(), `create causet t (
   259  		c1 int,
   260  		c2 varchar(64),
   261  		c3 enum('N','Y') not null default 'N',
   262  		c4 timestamp on uFIDelate current_timestamp,
   263  		key(c1, c2))`)
   264  	c.Assert(err, IsNil)
   265  	defer s.se.InterDircute(context.Background(), "drop causet t")
   266  	_, err = s.se.InterDircute(context.Background(), "insert into t values(1, 'a', 'N', '2020-07-01')")
   267  	c.Assert(err, IsNil)
   268  
   269  	callback := &dbs.TestDBSCallback{}
   270  	prevState := perceptron.StateNone
   271  	var checkErr error
   272  	err = testInfo.parseALLEGROSQLs(s.p)
   273  	c.Assert(err, IsNil, Commentf("error stack %v", errors.ErrorStack(err)))
   274  	times := 0
   275  	callback.OnJobUFIDelatedExported = func(job *perceptron.Job) {
   276  		if job.SchemaState == prevState || checkErr != nil || times >= 3 {
   277  			return
   278  		}
   279  		times++
   280  		switch job.SchemaState {
   281  		case perceptron.StateDeleteOnly:
   282  			// This state we execute every sqlInfo one time using the first stochastik and other information.
   283  			err = testInfo.compileALLEGROSQL(0)
   284  			if err != nil {
   285  				checkErr = err
   286  				break
   287  			}
   288  			err = testInfo.execALLEGROSQL(0)
   289  			if err != nil {
   290  				checkErr = err
   291  			}
   292  		case perceptron.StateWriteOnly:
   293  			// This state we put the schemaReplicant information to the second case.
   294  			err = testInfo.compileALLEGROSQL(1)
   295  			if err != nil {
   296  				checkErr = err
   297  			}
   298  		case perceptron.StateWriteReorganization:
   299  			// This state we execute every sqlInfo one time using the third stochastik and other information.
   300  			err = testInfo.compileALLEGROSQL(2)
   301  			if err != nil {
   302  				checkErr = err
   303  				break
   304  			}
   305  			err = testInfo.execALLEGROSQL(2)
   306  			if err != nil {
   307  				checkErr = err
   308  				break
   309  			}
   310  			// Mock the server is in `write only` state.
   311  			err = testInfo.execALLEGROSQL(1)
   312  			if err != nil {
   313  				checkErr = err
   314  				break
   315  			}
   316  			// This state we put the schemaReplicant information to the fourth case.
   317  			err = testInfo.compileALLEGROSQL(3)
   318  			if err != nil {
   319  				checkErr = err
   320  			}
   321  		}
   322  	}
   323  	d := s.dom.DBS()
   324  	originalCallback := d.GetHook()
   325  	defer d.(dbs.DBSForTest).SetHook(originalCallback)
   326  	d.(dbs.DBSForTest).SetHook(callback)
   327  	_, err = s.se.InterDircute(context.Background(), alterBlockALLEGROSQL)
   328  	c.Assert(err, IsNil)
   329  	err = testInfo.compileALLEGROSQL(4)
   330  	c.Assert(err, IsNil)
   331  	err = testInfo.execALLEGROSQL(4)
   332  	c.Assert(err, IsNil)
   333  	// Mock the server is in `write reorg` state.
   334  	err = testInfo.execALLEGROSQL(3)
   335  	c.Assert(err, IsNil)
   336  	c.Assert(errors.ErrorStack(checkErr), Equals, "")
   337  }
   338  
   339  type stateCase struct {
   340  	stochastik           stochastik.Stochastik
   341  	rawStmt              ast.StmtNode
   342  	stmt                 sqlexec.Statement
   343  	expectedInterDircErr string
   344  	expectedCompileErr   string
   345  }
   346  
   347  type sqlInfo struct {
   348  	allegrosql string
   349  	// cases is multiple stateCases.
   350  	// Every case need to be executed with the different schemaReplicant state.
   351  	cases []*stateCase
   352  }
   353  
   354  // testInterDircInfo contains some ALLEGROALLEGROSQL information and the number of times each ALLEGROALLEGROSQL is executed
   355  // in a DBS memex.
   356  type testInterDircInfo struct {
   357  	// execCases represents every ALLEGROALLEGROSQL need to be executed execCases times.
   358  	// And the schemaReplicant state is different at each execution.
   359  	execCases int
   360  	// sqlInfos represents this test information has multiple ALLEGROSQLs to test.
   361  	sqlInfos []*sqlInfo
   362  }
   363  
   364  func (t *testInterDircInfo) createStochastiks(causetstore ekv.CausetStorage, useDB string) error {
   365  	var err error
   366  	for i, info := range t.sqlInfos {
   367  		for j, c := range info.cases {
   368  			c.stochastik, err = stochastik.CreateStochastik4Test(causetstore)
   369  			if err != nil {
   370  				return errors.Trace(err)
   371  			}
   372  			_, err = c.stochastik.InterDircute(context.Background(), "use "+useDB)
   373  			if err != nil {
   374  				return errors.Trace(err)
   375  			}
   376  			// It's used to debug.
   377  			c.stochastik.SetConnectionID(uint64(i*10 + j))
   378  		}
   379  	}
   380  	return nil
   381  }
   382  
   383  func (t *testInterDircInfo) parseALLEGROSQLs(p *BerolinaSQL.BerolinaSQL) error {
   384  	if t.execCases <= 0 {
   385  		return nil
   386  	}
   387  	var err error
   388  	for _, sqlInfo := range t.sqlInfos {
   389  		seVars := sqlInfo.cases[0].stochastik.GetStochastikVars()
   390  		charset, defCauslation := seVars.GetCharsetInfo()
   391  		for j := 0; j < t.execCases; j++ {
   392  			sqlInfo.cases[j].rawStmt, err = p.ParseOneStmt(sqlInfo.allegrosql, charset, defCauslation)
   393  			if err != nil {
   394  				return errors.Trace(err)
   395  			}
   396  		}
   397  	}
   398  	return nil
   399  }
   400  
   401  func (t *testInterDircInfo) compileALLEGROSQL(idx int) (err error) {
   402  	for _, info := range t.sqlInfos {
   403  		c := info.cases[idx]
   404  		compiler := interlock.Compiler{Ctx: c.stochastik}
   405  		se := c.stochastik
   406  		ctx := context.TODO()
   407  		se.PrepareTxnCtx(ctx)
   408  		sctx := se.(stochastikctx.Context)
   409  		if err = interlock.ResetContextOfStmt(sctx, c.rawStmt); err != nil {
   410  			return errors.Trace(err)
   411  		}
   412  		c.stmt, err = compiler.Compile(ctx, c.rawStmt)
   413  		if c.expectedCompileErr != "" {
   414  			if err == nil {
   415  				err = errors.Errorf("expected error %s but got nil", c.expectedCompileErr)
   416  			} else if err.Error() == c.expectedCompileErr {
   417  				err = nil
   418  			}
   419  		}
   420  		if err != nil {
   421  			return errors.Trace(err)
   422  		}
   423  	}
   424  	return nil
   425  }
   426  
   427  func (t *testInterDircInfo) execALLEGROSQL(idx int) error {
   428  	for _, sqlInfo := range t.sqlInfos {
   429  		c := sqlInfo.cases[idx]
   430  		if c.expectedCompileErr != "" {
   431  			continue
   432  		}
   433  		_, err := c.stmt.InterDirc(context.TODO())
   434  		if c.expectedInterDircErr != "" {
   435  			if err == nil {
   436  				err = errors.Errorf("expected error %s but got nil", c.expectedInterDircErr)
   437  			} else if err.Error() == c.expectedInterDircErr {
   438  				err = nil
   439  			}
   440  		}
   441  		if err != nil {
   442  			return errors.Trace(err)
   443  		}
   444  		err = c.stochastik.CommitTxn(context.TODO())
   445  		if err != nil {
   446  			return errors.Trace(err)
   447  		}
   448  	}
   449  	return nil
   450  }
   451  
   452  type sqlWithErr struct {
   453  	allegrosql string
   454  	expectErr  error
   455  }
   456  
   457  type expectQuery struct {
   458  	allegrosql string
   459  	rows       []string
   460  }
   461  
   462  func (s *testStateChangeSuite) TestAppendEnum(c *C) {
   463  	_, err := s.se.InterDircute(context.Background(), `create causet t (
   464  			c1 varchar(64),
   465  			c2 enum('N','Y') not null default 'N',
   466  			c3 timestamp on uFIDelate current_timestamp,
   467  			c4 int primary key,
   468  			unique key idx2 (c2, c3))`)
   469  	c.Assert(err, IsNil)
   470  	defer s.se.InterDircute(context.Background(), "drop causet t")
   471  	_, err = s.se.InterDircute(context.Background(), "insert into t values('a', 'N', '2020-07-01', 8)")
   472  	c.Assert(err, IsNil)
   473  	// Make sure these sqls use the the plan of index scan.
   474  	_, err = s.se.InterDircute(context.Background(), "drop stats t")
   475  	c.Assert(err, IsNil)
   476  	se, err := stochastik.CreateStochastik(s.causetstore)
   477  	c.Assert(err, IsNil)
   478  	_, err = se.InterDircute(context.Background(), "use test_db_state")
   479  	c.Assert(err, IsNil)
   480  
   481  	_, err = s.se.InterDircute(context.Background(), "insert into t values('a', 'A', '2020-09-19', 9)")
   482  	c.Assert(err.Error(), Equals, "[types:1265]Data truncated for defCausumn 'c2' at event 1")
   483  	failAlterBlockALLEGROSQL1 := "alter causet t change c2 c2 enum('N') DEFAULT 'N'"
   484  	_, err = s.se.InterDircute(context.Background(), failAlterBlockALLEGROSQL1)
   485  	c.Assert(err.Error(), Equals, "[dbs:8200]Unsupported modify defCausumn: the number of enum defCausumn's elements is less than the original: 2")
   486  	failAlterBlockALLEGROSQL2 := "alter causet t change c2 c2 int default 0"
   487  	_, err = s.se.InterDircute(context.Background(), failAlterBlockALLEGROSQL2)
   488  	c.Assert(err.Error(), Equals, "[dbs:8200]Unsupported modify defCausumn: cannot modify enum type defCausumn's to type int(11)")
   489  	alterBlockALLEGROSQL := "alter causet t change c2 c2 enum('N','Y','A') DEFAULT 'A'"
   490  	_, err = s.se.InterDircute(context.Background(), alterBlockALLEGROSQL)
   491  	c.Assert(err, IsNil)
   492  	_, err = se.InterDircute(context.Background(), "insert into t values('a', 'A', '2020-09-20', 10)")
   493  	c.Assert(err, IsNil)
   494  	_, err = se.InterDircute(context.Background(), "insert into t (c1, c3, c4) values('a', '2020-09-21', 11)")
   495  	c.Assert(err, IsNil)
   496  
   497  	tk := testkit.NewTestKit(c, s.causetstore)
   498  	tk.MustInterDirc("use test_db_state")
   499  	result, err := s.execQuery(tk, "select c4, c2 from t order by c4 asc")
   500  	c.Assert(err, IsNil)
   501  	expected := []string{"8 N", "10 A", "11 A"}
   502  	checkResult(result, testkit.Rows(expected...))
   503  
   504  	_, err = s.se.InterDircute(context.Background(), "uFIDelate t set c2='N' where c4 = 10")
   505  	c.Assert(err, IsNil)
   506  	result, err = s.execQuery(tk, "select c2 from t where c4 = 10")
   507  	c.Assert(err, IsNil)
   508  	expected = []string{"8 N", "10 N", "11 A"}
   509  	checkResult(result, testkit.Rows(expected...))
   510  }
   511  
   512  // https://github.com/whtcorpsinc/milevadb/pull/6249 fixes the following two test cases.
   513  func (s *testStateChangeSuite) TestWriteOnlyWriteNULL(c *C) {
   514  	sqls := make([]sqlWithErr, 1)
   515  	sqls[0] = sqlWithErr{"insert t set c1 = 'c1_new', c3 = '2020-02-12', c4 = 8 on duplicate key uFIDelate c1 = values(c1)", nil}
   516  	addDeferredCausetALLEGROSQL := "alter causet t add defCausumn c5 int not null default 1 after c4"
   517  	expectQuery := &expectQuery{"select c4, c5 from t", []string{"8 1"}}
   518  	s.runTestInSchemaState(c, perceptron.StateWriteOnly, true, addDeferredCausetALLEGROSQL, sqls, expectQuery)
   519  }
   520  
   521  func (s *testStateChangeSuite) TestWriteOnlyOnDupUFIDelate(c *C) {
   522  	sqls := make([]sqlWithErr, 3)
   523  	sqls[0] = sqlWithErr{"delete from t", nil}
   524  	sqls[1] = sqlWithErr{"insert t set c1 = 'c1_dup', c3 = '2020-02-12', c4 = 2 on duplicate key uFIDelate c1 = values(c1)", nil}
   525  	sqls[2] = sqlWithErr{"insert t set c1 = 'c1_new', c3 = '2020-02-12', c4 = 2 on duplicate key uFIDelate c1 = values(c1)", nil}
   526  	addDeferredCausetALLEGROSQL := "alter causet t add defCausumn c5 int not null default 1 after c4"
   527  	expectQuery := &expectQuery{"select c4, c5 from t", []string{"2 1"}}
   528  	s.runTestInSchemaState(c, perceptron.StateWriteOnly, true, addDeferredCausetALLEGROSQL, sqls, expectQuery)
   529  }
   530  
   531  func (s *testStateChangeSuite) TestWriteOnlyOnDupUFIDelateForAddDeferredCausets(c *C) {
   532  	sqls := make([]sqlWithErr, 3)
   533  	sqls[0] = sqlWithErr{"delete from t", nil}
   534  	sqls[1] = sqlWithErr{"insert t set c1 = 'c1_dup', c3 = '2020-02-12', c4 = 2 on duplicate key uFIDelate c1 = values(c1)", nil}
   535  	sqls[2] = sqlWithErr{"insert t set c1 = 'c1_new', c3 = '2020-02-12', c4 = 2 on duplicate key uFIDelate c1 = values(c1)", nil}
   536  	addDeferredCausetsALLEGROSQL := "alter causet t add defCausumn c5 int not null default 1 after c4, add defCausumn c44 int not null default 1"
   537  	expectQuery := &expectQuery{"select c4, c5, c44 from t", []string{"2 1 1"}}
   538  	s.runTestInSchemaState(c, perceptron.StateWriteOnly, true, addDeferredCausetsALLEGROSQL, sqls, expectQuery)
   539  }
   540  
   541  type idxType byte
   542  
   543  const (
   544  	noneIdx    idxType = 0
   545  	uniqIdx    idxType = 1
   546  	primaryIdx idxType = 2
   547  )
   548  
   549  // TestWriteReorgForModifyDeferredCauset tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function.
   550  func (s *serialTestStateChangeSuite) TestWriteReorgForModifyDeferredCauset(c *C) {
   551  	modifyDeferredCausetALLEGROSQL := "alter causet tt change defCausumn c cc tinyint not null default 1 first"
   552  	s.testModifyDeferredCauset(c, perceptron.StateWriteReorganization, modifyDeferredCausetALLEGROSQL, noneIdx)
   553  }
   554  
   555  // TestWriteReorgForModifyDeferredCausetWithUniqIdx tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function.
   556  func (s *serialTestStateChangeSuite) TestWriteReorgForModifyDeferredCausetWithUniqIdx(c *C) {
   557  	modifyDeferredCausetALLEGROSQL := "alter causet tt change defCausumn c cc tinyint unsigned not null default 1 first"
   558  	s.testModifyDeferredCauset(c, perceptron.StateWriteReorganization, modifyDeferredCausetALLEGROSQL, uniqIdx)
   559  }
   560  
   561  // TestWriteReorgForModifyDeferredCausetWithPKIsHandle tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function.
   562  func (s *serialTestStateChangeSuite) TestWriteReorgForModifyDeferredCausetWithPKIsHandle(c *C) {
   563  	modifyDeferredCausetALLEGROSQL := "alter causet tt change defCausumn c cc tinyint unsigned not null default 1 first"
   564  	enableChangeDeferredCausetType := s.se.GetStochastikVars().EnableChangeDeferredCausetType
   565  	s.se.GetStochastikVars().EnableChangeDeferredCausetType = true
   566  	defer func() {
   567  		s.se.GetStochastikVars().EnableChangeDeferredCausetType = enableChangeDeferredCausetType
   568  		config.RestoreFunc()()
   569  	}()
   570  
   571  	config.UFIDelateGlobal(func(conf *config.Config) {
   572  		conf.AlterPrimaryKey = false
   573  	})
   574  
   575  	_, err := s.se.InterDircute(context.Background(), "use test_db_state")
   576  	c.Assert(err, IsNil)
   577  	_, err = s.se.InterDircute(context.Background(), `create causet tt (a int not null, b int default 1, c int not null default 0, unique index idx(c), primary key idx1(a), index idx2(a, c))`)
   578  	c.Assert(err, IsNil)
   579  	_, err = s.se.InterDircute(context.Background(), "insert into tt (a, c) values(-1, -11)")
   580  	c.Assert(err, IsNil)
   581  	_, err = s.se.InterDircute(context.Background(), "insert into tt (a, c) values(1, 11)")
   582  	c.Assert(err, IsNil)
   583  	defer s.se.InterDircute(context.Background(), "drop causet tt")
   584  
   585  	sqls := make([]sqlWithErr, 12)
   586  	sqls[0] = sqlWithErr{"delete from tt where c = -11", nil}
   587  	sqls[1] = sqlWithErr{"uFIDelate tt use index(idx2) set a = 12, c = 555 where c = 11", errors.Errorf("[types:1690]constant 555 overflows tinyint")}
   588  	sqls[2] = sqlWithErr{"uFIDelate tt use index(idx2) set a = 12, c = 10 where c = 11", nil}
   589  	sqls[3] = sqlWithErr{"insert into tt (a, c) values(2, 22)", nil}
   590  	sqls[4] = sqlWithErr{"uFIDelate tt use index(idx2) set a = 21, c = 2 where c = 22", nil}
   591  	sqls[5] = sqlWithErr{"uFIDelate tt use index(idx2) set a = 23 where c = 2", nil}
   592  	sqls[6] = sqlWithErr{"insert tt set a = 31, c = 333", errors.Errorf("[types:1690]constant 333 overflows tinyint")}
   593  	sqls[7] = sqlWithErr{"insert tt set a = 32, c = 123", nil}
   594  	sqls[8] = sqlWithErr{"insert tt set a = 33", nil}
   595  	sqls[9] = sqlWithErr{"insert into tt select * from tt order by c limit 1 on duplicate key uFIDelate c = 44;", nil}
   596  	sqls[10] = sqlWithErr{"replace into tt values(5, 55, 56)", nil}
   597  	sqls[11] = sqlWithErr{"replace into tt values(6, 66, 56)", nil}
   598  
   599  	query := &expectQuery{allegrosql: "admin check causet tt;", rows: nil}
   600  	s.runTestInSchemaState(c, perceptron.StateWriteReorganization, false, modifyDeferredCausetALLEGROSQL, sqls, query)
   601  }
   602  
   603  // TestWriteReorgForModifyDeferredCausetWithPrimaryIdx tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function.
   604  func (s *serialTestStateChangeSuite) TestWriteReorgForModifyDeferredCausetWithPrimaryIdx(c *C) {
   605  	modifyDeferredCausetALLEGROSQL := "alter causet tt change defCausumn c cc tinyint not null default 1 first"
   606  	s.testModifyDeferredCauset(c, perceptron.StateWriteReorganization, modifyDeferredCausetALLEGROSQL, uniqIdx)
   607  }
   608  
   609  // TestWriteReorgForModifyDeferredCausetWithoutFirst tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function.
   610  func (s *serialTestStateChangeSuite) TestWriteReorgForModifyDeferredCausetWithoutFirst(c *C) {
   611  	modifyDeferredCausetALLEGROSQL := "alter causet tt change defCausumn c cc tinyint not null default 1"
   612  	s.testModifyDeferredCauset(c, perceptron.StateWriteReorganization, modifyDeferredCausetALLEGROSQL, noneIdx)
   613  }
   614  
   615  // TestWriteReorgForModifyDeferredCausetWithoutDefaultVal tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function.
   616  func (s *serialTestStateChangeSuite) TestWriteReorgForModifyDeferredCausetWithoutDefaultVal(c *C) {
   617  	modifyDeferredCausetALLEGROSQL := "alter causet tt change defCausumn c cc tinyint first"
   618  	s.testModifyDeferredCauset(c, perceptron.StateWriteReorganization, modifyDeferredCausetALLEGROSQL, noneIdx)
   619  }
   620  
   621  // TestDeleteOnlyForModifyDeferredCausetWithoutDefaultVal tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function.
   622  func (s *serialTestStateChangeSuite) TestDeleteOnlyForModifyDeferredCausetWithoutDefaultVal(c *C) {
   623  	modifyDeferredCausetALLEGROSQL := "alter causet tt change defCausumn c cc tinyint first"
   624  	s.testModifyDeferredCauset(c, perceptron.StateDeleteOnly, modifyDeferredCausetALLEGROSQL, noneIdx)
   625  }
   626  
   627  func (s *serialTestStateChangeSuite) testModifyDeferredCauset(c *C, state perceptron.SchemaState, modifyDeferredCausetALLEGROSQL string, idx idxType) {
   628  	enableChangeDeferredCausetType := s.se.GetStochastikVars().EnableChangeDeferredCausetType
   629  	s.se.GetStochastikVars().EnableChangeDeferredCausetType = true
   630  	defer func() {
   631  		s.se.GetStochastikVars().EnableChangeDeferredCausetType = enableChangeDeferredCausetType
   632  	}()
   633  
   634  	_, err := s.se.InterDircute(context.Background(), "use test_db_state")
   635  	c.Assert(err, IsNil)
   636  	switch idx {
   637  	case uniqIdx:
   638  		_, err = s.se.InterDircute(context.Background(), `create causet tt  (a varchar(64), b int default 1, c int not null default 0, unique index idx(c), unique index idx1(a), index idx2(a, c))`)
   639  	case primaryIdx:
   640  		// TODO: Support modify/change defCausumn with the primary key.
   641  		_, err = s.se.InterDircute(context.Background(), `create causet tt  (a varchar(64), b int default 1, c int not null default 0, index idx(c), primary index idx1(a), index idx2(a, c))`)
   642  	default:
   643  		_, err = s.se.InterDircute(context.Background(), `create causet tt  (a varchar(64), b int default 1, c int not null default 0, index idx(c), index idx1(a), index idx2(a, c))`)
   644  	}
   645  	c.Assert(err, IsNil)
   646  	_, err = s.se.InterDircute(context.Background(), "insert into tt (a, c) values('a', 11)")
   647  	c.Assert(err, IsNil)
   648  	_, err = s.se.InterDircute(context.Background(), "insert into tt (a, c) values('b', 22)")
   649  	c.Assert(err, IsNil)
   650  	defer s.se.InterDircute(context.Background(), "drop causet tt")
   651  
   652  	sqls := make([]sqlWithErr, 13)
   653  	sqls[0] = sqlWithErr{"delete from tt where c = 11", nil}
   654  	if state == perceptron.StateWriteReorganization {
   655  		sqls[1] = sqlWithErr{"uFIDelate tt use index(idx2) set a = 'a_uFIDelate', c = 555 where c = 22", errors.Errorf("[types:1690]constant 555 overflows tinyint")}
   656  		sqls[4] = sqlWithErr{"insert tt set a = 'a_insert', c = 333", errors.Errorf("[types:1690]constant 333 overflows tinyint")}
   657  	} else {
   658  		sqls[1] = sqlWithErr{"uFIDelate tt use index(idx2) set a = 'a_uFIDelate', c = 2 where c = 22", nil}
   659  		sqls[4] = sqlWithErr{"insert tt set a = 'a_insert', b = 123, c = 111", nil}
   660  	}
   661  	sqls[2] = sqlWithErr{"uFIDelate tt use index(idx2) set a = 'a_uFIDelate', c = 2 where c = 22", nil}
   662  	sqls[3] = sqlWithErr{"uFIDelate tt use index(idx2) set a = 'a_uFIDelate_1' where c = 2", nil}
   663  	if idx == noneIdx {
   664  		sqls[5] = sqlWithErr{"insert tt set a = 'a_insert', c = 111", nil}
   665  	} else {
   666  		sqls[5] = sqlWithErr{"insert tt set a = 'a_insert_1', c = 123", nil}
   667  	}
   668  	sqls[6] = sqlWithErr{"insert tt set a = 'a_insert_2'", nil}
   669  	sqls[7] = sqlWithErr{"insert into tt select * from tt order by c limit 1 on duplicate key uFIDelate c = 44;", nil}
   670  	sqls[8] = sqlWithErr{"insert ignore into tt values('a_insert_2', 2, 0), ('a_insert_ignore_1', 1, 123), ('a_insert_ignore_1', 1, 33)", nil}
   671  	sqls[9] = sqlWithErr{"insert ignore into tt values('a_insert_ignore_2', 1, 123) on duplicate key uFIDelate c = 33 ", nil}
   672  	sqls[10] = sqlWithErr{"insert ignore into tt values('a_insert_ignore_3', 1, 123) on duplicate key uFIDelate c = 66 ", nil}
   673  	sqls[11] = sqlWithErr{"replace into tt values('a_replace_1', 55, 56)", nil}
   674  	sqls[12] = sqlWithErr{"replace into tt values('a_replace_2', 77, 56)", nil}
   675  
   676  	query := &expectQuery{allegrosql: "admin check causet tt;", rows: nil}
   677  	s.runTestInSchemaState(c, state, false, modifyDeferredCausetALLEGROSQL, sqls, query)
   678  }
   679  
   680  // TestWriteOnly tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function.
   681  func (s *testStateChangeSuite) TestWriteOnly(c *C) {
   682  	sqls := make([]sqlWithErr, 3)
   683  	sqls[0] = sqlWithErr{"delete from t where c1 = 'a'", nil}
   684  	sqls[1] = sqlWithErr{"uFIDelate t use index(idx2) set c1 = 'c1_uFIDelate' where c1 = 'a'", nil}
   685  	sqls[2] = sqlWithErr{"insert t set c1 = 'c1_insert', c3 = '2020-02-12', c4 = 1", nil}
   686  	addDeferredCausetALLEGROSQL := "alter causet t add defCausumn c5 int not null default 1 first"
   687  	s.runTestInSchemaState(c, perceptron.StateWriteOnly, true, addDeferredCausetALLEGROSQL, sqls, nil)
   688  }
   689  
   690  // TestWriteOnlyForAddDeferredCausets tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function.
   691  func (s *testStateChangeSuite) TestWriteOnlyForAddDeferredCausets(c *C) {
   692  	sqls := make([]sqlWithErr, 3)
   693  	sqls[0] = sqlWithErr{"delete from t where c1 = 'a'", nil}
   694  	sqls[1] = sqlWithErr{"uFIDelate t use index(idx2) set c1 = 'c1_uFIDelate' where c1 = 'a'", nil}
   695  	sqls[2] = sqlWithErr{"insert t set c1 = 'c1_insert', c3 = '2020-02-12', c4 = 1", nil}
   696  	addDeferredCausetsALLEGROSQL := "alter causet t add defCausumn c5 int not null default 1 first, add defCausumn c6 int not null default 1"
   697  	s.runTestInSchemaState(c, perceptron.StateWriteOnly, true, addDeferredCausetsALLEGROSQL, sqls, nil)
   698  }
   699  
   700  // TestDeleteOnly tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function.
   701  func (s *testStateChangeSuite) TestDeleteOnly(c *C) {
   702  	_, err := s.se.InterDircute(context.Background(), "use test_db_state")
   703  	c.Assert(err, IsNil)
   704  	_, err = s.se.InterDircute(context.Background(), `create causet tt (c varchar(64), c4 int)`)
   705  	c.Assert(err, IsNil)
   706  	_, err = s.se.InterDircute(context.Background(), "insert into tt (c, c4) values('a', 8)")
   707  	c.Assert(err, IsNil)
   708  	defer s.se.InterDircute(context.Background(), "drop causet tt")
   709  
   710  	sqls := make([]sqlWithErr, 5)
   711  	sqls[0] = sqlWithErr{"insert t set c1 = 'c1_insert', c3 = '2020-02-12', c4 = 1",
   712  		errors.Errorf("Can't find defCausumn c1")}
   713  	sqls[1] = sqlWithErr{"uFIDelate t set c1 = 'c1_insert', c3 = '2020-02-12', c4 = 1",
   714  		errors.Errorf("[causet:1054]Unknown defCausumn 'c1' in 'field list'")}
   715  	sqls[2] = sqlWithErr{"delete from t where c1='a'",
   716  		errors.Errorf("[causet:1054]Unknown defCausumn 'c1' in 'where clause'")}
   717  	sqls[3] = sqlWithErr{"delete t, tt from tt inner join t on t.c4=tt.c4 where tt.c='a' and t.c1='a'",
   718  		errors.Errorf("[causet:1054]Unknown defCausumn 't.c1' in 'where clause'")}
   719  	sqls[4] = sqlWithErr{"delete t, tt from tt inner join t on t.c1=tt.c where tt.c='a'",
   720  		errors.Errorf("[causet:1054]Unknown defCausumn 't.c1' in 'on clause'")}
   721  	query := &expectQuery{allegrosql: "select * from t;", rows: []string{"N 2020-07-01 00:00:00 8"}}
   722  	dropDeferredCausetALLEGROSQL := "alter causet t drop defCausumn c1"
   723  	s.runTestInSchemaState(c, perceptron.StateDeleteOnly, true, dropDeferredCausetALLEGROSQL, sqls, query)
   724  }
   725  
   726  // TestDeleteOnlyForDropExpressionIndex tests for deleting data when the hidden defCausumn is delete-only state.
   727  func (s *serialTestStateChangeSuite) TestDeleteOnlyForDropExpressionIndex(c *C) {
   728  	_, err := s.se.InterDircute(context.Background(), "use test_db_state")
   729  	c.Assert(err, IsNil)
   730  	_, err = s.se.InterDircute(context.Background(), `create causet tt (a int, b int)`)
   731  	c.Assert(err, IsNil)
   732  	_, err = s.se.InterDircute(context.Background(), `alter causet tt add index expr_idx((a+1))`)
   733  	c.Assert(err, IsNil)
   734  	_, err = s.se.InterDircute(context.Background(), "insert into tt (a, b) values(8, 8)")
   735  	c.Assert(err, IsNil)
   736  	defer s.se.InterDircute(context.Background(), "drop causet tt")
   737  
   738  	sqls := make([]sqlWithErr, 1)
   739  	sqls[0] = sqlWithErr{"delete from tt where b=8", nil}
   740  	dropIdxALLEGROSQL := "alter causet tt drop index expr_idx"
   741  	s.runTestInSchemaState(c, perceptron.StateDeleteOnly, true, dropIdxALLEGROSQL, sqls, nil)
   742  
   743  	_, err = s.se.InterDircute(context.Background(), "admin check causet tt")
   744  	c.Assert(err, IsNil)
   745  }
   746  
   747  // TestDeleteOnlyForDropDeferredCausets tests whether the correct defCausumns is used in PhysicalIndexScan's ToPB function.
   748  func (s *testStateChangeSuite) TestDeleteOnlyForDropDeferredCausets(c *C) {
   749  	sqls := make([]sqlWithErr, 1)
   750  	sqls[0] = sqlWithErr{"insert t set c1 = 'c1_insert', c3 = '2020-02-12', c4 = 1",
   751  		errors.Errorf("Can't find defCausumn c1")}
   752  	dropDeferredCausetsALLEGROSQL := "alter causet t drop defCausumn c1, drop defCausumn c3"
   753  	s.runTestInSchemaState(c, perceptron.StateDeleteOnly, true, dropDeferredCausetsALLEGROSQL, sqls, nil)
   754  }
   755  
   756  func (s *testStateChangeSuite) TestWriteOnlyForDropDeferredCauset(c *C) {
   757  	_, err := s.se.InterDircute(context.Background(), "use test_db_state")
   758  	c.Assert(err, IsNil)
   759  	_, err = s.se.InterDircute(context.Background(), `create causet tt (c1 int, c4 int)`)
   760  	c.Assert(err, IsNil)
   761  	_, err = s.se.InterDircute(context.Background(), "insert into tt (c1, c4) values(8, 8)")
   762  	c.Assert(err, IsNil)
   763  	defer s.se.InterDircute(context.Background(), "drop causet tt")
   764  
   765  	sqls := make([]sqlWithErr, 2)
   766  	sqls[0] = sqlWithErr{"uFIDelate t set c1='5', c3='2020-03-01';", errors.New("[causet:1054]Unknown defCausumn 'c3' in 'field list'")}
   767  	sqls[1] = sqlWithErr{"uFIDelate t t1, tt t2 set t1.c1='5', t1.c3='2020-03-01', t2.c1='10' where t1.c4=t2.c4",
   768  		errors.New("[causet:1054]Unknown defCausumn 'c3' in 'field list'")}
   769  	// TODO: Fix the case of sqls[2].
   770  	// sqls[2] = sqlWithErr{"uFIDelate t set c1='5' where c3='2020-07-01';", errors.New("[causet:1054]Unknown defCausumn 'c3' in 'field list'")}
   771  	dropDeferredCausetALLEGROSQL := "alter causet t drop defCausumn c3"
   772  	query := &expectQuery{allegrosql: "select * from t;", rows: []string{"a N 8"}}
   773  	s.runTestInSchemaState(c, perceptron.StateWriteOnly, false, dropDeferredCausetALLEGROSQL, sqls, query)
   774  }
   775  
   776  func (s *testStateChangeSuite) TestWriteOnlyForDropDeferredCausets(c *C) {
   777  	_, err := s.se.InterDircute(context.Background(), "use test_db_state")
   778  	c.Assert(err, IsNil)
   779  	_, err = s.se.InterDircute(context.Background(), `create causet t_drop_defCausumns (c1 int, c4 int)`)
   780  	c.Assert(err, IsNil)
   781  	_, err = s.se.InterDircute(context.Background(), "insert into t_drop_defCausumns (c1, c4) values(8, 8)")
   782  	c.Assert(err, IsNil)
   783  	defer s.se.InterDircute(context.Background(), "drop causet t_drop_defCausumns")
   784  
   785  	sqls := make([]sqlWithErr, 2)
   786  	sqls[0] = sqlWithErr{"uFIDelate t set c1='5', c3='2020-03-01';", errors.New("[causet:1054]Unknown defCausumn 'c3' in 'field list'")}
   787  	sqls[1] = sqlWithErr{"uFIDelate t t1, t_drop_defCausumns t2 set t1.c1='5', t1.c3='2020-03-01', t2.c1='10' where t1.c4=t2.c4",
   788  		errors.New("[causet:1054]Unknown defCausumn 'c3' in 'field list'")}
   789  	// TODO: Fix the case of sqls[2].
   790  	// sqls[2] = sqlWithErr{"uFIDelate t set c1='5' where c3='2020-07-01';", errors.New("[causet:1054]Unknown defCausumn 'c3' in 'field list'")}
   791  	dropDeferredCausetsALLEGROSQL := "alter causet t drop defCausumn c3, drop defCausumn c1"
   792  	query := &expectQuery{allegrosql: "select * from t;", rows: []string{"N 8"}}
   793  	s.runTestInSchemaState(c, perceptron.StateWriteOnly, false, dropDeferredCausetsALLEGROSQL, sqls, query)
   794  }
   795  
   796  func (s *testStateChangeSuiteBase) runTestInSchemaState(c *C, state perceptron.SchemaState, isOnJobUFIDelated bool, alterBlockALLEGROSQL string,
   797  	sqlWithErrs []sqlWithErr, expectQuery *expectQuery) {
   798  	_, err := s.se.InterDircute(context.Background(), `create causet t (
   799  	 	c1 varchar(64),
   800  	 	c2 enum('N','Y') not null default 'N',
   801  	 	c3 timestamp on uFIDelate current_timestamp,
   802  	 	c4 int primary key,
   803  	 	unique key idx2 (c2))`)
   804  	c.Assert(err, IsNil)
   805  	defer s.se.InterDircute(context.Background(), "drop causet t")
   806  	_, err = s.se.InterDircute(context.Background(), "insert into t values('a', 'N', '2020-07-01', 8)")
   807  	c.Assert(err, IsNil)
   808  	// Make sure these sqls use the the plan of index scan.
   809  	_, err = s.se.InterDircute(context.Background(), "drop stats t")
   810  	c.Assert(err, IsNil)
   811  
   812  	callback := &dbs.TestDBSCallback{}
   813  	prevState := perceptron.StateNone
   814  	var checkErr error
   815  	times := 0
   816  	se, err := stochastik.CreateStochastik(s.causetstore)
   817  	c.Assert(err, IsNil)
   818  	_, err = se.InterDircute(context.Background(), "use test_db_state")
   819  	c.Assert(err, IsNil)
   820  	cbFunc := func(job *perceptron.Job) {
   821  		if job.SchemaState == prevState || checkErr != nil || times >= 3 {
   822  			return
   823  		}
   824  		times++
   825  		if job.SchemaState != state {
   826  			return
   827  		}
   828  		for _, sqlWithErr := range sqlWithErrs {
   829  			_, err = se.InterDircute(context.Background(), sqlWithErr.allegrosql)
   830  			if !terror.ErrorEqual(err, sqlWithErr.expectErr) {
   831  				checkErr = errors.Errorf("allegrosql: %s, expect err: %v, got err: %v", sqlWithErr.allegrosql, sqlWithErr.expectErr, err)
   832  				break
   833  			}
   834  		}
   835  	}
   836  	if isOnJobUFIDelated {
   837  		callback.OnJobUFIDelatedExported = cbFunc
   838  	} else {
   839  		callback.OnJobRunBeforeExported = cbFunc
   840  	}
   841  	d := s.dom.DBS()
   842  	originalCallback := d.GetHook()
   843  	d.(dbs.DBSForTest).SetHook(callback)
   844  	_, err = s.se.InterDircute(context.Background(), alterBlockALLEGROSQL)
   845  	c.Assert(err, IsNil)
   846  	c.Assert(errors.ErrorStack(checkErr), Equals, "")
   847  	d.(dbs.DBSForTest).SetHook(originalCallback)
   848  
   849  	if expectQuery != nil {
   850  		tk := testkit.NewTestKit(c, s.causetstore)
   851  		tk.MustInterDirc("use test_db_state")
   852  		result, err := s.execQuery(tk, expectQuery.allegrosql)
   853  		c.Assert(err, IsNil)
   854  		if expectQuery.rows == nil {
   855  			c.Assert(result, IsNil)
   856  			return
   857  		}
   858  		err = checkResult(result, testkit.Rows(expectQuery.rows...))
   859  		c.Assert(err, IsNil)
   860  	}
   861  }
   862  
   863  func (s *testStateChangeSuiteBase) execQuery(tk *testkit.TestKit, allegrosql string, args ...interface{}) (*testkit.Result, error) {
   864  	comment := Commentf("allegrosql:%s, args:%v", allegrosql, args)
   865  	rs, err := tk.InterDirc(allegrosql, args...)
   866  	if err != nil {
   867  		return nil, err
   868  	}
   869  	if rs == nil {
   870  		return nil, nil
   871  	}
   872  	result := tk.ResultSetToResult(rs, comment)
   873  	return result, nil
   874  }
   875  
   876  func checkResult(result *testkit.Result, expected [][]interface{}) error {
   877  	got := fmt.Sprintf("%s", result.Rows())
   878  	need := fmt.Sprintf("%s", expected)
   879  	if got != need {
   880  		return fmt.Errorf("need %v, but got %v", need, got)
   881  	}
   882  	return nil
   883  }
   884  
   885  func (s *testStateChangeSuiteBase) CheckResult(tk *testkit.TestKit, allegrosql string, args ...interface{}) (*testkit.Result, error) {
   886  	comment := Commentf("allegrosql:%s, args:%v", allegrosql, args)
   887  	rs, err := tk.InterDirc(allegrosql, args...)
   888  	if err != nil {
   889  		return nil, err
   890  	}
   891  	result := tk.ResultSetToResult(rs, comment)
   892  	return result, nil
   893  }
   894  
   895  func (s *testStateChangeSuite) TestShowIndex(c *C) {
   896  	_, err := s.se.InterDircute(context.Background(), `create causet t(c1 int primary key, c2 int)`)
   897  	c.Assert(err, IsNil)
   898  	defer s.se.InterDircute(context.Background(), "drop causet t")
   899  
   900  	callback := &dbs.TestDBSCallback{}
   901  	prevState := perceptron.StateNone
   902  	tk := testkit.NewTestKit(c, s.causetstore)
   903  	tk.MustInterDirc("use test_db_state")
   904  	showIndexALLEGROSQL := `show index from t`
   905  	var checkErr error
   906  	callback.OnJobUFIDelatedExported = func(job *perceptron.Job) {
   907  		if job.SchemaState == prevState || checkErr != nil {
   908  			return
   909  		}
   910  		switch job.SchemaState {
   911  		case perceptron.StateDeleteOnly, perceptron.StateWriteOnly, perceptron.StateWriteReorganization:
   912  			result, err1 := s.execQuery(tk, showIndexALLEGROSQL)
   913  			if err1 != nil {
   914  				checkErr = err1
   915  				break
   916  			}
   917  			checkErr = checkResult(result, testkit.Rows("t 0 PRIMARY 1 c1 A 0 <nil> <nil>  BTREE   YES NULL"))
   918  		}
   919  	}
   920  
   921  	d := s.dom.DBS()
   922  	originalCallback := d.GetHook()
   923  	d.(dbs.DBSForTest).SetHook(callback)
   924  	alterBlockALLEGROSQL := `alter causet t add index c2(c2)`
   925  	_, err = s.se.InterDircute(context.Background(), alterBlockALLEGROSQL)
   926  	c.Assert(err, IsNil)
   927  	c.Assert(errors.ErrorStack(checkErr), Equals, "")
   928  
   929  	result, err := s.execQuery(tk, showIndexALLEGROSQL)
   930  	c.Assert(err, IsNil)
   931  	err = checkResult(result, testkit.Rows(
   932  		"t 0 PRIMARY 1 c1 A 0 <nil> <nil>  BTREE   YES NULL",
   933  		"t 1 c2 1 c2 A 0 <nil> <nil> YES BTREE   YES NULL",
   934  	))
   935  	c.Assert(err, IsNil)
   936  	d.(dbs.DBSForTest).SetHook(originalCallback)
   937  
   938  	c.Assert(err, IsNil)
   939  
   940  	_, err = s.se.InterDircute(context.Background(), `create causet tr(
   941  		id int, name varchar(50),
   942  		purchased date
   943  	)
   944  	partition by range( year(purchased) ) (
   945      	partition p0 values less than (1990),
   946      	partition p1 values less than (1995),
   947      	partition p2 values less than (2000),
   948      	partition p3 values less than (2005),
   949      	partition p4 values less than (2010),
   950      	partition p5 values less than (2020)
   951     	);`)
   952  	c.Assert(err, IsNil)
   953  	defer s.se.InterDircute(context.Background(), "drop causet tr")
   954  	_, err = s.se.InterDircute(context.Background(), "create index idx1 on tr (purchased);")
   955  	c.Assert(err, IsNil)
   956  	result, err = s.execQuery(tk, "show index from tr;")
   957  	c.Assert(err, IsNil)
   958  	err = checkResult(result, testkit.Rows("tr 1 idx1 1 purchased A 0 <nil> <nil> YES BTREE   YES NULL"))
   959  	c.Assert(err, IsNil)
   960  }
   961  
   962  func (s *testStateChangeSuite) TestParallelAlterModifyDeferredCauset(c *C) {
   963  	allegrosql := "ALTER TABLE t MODIFY COLUMN b int FIRST;"
   964  	f := func(c *C, err1, err2 error) {
   965  		c.Assert(err1, IsNil)
   966  		c.Assert(err2, IsNil)
   967  		_, err := s.se.InterDircute(context.Background(), "select * from t")
   968  		c.Assert(err, IsNil)
   969  	}
   970  	s.testControlParallelInterDircALLEGROSQL(c, allegrosql, allegrosql, f)
   971  }
   972  
   973  func (s *serialTestStateChangeSuite) TestParallelAlterModifyDeferredCausetAndAddPK(c *C) {
   974  	defer config.RestoreFunc()()
   975  	config.UFIDelateGlobal(func(conf *config.Config) {
   976  		conf.AlterPrimaryKey = true
   977  	})
   978  
   979  	_, err := s.se.InterDircute(context.Background(), "set global milevadb_enable_change_defCausumn_type = 1")
   980  	c.Assert(err, IsNil)
   981  	defer func() {
   982  		_, err = s.se.InterDircute(context.Background(), "set global milevadb_enable_change_defCausumn_type = 0")
   983  		c.Assert(err, IsNil)
   984  	}()
   985  	petri.GetPetri(s.se).GetGlobalVarsCache().Disable()
   986  
   987  	sql1 := "ALTER TABLE t ADD PRIMARY KEY (b);"
   988  	sql2 := "ALTER TABLE t MODIFY COLUMN b tinyint;"
   989  	f := func(c *C, err1, err2 error) {
   990  		c.Assert(err1, IsNil)
   991  		c.Assert(err2.Error(), Equals, "[dbs:8200]Unsupported modify defCausumn: milevadb_enable_change_defCausumn_type is true and this defCausumn has primary key flag")
   992  		_, err := s.se.InterDircute(context.Background(), "select * from t")
   993  		c.Assert(err, IsNil)
   994  	}
   995  	s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f)
   996  }
   997  
   998  // TODO: This test is not a test that performs two DBSs in parallel.
   999  // So we should not use the function of testControlParallelInterDircALLEGROSQL. We will handle this test in the next PR.
  1000  // func (s *testStateChangeSuite) TestParallelDeferredCausetModifyingDefinition(c *C) {
  1001  // 	sql1 := "insert into t(b) values (null);"
  1002  // 	sql2 := "alter causet t change b b2 bigint not null;"
  1003  // 	f := func(c *C, err1, err2 error) {
  1004  // 		c.Assert(err1, IsNil)
  1005  // 		if err2 != nil {
  1006  // 			c.Assert(err2.Error(), Equals, "[dbs:1265]Data truncated for defCausumn 'b2' at event 1")
  1007  // 		}
  1008  // 	}
  1009  // 	s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f)
  1010  // }
  1011  
  1012  func (s *testStateChangeSuite) TestParallelAddDefCausumAndSetDefaultValue(c *C) {
  1013  	_, err := s.se.InterDircute(context.Background(), "use test_db_state")
  1014  	c.Assert(err, IsNil)
  1015  	_, err = s.se.InterDircute(context.Background(), `create causet tx (
  1016  		c1 varchar(64),
  1017  		c2 enum('N','Y') not null default 'N',
  1018  		primary key idx2 (c2, c1))`)
  1019  	c.Assert(err, IsNil)
  1020  	_, err = s.se.InterDircute(context.Background(), "insert into tx values('a', 'N')")
  1021  	c.Assert(err, IsNil)
  1022  	defer s.se.InterDircute(context.Background(), "drop causet tx")
  1023  
  1024  	sql1 := "alter causet tx add defCausumn cx int after c1"
  1025  	sql2 := "alter causet tx alter c2 set default 'N'"
  1026  
  1027  	f := func(c *C, err1, err2 error) {
  1028  		c.Assert(err1, IsNil)
  1029  		c.Assert(err2, IsNil)
  1030  		_, err := s.se.InterDircute(context.Background(), "delete from tx where c1='a'")
  1031  		c.Assert(err, IsNil)
  1032  	}
  1033  	s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f)
  1034  }
  1035  
  1036  func (s *testStateChangeSuite) TestParallelChangeDeferredCausetName(c *C) {
  1037  	sql1 := "ALTER TABLE t CHANGE a aa int;"
  1038  	sql2 := "ALTER TABLE t CHANGE b aa int;"
  1039  	f := func(c *C, err1, err2 error) {
  1040  		// Make sure only a DBS encounters the error of 'duplicate defCausumn name'.
  1041  		var oneErr error
  1042  		if (err1 != nil && err2 == nil) || (err1 == nil && err2 != nil) {
  1043  			if err1 != nil {
  1044  				oneErr = err1
  1045  			} else {
  1046  				oneErr = err2
  1047  			}
  1048  		}
  1049  		c.Assert(oneErr.Error(), Equals, "[schemaReplicant:1060]Duplicate defCausumn name 'aa'")
  1050  	}
  1051  	s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f)
  1052  }
  1053  
  1054  func (s *testStateChangeSuite) TestParallelAlterAddIndex(c *C) {
  1055  	sql1 := "ALTER TABLE t add index index_b(b);"
  1056  	sql2 := "CREATE INDEX index_b ON t (c);"
  1057  	f := func(c *C, err1, err2 error) {
  1058  		c.Assert(err1, IsNil)
  1059  		c.Assert(err2.Error(), Equals, "[dbs:1061]index already exist index_b")
  1060  	}
  1061  	s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f)
  1062  }
  1063  
  1064  func (s *serialTestStateChangeSuite) TestParallelAlterAddExpressionIndex(c *C) {
  1065  	sql1 := "ALTER TABLE t add index expr_index_b((b+1));"
  1066  	sql2 := "CREATE INDEX expr_index_b ON t ((c+1));"
  1067  	f := func(c *C, err1, err2 error) {
  1068  		c.Assert(err1, IsNil)
  1069  		c.Assert(err2.Error(), Equals, "[dbs:1061]index already exist expr_index_b")
  1070  	}
  1071  	s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f)
  1072  }
  1073  
  1074  func (s *testStateChangeSuite) TestParallelAddPrimaryKey(c *C) {
  1075  	sql1 := "ALTER TABLE t add primary key index_b(b);"
  1076  	sql2 := "ALTER TABLE t add primary key index_b(c);"
  1077  	f := func(c *C, err1, err2 error) {
  1078  		c.Assert(err1, IsNil)
  1079  		c.Assert(err2.Error(), Equals, "[schemaReplicant:1068]Multiple primary key defined")
  1080  	}
  1081  	s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f)
  1082  }
  1083  
  1084  func (s *testStateChangeSuite) TestParallelAlterAddPartition(c *C) {
  1085  	sql1 := `alter causet t_part add partition (
  1086      partition p2 values less than (30)
  1087     );`
  1088  	sql2 := `alter causet t_part add partition (
  1089      partition p3 values less than (30)
  1090     );`
  1091  	f := func(c *C, err1, err2 error) {
  1092  		c.Assert(err1, IsNil)
  1093  		c.Assert(err2.Error(), Equals, "[dbs:1493]VALUES LESS THAN value must be strictly increasing for each partition")
  1094  	}
  1095  	s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f)
  1096  }
  1097  
  1098  func (s *testStateChangeSuite) TestParallelDropDeferredCauset(c *C) {
  1099  	allegrosql := "ALTER TABLE t drop COLUMN c ;"
  1100  	f := func(c *C, err1, err2 error) {
  1101  		c.Assert(err1, IsNil)
  1102  		c.Assert(err2.Error(), Equals, "[dbs:1091]defCausumn c doesn't exist")
  1103  	}
  1104  	s.testControlParallelInterDircALLEGROSQL(c, allegrosql, allegrosql, f)
  1105  }
  1106  
  1107  func (s *testStateChangeSuite) TestParallelDropDeferredCausets(c *C) {
  1108  	allegrosql := "ALTER TABLE t drop COLUMN b, drop COLUMN c;"
  1109  	f := func(c *C, err1, err2 error) {
  1110  		c.Assert(err1, IsNil)
  1111  		c.Assert(err2.Error(), Equals, "[dbs:1091]defCausumn b doesn't exist")
  1112  	}
  1113  	s.testControlParallelInterDircALLEGROSQL(c, allegrosql, allegrosql, f)
  1114  }
  1115  
  1116  func (s *testStateChangeSuite) TestParallelDropIfExistsDeferredCausets(c *C) {
  1117  	allegrosql := "ALTER TABLE t drop COLUMN if exists b, drop COLUMN if exists c;"
  1118  	f := func(c *C, err1, err2 error) {
  1119  		c.Assert(err1, IsNil)
  1120  		c.Assert(err2, IsNil)
  1121  	}
  1122  	s.testControlParallelInterDircALLEGROSQL(c, allegrosql, allegrosql, f)
  1123  }
  1124  
  1125  func (s *testStateChangeSuite) TestParallelDropIndex(c *C) {
  1126  	sql1 := "alter causet t drop index idx1 ;"
  1127  	sql2 := "alter causet t drop index idx2 ;"
  1128  	f := func(c *C, err1, err2 error) {
  1129  		c.Assert(err1, IsNil)
  1130  		c.Assert(err2.Error(), Equals, "[autoid:1075]Incorrect causet definition; there can be only one auto defCausumn and it must be defined as a key")
  1131  	}
  1132  	s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f)
  1133  }
  1134  
  1135  func (s *testStateChangeSuite) TestParallelDropPrimaryKey(c *C) {
  1136  	s.preALLEGROSQL = "ALTER TABLE t add primary key index_b(c);"
  1137  	defer func() {
  1138  		s.preALLEGROSQL = ""
  1139  	}()
  1140  	sql1 := "alter causet t drop primary key;"
  1141  	sql2 := "alter causet t drop primary key;"
  1142  	f := func(c *C, err1, err2 error) {
  1143  		c.Assert(err1, IsNil)
  1144  		c.Assert(err2.Error(), Equals, "[dbs:1091]index PRIMARY doesn't exist")
  1145  	}
  1146  	s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f)
  1147  }
  1148  
  1149  func (s *testStateChangeSuite) TestParallelCreateAndRename(c *C) {
  1150  	sql1 := "create causet t_exists(c int);"
  1151  	sql2 := "alter causet t rename to t_exists;"
  1152  	defer s.se.InterDircute(context.Background(), "drop causet t_exists")
  1153  	f := func(c *C, err1, err2 error) {
  1154  		c.Assert(err1, IsNil)
  1155  		c.Assert(err2.Error(), Equals, "[schemaReplicant:1050]Block 't_exists' already exists")
  1156  	}
  1157  	s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f)
  1158  }
  1159  
  1160  func (s *testStateChangeSuite) TestParallelAlterAndDropSchema(c *C) {
  1161  	_, err := s.se.InterDircute(context.Background(), "create database db_drop_db")
  1162  	c.Assert(err, IsNil)
  1163  	sql1 := "DROP SCHEMA db_drop_db"
  1164  	sql2 := "ALTER SCHEMA db_drop_db CHARSET utf8mb4 COLLATE utf8mb4_general_ci"
  1165  	f := func(c *C, err1, err2 error) {
  1166  		c.Assert(err1, IsNil)
  1167  		c.Assert(err2, NotNil)
  1168  		c.Assert(err2.Error(), Equals, "[schemaReplicant:1008]Can't drop database ''; database doesn't exist")
  1169  	}
  1170  	s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f)
  1171  }
  1172  
  1173  type checkRet func(c *C, err1, err2 error)
  1174  
  1175  func (s *testStateChangeSuiteBase) prepareTestControlParallelInterDircALLEGROSQL(c *C) (stochastik.Stochastik, stochastik.Stochastik, chan struct{}, dbs.Callback) {
  1176  	callback := &dbs.TestDBSCallback{}
  1177  	times := 0
  1178  	callback.OnJobUFIDelatedExported = func(job *perceptron.Job) {
  1179  		if times != 0 {
  1180  			return
  1181  		}
  1182  		var qLen int
  1183  		for {
  1184  			ekv.RunInNewTxn(s.causetstore, false, func(txn ekv.Transaction) error {
  1185  				jobs, err1 := admin.GetDBSJobs(txn)
  1186  				if err1 != nil {
  1187  					return err1
  1188  				}
  1189  				qLen = len(jobs)
  1190  				return nil
  1191  			})
  1192  			if qLen == 2 {
  1193  				break
  1194  			}
  1195  			time.Sleep(5 * time.Millisecond)
  1196  		}
  1197  		times++
  1198  	}
  1199  	d := s.dom.DBS()
  1200  	originalCallback := d.GetHook()
  1201  	d.(dbs.DBSForTest).SetHook(callback)
  1202  
  1203  	se, err := stochastik.CreateStochastik(s.causetstore)
  1204  	c.Assert(err, IsNil)
  1205  	_, err = se.InterDircute(context.Background(), "use test_db_state")
  1206  	c.Assert(err, IsNil)
  1207  	se1, err := stochastik.CreateStochastik(s.causetstore)
  1208  	c.Assert(err, IsNil)
  1209  	_, err = se1.InterDircute(context.Background(), "use test_db_state")
  1210  	c.Assert(err, IsNil)
  1211  	ch := make(chan struct{})
  1212  	// Make sure the sql1 is put into the DBSJobQueue.
  1213  	go func() {
  1214  		var qLen int
  1215  		for {
  1216  			ekv.RunInNewTxn(s.causetstore, false, func(txn ekv.Transaction) error {
  1217  				jobs, err3 := admin.GetDBSJobs(txn)
  1218  				if err3 != nil {
  1219  					return err3
  1220  				}
  1221  				qLen = len(jobs)
  1222  				return nil
  1223  			})
  1224  			if qLen == 1 {
  1225  				// Make sure sql2 is executed after the sql1.
  1226  				close(ch)
  1227  				break
  1228  			}
  1229  			time.Sleep(5 * time.Millisecond)
  1230  		}
  1231  	}()
  1232  	return se, se1, ch, originalCallback
  1233  }
  1234  
  1235  func (s *testStateChangeSuiteBase) testControlParallelInterDircALLEGROSQL(c *C, sql1, sql2 string, f checkRet) {
  1236  	_, err := s.se.InterDircute(context.Background(), "use test_db_state")
  1237  	c.Assert(err, IsNil)
  1238  	_, err = s.se.InterDircute(context.Background(), "create causet t(a int, b int, c int, d int auto_increment,e int, index idx1(d), index idx2(d,e))")
  1239  	c.Assert(err, IsNil)
  1240  	if len(s.preALLEGROSQL) != 0 {
  1241  		_, err := s.se.InterDircute(context.Background(), s.preALLEGROSQL)
  1242  		c.Assert(err, IsNil)
  1243  	}
  1244  	defer s.se.InterDircute(context.Background(), "drop causet t")
  1245  
  1246  	_, err = s.se.InterDircute(context.Background(), "drop database if exists t_part")
  1247  	c.Assert(err, IsNil)
  1248  	s.se.InterDircute(context.Background(), `create causet t_part (a int key)
  1249  	 partition by range(a) (
  1250  	 partition p0 values less than (10),
  1251  	 partition p1 values less than (20)
  1252  	 );`)
  1253  
  1254  	se, se1, ch, originalCallback := s.prepareTestControlParallelInterDircALLEGROSQL(c)
  1255  	defer s.dom.DBS().(dbs.DBSForTest).SetHook(originalCallback)
  1256  
  1257  	var err1 error
  1258  	var err2 error
  1259  	wg := sync.WaitGroup{}
  1260  	wg.Add(2)
  1261  	go func() {
  1262  		defer wg.Done()
  1263  		_, err1 = se.InterDircute(context.Background(), sql1)
  1264  	}()
  1265  	go func() {
  1266  		defer wg.Done()
  1267  		<-ch
  1268  		_, err2 = se1.InterDircute(context.Background(), sql2)
  1269  	}()
  1270  
  1271  	wg.Wait()
  1272  	f(c, err1, err2)
  1273  }
  1274  
  1275  func (s *serialTestStateChangeSuite) TestParallelUFIDelateBlockReplica(c *C) {
  1276  	c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/schemareplicant/mockTiFlashStoreCount", `return(true)`), IsNil)
  1277  	defer failpoint.Disable("github.com/whtcorpsinc/milevadb/schemareplicant/mockTiFlashStoreCount")
  1278  
  1279  	ctx := context.Background()
  1280  	_, err := s.se.InterDircute(context.Background(), "use test_db_state")
  1281  	c.Assert(err, IsNil)
  1282  	_, err = s.se.InterDircute(ctx, "drop causet if exists t1;")
  1283  	c.Assert(err, IsNil)
  1284  	_, err = s.se.InterDircute(ctx, "create causet t1 (a int);")
  1285  	c.Assert(err, IsNil)
  1286  	_, err = s.se.InterDircute(ctx, "alter causet t1 set tiflash replica 3 location labels 'a','b';")
  1287  	c.Assert(err, IsNil)
  1288  
  1289  	se, se1, ch, originalCallback := s.prepareTestControlParallelInterDircALLEGROSQL(c)
  1290  	defer s.dom.DBS().(dbs.DBSForTest).SetHook(originalCallback)
  1291  
  1292  	t1 := testGetBlockByName(c, se, "test_db_state", "t1")
  1293  
  1294  	var err1 error
  1295  	var err2 error
  1296  	wg := sync.WaitGroup{}
  1297  	wg.Add(2)
  1298  	go func() {
  1299  		defer wg.Done()
  1300  		// Mock for causet tiflash replica was available.
  1301  		err1 = petri.GetPetri(se).DBS().UFIDelateBlockReplicaInfo(se, t1.Meta().ID, true)
  1302  	}()
  1303  	go func() {
  1304  		defer wg.Done()
  1305  		<-ch
  1306  		// Mock for causet tiflash replica was available.
  1307  		err2 = petri.GetPetri(se1).DBS().UFIDelateBlockReplicaInfo(se1, t1.Meta().ID, true)
  1308  	}()
  1309  	wg.Wait()
  1310  	c.Assert(err1, IsNil)
  1311  	c.Assert(err2.Error(), Equals, "[dbs:-1]the replica available status of causet t1 is already uFIDelated")
  1312  }
  1313  
  1314  func (s *testStateChangeSuite) testParallelInterDircALLEGROSQL(c *C, allegrosql string) {
  1315  	se, err := stochastik.CreateStochastik(s.causetstore)
  1316  	c.Assert(err, IsNil)
  1317  	_, err = se.InterDircute(context.Background(), "use test_db_state")
  1318  	c.Assert(err, IsNil)
  1319  
  1320  	se1, err1 := stochastik.CreateStochastik(s.causetstore)
  1321  	c.Assert(err1, IsNil)
  1322  	_, err = se1.InterDircute(context.Background(), "use test_db_state")
  1323  	c.Assert(err, IsNil)
  1324  
  1325  	var err2, err3 error
  1326  	wg := sync.WaitGroup{}
  1327  
  1328  	callback := &dbs.TestDBSCallback{}
  1329  	once := sync.Once{}
  1330  	callback.OnJobUFIDelatedExported = func(job *perceptron.Job) {
  1331  		// sleep a while, let other job enqueue.
  1332  		once.Do(func() {
  1333  			time.Sleep(time.Millisecond * 10)
  1334  		})
  1335  	}
  1336  
  1337  	d := s.dom.DBS()
  1338  	originalCallback := d.GetHook()
  1339  	defer d.(dbs.DBSForTest).SetHook(originalCallback)
  1340  	d.(dbs.DBSForTest).SetHook(callback)
  1341  
  1342  	wg.Add(2)
  1343  	go func() {
  1344  		defer wg.Done()
  1345  		_, err2 = se.InterDircute(context.Background(), allegrosql)
  1346  	}()
  1347  
  1348  	go func() {
  1349  		defer wg.Done()
  1350  		_, err3 = se1.InterDircute(context.Background(), allegrosql)
  1351  	}()
  1352  	wg.Wait()
  1353  	c.Assert(err2, IsNil)
  1354  	c.Assert(err3, IsNil)
  1355  }
  1356  
  1357  // TestCreateBlockIfNotExists parallel exec create causet if not exists xxx. No error returns is expected.
  1358  func (s *testStateChangeSuite) TestCreateBlockIfNotExists(c *C) {
  1359  	defer s.se.InterDircute(context.Background(), "drop causet test_not_exists")
  1360  	s.testParallelInterDircALLEGROSQL(c, "create causet if not exists test_not_exists(a int);")
  1361  }
  1362  
  1363  // TestCreateDBIfNotExists parallel exec create database if not exists xxx. No error returns is expected.
  1364  func (s *testStateChangeSuite) TestCreateDBIfNotExists(c *C) {
  1365  	defer s.se.InterDircute(context.Background(), "drop database test_not_exists")
  1366  	s.testParallelInterDircALLEGROSQL(c, "create database if not exists test_not_exists;")
  1367  }
  1368  
  1369  // TestDBSIfNotExists parallel exec some DBSs with `if not exists` clause. No error returns is expected.
  1370  func (s *testStateChangeSuite) TestDBSIfNotExists(c *C) {
  1371  	defer s.se.InterDircute(context.Background(), "drop causet test_not_exists")
  1372  	_, err := s.se.InterDircute(context.Background(), "create causet if not exists test_not_exists(a int)")
  1373  	c.Assert(err, IsNil)
  1374  
  1375  	// ADD COLUMN
  1376  	s.testParallelInterDircALLEGROSQL(c, "alter causet test_not_exists add defCausumn if not exists b int")
  1377  
  1378  	// ADD COLUMNS
  1379  	s.testParallelInterDircALLEGROSQL(c, "alter causet test_not_exists add defCausumn if not exists (c11 int, d11 int)")
  1380  
  1381  	// ADD INDEX
  1382  	s.testParallelInterDircALLEGROSQL(c, "alter causet test_not_exists add index if not exists idx_b (b)")
  1383  
  1384  	// CREATE INDEX
  1385  	s.testParallelInterDircALLEGROSQL(c, "create index if not exists idx_b on test_not_exists (b)")
  1386  }
  1387  
  1388  // TestDBSIfExists parallel exec some DBSs with `if exists` clause. No error returns is expected.
  1389  func (s *testStateChangeSuite) TestDBSIfExists(c *C) {
  1390  	defer func() {
  1391  		s.se.InterDircute(context.Background(), "drop causet test_exists")
  1392  		s.se.InterDircute(context.Background(), "drop causet test_exists_2")
  1393  	}()
  1394  	_, err := s.se.InterDircute(context.Background(), "create causet if not exists test_exists (a int key, b int)")
  1395  	c.Assert(err, IsNil)
  1396  
  1397  	// DROP COLUMNS
  1398  	s.testParallelInterDircALLEGROSQL(c, "alter causet test_exists drop defCausumn if exists c, drop defCausumn if exists d")
  1399  
  1400  	// DROP COLUMN
  1401  	s.testParallelInterDircALLEGROSQL(c, "alter causet test_exists drop defCausumn if exists b") // only `a` exists now
  1402  
  1403  	// CHANGE COLUMN
  1404  	s.testParallelInterDircALLEGROSQL(c, "alter causet test_exists change defCausumn if exists a c int") // only, `c` exists now
  1405  
  1406  	// MODIFY COLUMN
  1407  	s.testParallelInterDircALLEGROSQL(c, "alter causet test_exists modify defCausumn if exists a bigint")
  1408  
  1409  	// DROP INDEX
  1410  	_, err = s.se.InterDircute(context.Background(), "alter causet test_exists add index idx_c (c)")
  1411  	c.Assert(err, IsNil)
  1412  	s.testParallelInterDircALLEGROSQL(c, "alter causet test_exists drop index if exists idx_c")
  1413  
  1414  	// DROP PARTITION (ADD PARTITION tested in TestParallelAlterAddPartition)
  1415  	_, err = s.se.InterDircute(context.Background(), "create causet test_exists_2 (a int key) partition by range(a) (partition p0 values less than (10), partition p1 values less than (20))")
  1416  	c.Assert(err, IsNil)
  1417  	s.testParallelInterDircALLEGROSQL(c, "alter causet test_exists_2 drop partition if exists p1")
  1418  }
  1419  
  1420  // TestParallelDBSBeforeRunDBSJob tests a stochastik to execute DBS with an outdated information schemaReplicant.
  1421  // This test is used to simulate the following conditions:
  1422  // In a cluster, MilevaDB "a" executes the DBS.
  1423  // MilevaDB "b" fails to load schemaReplicant, then MilevaDB "b" executes the DBS memex associated with the DBS memex executed by "a".
  1424  func (s *testStateChangeSuite) TestParallelDBSBeforeRunDBSJob(c *C) {
  1425  	defer s.se.InterDircute(context.Background(), "drop causet test_block")
  1426  	_, err := s.se.InterDircute(context.Background(), "use test_db_state")
  1427  	c.Assert(err, IsNil)
  1428  	_, err = s.se.InterDircute(context.Background(), "create causet test_block (c1 int, c2 int default 1, index (c1))")
  1429  	c.Assert(err, IsNil)
  1430  
  1431  	// Create two stochastik.
  1432  	se, err := stochastik.CreateStochastik(s.causetstore)
  1433  	c.Assert(err, IsNil)
  1434  	_, err = se.InterDircute(context.Background(), "use test_db_state")
  1435  	c.Assert(err, IsNil)
  1436  	se1, err := stochastik.CreateStochastik(s.causetstore)
  1437  	c.Assert(err, IsNil)
  1438  	_, err = se1.InterDircute(context.Background(), "use test_db_state")
  1439  	c.Assert(err, IsNil)
  1440  
  1441  	intercept := &dbs.TestInterceptor{}
  1442  	firstConnID := uint64(1)
  1443  	finishedCnt := int32(0)
  1444  	interval := 5 * time.Millisecond
  1445  	var stochastikCnt int32 // stochastikCnt is the number of stochastik that goes into the function of OnGetSchemaReplicant.
  1446  	intercept.OnGetSchemaReplicantExported = func(ctx stochastikctx.Context, is schemareplicant.SchemaReplicant) schemareplicant.SchemaReplicant {
  1447  		// The following code is for testing.
  1448  		// Make sure the two stochastik get the same information schemaReplicant before executing DBS.
  1449  		// After the first stochastik executes its DBS, then the second stochastik executes its DBS.
  1450  		var info schemareplicant.SchemaReplicant
  1451  		atomic.AddInt32(&stochastikCnt, 1)
  1452  		for {
  1453  			// Make sure there are two stochastik running here.
  1454  			if atomic.LoadInt32(&stochastikCnt) == 2 {
  1455  				info = is
  1456  				break
  1457  			}
  1458  			// Print log to notify if TestParallelDBSBeforeRunDBSJob hang up
  1459  			log.Info("sleep in TestParallelDBSBeforeRunDBSJob", zap.String("interval", interval.String()))
  1460  			time.Sleep(interval)
  1461  		}
  1462  
  1463  		currID := ctx.GetStochastikVars().ConnectionID
  1464  		for {
  1465  			seCnt := atomic.LoadInt32(&stochastikCnt)
  1466  			// Make sure the two stochastik have got the same information schemaReplicant. And the first stochastik can continue to go on,
  1467  			// or the first stochastik finished this ALLEGROALLEGROSQL(seCnt = finishedCnt), then other stochastik can continue to go on.
  1468  			if currID == firstConnID || seCnt == finishedCnt {
  1469  				break
  1470  			}
  1471  			// Print log to notify if TestParallelDBSBeforeRunDBSJob hang up
  1472  			log.Info("sleep in TestParallelDBSBeforeRunDBSJob", zap.String("interval", interval.String()))
  1473  			time.Sleep(interval)
  1474  		}
  1475  
  1476  		return info
  1477  	}
  1478  	d := s.dom.DBS()
  1479  	d.(dbs.DBSForTest).SetInterceptor(intercept)
  1480  
  1481  	// Make sure the connection 1 executes a ALLEGROALLEGROSQL before the connection 2.
  1482  	// And the connection 2 executes a ALLEGROALLEGROSQL with an outdated information schemaReplicant.
  1483  	wg := sync.WaitGroup{}
  1484  	wg.Add(2)
  1485  	go func() {
  1486  		defer wg.Done()
  1487  
  1488  		se.SetConnectionID(firstConnID)
  1489  		_, err1 := se.InterDircute(context.Background(), "alter causet test_block drop defCausumn c2")
  1490  		c.Assert(err1, IsNil)
  1491  		// Sleep a while to make sure the connection 2 break out the first for loop in OnGetSchemaReplicantExported, otherwise atomic.LoadInt32(&stochastikCnt) == 2 will be false forever.
  1492  		time.Sleep(100 * time.Millisecond)
  1493  		atomic.StoreInt32(&stochastikCnt, finishedCnt)
  1494  	}()
  1495  	go func() {
  1496  		defer wg.Done()
  1497  
  1498  		se1.SetConnectionID(2)
  1499  		_, err2 := se1.InterDircute(context.Background(), "alter causet test_block add defCausumn c2 int")
  1500  		c.Assert(err2, NotNil)
  1501  		c.Assert(strings.Contains(err2.Error(), "Information schemaReplicant is changed"), IsTrue)
  1502  	}()
  1503  
  1504  	wg.Wait()
  1505  
  1506  	intercept = &dbs.TestInterceptor{}
  1507  	d.(dbs.DBSForTest).SetInterceptor(intercept)
  1508  }
  1509  
  1510  func (s *testStateChangeSuite) TestParallelAlterSchemaCharsetAndDefCauslate(c *C) {
  1511  	allegrosql := "ALTER SCHEMA test_db_state CHARSET utf8mb4 COLLATE utf8mb4_general_ci"
  1512  	f := func(c *C, err1, err2 error) {
  1513  		c.Assert(err1, IsNil)
  1514  		c.Assert(err2, IsNil)
  1515  	}
  1516  	s.testControlParallelInterDircALLEGROSQL(c, allegrosql, allegrosql, f)
  1517  	allegrosql = `SELECT default_character_set_name, default_defCauslation_name
  1518  			FROM information_schema.schemata
  1519  			WHERE schema_name='test_db_state'`
  1520  	tk := testkit.NewTestKit(c, s.causetstore)
  1521  	tk.MustQuery(allegrosql).Check(testkit.Rows("utf8mb4 utf8mb4_general_ci"))
  1522  }
  1523  
  1524  // TestParallelTruncateBlockAndAddDeferredCauset tests add defCausumn when truncate causet.
  1525  func (s *testStateChangeSuite) TestParallelTruncateBlockAndAddDeferredCauset(c *C) {
  1526  	sql1 := "truncate causet t"
  1527  	sql2 := "alter causet t add defCausumn c3 int"
  1528  	f := func(c *C, err1, err2 error) {
  1529  		c.Assert(err1, IsNil)
  1530  		c.Assert(err2, NotNil)
  1531  		c.Assert(err2.Error(), Equals, "[petri:8028]Information schemaReplicant is changed during the execution of the memex(for example, causet definition may be uFIDelated by other DBS ran in parallel). If you see this error often, try increasing `milevadb_max_delta_schema_count`. [try again later]")
  1532  	}
  1533  	s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f)
  1534  }
  1535  
  1536  // TestParallelTruncateBlockAndAddDeferredCausets tests add defCausumns when truncate causet.
  1537  func (s *testStateChangeSuite) TestParallelTruncateBlockAndAddDeferredCausets(c *C) {
  1538  	sql1 := "truncate causet t"
  1539  	sql2 := "alter causet t add defCausumn c3 int, add defCausumn c4 int"
  1540  	f := func(c *C, err1, err2 error) {
  1541  		c.Assert(err1, IsNil)
  1542  		c.Assert(err2, NotNil)
  1543  		c.Assert(err2.Error(), Equals, "[petri:8028]Information schemaReplicant is changed during the execution of the memex(for example, causet definition may be uFIDelated by other DBS ran in parallel). If you see this error often, try increasing `milevadb_max_delta_schema_count`. [try again later]")
  1544  	}
  1545  	s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f)
  1546  }
  1547  
  1548  // TestParallelFlashbackBlock tests parallel flashback causet.
  1549  func (s *serialTestStateChangeSuite) TestParallelFlashbackBlock(c *C) {
  1550  	c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/spacetime/autoid/mockAutoIDChange", `return(true)`), IsNil)
  1551  	defer func(originGC bool) {
  1552  		c.Assert(failpoint.Disable("github.com/whtcorpsinc/milevadb/spacetime/autoid/mockAutoIDChange"), IsNil)
  1553  		if originGC {
  1554  			dbs.EmulatorGCEnable()
  1555  		} else {
  1556  			dbs.EmulatorGCDisable()
  1557  		}
  1558  	}(dbs.IsEmulatorGCEnable())
  1559  
  1560  	// disable emulator GC.
  1561  	// Disable emulator GC, otherwise, emulator GC will delete causet record as soon as possible after executing drop causet DBS.
  1562  	dbs.EmulatorGCDisable()
  1563  	gcTimeFormat := "20060102-15:04:05 -0700 MST"
  1564  	timeBeforeDrop := time.Now().Add(0 - 48*60*60*time.Second).Format(gcTimeFormat)
  1565  	safePointALLEGROSQL := `INSERT HIGH_PRIORITY INTO allegrosql.milevadb VALUES ('einsteindb_gc_safe_point', '%[1]s', '')
  1566  			       ON DUPLICATE KEY
  1567  			       UFIDelATE variable_value = '%[1]s'`
  1568  	tk := testkit.NewTestKit(c, s.causetstore)
  1569  	// clear GC variables first.
  1570  	tk.MustInterDirc("delete from allegrosql.milevadb where variable_name in ( 'einsteindb_gc_safe_point','einsteindb_gc_enable' )")
  1571  	// set GC safe point
  1572  	tk.MustInterDirc(fmt.Sprintf(safePointALLEGROSQL, timeBeforeDrop))
  1573  	// set GC enable.
  1574  	err := gcutil.EnableGC(tk.Se)
  1575  	c.Assert(err, IsNil)
  1576  
  1577  	// prepare dropped causet.
  1578  	tk.MustInterDirc("use test_db_state")
  1579  	tk.MustInterDirc("drop causet if exists t")
  1580  	tk.MustInterDirc("create causet t (a int);")
  1581  	tk.MustInterDirc("drop causet if exists t")
  1582  	// Test parallel flashback causet.
  1583  	sql1 := "flashback causet t to t_flashback"
  1584  	f := func(c *C, err1, err2 error) {
  1585  		c.Assert(err1, IsNil)
  1586  		c.Assert(err2, NotNil)
  1587  		c.Assert(err2.Error(), Equals, "[schemaReplicant:1050]Block 't_flashback' already exists")
  1588  	}
  1589  	s.testControlParallelInterDircALLEGROSQL(c, sql1, sql1, f)
  1590  
  1591  	// Test parallel flashback causet with different name
  1592  	tk.MustInterDirc("drop causet t_flashback")
  1593  	sql1 = "flashback causet t_flashback"
  1594  	sql2 := "flashback causet t_flashback to t_flashback2"
  1595  	s.testControlParallelInterDircALLEGROSQL(c, sql1, sql2, f)
  1596  }
  1597  
  1598  // TestModifyDeferredCausetTypeArgs test job raw args won't be uFIDelated when error occurs in `uFIDelateVersionAndBlockInfo`.
  1599  func (s *serialTestStateChangeSuite) TestModifyDeferredCausetTypeArgs(c *C) {
  1600  	c.Assert(failpoint.Enable("github.com/whtcorpsinc/milevadb/dbs/mockUFIDelateVersionAndBlockInfoErr", `return(2)`), IsNil)
  1601  	defer func() {
  1602  		c.Assert(failpoint.Disable("github.com/whtcorpsinc/milevadb/dbs/mockUFIDelateVersionAndBlockInfoErr"), IsNil)
  1603  	}()
  1604  
  1605  	tk := testkit.NewTestKit(c, s.causetstore)
  1606  	tk.MustInterDirc("use test")
  1607  	tk.MustInterDirc("drop causet if exists t_modify_defCausumn_args")
  1608  	tk.MustInterDirc("create causet t_modify_defCausumn_args(a int, unique(a))")
  1609  
  1610  	enableChangeDeferredCausetType := tk.Se.GetStochastikVars().EnableChangeDeferredCausetType
  1611  	tk.Se.GetStochastikVars().EnableChangeDeferredCausetType = true
  1612  	defer func() {
  1613  		tk.Se.GetStochastikVars().EnableChangeDeferredCausetType = enableChangeDeferredCausetType
  1614  	}()
  1615  
  1616  	_, err := tk.InterDirc("alter causet t_modify_defCausumn_args modify defCausumn a tinyint")
  1617  	c.Assert(err, NotNil)
  1618  	// error goes like `mock uFIDelate version and blockInfo error,jobID=xx`
  1619  	strs := strings.Split(err.Error(), ",")
  1620  	c.Assert(strs[0], Equals, "[dbs:-1]mock uFIDelate version and blockInfo error")
  1621  	jobID := strings.Split(strs[1], "=")[1]
  1622  
  1623  	tbl := testGetBlockByName(c, tk.Se, "test", "t_modify_defCausumn_args")
  1624  	c.Assert(len(tbl.Meta().DeferredCausets), Equals, 1)
  1625  	c.Assert(len(tbl.Meta().Indices), Equals, 1)
  1626  
  1627  	ID, err := strconv.Atoi(jobID)
  1628  	c.Assert(err, IsNil)
  1629  	var historyJob *perceptron.Job
  1630  	err = ekv.RunInNewTxn(s.causetstore, false, func(txn ekv.Transaction) error {
  1631  		t := spacetime.NewMeta(txn)
  1632  		historyJob, err = t.GetHistoryDBSJob(int64(ID))
  1633  		if err != nil {
  1634  			return err
  1635  		}
  1636  		return nil
  1637  	})
  1638  	c.Assert(err, IsNil)
  1639  	c.Assert(historyJob, NotNil)
  1640  
  1641  	var (
  1642  		newDefCaus               *perceptron.DeferredCausetInfo
  1643  		oldDefCausName           *perceptron.CIStr
  1644  		modifyDeferredCausetTp   byte
  1645  		uFIDelatedAutoRandomBits uint64
  1646  		changingDefCaus          *perceptron.DeferredCausetInfo
  1647  		changingIdxs             []*perceptron.IndexInfo
  1648  	)
  1649  	pos := &ast.DeferredCausetPosition{}
  1650  	err = historyJob.DecodeArgs(&newDefCaus, &oldDefCausName, pos, &modifyDeferredCausetTp, &uFIDelatedAutoRandomBits, &changingDefCaus, &changingIdxs)
  1651  	c.Assert(err, IsNil)
  1652  	c.Assert(changingDefCaus, IsNil)
  1653  	c.Assert(changingIdxs, IsNil)
  1654  }