| 2236 | } |
| 2237 | |
| 2238 | void DatabaseReplicated::renameTable(ContextPtr local_context, const String & table_name, IDatabase & to_database, |
| 2239 | const String & to_table_name, bool exchange, bool dictionary) |
| 2240 | { |
| 2241 | auto txn = local_context->getZooKeeperMetadataTransaction(); |
| 2242 | chassert(txn); |
| 2243 | |
| 2244 | if (this != &to_database) |
| 2245 | throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Moving tables between databases is not supported for Replicated engine"); |
| 2246 | if (table_name == to_table_name) |
| 2247 | throw Exception(ErrorCodes::INCORRECT_QUERY, "Cannot rename table to itself"); |
| 2248 | if (!isTableExist(table_name, local_context)) |
| 2249 | throw Exception(ErrorCodes::UNKNOWN_TABLE, "Table {} does not exist", table_name); |
| 2250 | if (exchange && !to_database.isTableExist(to_table_name, local_context)) |
| 2251 | throw Exception(ErrorCodes::UNKNOWN_TABLE, "Table {} does not exist", to_table_name); |
| 2252 | |
| 2253 | waitDatabaseStarted(); |
| 2254 | |
| 2255 | std::lock_guard lock{metadata_mutex}; |
| 2256 | |
| 2257 | String statement = readMetadataFile(table_name); |
| 2258 | String statement_to; |
| 2259 | if (exchange) |
| 2260 | statement_to = readMetadataFile(to_table_name); |
| 2261 | |
| 2262 | if (txn->isInitialQuery()) |
| 2263 | { |
| 2264 | String metadata_zk_path = zookeeper_path + "/metadata/" + escapeForFileName(table_name); |
| 2265 | String metadata_zk_path_to = zookeeper_path + "/metadata/" + escapeForFileName(to_table_name); |
| 2266 | |
| 2267 | String zk_statement; |
| 2268 | Coordination::Stat stat; |
| 2269 | String zk_statement_to; |
| 2270 | Coordination::Stat stat_to; |
| 2271 | |
| 2272 | /// When performing an ALTER operation on ReplicatedMergeTree tables, |
| 2273 | /// we update the metadata in ZooKeeper before updating it locally. |
| 2274 | /// To prevent overwriting the new version of the metadata, we fetch and |
| 2275 | /// use the latest version and ensure it hasn't changed using a version check. |
| 2276 | auto zookeeper = txn->getZooKeeper(); |
| 2277 | zookeeper->tryGet(metadata_zk_path, zk_statement, &stat); |
| 2278 | zookeeper->tryGet(metadata_zk_path_to, zk_statement_to, &stat_to); |
| 2279 | |
| 2280 | if (!txn->isCreateOrReplaceQuery()) |
| 2281 | txn->addOp(zkutil::makeRemoveRequest(metadata_zk_path, stat.version)); |
| 2282 | |
| 2283 | if (exchange) |
| 2284 | { |
| 2285 | txn->addOp(zkutil::makeRemoveRequest(metadata_zk_path_to, stat_to.version)); |
| 2286 | if (!txn->isCreateOrReplaceQuery()) |
| 2287 | txn->addOp(zkutil::makeCreateRequest(metadata_zk_path, zk_statement_to, zkutil::CreateMode::Persistent)); |
| 2288 | } |
| 2289 | |
| 2290 | /// In case of CREATE OR REPLACE there is no statement for the temporary table in ZK, so we use the local definition |
| 2291 | if (txn->isCreateOrReplaceQuery()) |
| 2292 | txn->addOp(zkutil::makeCreateRequest(metadata_zk_path_to, statement, zkutil::CreateMode::Persistent)); |
| 2293 | else |
| 2294 | txn->addOp(zkutil::makeCreateRequest(metadata_zk_path_to, zk_statement, zkutil::CreateMode::Persistent)); |
| 2295 | } |
nothing calls this directly
no test coverage detected