diff --git a/dbms/src/Debug/DBGInvoker.cpp b/dbms/src/Debug/DBGInvoker.cpp index ce80ba28ab1..230a9aff95b 100644 --- a/dbms/src/Debug/DBGInvoker.cpp +++ b/dbms/src/Debug/DBGInvoker.cpp @@ -40,6 +40,8 @@ DBGInvoker::DBGInvoker() regFunc("add_column_to_tidb_table", MockTiDBTable::dbgFuncAddColumnToTiDBTable); regFunc("drop_column_from_tidb_table", MockTiDBTable::dbgFuncDropColumnFromTiDBTable); regFunc("modify_column_in_tidb_table", MockTiDBTable::dbgFuncModifyColumnInTiDBTable); + regFunc("rename_tidb_table", MockTiDBTable::dbgFuncRenameTiDBTable); + regFunc("truncate_tidb_table", MockTiDBTable::dbgFuncTruncateTiDBTable); regFunc("set_flush_threshold", dbgFuncSetFlushThreshold); diff --git a/dbms/src/Debug/MockTiDB.cpp b/dbms/src/Debug/MockTiDB.cpp index 6f2d4928840..e6692ab59c1 100644 --- a/dbms/src/Debug/MockTiDB.cpp +++ b/dbms/src/Debug/MockTiDB.cpp @@ -221,6 +221,36 @@ void MockTiDB::modifyColumnInTable(const String & database_name, const String & it->tp = column_info.tp; } +void MockTiDB::renameTable(const String & database_name, const String & table_name, const String & new_table_name) +{ + std::lock_guard lock(tables_mutex); + + 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(database_name, 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); +} + +void MockTiDB::truncateTable(const String & database_name, const String & table_name) +{ + std::lock_guard lock(tables_mutex); + + TablePtr table = getTableByNameInternal(database_name, table_name); + + TableID old_table_id = table->table_info.id; + table->table_info.id += 1000; // Just big enough is OK. + + tables_by_id.erase(old_table_id); + tables_by_id.emplace(table->id(), table); +} + TablePtr MockTiDB::getTableByName(const String & database_name, const String & table_name) { std::lock_guard lock(tables_mutex); diff --git a/dbms/src/Debug/MockTiDB.h b/dbms/src/Debug/MockTiDB.h index 5adc0dce5eb..f60c0fe8b59 100644 --- a/dbms/src/Debug/MockTiDB.h +++ b/dbms/src/Debug/MockTiDB.h @@ -74,6 +74,10 @@ class MockTiDB : public ext::singleton void modifyColumnInTable(const String & database_name, const String & table_name, const NameAndTypePair & column); + void renameTable(const String & database_name, const String & table_name, const String & new_table_name); + + void truncateTable(const String & database_name, const String & table_name); + TablePtr getTableByName(const String & database_name, const String & table_name); void traverseTables(std::function f); diff --git a/dbms/src/Debug/dbgFuncMockTiDBTable.cpp b/dbms/src/Debug/dbgFuncMockTiDBTable.cpp index efd17c4dfef..2db846688b9 100644 --- a/dbms/src/Debug/dbgFuncMockTiDBTable.cpp +++ b/dbms/src/Debug/dbgFuncMockTiDBTable.cpp @@ -230,4 +230,35 @@ void MockTiDBTable::dbgFuncModifyColumnInTiDBTable(DB::Context & context, const output(ss.str()); } +void MockTiDBTable::dbgFuncRenameTiDBTable(Context & /*context*/, const ASTs & args, DBGInvoker::Printer output) +{ + if (args.size() != 3) + throw Exception("Args not matched, should be: database-name, table-name, new-table-name", ErrorCodes::BAD_ARGUMENTS); + + const String & database_name = typeid_cast(*args[0]).name; + const String & table_name = typeid_cast(*args[1]).name; + const String & new_table_name = typeid_cast(*args[2]).name; + + MockTiDB::instance().renameTable(database_name, table_name, new_table_name); + + std::stringstream ss; + ss << "renamed table " << database_name << "." << table_name << " to " << database_name << "." << new_table_name; + output(ss.str()); +} + +void MockTiDBTable::dbgFuncTruncateTiDBTable(Context & /*context*/, const ASTs & args, DBGInvoker::Printer output) +{ + if (args.size() != 2) + throw Exception("Args not matched, should be: database-name, table-name", ErrorCodes::BAD_ARGUMENTS); + + const String & database_name = typeid_cast(*args[0]).name; + const String & table_name = typeid_cast(*args[1]).name; + + MockTiDB::instance().truncateTable(database_name, table_name); + + std::stringstream ss; + ss << "truncated table " << database_name << "." << table_name; + output(ss.str()); +} + } // namespace DB diff --git a/dbms/src/Debug/dbgFuncMockTiDBTable.h b/dbms/src/Debug/dbgFuncMockTiDBTable.h index 27414b5582d..92b29a7589a 100644 --- a/dbms/src/Debug/dbgFuncMockTiDBTable.h +++ b/dbms/src/Debug/dbgFuncMockTiDBTable.h @@ -48,6 +48,16 @@ struct MockTiDBTable // Usage: // ./storages-client.sh "DBGInvoke modify_column_in_tidb_table(database_name, table_name, 'col type')" static void dbgFuncModifyColumnInTiDBTable(Context & context, const ASTs & args, DBGInvoker::Printer output); + + // Rename a TiDB table. + // Usage: + // ./storages-client.sh "DBGInvoke rename_tidb_table(database_name, table_name, new_table)" + static void dbgFuncRenameTiDBTable(Context & context, const ASTs & args, DBGInvoker::Printer output); + + // Truncate a TiDB table. + // Usage: + // ./storages-client.sh "DBGInvoke truncate_tidb_table(database_name, table_name)" + static void dbgFuncTruncateTiDBTable(Context & context, const ASTs & args, DBGInvoker::Printer output); }; } // namespace DB diff --git a/tests/mutable-test/txn_schema/rename_on_read.test b/tests/mutable-test/txn_schema/rename_on_read.test new file mode 100644 index 00000000000..ab1b1148c0d --- /dev/null +++ b/tests/mutable-test/txn_schema/rename_on_read.test @@ -0,0 +1,25 @@ +=> DBGInvoke __enable_schema_sync_service('false') + +=> DBGInvoke __drop_tidb_table(default, test) +=> drop table if exists default.test + +=> DBGInvoke __drop_tidb_table(default, test1) +=> drop table if exists default.test1 + +=> DBGInvoke __set_flush_threshold(1000000, 1000000) +=> DBGInvoke __mock_schema_syncer('true') + +=> DBGInvoke __mock_tidb_table(default, test, 'col_1 String') +=> DBGInvoke __refresh_schemas() +=> select * from default.test +=> DBGInvoke __rename_tidb_table(default, test, test1) +=> select * from default.test +=> select * from default.test " --schema_version "100 +Received exception from server (version {#WORD}): +Code: 60. DB::Exception: Received from {#WORD} DB::Exception: Table default.test doesn't exist.. +=> select * from default.test1 +=> select * from default.test1 " --schema_version "100 + +=> DBGInvoke __drop_tidb_table(default, test1) +=> drop table if exists default.test1 +=> DBGInvoke __enable_schema_sync_service('true') diff --git a/tests/mutable-test/txn_schema/rename_on_write.test b/tests/mutable-test/txn_schema/rename_on_write.test new file mode 100644 index 00000000000..3b031c45f09 --- /dev/null +++ b/tests/mutable-test/txn_schema/rename_on_write.test @@ -0,0 +1,30 @@ +=> DBGInvoke __enable_schema_sync_service('false') + +=> DBGInvoke __drop_tidb_table(default, test) +=> drop table if exists default.test + +=> DBGInvoke __drop_tidb_table(default, test1) +=> drop table if exists default.test1 + +=> DBGInvoke __set_flush_threshold(1000000, 1000000) +=> DBGInvoke __mock_schema_syncer('true') + +=> DBGInvoke __mock_tidb_table(default, test, 'col_1 String') +=> DBGInvoke __refresh_schemas() +=> DBGInvoke __put_region(4, 0, 100, default, test) +=> select col_1 from default.test +=> DBGInvoke __add_column_to_tidb_table(default, test, 'col_2 Nullable(Int8)') +=> DBGInvoke __raft_insert_row(default, test, 4, 50, 'test1', 1) +=> DBGInvoke __rename_tidb_table(default, test, test1) +=> DBGInvoke __try_flush_region(4) +=> select * from default.test +Received exception from server (version {#WORD}): +Code: 60. DB::Exception: Received from {#WORD} DB::Exception: Table default.test doesn't exist.. +=> select * from default.test1 +┌─col_1─┬─_tidb_rowid─┬─col_2─┐ +│ test1 │ 50 │ 1 │ +└───────┴─────────────┴───────┘ + +=> DBGInvoke __drop_tidb_table(default, test1) +=> drop table if exists default.test1 +=> DBGInvoke __enable_schema_sync_service('true') diff --git a/tests/mutable-test/txn_schema/truncate_on_read.test b/tests/mutable-test/txn_schema/truncate_on_read.test new file mode 100644 index 00000000000..9aa469e118b --- /dev/null +++ b/tests/mutable-test/txn_schema/truncate_on_read.test @@ -0,0 +1,26 @@ +=> DBGInvoke __enable_schema_sync_service('false') + +=> DBGInvoke __drop_tidb_table(default, test) +=> drop table if exists default.test + +=> DBGInvoke __set_flush_threshold(1000000, 1000000) +=> DBGInvoke __mock_schema_syncer('true') + +=> DBGInvoke __mock_tidb_table(default, test, 'col_1 String') +=> DBGInvoke __refresh_schemas() +=> DBGInvoke __put_region(4, 0, 100, default, test) +=> DBGInvoke __raft_insert_row(default, test, 4, 50, 'test1') +=> select * from default.test +┌─col_1─┬─_tidb_rowid─┐ +│ test1 │ 50 │ +└───────┴─────────────┘ +=> DBGInvoke __truncate_tidb_table(default, test) +=> select * from default.test +┌─col_1─┬─_tidb_rowid─┐ +│ test1 │ 50 │ +└───────┴─────────────┘ +=> select * from default.test " --schema_version "100 + +=> DBGInvoke __drop_tidb_table(default, test) +=> drop table if exists default.test +=> DBGInvoke __enable_schema_sync_service('true') diff --git a/tests/mutable-test/txn_schema/truncate_on_write.test b/tests/mutable-test/txn_schema/truncate_on_write.test new file mode 100644 index 00000000000..62cb594151b --- /dev/null +++ b/tests/mutable-test/txn_schema/truncate_on_write.test @@ -0,0 +1,25 @@ +=> DBGInvoke __enable_schema_sync_service('false') + +=> DBGInvoke __drop_tidb_table(default, test) +=> drop table if exists default.test + +=> DBGInvoke __set_flush_threshold(1000000, 1000000) +=> DBGInvoke __mock_schema_syncer('true') + +=> DBGInvoke __mock_tidb_table(default, test, 'col_1 String') +=> DBGInvoke __refresh_schemas() +=> DBGInvoke __put_region(4, 0, 100, default, test) +=> DBGInvoke __raft_insert_row(default, test, 4, 50, 'test1') +=> select col_1 from default.test +┌─col_1─┐ +│ test1 │ +└───────┘ +=> DBGInvoke __add_column_to_tidb_table(default, test, 'col_2 Nullable(Int8)') +=> DBGInvoke __raft_insert_row(default, test, 4, 51, 'test1', 1) +=> DBGInvoke __truncate_tidb_table(default, test) +=> DBGInvoke __try_flush_region(4) +=> select * from default.test + +=> DBGInvoke __drop_tidb_table(default, test) +=> drop table if exists default.test +=> DBGInvoke __enable_schema_sync_service('true')