Repository: ClickHouse/ClickHouse
File: src/Interpreters/executeQuery.cpp (C++)

Code before:
    static std::mutex mutex;
    static std::shared_ptr<QueryFuzzer> fuzzer = std::make_shared<QueryFuzzer>(randomSeed());
    return {fuzzer, std::unique_lock(mutex)};
}


static bool isReadOnlyQuery(const ASTPtr & ast)
{
    auto kind = ast->getQueryKind();
    return kind == IAST::QueryKind::Select
        || kind == IAST::QueryKind::Explain
        || kind == IAST::QueryKind::Show
        || kind == IAST::QueryKind::Describe
        || kind == IAST::QueryKind::Exists;
}


static void executeASTFuzzerQueries(const ASTPtr & ast, const ContextMutablePtr & context, Float64 ast_fuzzer_runs_value, bool any_query)
{
    if (!any_query && !isReadOnlyQuery(ast))
        return;

    size_t num_runs = 0;
    if (ast_fuzzer_runs_value >= 1.0)
    {
        num_runs = static_cast<size_t>(ast_fuzzer_runs_value);
    }
    else
    {
        std::bernoulli_distribution dist(ast_fuzzer_runs_value);
        if (dist(thread_local_rng))
            num_runs = 1;
    }

    if (num_runs == 0)
        return;

    auto logger = getLogger("ASTFuzzer");

    ASTPtr base_ast = ast;

    for (size_t i = 0; i < num_runs; ++i)
    {
        ASTPtr fuzzed_ast;
        {
            auto [fuzzer, lock] = getGlobalASTFuzzer();
            fuzzed_ast = base_ast->clone();
            fuzzer->fuzzMain(fuzzed_ast);
        }

        WriteBufferFromOwnString fuzzed_query_buf;

Review comment (suggestion):
Just for purity, for fractional values, let's also use the Bernoulli distribution that will choose between the floor and ceil with the probability proportional to the fraction. This will generalize the branches.

Code after:
{
    static std::mutex mutex;
    static std::shared_ptr<QueryFuzzer> fuzzer = std::make_shared<QueryFuzzer>(randomSeed());
    return {fuzzer, std::unique_lock(mutex)};
}


static bool isReadOnlyQuery(const ASTPtr & ast)
{
    auto kind = ast->getQueryKind();
    return kind == IAST::QueryKind::Select
        || kind == IAST::QueryKind::Explain
        || kind == IAST::QueryKind::Show
        || kind == IAST::QueryKind::Describe
        || kind == IAST::QueryKind::Exists;
}


static void executeASTFuzzerQueries(const ASTPtr & ast, const ContextMutablePtr & context, Float64 ast_fuzzer_runs_value, bool any_query)
{
    if (!any_query && !isReadOnlyQuery(ast))
        return;

    size_t num_runs = static_cast<size_t>(ast_fuzzer_runs_value);
    double fractional = ast_fuzzer_runs_value - static_cast<double>(num_runs);
    if (fractional > 0)
    {
        std::bernoulli_distribution dist(fractional);
        if (dist(thread_local_rng))
            ++num_runs;
    }

    if (num_runs == 0)
        return;

    auto logger = getLogger("ASTFuzzer");

    ASTPtr base_ast = ast;

    for (size_t i = 0; i < num_runs; ++i)
    {
        ASTPtr fuzzed_ast;
        {
            auto [fuzzer, lock] = getGlobalASTFuzzer();
            fuzzed_ast = base_ast->clone();
            fuzzer->fuzzMain(fuzzed_ast);
        }

        WriteBufferFromOwnString fuzzed_query_buf;
        fuzzed_ast->format(fuzzed_query_buf, IAST::FormatSettings(/*one_line=*/true));
        String fuzzed_query = fuzzed_query_buf.str();