github.com/pingcap/br@v5.3.0-alpha.0.20220125034240-ec59c7b6ce30+incompatible/pkg/lightning/restore/tidb_test.go (about)

     1  // Copyright 2019 PingCAP, 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 restore
    15  
    16  import (
    17  	"context"
    18  	"testing"
    19  
    20  	"github.com/DATA-DOG/go-sqlmock"
    21  	"github.com/go-sql-driver/mysql"
    22  	. "github.com/pingcap/check"
    23  	"github.com/pingcap/errors"
    24  	"github.com/pingcap/parser/ast"
    25  	"github.com/pingcap/parser/model"
    26  	tmysql "github.com/pingcap/parser/mysql"
    27  	"github.com/pingcap/tidb/ddl"
    28  	"github.com/pingcap/tidb/util/mock"
    29  
    30  	"github.com/pingcap/br/pkg/lightning/checkpoints"
    31  	"github.com/pingcap/br/pkg/lightning/glue"
    32  	"github.com/pingcap/br/pkg/lightning/metric"
    33  	"github.com/pingcap/br/pkg/lightning/mydump"
    34  )
    35  
    36  var _ = Suite(&tidbSuite{})
    37  
    38  type tidbSuite struct {
    39  	mockDB sqlmock.Sqlmock
    40  	timgr  *TiDBManager
    41  	tiGlue glue.Glue
    42  }
    43  
    44  func TestTiDB(t *testing.T) {
    45  	TestingT(t)
    46  }
    47  
    48  func (s *tidbSuite) SetUpTest(c *C) {
    49  	db, mock, err := sqlmock.New()
    50  	c.Assert(err, IsNil)
    51  
    52  	s.mockDB = mock
    53  	defaultSQLMode, err := tmysql.GetSQLMode(tmysql.DefaultSQLMode)
    54  	c.Assert(err, IsNil)
    55  
    56  	s.timgr = NewTiDBManagerWithDB(db, defaultSQLMode)
    57  	s.tiGlue = glue.NewExternalTiDBGlue(db, defaultSQLMode)
    58  }
    59  
    60  func (s *tidbSuite) TearDownTest(c *C) {
    61  	s.timgr.Close()
    62  	c.Assert(s.mockDB.ExpectationsWereMet(), IsNil)
    63  }
    64  
    65  func (s *tidbSuite) TestCreateTableIfNotExistsStmt(c *C) {
    66  	dbName := "testdb"
    67  	createTableIfNotExistsStmt := func(createTable, tableName string) []string {
    68  		res, err := createTableIfNotExistsStmt(s.tiGlue.GetParser(), createTable, dbName, tableName)
    69  		c.Assert(err, IsNil)
    70  		return res
    71  	}
    72  
    73  	c.Assert(
    74  		createTableIfNotExistsStmt("CREATE TABLE `foo`(`bar` TINYINT(1));", "foo"),
    75  		DeepEquals,
    76  		[]string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` TINYINT(1));"},
    77  	)
    78  
    79  	c.Assert(
    80  		createTableIfNotExistsStmt("CREATE TABLE IF NOT EXISTS `foo`(`bar` TINYINT(1));", "foo"),
    81  		DeepEquals,
    82  		[]string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` TINYINT(1));"},
    83  	)
    84  
    85  	// case insensitive
    86  	c.Assert(
    87  		createTableIfNotExistsStmt("/* cOmmEnt */ creAte tablE `fOo`(`bar` TinyinT(1));", "fOo"),
    88  		DeepEquals,
    89  		[]string{"CREATE TABLE IF NOT EXISTS `testdb`.`fOo` (`bar` TINYINT(1));"},
    90  	)
    91  
    92  	c.Assert(
    93  		createTableIfNotExistsStmt("/* coMMenT */ crEatE tAble If not EXISts `FoO`(`bAR` tiNyInT(1));", "FoO"),
    94  		DeepEquals,
    95  		[]string{"CREATE TABLE IF NOT EXISTS `testdb`.`FoO` (`bAR` TINYINT(1));"},
    96  	)
    97  
    98  	// only one "CREATE TABLE" is replaced
    99  	c.Assert(
   100  		createTableIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) COMMENT 'CREATE TABLE');", "foo"),
   101  		DeepEquals,
   102  		[]string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) COMMENT 'CREATE TABLE');"},
   103  	)
   104  
   105  	// test clustered index consistency
   106  	c.Assert(
   107  		createTableIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) PRIMARY KEY CLUSTERED COMMENT 'CREATE TABLE');", "foo"),
   108  		DeepEquals,
   109  		[]string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) PRIMARY KEY /*T![clustered_index] CLUSTERED */ COMMENT 'CREATE TABLE');"},
   110  	)
   111  	c.Assert(
   112  		createTableIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) COMMENT 'CREATE TABLE', PRIMARY KEY (`bar`) NONCLUSTERED);", "foo"),
   113  		DeepEquals,
   114  		[]string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) COMMENT 'CREATE TABLE',PRIMARY KEY(`bar`) /*T![clustered_index] NONCLUSTERED */);"},
   115  	)
   116  	c.Assert(
   117  		createTableIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) PRIMARY KEY /*T![clustered_index] NONCLUSTERED */ COMMENT 'CREATE TABLE');", "foo"),
   118  		DeepEquals,
   119  		[]string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) PRIMARY KEY /*T![clustered_index] NONCLUSTERED */ COMMENT 'CREATE TABLE');"},
   120  	)
   121  	c.Assert(
   122  		createTableIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) COMMENT 'CREATE TABLE', PRIMARY KEY (`bar`) /*T![clustered_index] CLUSTERED */);", "foo"),
   123  		DeepEquals,
   124  		[]string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) COMMENT 'CREATE TABLE',PRIMARY KEY(`bar`) /*T![clustered_index] CLUSTERED */);"},
   125  	)
   126  
   127  	c.Assert(
   128  		createTableIfNotExistsStmt("CREATE TABLE `foo`(`bar` INT(1) PRIMARY KEY AUTO_RANDOM(2) COMMENT 'CREATE TABLE');", "foo"),
   129  		DeepEquals,
   130  		[]string{"CREATE TABLE IF NOT EXISTS `testdb`.`foo` (`bar` INT(1) PRIMARY KEY /*T![auto_rand] AUTO_RANDOM(2) */ COMMENT 'CREATE TABLE');"},
   131  	)
   132  
   133  	// upper case becomes shorter
   134  	c.Assert(
   135  		createTableIfNotExistsStmt("CREATE TABLE `ſ`(`ı` TINYINT(1));", "ſ"),
   136  		DeepEquals,
   137  		[]string{"CREATE TABLE IF NOT EXISTS `testdb`.`ſ` (`ı` TINYINT(1));"},
   138  	)
   139  
   140  	// upper case becomes longer
   141  	c.Assert(
   142  		createTableIfNotExistsStmt("CREATE TABLE `ɑ`(`ȿ` TINYINT(1));", "ɑ"),
   143  		DeepEquals,
   144  		[]string{"CREATE TABLE IF NOT EXISTS `testdb`.`ɑ` (`ȿ` TINYINT(1));"},
   145  	)
   146  
   147  	// non-utf-8
   148  	c.Assert(
   149  		createTableIfNotExistsStmt("CREATE TABLE `\xcc\xcc\xcc`(`\xdd\xdd\xdd` TINYINT(1));", "\xcc\xcc\xcc"),
   150  		DeepEquals,
   151  		[]string{"CREATE TABLE IF NOT EXISTS `testdb`.`\xcc\xcc\xcc` (`ÝÝÝ` TINYINT(1));"},
   152  	)
   153  
   154  	// renaming a table
   155  	c.Assert(
   156  		createTableIfNotExistsStmt("create table foo(x int);", "ba`r"),
   157  		DeepEquals,
   158  		[]string{"CREATE TABLE IF NOT EXISTS `testdb`.`ba``r` (`x` INT);"},
   159  	)
   160  
   161  	// conditional comments
   162  	c.Assert(
   163  		createTableIfNotExistsStmt(`
   164  			/*!40101 SET NAMES binary*/;
   165  			/*!40014 SET FOREIGN_KEY_CHECKS=0*/;
   166  			CREATE TABLE x.y (z double) ENGINE=InnoDB AUTO_INCREMENT=8343230 DEFAULT CHARSET=utf8;
   167  		`, "m"),
   168  		DeepEquals,
   169  		[]string{
   170  			"SET NAMES 'binary';",
   171  			"SET @@SESSION.`FOREIGN_KEY_CHECKS`=0;",
   172  			"CREATE TABLE IF NOT EXISTS `testdb`.`m` (`z` DOUBLE) ENGINE = InnoDB AUTO_INCREMENT = 8343230 DEFAULT CHARACTER SET = UTF8;",
   173  		},
   174  	)
   175  
   176  	// create view
   177  	c.Assert(
   178  		createTableIfNotExistsStmt(`
   179  			/*!40101 SET NAMES binary*/;
   180  			DROP TABLE IF EXISTS v2;
   181  			DROP VIEW IF EXISTS v2;
   182  			SET @PREV_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT;
   183  			SET @PREV_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS;
   184  			SET @PREV_COLLATION_CONNECTION=@@COLLATION_CONNECTION;
   185  			SET character_set_client = utf8;
   186  			SET character_set_results = utf8;
   187  			SET collation_connection = utf8_general_ci;
   188  			CREATE ALGORITHM=UNDEFINED DEFINER=root@192.168.198.178 SQL SECURITY DEFINER VIEW v2 (s) AS SELECT s FROM db1.v1 WHERE i<2;
   189  			SET character_set_client = @PREV_CHARACTER_SET_CLIENT;
   190  			SET character_set_results = @PREV_CHARACTER_SET_RESULTS;
   191  			SET collation_connection = @PREV_COLLATION_CONNECTION;
   192  		`, "m"),
   193  		DeepEquals,
   194  		[]string{
   195  			"SET NAMES 'binary';",
   196  			"DROP TABLE IF EXISTS `testdb`.`m`;",
   197  			"DROP VIEW IF EXISTS `testdb`.`m`;",
   198  			"SET @`PREV_CHARACTER_SET_CLIENT`=@@`character_set_client`;",
   199  			"SET @`PREV_CHARACTER_SET_RESULTS`=@@`character_set_results`;",
   200  			"SET @`PREV_COLLATION_CONNECTION`=@@`collation_connection`;",
   201  			"SET @@SESSION.`character_set_client`=`utf8`;",
   202  			"SET @@SESSION.`character_set_results`=`utf8`;",
   203  			"SET @@SESSION.`collation_connection`=`utf8_general_ci`;",
   204  			"CREATE ALGORITHM = UNDEFINED DEFINER = `root`@`192.168.198.178` SQL SECURITY DEFINER VIEW `testdb`.`m` (`s`) AS SELECT `s` FROM `db1`.`v1` WHERE `i`<2;",
   205  			"SET @@SESSION.`character_set_client`=@`PREV_CHARACTER_SET_CLIENT`;",
   206  			"SET @@SESSION.`character_set_results`=@`PREV_CHARACTER_SET_RESULTS`;",
   207  			"SET @@SESSION.`collation_connection`=@`PREV_COLLATION_CONNECTION`;",
   208  		},
   209  	)
   210  }
   211  
   212  func (s *tidbSuite) TestInitSchema(c *C) {
   213  	ctx := context.Background()
   214  
   215  	s.mockDB.
   216  		ExpectExec("CREATE DATABASE IF NOT EXISTS `db`").
   217  		WillReturnResult(sqlmock.NewResult(1, 1))
   218  	s.mockDB.
   219  		ExpectExec("\\QCREATE TABLE IF NOT EXISTS `db`.`t1` (`a` INT PRIMARY KEY,`b` VARCHAR(200));\\E").
   220  		WillReturnResult(sqlmock.NewResult(2, 1))
   221  	s.mockDB.
   222  		ExpectExec("\\QSET @@SESSION.`FOREIGN_KEY_CHECKS`=0;\\E").
   223  		WillReturnResult(sqlmock.NewResult(0, 0))
   224  	s.mockDB.
   225  		ExpectExec("\\QCREATE TABLE IF NOT EXISTS `db`.`t2` (`xx` TEXT) AUTO_INCREMENT = 11203;\\E").
   226  		WillReturnResult(sqlmock.NewResult(2, 1))
   227  	s.mockDB.
   228  		ExpectClose()
   229  
   230  	s.mockDB.MatchExpectationsInOrder(false) // maps are unordered.
   231  	err := InitSchema(ctx, s.tiGlue, "db", map[string]string{
   232  		"t1": "create table t1 (a int primary key, b varchar(200));",
   233  		"t2": "/*!40014 SET FOREIGN_KEY_CHECKS=0*/;CREATE TABLE `db`.`t2` (xx TEXT) AUTO_INCREMENT=11203;",
   234  	})
   235  	s.mockDB.MatchExpectationsInOrder(true)
   236  	c.Assert(err, IsNil)
   237  }
   238  
   239  func (s *tidbSuite) TestInitSchemaSyntaxError(c *C) {
   240  	ctx := context.Background()
   241  
   242  	s.mockDB.
   243  		ExpectExec("CREATE DATABASE IF NOT EXISTS `db`").
   244  		WillReturnResult(sqlmock.NewResult(1, 1))
   245  	s.mockDB.
   246  		ExpectClose()
   247  
   248  	err := InitSchema(ctx, s.tiGlue, "db", map[string]string{
   249  		"t1": "create table `t1` with invalid syntax;",
   250  	})
   251  	c.Assert(err, NotNil)
   252  }
   253  
   254  func (s *tidbSuite) TestInitSchemaErrorLost(c *C) {
   255  	ctx := context.Background()
   256  
   257  	s.mockDB.
   258  		ExpectExec("CREATE DATABASE IF NOT EXISTS `db`").
   259  		WillReturnResult(sqlmock.NewResult(1, 1))
   260  
   261  	s.mockDB.
   262  		ExpectExec("CREATE TABLE IF NOT EXISTS.*").
   263  		WillReturnError(&mysql.MySQLError{
   264  			Number:  tmysql.ErrTooBigFieldlength,
   265  			Message: "Column length too big",
   266  		})
   267  
   268  	s.mockDB.
   269  		ExpectClose()
   270  
   271  	err := InitSchema(ctx, s.tiGlue, "db", map[string]string{
   272  		"t1": "create table `t1` (a int);",
   273  		"t2": "create table t2 (a int primary key, b varchar(200));",
   274  	})
   275  	c.Assert(err, ErrorMatches, ".*Column length too big.*")
   276  }
   277  
   278  func (s *tidbSuite) TestInitSchemaUnsupportedSchemaError(c *C) {
   279  	ctx := context.Background()
   280  
   281  	s.mockDB.
   282  		ExpectExec("CREATE DATABASE IF NOT EXISTS `db`").
   283  		WillReturnResult(sqlmock.NewResult(1, 1))
   284  	s.mockDB.
   285  		ExpectExec("CREATE TABLE IF NOT EXISTS `db`.`t1`.*").
   286  		WillReturnError(&mysql.MySQLError{
   287  			Number:  tmysql.ErrTooBigFieldlength,
   288  			Message: "Column length too big",
   289  		})
   290  	s.mockDB.
   291  		ExpectClose()
   292  
   293  	err := InitSchema(ctx, s.tiGlue, "db", map[string]string{
   294  		"t1": "create table `t1` (a VARCHAR(999999999));",
   295  	})
   296  	c.Assert(err, ErrorMatches, ".*Column length too big.*")
   297  }
   298  
   299  func (s *tidbSuite) TestDropTable(c *C) {
   300  	ctx := context.Background()
   301  
   302  	s.mockDB.
   303  		ExpectExec("DROP TABLE `db`.`table`").
   304  		WillReturnResult(sqlmock.NewResult(1, 1))
   305  	s.mockDB.
   306  		ExpectClose()
   307  
   308  	err := s.timgr.DropTable(ctx, "`db`.`table`")
   309  	c.Assert(err, IsNil)
   310  }
   311  
   312  func (s *tidbSuite) TestLoadSchemaInfo(c *C) {
   313  	ctx := context.Background()
   314  
   315  	tableCntBefore := metric.ReadCounter(metric.TableCounter.WithLabelValues(metric.TableStatePending, metric.TableResultSuccess))
   316  
   317  	// Prepare the mock reply.
   318  	nodes, _, err := s.timgr.parser.Parse(
   319  		"CREATE TABLE `t1` (`a` INT PRIMARY KEY);"+
   320  			"CREATE TABLE `t2` (`b` VARCHAR(20), `c` BOOL, KEY (`b`, `c`));"+
   321  			// an extra table that not exists in dbMetas
   322  			"CREATE TABLE `t3` (`d` VARCHAR(20), `e` BOOL);",
   323  		"", "")
   324  	c.Assert(err, IsNil)
   325  	tableInfos := make([]*model.TableInfo, 0, len(nodes))
   326  	sctx := mock.NewContext()
   327  	for i, node := range nodes {
   328  		c.Assert(node, FitsTypeOf, &ast.CreateTableStmt{})
   329  		info, err := ddl.MockTableInfo(sctx, node.(*ast.CreateTableStmt), int64(i+100))
   330  		c.Assert(err, IsNil)
   331  		info.State = model.StatePublic
   332  		tableInfos = append(tableInfos, info)
   333  	}
   334  
   335  	dbMetas := []*mydump.MDDatabaseMeta{
   336  		{
   337  			Name: "db",
   338  			Tables: []*mydump.MDTableMeta{
   339  				{
   340  					DB:   "db",
   341  					Name: "t1",
   342  				},
   343  				{
   344  					DB:   "db",
   345  					Name: "t2",
   346  				},
   347  			},
   348  		},
   349  	}
   350  
   351  	loaded, err := LoadSchemaInfo(ctx, dbMetas, func(ctx context.Context, schema string) ([]*model.TableInfo, error) {
   352  		c.Assert(schema, Equals, "db")
   353  		return tableInfos, nil
   354  	})
   355  	c.Assert(err, IsNil)
   356  	c.Assert(loaded, DeepEquals, map[string]*checkpoints.TidbDBInfo{
   357  		"db": {
   358  			Name: "db",
   359  			Tables: map[string]*checkpoints.TidbTableInfo{
   360  				"t1": {
   361  					ID:   100,
   362  					DB:   "db",
   363  					Name: "t1",
   364  					Core: tableInfos[0],
   365  				},
   366  				"t2": {
   367  					ID:   101,
   368  					DB:   "db",
   369  					Name: "t2",
   370  					Core: tableInfos[1],
   371  				},
   372  			},
   373  		},
   374  	})
   375  
   376  	tableCntAfter := metric.ReadCounter(metric.TableCounter.WithLabelValues(metric.TableStatePending, metric.TableResultSuccess))
   377  
   378  	c.Assert(tableCntAfter-tableCntBefore, Equals, 2.0)
   379  }
   380  
   381  func (s *tidbSuite) TestLoadSchemaInfoMissing(c *C) {
   382  	ctx := context.Background()
   383  
   384  	_, err := LoadSchemaInfo(ctx, []*mydump.MDDatabaseMeta{{Name: "asdjalsjdlas"}}, func(ctx context.Context, schema string) ([]*model.TableInfo, error) {
   385  		return nil, errors.Errorf("[schema:1049]Unknown database '%s'", schema)
   386  	})
   387  	c.Assert(err, ErrorMatches, ".*Unknown database.*")
   388  }
   389  
   390  func (s *tidbSuite) TestGetGCLifetime(c *C) {
   391  	ctx := context.Background()
   392  
   393  	s.mockDB.
   394  		ExpectQuery("\\QSELECT VARIABLE_VALUE FROM mysql.tidb WHERE VARIABLE_NAME = 'tikv_gc_life_time'\\E").
   395  		WillReturnRows(sqlmock.NewRows([]string{"VARIABLE_VALUE"}).AddRow("10m"))
   396  	s.mockDB.
   397  		ExpectClose()
   398  
   399  	res, err := ObtainGCLifeTime(ctx, s.timgr.db)
   400  	c.Assert(err, IsNil)
   401  	c.Assert(res, Equals, "10m")
   402  }
   403  
   404  func (s *tidbSuite) TestSetGCLifetime(c *C) {
   405  	ctx := context.Background()
   406  
   407  	s.mockDB.
   408  		ExpectExec("\\QUPDATE mysql.tidb SET VARIABLE_VALUE = ? WHERE VARIABLE_NAME = 'tikv_gc_life_time'\\E").
   409  		WithArgs("12m").
   410  		WillReturnResult(sqlmock.NewResult(1, 1))
   411  	s.mockDB.
   412  		ExpectClose()
   413  
   414  	err := UpdateGCLifeTime(ctx, s.timgr.db, "12m")
   415  	c.Assert(err, IsNil)
   416  }
   417  
   418  func (s *tidbSuite) TestAlterAutoInc(c *C) {
   419  	ctx := context.Background()
   420  
   421  	s.mockDB.
   422  		ExpectExec("\\QALTER TABLE `db`.`table` AUTO_INCREMENT=12345\\E").
   423  		WillReturnResult(sqlmock.NewResult(1, 1))
   424  	s.mockDB.
   425  		ExpectClose()
   426  
   427  	err := AlterAutoIncrement(ctx, s.tiGlue.GetSQLExecutor(), "`db`.`table`", 12345)
   428  	c.Assert(err, IsNil)
   429  }
   430  
   431  func (s *tidbSuite) TestAlterAutoRandom(c *C) {
   432  	ctx := context.Background()
   433  
   434  	s.mockDB.
   435  		ExpectExec("\\QALTER TABLE `db`.`table` AUTO_RANDOM_BASE=12345\\E").
   436  		WillReturnResult(sqlmock.NewResult(1, 1))
   437  	s.mockDB.
   438  		ExpectClose()
   439  
   440  	err := AlterAutoRandom(ctx, s.tiGlue.GetSQLExecutor(), "`db`.`table`", 12345)
   441  	c.Assert(err, IsNil)
   442  }
   443  
   444  func (s *tidbSuite) TestObtainRowFormatVersionSucceed(c *C) {
   445  	ctx := context.Background()
   446  
   447  	s.mockDB.
   448  		ExpectBegin()
   449  	s.mockDB.
   450  		ExpectQuery(`SHOW VARIABLES WHERE Variable_name IN \(.*'tidb_row_format_version'.*\)`).
   451  		WillReturnRows(sqlmock.NewRows([]string{"Variable_name", "Value"}).
   452  			AddRow("tidb_row_format_version", "2").
   453  			AddRow("max_allowed_packet", "1073741824").
   454  			AddRow("div_precision_increment", "10").
   455  			AddRow("time_zone", "-08:00").
   456  			AddRow("lc_time_names", "ja_JP").
   457  			AddRow("default_week_format", "1").
   458  			AddRow("block_encryption_mode", "aes-256-cbc").
   459  			AddRow("group_concat_max_len", "1073741824"))
   460  	s.mockDB.
   461  		ExpectCommit()
   462  	s.mockDB.
   463  		ExpectClose()
   464  
   465  	sysVars := ObtainImportantVariables(ctx, s.tiGlue.GetSQLExecutor())
   466  	c.Assert(sysVars, DeepEquals, map[string]string{
   467  		"tidb_row_format_version": "2",
   468  		"max_allowed_packet":      "1073741824",
   469  		"div_precision_increment": "10",
   470  		"time_zone":               "-08:00",
   471  		"lc_time_names":           "ja_JP",
   472  		"default_week_format":     "1",
   473  		"block_encryption_mode":   "aes-256-cbc",
   474  		"group_concat_max_len":    "1073741824",
   475  	})
   476  }
   477  
   478  func (s *tidbSuite) TestObtainRowFormatVersionFailure(c *C) {
   479  	ctx := context.Background()
   480  
   481  	s.mockDB.
   482  		ExpectBegin()
   483  	s.mockDB.
   484  		ExpectQuery(`SHOW VARIABLES WHERE Variable_name IN \(.*'tidb_row_format_version'.*\)`).
   485  		WillReturnRows(sqlmock.NewRows([]string{"Variable_name", "Value"}).AddRow("time_zone", "+00:00"))
   486  	s.mockDB.
   487  		ExpectCommit()
   488  	s.mockDB.
   489  		ExpectClose()
   490  
   491  	sysVars := ObtainImportantVariables(ctx, s.tiGlue.GetSQLExecutor())
   492  	c.Assert(sysVars, DeepEquals, map[string]string{
   493  		"tidb_row_format_version": "1",
   494  		"max_allowed_packet":      "67108864",
   495  		"div_precision_increment": "4",
   496  		"time_zone":               "+00:00",
   497  		"lc_time_names":           "en_US",
   498  		"default_week_format":     "0",
   499  		"block_encryption_mode":   "aes-128-ecb",
   500  		"group_concat_max_len":    "1024",
   501  	})
   502  }
   503  
   504  func (s *tidbSuite) TestObtainNewCollationEnabled(c *C) {
   505  	ctx := context.Background()
   506  
   507  	s.mockDB.
   508  		ExpectQuery("\\QSELECT variable_value FROM mysql.tidb WHERE variable_name = 'new_collation_enabled'\\E")
   509  	version := ObtainNewCollationEnabled(ctx, s.tiGlue.GetSQLExecutor())
   510  	c.Assert(version, Equals, false)
   511  
   512  	kvMap := map[string]bool{
   513  		"True":  true,
   514  		"False": false,
   515  	}
   516  	for k, v := range kvMap {
   517  		s.mockDB.
   518  			ExpectQuery("\\QSELECT variable_value FROM mysql.tidb WHERE variable_name = 'new_collation_enabled'\\E").
   519  			WillReturnRows(sqlmock.NewRows([]string{"variable_value"}).AddRow(k))
   520  
   521  		version := ObtainNewCollationEnabled(ctx, s.tiGlue.GetSQLExecutor())
   522  		c.Assert(version, Equals, v)
   523  	}
   524  	s.mockDB.
   525  		ExpectClose()
   526  }