| 2234 | |
| 2235 | |
| 2236 | BlockIO InterpreterCreateQuery::doCreateOrReplaceTable(ASTCreateQuery & create, |
| 2237 | const InterpreterCreateQuery::TableProperties & properties, LoadingStrictnessLevel mode) |
| 2238 | { |
| 2239 | /// Replicated database requires separate contexts for each DDL query |
| 2240 | ContextPtr current_context = getContext(); |
| 2241 | if (auto txn = current_context->getZooKeeperMetadataTransaction()) |
| 2242 | txn->setIsCreateOrReplaceQuery(); |
| 2243 | ContextMutablePtr create_context = Context::createCopy(current_context); |
| 2244 | create_context->setQueryContext(std::const_pointer_cast<Context>(current_context)); |
| 2245 | |
| 2246 | /// Before actually creating/replacing the table, check if it will lead to cyclic dependencies. |
| 2247 | checkTableCanBeAddedWithNoCyclicDependencies(create, query_ptr, create_context); |
| 2248 | |
| 2249 | auto make_drop_context = [&]() -> ContextMutablePtr |
| 2250 | { |
| 2251 | ContextMutablePtr drop_context = Context::createCopy(current_context); |
| 2252 | drop_context->setQueryContext(std::const_pointer_cast<Context>(current_context)); |
| 2253 | return drop_context; |
| 2254 | }; |
| 2255 | |
| 2256 | auto ast_drop = make_intrusive<ASTDropQuery>(); |
| 2257 | String table_to_replace_name = create.getTable(); |
| 2258 | |
| 2259 | { |
| 2260 | auto database = DatabaseCatalog::instance().getDatabase(create.getDatabase()); |
| 2261 | if (database->getUUID() == UUIDHelpers::Nil) |
| 2262 | throw Exception(ErrorCodes::INCORRECT_QUERY, |
| 2263 | "{} query is supported only for Atomic databases", |
| 2264 | create.create_or_replace |
| 2265 | ? (create.is_materialized_view ? "CREATE OR REPLACE MATERIALIZED VIEW" |
| 2266 | : (create.isView() ? "CREATE OR REPLACE VIEW" : "CREATE OR REPLACE TABLE")) |
| 2267 | : "REPLACE TABLE"); |
| 2268 | |
| 2269 | if (mode <= LoadingStrictnessLevel::CREATE) |
| 2270 | database->checkTableNameLength(table_to_replace_name); |
| 2271 | } |
| 2272 | |
| 2273 | { |
| 2274 | const String name_hash = TemporaryReplaceTableName::calculateHash(create.getDatabase(), create.getTable()); |
| 2275 | const String random_suffix = [&]() |
| 2276 | { |
| 2277 | if (auto txn = current_context->getZooKeeperMetadataTransaction()) |
| 2278 | { |
| 2279 | /// Avoid different table name on database replicas |
| 2280 | UInt64 hashed_zk_path = sipHash64(txn->getTaskZooKeeperPath()); |
| 2281 | return getHexUIntLowercase(hashed_zk_path); |
| 2282 | } |
| 2283 | if (!current_context->getCurrentQueryId().empty()) |
| 2284 | { |
| 2285 | const UInt32 hashed_query_id = static_cast<UInt32>(sipHash64(current_context->getCurrentQueryId())); |
| 2286 | return getRandomASCIIString(/*length=*/8) + getHexUIntLowercase(hashed_query_id); |
| 2287 | } |
| 2288 | return getRandomASCIIString(/*length=*/16); |
| 2289 | }(); |
| 2290 | |
| 2291 | const String tmp_replace_table_name = TemporaryReplaceTableName{.name_hash = name_hash, .random_suffix = random_suffix}.toString(); |
| 2292 | create.setTable(tmp_replace_table_name); |
| 2293 |
nothing calls this directly
no test coverage detected