From 6887f4e6b49bb9f32f3d3f137e00bc7bfa248074 Mon Sep 17 00:00:00 2001 From: glorv Date: Tue, 27 Oct 2020 23:50:27 +0800 Subject: [PATCH] fix autoid for v4.0.0 (#430) --- lightning/backend/tidb.go | 27 ++++++- lightning/backend/tidb_test.go | 138 +++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+), 4 deletions(-) diff --git a/lightning/backend/tidb.go b/lightning/backend/tidb.go index 448bdada5..165387cd3 100644 --- a/lightning/backend/tidb.go +++ b/lightning/backend/tidb.go @@ -432,7 +432,7 @@ func (be *tidbBackend) FetchRemoteTableModels(ctx context.Context, schemaName st // init auto id column for each table for _, tbl := range tables { tblName := common.UniqueTable(schemaName, tbl.Name.O) - rows, e = tx.Query(fmt.Sprintf("SHOW TABLE %s next_row_id", tblName)) + rows, e = tx.Query(fmt.Sprintf("SHOW TABLE %s NEXT_ROW_ID", tblName)) if e != nil { return e } @@ -441,10 +441,29 @@ func (be *tidbBackend) FetchRemoteTableModels(ctx context.Context, schemaName st dbName, tblName, columnName, idType string nextID int64 ) - if e := rows.Scan(&dbName, &tblName, &columnName, &nextID, &idType); e != nil { - _ = rows.Close() - return e + columns, err := rows.Columns() + if err != nil { + return err } + + //+--------------+------------+-------------+--------------------+----------------+ + //| DB_NAME | TABLE_NAME | COLUMN_NAME | NEXT_GLOBAL_ROW_ID | ID_TYPE | + //+--------------+------------+-------------+--------------------+----------------+ + //| testsysbench | t | _tidb_rowid | 1 | AUTO_INCREMENT | + //+--------------+------------+-------------+--------------------+----------------+ + + // if columns length is 4, it doesn't contains the last column `ID_TYPE`, and it will always be 'AUTO_INCREMENT' + // for v4.0.0~v4.0.2 show table t next_row_id only returns 4 columns. + if len(columns) == 4 { + err = rows.Scan(&dbName, &tblName, &columnName, &nextID) + idType = "AUTO_INCREMENT" + } else { + err = rows.Scan(&dbName, &tblName, &columnName, &nextID, &idType) + } + if err != nil { + return err + } + for _, col := range tbl.Columns { if col.Name.O == columnName { switch idType { diff --git a/lightning/backend/tidb_test.go b/lightning/backend/tidb_test.go index 482a0bc53..5718c160c 100644 --- a/lightning/backend/tidb_test.go +++ b/lightning/backend/tidb_test.go @@ -201,3 +201,141 @@ func (s *mysqlSuite) TestStrictMode(c *C) { }, 1, []int{1, 0, -1}) c.Assert(err, ErrorMatches, ".*incorrect ascii value .* for column s1") } + +func (s *mysqlSuite) TestFetchRemoteTableModels_3_x(c *C) { + s.mockDB.ExpectBegin() + s.mockDB.ExpectQuery("SELECT version()"). + WillReturnRows(sqlmock.NewRows([]string{"version()"}).AddRow("5.7.25-TiDB-v3.0.18")) + s.mockDB.ExpectQuery("\\QSELECT table_name, column_name, column_type, extra FROM information_schema.columns WHERE table_schema = ? ORDER BY table_name, ordinal_position;\\E"). + WithArgs("test"). + WillReturnRows(sqlmock.NewRows([]string{"table_name", "column_name", "column_type", "extra"}). + AddRow("t", "id", "int(10)", "auto_increment")) + s.mockDB.ExpectCommit() + + bk := kv.NewTiDBBackend(s.dbHandle, config.ErrorOnDup) + tableInfos, err := bk.FetchRemoteTableModels(context.Background(), "test") + c.Assert(err, IsNil) + c.Assert(tableInfos, DeepEquals, []*model.TableInfo{ + { + Name: model.NewCIStr("t"), + State: model.StatePublic, + PKIsHandle: true, + Columns: []*model.ColumnInfo{ + { + Name: model.NewCIStr("id"), + Offset: 0, + State: model.StatePublic, + FieldType: types.FieldType{ + Flag: mysql.AutoIncrementFlag, + }, + }, + }, + }, + }) +} + +func (s *mysqlSuite) TestFetchRemoteTableModels_4_0(c *C) { + s.mockDB.ExpectBegin() + s.mockDB.ExpectQuery("SELECT version()"). + WillReturnRows(sqlmock.NewRows([]string{"version()"}).AddRow("5.7.25-TiDB-v4.0.0")) + s.mockDB.ExpectQuery("\\QSELECT table_name, column_name, column_type, extra FROM information_schema.columns WHERE table_schema = ? ORDER BY table_name, ordinal_position;\\E"). + WithArgs("test"). + WillReturnRows(sqlmock.NewRows([]string{"table_name", "column_name", "column_type", "extra"}). + AddRow("t", "id", "bigint(20) unsigned", "auto_increment")) + s.mockDB.ExpectQuery("SHOW TABLE `test`.`t` NEXT_ROW_ID"). + WillReturnRows(sqlmock.NewRows([]string{"DB_NAME", "TABLE_NAME", "COLUMN_NAME", "NEXT_GLOBAL_ROW_ID"}). + AddRow("test", "t", "id", int64(1))) + s.mockDB.ExpectCommit() + + bk := kv.NewTiDBBackend(s.dbHandle, config.ErrorOnDup) + tableInfos, err := bk.FetchRemoteTableModels(context.Background(), "test") + c.Assert(err, IsNil) + c.Assert(tableInfos, DeepEquals, []*model.TableInfo{ + { + Name: model.NewCIStr("t"), + State: model.StatePublic, + PKIsHandle: true, + Columns: []*model.ColumnInfo{ + { + Name: model.NewCIStr("id"), + Offset: 0, + State: model.StatePublic, + FieldType: types.FieldType{ + Flag: mysql.AutoIncrementFlag | mysql.UnsignedFlag, + }, + }, + }, + }, + }) +} + +func (s *mysqlSuite) TestFetchRemoteTableModels_4_x_auto_increment(c *C) { + s.mockDB.ExpectBegin() + s.mockDB.ExpectQuery("SELECT version()"). + WillReturnRows(sqlmock.NewRows([]string{"version()"}).AddRow("5.7.25-TiDB-v4.0.7")) + s.mockDB.ExpectQuery("\\QSELECT table_name, column_name, column_type, extra FROM information_schema.columns WHERE table_schema = ? ORDER BY table_name, ordinal_position;\\E"). + WithArgs("test"). + WillReturnRows(sqlmock.NewRows([]string{"table_name", "column_name", "column_type", "extra"}). + AddRow("t", "id", "bigint(20)", "")) + s.mockDB.ExpectQuery("SHOW TABLE `test`.`t` NEXT_ROW_ID"). + WillReturnRows(sqlmock.NewRows([]string{"DB_NAME", "TABLE_NAME", "COLUMN_NAME", "NEXT_GLOBAL_ROW_ID", "ID_TYPE"}). + AddRow("test", "t", "id", int64(1), "AUTO_INCREMENT")) + s.mockDB.ExpectCommit() + + bk := kv.NewTiDBBackend(s.dbHandle, config.ErrorOnDup) + tableInfos, err := bk.FetchRemoteTableModels(context.Background(), "test") + c.Assert(err, IsNil) + c.Assert(tableInfos, DeepEquals, []*model.TableInfo{ + { + Name: model.NewCIStr("t"), + State: model.StatePublic, + PKIsHandle: true, + Columns: []*model.ColumnInfo{ + { + Name: model.NewCIStr("id"), + Offset: 0, + State: model.StatePublic, + FieldType: types.FieldType{ + Flag: mysql.AutoIncrementFlag, + }, + }, + }, + }, + }) +} + +func (s *mysqlSuite) TestFetchRemoteTableModels_4_x_auto_random(c *C) { + s.mockDB.ExpectBegin() + s.mockDB.ExpectQuery("SELECT version()"). + WillReturnRows(sqlmock.NewRows([]string{"version()"}).AddRow("5.7.25-TiDB-v4.0.7")) + s.mockDB.ExpectQuery("\\QSELECT table_name, column_name, column_type, extra FROM information_schema.columns WHERE table_schema = ? ORDER BY table_name, ordinal_position;\\E"). + WithArgs("test"). + WillReturnRows(sqlmock.NewRows([]string{"table_name", "column_name", "column_type", "extra"}). + AddRow("t", "id", "bigint(20)", "")) + s.mockDB.ExpectQuery("SHOW TABLE `test`.`t` NEXT_ROW_ID"). + WillReturnRows(sqlmock.NewRows([]string{"DB_NAME", "TABLE_NAME", "COLUMN_NAME", "NEXT_GLOBAL_ROW_ID", "ID_TYPE"}). + AddRow("test", "t", "id", int64(1), "AUTO_RANDOM")) + s.mockDB.ExpectCommit() + + bk := kv.NewTiDBBackend(s.dbHandle, config.ErrorOnDup) + tableInfos, err := bk.FetchRemoteTableModels(context.Background(), "test") + c.Assert(err, IsNil) + c.Assert(tableInfos, DeepEquals, []*model.TableInfo{ + { + Name: model.NewCIStr("t"), + State: model.StatePublic, + PKIsHandle: true, + AutoRandomBits: 1, + Columns: []*model.ColumnInfo{ + { + Name: model.NewCIStr("id"), + Offset: 0, + State: model.StatePublic, + FieldType: types.FieldType{ + Flag: mysql.PriKeyFlag, + }, + }, + }, + }, + }) +}