Skip to content

Commit

Permalink
Support ddl job type of ActionRenameTables in TiFlash (#4234)
Browse files Browse the repository at this point in the history
close #4215
  • Loading branch information
CalvinNeo authored Mar 15, 2022
1 parent 3aefd55 commit 4c82be1
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 7 deletions.
1 change: 1 addition & 0 deletions dbms/src/Debug/DBGInvoker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ DBGInvoker::DBGInvoker()
regSchemalessFunc("rename_tidb_table", MockTiDBTable::dbgFuncRenameTiDBTable);
regSchemalessFunc("truncate_tidb_table", MockTiDBTable::dbgFuncTruncateTiDBTable);
regSchemalessFunc("create_tidb_tables", MockTiDBTable::dbgFuncCreateTiDBTables);
regSchemalessFunc("rename_tidb_tables", MockTiDBTable::dbgFuncRenameTiDBTables);

regSchemalessFunc("set_flush_threshold", dbgFuncSetFlushThreshold);

Expand Down
39 changes: 39 additions & 0 deletions dbms/src/Debug/MockTiDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,45 @@ void MockTiDB::renameTable(const String & database_name, const String & table_na
version_diff[version] = diff;
}

void MockTiDB::renameTables(const std::vector<std::tuple<std::string, std::string, std::string>> & table_name_map)
{
std::lock_guard lock(tables_mutex);
version++;
SchemaDiff diff;
for (const auto & [database_name, table_name, new_table_name] : table_name_map)
{
TablePtr table = getTableByNameInternal(database_name, table_name);
String qualified_name = database_name + "." + table_name;
String new_qualified_name = database_name + "." + new_table_name;

TableInfo new_table_info = table->table_info;
new_table_info.name = new_table_name;
auto new_table = std::make_shared<Table>(database_name, table->database_id, new_table_name, std::move(new_table_info));

tables_by_id[new_table->table_info.id] = new_table;
tables_by_name.erase(qualified_name);
tables_by_name.emplace(new_qualified_name, new_table);

AffectedOption opt;
opt.schema_id = table->database_id;
opt.table_id = new_table->id();
opt.old_schema_id = table->database_id;
opt.old_table_id = table->id();
diff.affected_opts.push_back(std::move(opt));
}

if (diff.affected_opts.empty())
throw Exception("renameTables should have at least 1 affected_opts", ErrorCodes::LOGICAL_ERROR);

diff.type = SchemaActionType::RenameTables;
diff.schema_id = diff.affected_opts[0].schema_id;
diff.old_schema_id = diff.affected_opts[0].schema_id;
diff.table_id = diff.affected_opts[0].table_id;
diff.old_table_id = diff.affected_opts[0].old_table_id;
diff.version = version;
version_diff[version] = diff;
}

void MockTiDB::truncateTable(const String & database_name, const String & table_name)
{
std::lock_guard lock(tables_mutex);
Expand Down
2 changes: 2 additions & 0 deletions dbms/src/Debug/MockTiDB.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ class MockTiDB : public ext::Singleton<MockTiDB>

void renameTable(const String & database_name, const String & table_name, const String & new_table_name);

void renameTables(const std::vector<std::tuple<std::string, std::string, std::string>> & table_name_map);

void truncateTable(const String & database_name, const String & table_name);

TablePtr getTableByName(const String & database_name, const String & table_name);
Expand Down
16 changes: 16 additions & 0 deletions dbms/src/Debug/dbgFuncMockTiDBTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -317,4 +317,20 @@ void MockTiDBTable::dbgFuncCreateTiDBTables(Context & context, const ASTs & args
output("");
}

void MockTiDBTable::dbgFuncRenameTiDBTables(Context & /*context*/, const ASTs & args, DBGInvoker::Printer output)
{
if (args.size() % 3 != 0)
throw Exception("Args not matched, should be: database-name, table-name, new-table-name, ..., [database-name, table-name, new-table-name]", ErrorCodes::BAD_ARGUMENTS);
std::vector<std::tuple<std::string, std::string, std::string>> table_map;
for (ASTs::size_type i = 0; i < args.size() / 3; i++)
{
const String & database_name = typeid_cast<const ASTIdentifier &>(*args[3 * i]).name;
const String & table_name = typeid_cast<const ASTIdentifier &>(*args[3 * i + 1]).name;
const String & new_table_name = typeid_cast<const ASTIdentifier &>(*args[3 * i + 2]).name;
table_map.emplace_back(database_name, table_name, new_table_name);
}
MockTiDB::instance().renameTables(table_map);
output(fmt::format("renamed tables"));
}

} // namespace DB
5 changes: 5 additions & 0 deletions dbms/src/Debug/dbgFuncMockTiDBTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ struct MockTiDBTable
// ./storage-client.sh "DBGInvoke create_tidb_tables(db_name, table_name, [table_name], ..., [table_name])"
static void dbgFuncCreateTiDBTables(Context & context, const ASTs & args, DBGInvoker::Printer output);

// Trigger a rename tables ddl job.
// Usage:
// ./storage-client.sh "DBGInvoke rename_tidb_tables(database-name, table-name, new-table-name, ..., [database-name, table-name, new-table-name])"
static void dbgFuncRenameTiDBTables(Context & /*context*/, const ASTs & args, DBGInvoker::Printer output);

private:
static void dbgFuncDropTiDBTableImpl(
Context & context,
Expand Down
17 changes: 12 additions & 5 deletions dbms/src/Storages/Transaction/SchemaBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,18 @@ void SchemaBuilder<Getter, NameMapper>::applyDiff(const SchemaDiff & diff)
return;
}

if (diff.type == SchemaActionType::RenameTables)
{
for (auto && opt : diff.affected_opts)
{
auto db_info = getter.getDatabase(opt.schema_id);
if (db_info == nullptr)
throw TiFlashException("miss database: " + std::to_string(diff.schema_id), Errors::DDL::StaleSchema);
applyRenameTable(db_info, opt.table_id);
}
return;
}

auto db_info = getter.getDatabase(diff.schema_id);
if (db_info == nullptr)
{
Expand Down Expand Up @@ -494,11 +506,6 @@ void SchemaBuilder<Getter, NameMapper>::applyDiff(const SchemaDiff & diff)
applySetTiFlashReplica(db_info, diff.table_id);
break;
}
case SchemaActionType::RenameTables:
{
LOG_FMT_WARNING(log, "change type RenameTables is not supported");
break;
}
default:
{
if (diff.type < SchemaActionType::MaxRecognizedType)
Expand Down
2 changes: 1 addition & 1 deletion dbms/src/Storages/Transaction/TiDBSchemaSyncer.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ struct TiDBSchemaSyncer : public SchemaSyncer
used_version++;
diffs.push_back(getter.getSchemaDiff(used_version));
}
LOG_DEBUG(log, "end load schema diffs.");
LOG_FMT_DEBUG(log, "end load schema diffs with total {} entries.", diffs.size());
try
{
for (const auto & diff : diffs)
Expand Down
4 changes: 3 additions & 1 deletion tests/delta-merge-test/raft/schema/create_tidb_tables.test
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@
│ default │ t3 │ DeltaMerge │
└──────────┴──────┴────────────┘

# clean
=> DBGInvoke __drop_tidb_table(default, test)
=> DBGInvoke __drop_tidb_table(default, t1)
=> DBGInvoke __drop_tidb_table(default, t2)
=> DBGInvoke __drop_tidb_table(default, t3)
=> drop table if exists default.t1
=> drop table if exists default.t2
=> drop table if exists default.t3
=> drop table if exists default.t3
=> DBGInvoke __enable_schema_sync_service('true')
31 changes: 31 additions & 0 deletions tests/delta-merge-test/raft/schema/rename_tables.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Preparation.
=> DBGInvoke __enable_schema_sync_service('false')

=> DBGInvoke __drop_tidb_table(default, t1)
=> DBGInvoke __drop_tidb_table(default, t2)
=> drop table if exists default.t1
=> drop table if exists default.t2
=> DBGInvoke __refresh_schemas()

=> DBGInvoke __set_flush_threshold(1000000, 1000000)


=> DBGInvoke __create_tidb_tables(default, t1, t2)
# rename table
=> DBGInvoke __rename_tidb_tables(default, t1, r1, default, t2, r2)
=> DBGInvoke __refresh_schemas()
=> select database,name,engine from system.tables where database='default' and name='r1'
┌─database─┬─name─┬─engine─────┐
│ default │ r1 │ DeltaMerge │
└──────────┴──────┴────────────┘
=> select database,name,engine from system.tables where database='default' and name='r2'
┌─database─┬─name─┬─engine─────┐
│ default │ r2 │ DeltaMerge │
└──────────┴──────┴────────────┘

# clean
=> DBGInvoke __drop_tidb_table(default, r1)
=> DBGInvoke __drop_tidb_table(default, r2)
=> drop table if exists default.r1
=> drop table if exists default.r2
=> DBGInvoke __enable_schema_sync_service('true')
43 changes: 43 additions & 0 deletions tests/fullstack-test2/ddl/rename_table.test
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,46 @@ mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t_n
└───────────────┴───────────┘

mysql> drop table if exists test.t_new;


# test rename tables
mysql> drop table if exists test.t1;
mysql> drop table if exists test.t2;
mysql> drop table if exists test.r1;
mysql> drop table if exists test.r2;
mysql> create table test.t1(a int, b int);
mysql> create table test.t2(a int, b int);
mysql> alter table test.t1 set tiflash replica 1 location labels 'rack', 'host', 'abc'
mysql> alter table test.t2 set tiflash replica 1 location labels 'rack', 'host', 'abc'
func> wait_table test t1
func> wait_table test t2
mysql> insert into test.t1 values (1, 2);
mysql> insert into test.t2 values (3, 4);
mysql> rename table test.t1 to test.r1, test.t2 to test.r2;
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t1;
ERROR 1146 (42S02) at line 1: Table 'test.t1' doesn't exist
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.r1;
+------+------+
| a | b |
+------+------+
| 1 | 2 |
+------+------+
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.t2;
ERROR 1146 (42S02) at line 1: Table 'test.t2' doesn't exist
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.r2;
+------+------+
| a | b |
+------+------+
| 3 | 4 |
+------+------+
mysql> rename table test.r2 to test.r1, test.r1 to test.r2;
ERROR 1050 (42S01) at line 1: Table 'test.r1' already exists
mysql> rename table test.r2 to test.tmp, test.r1 to test.r2, test.tmp to test.r1;
mysql> set session tidb_isolation_read_engines='tiflash'; select * from test.r1;
+------+------+
| a | b |
+------+------+
| 3 | 4 |
+------+------+
mysql> drop table if exists test.r1;
mysql> drop table if exists test.r2;

0 comments on commit 4c82be1

Please sign in to comment.