diff --git a/programs/client/Client.cpp b/programs/client/Client.cpp index d44827d7bec..9171f58b2e8 100644 --- a/programs/client/Client.cpp +++ b/programs/client/Client.cpp @@ -805,6 +805,7 @@ bool Client::processWithFuzzing(const String & full_query) // so that it doesn't influence the exit code. server_exception.reset(); client_exception.reset(); + fuzzer.notifyQueryFailed(ast_to_process); have_error = false; } else if (ast_to_process->formatForErrorMessage().size() > 500) diff --git a/src/Client/QueryFuzzer.cpp b/src/Client/QueryFuzzer.cpp index 3f786f84e2a..f7309695920 100644 --- a/src/Client/QueryFuzzer.cpp +++ b/src/Client/QueryFuzzer.cpp @@ -468,9 +468,21 @@ void QueryFuzzer::fuzzCreateQuery(ASTCreateQuery & create) if (create.storage && create.storage->engine) { + /// Replace ReplicatedMergeTree to ordinary MergeTree + /// to avoid inconsistency of metadata in zookeeper. auto & engine_name = create.storage->engine->name; if (startsWith(engine_name, "Replicated")) + { engine_name = engine_name.substr(strlen("Replicated")); + if (auto & arguments = create.storage->engine->arguments) + { + auto & children = arguments->children; + if (children.size() <= 2) + arguments.reset(); + else + children.erase(children.begin(), children.begin() + 2); + } + } } auto full_name = create.getTable(); @@ -493,7 +505,7 @@ void QueryFuzzer::fuzzCreateQuery(ASTCreateQuery & create) /// Save only tables with unique definition. if (created_tables_hashes.insert(hash).second) - original_table_name_to_fuzzed[original_name].push_back(new_name); + original_table_name_to_fuzzed[original_name].insert(new_name); } void QueryFuzzer::fuzzColumnDeclaration(ASTColumnDeclaration & column) @@ -640,8 +652,9 @@ void QueryFuzzer::fuzzTableName(ASTTableExpression & table) auto it = original_table_name_to_fuzzed.find(table_id.getTableName()); if (it != original_table_name_to_fuzzed.end() && !it->second.empty()) { - const auto & new_table_name = it->second[fuzz_rand() % it->second.size()]; - StorageID new_table_id(table_id.database_name, new_table_name); + auto new_table_name = it->second.begin(); + std::advance(new_table_name, fuzz_rand() % it->second.size()); + StorageID new_table_id(table_id.database_name, *new_table_name); table.database_and_table_name = std::make_shared(new_table_id); } } @@ -709,6 +722,25 @@ ASTs QueryFuzzer::getDropQueriesForFuzzedTables(const ASTDropQuery & drop_query) return queries; } +void QueryFuzzer::notifyQueryFailed(ASTPtr ast) +{ + auto remove_fuzzed_table = [this](const auto & table_name) + { + auto pos = table_name.find("__fuzz_"); + if (pos != std::string::npos) + { + auto original_name = table_name.substr(0, pos); + original_table_name_to_fuzzed[original_name].erase(table_name); + } + }; + + if (const auto * create = ast->as()) + remove_fuzzed_table(create->getTable()); + + if (const auto * insert = ast->as()) + remove_fuzzed_table(insert->getTable()); +} + void QueryFuzzer::fuzz(ASTs & asts) { for (auto & ast : asts) diff --git a/src/Client/QueryFuzzer.h b/src/Client/QueryFuzzer.h index 3771d2bc61a..9afe7867dd2 100644 --- a/src/Client/QueryFuzzer.h +++ b/src/Client/QueryFuzzer.h @@ -60,7 +60,7 @@ struct QueryFuzzer std::unordered_set debug_visited_nodes; ASTPtr * debug_top_ast = nullptr; - std::unordered_map> original_table_name_to_fuzzed; + std::unordered_map> original_table_name_to_fuzzed; std::unordered_map index_of_fuzzed_table; std::set created_tables_hashes; @@ -76,6 +76,7 @@ struct QueryFuzzer DataTypePtr getRandomType(); ASTs getInsertQueriesForFuzzedTables(const String & full_query); ASTs getDropQueriesForFuzzedTables(const ASTDropQuery & drop_query); + void notifyQueryFailed(ASTPtr ast); void replaceWithColumnLike(ASTPtr & ast); void replaceWithTableLike(ASTPtr & ast); void fuzzOrderByElement(ASTOrderByElement * elem); diff --git a/src/Storages/MergeTree/registerStorageMergeTree.cpp b/src/Storages/MergeTree/registerStorageMergeTree.cpp index 6982521f76a..7e2d5e1727b 100644 --- a/src/Storages/MergeTree/registerStorageMergeTree.cpp +++ b/src/Storages/MergeTree/registerStorageMergeTree.cpp @@ -265,7 +265,7 @@ static StoragePtr create(const StorageFactory::Arguments & args) if (max_num_params == 0) msg += "no parameters"; - if (min_num_params == max_num_params) + else if (min_num_params == max_num_params) msg += fmt::format("{} parameters: {}", min_num_params, needed_params); else msg += fmt::format("{} to {} parameters: {}", min_num_params, max_num_params, needed_params);