github.com/pingcap/tidb-lightning@v5.0.0-rc.0.20210428090220-84b649866577+incompatible/lightning/checkpoints/checkpoints_sql_test.go (about)

     1  package checkpoints_test
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"strings"
     7  	"time"
     8  
     9  	"github.com/DATA-DOG/go-sqlmock"
    10  	. "github.com/pingcap/check"
    11  
    12  	"github.com/pingcap/tidb-lightning/lightning/checkpoints"
    13  	"github.com/pingcap/tidb-lightning/lightning/common"
    14  	"github.com/pingcap/tidb-lightning/lightning/mydump"
    15  	"github.com/pingcap/tidb-lightning/lightning/verification"
    16  )
    17  
    18  var _ = Suite(&cpSQLSuite{})
    19  
    20  type cpSQLSuite struct {
    21  	db   *sql.DB
    22  	mock sqlmock.Sqlmock
    23  	cpdb *checkpoints.MySQLCheckpointsDB
    24  }
    25  
    26  func (s *cpSQLSuite) SetUpTest(c *C) {
    27  	db, mock, err := sqlmock.New()
    28  	c.Assert(err, IsNil)
    29  	s.db = db
    30  	s.mock = mock
    31  
    32  	// 1. create the checkpoints database.
    33  	s.mock.
    34  		ExpectExec("CREATE DATABASE IF NOT EXISTS `mock-schema`").
    35  		WillReturnResult(sqlmock.NewResult(1, 1))
    36  	s.mock.
    37  		ExpectExec("CREATE TABLE IF NOT EXISTS `mock-schema`\\.task_v\\d+ .+").
    38  		WillReturnResult(sqlmock.NewResult(2, 1))
    39  	s.mock.
    40  		ExpectExec("CREATE TABLE IF NOT EXISTS `mock-schema`\\.table_v\\d+ .+").
    41  		WillReturnResult(sqlmock.NewResult(3, 1))
    42  	s.mock.
    43  		ExpectExec("CREATE TABLE IF NOT EXISTS `mock-schema`\\.engine_v\\d+ .+").
    44  		WillReturnResult(sqlmock.NewResult(4, 1))
    45  	s.mock.
    46  		ExpectExec("CREATE TABLE IF NOT EXISTS `mock-schema`\\.chunk_v\\d+ .+").
    47  		WillReturnResult(sqlmock.NewResult(5, 1))
    48  
    49  	cpdb, err := checkpoints.NewMySQLCheckpointsDB(context.Background(), s.db, "mock-schema")
    50  	c.Assert(err, IsNil)
    51  	c.Assert(s.mock.ExpectationsWereMet(), IsNil)
    52  	s.cpdb = cpdb
    53  }
    54  
    55  func (s *cpSQLSuite) TearDownTest(c *C) {
    56  	s.mock.ExpectClose()
    57  	c.Assert(s.cpdb.Close(), IsNil)
    58  	c.Assert(s.mock.ExpectationsWereMet(), IsNil)
    59  }
    60  
    61  func (s *cpSQLSuite) TestNormalOperations(c *C) {
    62  	ctx := context.Background()
    63  	cpdb := s.cpdb
    64  
    65  	// 2. initialize with checkpoint data.
    66  
    67  	s.mock.ExpectBegin()
    68  	initializeStmt := s.mock.ExpectPrepare(
    69  		"REPLACE INTO `mock-schema`\\.task_v\\d+")
    70  	initializeStmt.ExpectExec().
    71  		WithArgs(123, "/data", "importer", "127.0.0.1:8287", "127.0.0.1", 4000, "127.0.0.1:2379", "/tmp/sorted-kv", common.ReleaseVersion).
    72  		WillReturnResult(sqlmock.NewResult(6, 1))
    73  	initializeStmt = s.mock.
    74  		ExpectPrepare("INSERT INTO `mock-schema`\\.table_v\\d+")
    75  	initializeStmt.ExpectExec().
    76  		WithArgs(123, "`db1`.`t1`", sqlmock.AnyArg(), int64(1)).
    77  		WillReturnResult(sqlmock.NewResult(7, 1))
    78  	initializeStmt.ExpectExec().
    79  		WithArgs(123, "`db1`.`t2`", sqlmock.AnyArg(), int64(2)).
    80  		WillReturnResult(sqlmock.NewResult(8, 1))
    81  	initializeStmt.ExpectExec().
    82  		WithArgs(123, "`db2`.`t3`", sqlmock.AnyArg(), int64(3)).
    83  		WillReturnResult(sqlmock.NewResult(9, 1))
    84  	s.mock.ExpectCommit()
    85  
    86  	s.mock.MatchExpectationsInOrder(false)
    87  	cfg := newTestConfig()
    88  	err := cpdb.Initialize(ctx, cfg, map[string]*checkpoints.TidbDBInfo{
    89  		"db1": {
    90  			Name: "db1",
    91  			Tables: map[string]*checkpoints.TidbTableInfo{
    92  				"t1": {Name: "t1", ID: 1},
    93  				"t2": {Name: "t2", ID: 2},
    94  			},
    95  		},
    96  		"db2": {
    97  			Name: "db2",
    98  			Tables: map[string]*checkpoints.TidbTableInfo{
    99  				"t3": {Name: "t3", ID: 3},
   100  			},
   101  		},
   102  	})
   103  	s.mock.MatchExpectationsInOrder(true)
   104  	c.Assert(err, IsNil)
   105  	c.Assert(s.mock.ExpectationsWereMet(), IsNil)
   106  
   107  	// 3. set some checkpoints
   108  
   109  	s.mock.ExpectBegin()
   110  	insertEngineStmt := s.mock.
   111  		ExpectPrepare("REPLACE INTO `mock-schema`\\.engine_v\\d+ .+")
   112  	insertEngineStmt.
   113  		ExpectExec().
   114  		WithArgs("`db1`.`t2`", 0, 30).
   115  		WillReturnResult(sqlmock.NewResult(8, 1))
   116  	insertEngineStmt.
   117  		ExpectExec().
   118  		WithArgs("`db1`.`t2`", -1, 30).
   119  		WillReturnResult(sqlmock.NewResult(9, 1))
   120  	insertChunkStmt := s.mock.
   121  		ExpectPrepare("REPLACE INTO `mock-schema`\\.chunk_v\\d+ .+")
   122  	insertChunkStmt.
   123  		ExpectExec().
   124  		WithArgs("`db1`.`t2`", 0, "/tmp/path/1.sql", 0, mydump.SourceTypeSQL, 0, "", 123, []byte("null"), 12, 102400, 1, 5000, 1234567890).
   125  		WillReturnResult(sqlmock.NewResult(10, 1))
   126  	s.mock.ExpectCommit()
   127  
   128  	s.mock.MatchExpectationsInOrder(false)
   129  	err = cpdb.InsertEngineCheckpoints(ctx, "`db1`.`t2`", map[int32]*checkpoints.EngineCheckpoint{
   130  		0: {
   131  			Status: checkpoints.CheckpointStatusLoaded,
   132  			Chunks: []*checkpoints.ChunkCheckpoint{{
   133  				Key: checkpoints.ChunkCheckpointKey{
   134  					Path:   "/tmp/path/1.sql",
   135  					Offset: 0,
   136  				},
   137  				FileMeta: mydump.SourceFileMeta{
   138  					Path:     "/tmp/path/1.sql",
   139  					Type:     mydump.SourceTypeSQL,
   140  					FileSize: 123,
   141  				},
   142  				Chunk: mydump.Chunk{
   143  					Offset:       12,
   144  					EndOffset:    102400,
   145  					PrevRowIDMax: 1,
   146  					RowIDMax:     5000,
   147  				},
   148  				Timestamp: 1234567890,
   149  			}},
   150  		},
   151  		-1: {
   152  			Status: checkpoints.CheckpointStatusLoaded,
   153  			Chunks: nil,
   154  		},
   155  	})
   156  	s.mock.MatchExpectationsInOrder(true)
   157  	c.Assert(err, IsNil)
   158  	c.Assert(s.mock.ExpectationsWereMet(), IsNil)
   159  
   160  	// 4. update some checkpoints
   161  
   162  	cpd := checkpoints.NewTableCheckpointDiff()
   163  	scm := checkpoints.StatusCheckpointMerger{
   164  		EngineID: 0,
   165  		Status:   checkpoints.CheckpointStatusImported,
   166  	}
   167  	scm.MergeInto(cpd)
   168  	scm = checkpoints.StatusCheckpointMerger{
   169  		EngineID: checkpoints.WholeTableEngineID,
   170  		Status:   checkpoints.CheckpointStatusAllWritten,
   171  	}
   172  	scm.MergeInto(cpd)
   173  	rcm := checkpoints.RebaseCheckpointMerger{
   174  		AllocBase: 132861,
   175  	}
   176  	rcm.MergeInto(cpd)
   177  	ccm := checkpoints.ChunkCheckpointMerger{
   178  		EngineID: 0,
   179  		Key:      checkpoints.ChunkCheckpointKey{Path: "/tmp/path/1.sql", Offset: 0},
   180  		Checksum: verification.MakeKVChecksum(4491, 586, 486070148917),
   181  		Pos:      55904,
   182  		RowID:    681,
   183  	}
   184  	ccm.MergeInto(cpd)
   185  
   186  	s.mock.ExpectBegin()
   187  	s.mock.
   188  		ExpectPrepare("UPDATE `mock-schema`\\.chunk_v\\d+ SET pos = .+").
   189  		ExpectExec().
   190  		WithArgs(
   191  			55904, 681, 4491, 586, 486070148917, []byte("null"),
   192  			"`db1`.`t2`", 0, "/tmp/path/1.sql", 0,
   193  		).
   194  		WillReturnResult(sqlmock.NewResult(11, 1))
   195  	s.mock.
   196  		ExpectPrepare("UPDATE `mock-schema`\\.table_v\\d+ SET alloc_base = .+").
   197  		ExpectExec().
   198  		WithArgs(132861, "`db1`.`t2`").
   199  		WillReturnResult(sqlmock.NewResult(12, 1))
   200  	s.mock.
   201  		ExpectPrepare("UPDATE `mock-schema`\\.engine_v\\d+ SET status = .+").
   202  		ExpectExec().
   203  		WithArgs(120, "`db1`.`t2`", 0).
   204  		WillReturnResult(sqlmock.NewResult(13, 1))
   205  	s.mock.
   206  		ExpectPrepare("UPDATE `mock-schema`\\.table_v\\d+ SET status = .+").
   207  		ExpectExec().
   208  		WithArgs(60, "`db1`.`t2`").
   209  		WillReturnResult(sqlmock.NewResult(14, 1))
   210  	s.mock.ExpectCommit()
   211  
   212  	s.mock.MatchExpectationsInOrder(false)
   213  	cpdb.Update(map[string]*checkpoints.TableCheckpointDiff{"`db1`.`t2`": cpd})
   214  	s.mock.MatchExpectationsInOrder(true)
   215  	c.Assert(s.mock.ExpectationsWereMet(), IsNil)
   216  
   217  	// 5. get back the checkpoints
   218  
   219  	s.mock.ExpectBegin()
   220  	s.mock.
   221  		ExpectQuery("SELECT .+ FROM `mock-schema`\\.engine_v\\d+").
   222  		WithArgs("`db1`.`t2`").
   223  		WillReturnRows(
   224  			sqlmock.NewRows([]string{"engine_id", "status"}).
   225  				AddRow(0, 120).
   226  				AddRow(-1, 30),
   227  		)
   228  	s.mock.
   229  		ExpectQuery("SELECT (?s:.+) FROM `mock-schema`\\.chunk_v\\d+").
   230  		WithArgs("`db1`.`t2`").
   231  		WillReturnRows(
   232  			sqlmock.NewRows([]string{
   233  				"engine_id", "path", "offset", "type", "compression", "sort_key", "file_size", "columns",
   234  				"pos", "end_offset", "prev_rowid_max", "rowid_max",
   235  				"kvc_bytes", "kvc_kvs", "kvc_checksum", "unix_timestamp(create_time)",
   236  			}).
   237  				AddRow(
   238  					0, "/tmp/path/1.sql", 0, mydump.SourceTypeSQL, 0, "", 123, "[]",
   239  					55904, 102400, 681, 5000,
   240  					4491, 586, 486070148917, 1234567894,
   241  				),
   242  		)
   243  	s.mock.
   244  		ExpectQuery("SELECT .+ FROM `mock-schema`\\.table_v\\d+").
   245  		WithArgs("`db1`.`t2`").
   246  		WillReturnRows(
   247  			sqlmock.NewRows([]string{"status", "alloc_base", "table_id"}).
   248  				AddRow(60, 132861, int64(2)),
   249  		)
   250  	s.mock.ExpectCommit()
   251  
   252  	cp, err := cpdb.Get(ctx, "`db1`.`t2`")
   253  	c.Assert(err, IsNil)
   254  	c.Assert(cp, DeepEquals, &checkpoints.TableCheckpoint{
   255  		Status:    checkpoints.CheckpointStatusAllWritten,
   256  		AllocBase: 132861,
   257  		TableID:   int64(2),
   258  		Engines: map[int32]*checkpoints.EngineCheckpoint{
   259  			-1: {Status: checkpoints.CheckpointStatusLoaded},
   260  			0: {
   261  				Status: checkpoints.CheckpointStatusImported,
   262  				Chunks: []*checkpoints.ChunkCheckpoint{{
   263  					Key: checkpoints.ChunkCheckpointKey{
   264  						Path:   "/tmp/path/1.sql",
   265  						Offset: 0,
   266  					},
   267  					FileMeta: mydump.SourceFileMeta{
   268  						Path:     "/tmp/path/1.sql",
   269  						Type:     mydump.SourceTypeSQL,
   270  						FileSize: 123,
   271  					},
   272  					ColumnPermutation: []int{},
   273  					Chunk: mydump.Chunk{
   274  						Offset:       55904,
   275  						EndOffset:    102400,
   276  						PrevRowIDMax: 681,
   277  						RowIDMax:     5000,
   278  					},
   279  					Checksum:  verification.MakeKVChecksum(4491, 586, 486070148917),
   280  					Timestamp: 1234567894,
   281  				}},
   282  			},
   283  		},
   284  	})
   285  	c.Assert(s.mock.ExpectationsWereMet(), IsNil)
   286  }
   287  
   288  func (s *cpSQLSuite) TestRemoveAllCheckpoints(c *C) {
   289  	s.mock.ExpectExec("DROP SCHEMA `mock-schema`").WillReturnResult(sqlmock.NewResult(0, 1))
   290  
   291  	err := s.cpdb.RemoveCheckpoint(context.Background(), "all")
   292  	c.Assert(err, IsNil)
   293  }
   294  
   295  func (s *cpSQLSuite) TestRemoveOneCheckpoint(c *C) {
   296  	s.mock.ExpectBegin()
   297  	s.mock.
   298  		ExpectExec("DELETE FROM `mock-schema`\\.chunk_v\\d+ WHERE table_name = \\?").
   299  		WithArgs("`db1`.`t2`").
   300  		WillReturnResult(sqlmock.NewResult(0, 4))
   301  	s.mock.
   302  		ExpectExec("DELETE FROM `mock-schema`\\.engine_v\\d+ WHERE table_name = \\?").
   303  		WithArgs("`db1`.`t2`").
   304  		WillReturnResult(sqlmock.NewResult(0, 2))
   305  	s.mock.
   306  		ExpectExec("DELETE FROM `mock-schema`\\.table_v\\d+ WHERE table_name = \\?").
   307  		WithArgs("`db1`.`t2`").
   308  		WillReturnResult(sqlmock.NewResult(0, 1))
   309  	s.mock.ExpectCommit()
   310  
   311  	err := s.cpdb.RemoveCheckpoint(context.Background(), "`db1`.`t2`")
   312  	c.Assert(err, IsNil)
   313  }
   314  
   315  func (s *cpSQLSuite) TestIgnoreAllErrorCheckpoints(c *C) {
   316  	s.mock.ExpectBegin()
   317  	s.mock.
   318  		ExpectExec("UPDATE `mock-schema`\\.engine_v\\d+ SET status = 30 WHERE 'all' = \\? AND status <= 25").
   319  		WithArgs(sqlmock.AnyArg()).
   320  		WillReturnResult(sqlmock.NewResult(5, 3))
   321  	s.mock.
   322  		ExpectExec("UPDATE `mock-schema`\\.table_v\\d+ SET status = 30 WHERE 'all' = \\? AND status <= 25").
   323  		WithArgs(sqlmock.AnyArg()).
   324  		WillReturnResult(sqlmock.NewResult(6, 2))
   325  	s.mock.ExpectCommit()
   326  
   327  	err := s.cpdb.IgnoreErrorCheckpoint(context.Background(), "all")
   328  	c.Assert(err, IsNil)
   329  }
   330  
   331  func (s *cpSQLSuite) TestIgnoreOneErrorCheckpoint(c *C) {
   332  	s.mock.ExpectBegin()
   333  	s.mock.
   334  		ExpectExec("UPDATE `mock-schema`\\.engine_v\\d+ SET status = 30 WHERE table_name = \\? AND status <= 25").
   335  		WithArgs("`db1`.`t2`").
   336  		WillReturnResult(sqlmock.NewResult(5, 2))
   337  	s.mock.
   338  		ExpectExec("UPDATE `mock-schema`\\.table_v\\d+ SET status = 30 WHERE table_name = \\? AND status <= 25").
   339  		WithArgs("`db1`.`t2`").
   340  		WillReturnResult(sqlmock.NewResult(6, 1))
   341  	s.mock.ExpectCommit()
   342  
   343  	err := s.cpdb.IgnoreErrorCheckpoint(context.Background(), "`db1`.`t2`")
   344  	c.Assert(err, IsNil)
   345  }
   346  
   347  func (s *cpSQLSuite) TestDestroyAllErrorCheckpoints(c *C) {
   348  	s.mock.ExpectBegin()
   349  	s.mock.
   350  		ExpectQuery("SELECT (?s:.+)'all' = \\?").
   351  		WithArgs(sqlmock.AnyArg()).
   352  		WillReturnRows(
   353  			sqlmock.NewRows([]string{"table_name", "__min__", "__max__"}).
   354  				AddRow("`db1`.`t2`", -1, 0),
   355  		)
   356  	s.mock.
   357  		ExpectExec("DELETE FROM `mock-schema`\\.chunk_v\\d+ WHERE table_name IN .+ 'all' = \\?").
   358  		WithArgs(sqlmock.AnyArg()).
   359  		WillReturnResult(sqlmock.NewResult(0, 5))
   360  	s.mock.
   361  		ExpectExec("DELETE FROM `mock-schema`\\.engine_v\\d+ WHERE table_name IN .+ 'all' = \\?").
   362  		WithArgs(sqlmock.AnyArg()).
   363  		WillReturnResult(sqlmock.NewResult(0, 3))
   364  	s.mock.
   365  		ExpectExec("DELETE FROM `mock-schema`\\.table_v\\d+ WHERE 'all' = \\?").
   366  		WithArgs(sqlmock.AnyArg()).
   367  		WillReturnResult(sqlmock.NewResult(0, 2))
   368  	s.mock.ExpectCommit()
   369  
   370  	dtc, err := s.cpdb.DestroyErrorCheckpoint(context.Background(), "all")
   371  	c.Assert(err, IsNil)
   372  	c.Assert(dtc, DeepEquals, []checkpoints.DestroyedTableCheckpoint{{
   373  		TableName:   "`db1`.`t2`",
   374  		MinEngineID: -1,
   375  		MaxEngineID: 0,
   376  	}})
   377  }
   378  
   379  func (s *cpSQLSuite) TestDestroyOneErrorCheckpoints(c *C) {
   380  	s.mock.ExpectBegin()
   381  	s.mock.
   382  		ExpectQuery("SELECT (?s:.+)table_name = \\?").
   383  		WithArgs("`db1`.`t2`").
   384  		WillReturnRows(
   385  			sqlmock.NewRows([]string{"table_name", "__min__", "__max__"}).
   386  				AddRow("`db1`.`t2`", -1, 0),
   387  		)
   388  	s.mock.
   389  		ExpectExec("DELETE FROM `mock-schema`\\.chunk_v\\d+ WHERE .+table_name = \\?").
   390  		WithArgs("`db1`.`t2`").
   391  		WillReturnResult(sqlmock.NewResult(0, 4))
   392  	s.mock.
   393  		ExpectExec("DELETE FROM `mock-schema`\\.engine_v\\d+ WHERE .+table_name = \\?").
   394  		WithArgs("`db1`.`t2`").
   395  		WillReturnResult(sqlmock.NewResult(0, 2))
   396  	s.mock.
   397  		ExpectExec("DELETE FROM `mock-schema`\\.table_v\\d+ WHERE table_name = \\?").
   398  		WithArgs("`db1`.`t2`").
   399  		WillReturnResult(sqlmock.NewResult(0, 1))
   400  	s.mock.ExpectCommit()
   401  
   402  	dtc, err := s.cpdb.DestroyErrorCheckpoint(context.Background(), "`db1`.`t2`")
   403  	c.Assert(err, IsNil)
   404  	c.Assert(dtc, DeepEquals, []checkpoints.DestroyedTableCheckpoint{{
   405  		TableName:   "`db1`.`t2`",
   406  		MinEngineID: -1,
   407  		MaxEngineID: 0,
   408  	}})
   409  }
   410  
   411  func (s *cpSQLSuite) TestDump(c *C) {
   412  	ctx := context.Background()
   413  	t := time.Unix(1555555555, 0).UTC()
   414  
   415  	s.mock.
   416  		ExpectQuery("SELECT (?s:.+) FROM `mock-schema`\\.chunk_v\\d+").
   417  		WillReturnRows(
   418  			sqlmock.NewRows([]string{
   419  				"table_name", "path", "offset", "type", "compression", "sort_key", "file_size", "columns",
   420  				"pos", "end_offset", "prev_rowid_max", "rowid_max",
   421  				"kvc_bytes", "kvc_kvs", "kvc_checksum",
   422  				"create_time", "update_time",
   423  			}).AddRow(
   424  				"`db1`.`t2`", "/tmp/path/1.sql", 0, mydump.SourceTypeSQL, mydump.CompressionNone, "", 456, "[]",
   425  				55904, 102400, 681, 5000,
   426  				4491, 586, 486070148917,
   427  				t, t,
   428  			),
   429  		)
   430  
   431  	var csvBuilder strings.Builder
   432  	err := s.cpdb.DumpChunks(ctx, &csvBuilder)
   433  	c.Assert(err, IsNil)
   434  	c.Assert(csvBuilder.String(), Equals,
   435  		"table_name,path,offset,type,compression,sort_key,file_size,columns,pos,end_offset,prev_rowid_max,rowid_max,kvc_bytes,kvc_kvs,kvc_checksum,create_time,update_time\n"+
   436  			"`db1`.`t2`,/tmp/path/1.sql,0,3,0,,456,[],55904,102400,681,5000,4491,586,486070148917,2019-04-18 02:45:55 +0000 UTC,2019-04-18 02:45:55 +0000 UTC\n",
   437  	)
   438  
   439  	s.mock.
   440  		ExpectQuery("SELECT .+ FROM `mock-schema`\\.engine_v\\d+").
   441  		WillReturnRows(
   442  			sqlmock.NewRows([]string{"table_name", "engine_id", "status", "create_time", "update_time"}).
   443  				AddRow("`db1`.`t2`", -1, 30, t, t).
   444  				AddRow("`db1`.`t2`", 0, 120, t, t),
   445  		)
   446  
   447  	csvBuilder.Reset()
   448  	err = s.cpdb.DumpEngines(ctx, &csvBuilder)
   449  	c.Assert(err, IsNil)
   450  	c.Assert(csvBuilder.String(), Equals,
   451  		"table_name,engine_id,status,create_time,update_time\n"+
   452  			"`db1`.`t2`,-1,30,2019-04-18 02:45:55 +0000 UTC,2019-04-18 02:45:55 +0000 UTC\n"+
   453  			"`db1`.`t2`,0,120,2019-04-18 02:45:55 +0000 UTC,2019-04-18 02:45:55 +0000 UTC\n",
   454  	)
   455  
   456  	s.mock.
   457  		ExpectQuery("SELECT .+ FROM `mock-schema`\\.table_v\\d+").
   458  		WillReturnRows(
   459  			sqlmock.NewRows([]string{"task_id", "table_name", "hash", "status", "alloc_base", "create_time", "update_time"}).
   460  				AddRow(1555555555, "`db1`.`t2`", 0, 90, 132861, t, t),
   461  		)
   462  
   463  	csvBuilder.Reset()
   464  	err = s.cpdb.DumpTables(ctx, &csvBuilder)
   465  	c.Assert(err, IsNil)
   466  	c.Assert(csvBuilder.String(), Equals,
   467  		"task_id,table_name,hash,status,alloc_base,create_time,update_time\n"+
   468  			"1555555555,`db1`.`t2`,0,90,132861,2019-04-18 02:45:55 +0000 UTC,2019-04-18 02:45:55 +0000 UTC\n",
   469  	)
   470  }
   471  
   472  func (s *cpSQLSuite) TestMoveCheckpoints(c *C) {
   473  	ctx := context.Background()
   474  
   475  	s.mock.
   476  		ExpectExec("CREATE SCHEMA IF NOT EXISTS `mock-schema\\.12345678\\.bak`").
   477  		WillReturnResult(sqlmock.NewResult(1, 1))
   478  	s.mock.
   479  		ExpectExec("RENAME TABLE `mock-schema`\\.chunk_v\\d+ TO `mock-schema\\.12345678\\.bak`\\.chunk_v\\d+").
   480  		WillReturnResult(sqlmock.NewResult(0, 1))
   481  	s.mock.
   482  		ExpectExec("RENAME TABLE `mock-schema`\\.engine_v\\d+ TO `mock-schema\\.12345678\\.bak`\\.engine_v\\d+").
   483  		WillReturnResult(sqlmock.NewResult(0, 1))
   484  	s.mock.
   485  		ExpectExec("RENAME TABLE `mock-schema`\\.table_v\\d+ TO `mock-schema\\.12345678\\.bak`\\.table_v\\d+").
   486  		WillReturnResult(sqlmock.NewResult(0, 1))
   487  	s.mock.
   488  		ExpectExec("RENAME TABLE `mock-schema`\\.task_v\\d+ TO `mock-schema\\.12345678\\.bak`\\.task_v\\d+").
   489  		WillReturnResult(sqlmock.NewResult(0, 1))
   490  
   491  	err := s.cpdb.MoveCheckpoints(ctx, 12345678)
   492  	c.Assert(err, IsNil)
   493  }