mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-27 18:12:02 +00:00
Merge pull request #32756 from CurtizJ/fix-index-hypothesis
Fix race in skipping index of type `hypothesis`
This commit is contained in:
commit
ec46cbef20
@ -146,10 +146,15 @@ bool MergeTreeIndexhypothesisMergedCondition::mayBeTrueOnGranule(const MergeTree
|
|||||||
values.push_back(granule->met);
|
values.push_back(granule->met);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ComparisonGraph * graph = nullptr;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard lock(cache_mutex);
|
||||||
if (const auto it = answer_cache.find(values); it != std::end(answer_cache))
|
if (const auto it = answer_cache.find(values); it != std::end(answer_cache))
|
||||||
return it->second;
|
return it->second;
|
||||||
|
|
||||||
const auto & graph = getGraph(values);
|
graph = getGraph(values);
|
||||||
|
}
|
||||||
|
|
||||||
bool always_false = false;
|
bool always_false = false;
|
||||||
expression_cnf->iterateGroups(
|
expression_cnf->iterateGroups(
|
||||||
@ -166,7 +171,7 @@ bool MergeTreeIndexhypothesisMergedCondition::mayBeTrueOnGranule(const MergeTree
|
|||||||
if (func && func->arguments->children.size() == 2)
|
if (func && func->arguments->children.size() == 2)
|
||||||
{
|
{
|
||||||
const auto expected = ComparisonGraph::atomToCompareResult(atom);
|
const auto expected = ComparisonGraph::atomToCompareResult(atom);
|
||||||
if (graph.isPossibleCompare(expected, func->arguments->children[0], func->arguments->children[1]))
|
if (graph->isPossibleCompare(expected, func->arguments->children[0], func->arguments->children[1]))
|
||||||
{
|
{
|
||||||
/// If graph failed use matching.
|
/// If graph failed use matching.
|
||||||
/// We don't need to check constraints.
|
/// We don't need to check constraints.
|
||||||
@ -177,6 +182,8 @@ bool MergeTreeIndexhypothesisMergedCondition::mayBeTrueOnGranule(const MergeTree
|
|||||||
always_false = true;
|
always_false = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
std::lock_guard lock(cache_mutex);
|
||||||
|
|
||||||
answer_cache[values] = !always_false;
|
answer_cache[values] = !always_false;
|
||||||
return !always_false;
|
return !always_false;
|
||||||
}
|
}
|
||||||
@ -195,11 +202,13 @@ std::unique_ptr<ComparisonGraph> MergeTreeIndexhypothesisMergedCondition::buildG
|
|||||||
return std::make_unique<ComparisonGraph>(active_atomic_formulas);
|
return std::make_unique<ComparisonGraph>(active_atomic_formulas);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ComparisonGraph & MergeTreeIndexhypothesisMergedCondition::getGraph(const std::vector<bool> & values) const
|
const ComparisonGraph * MergeTreeIndexhypothesisMergedCondition::getGraph(const std::vector<bool> & values) const
|
||||||
{
|
{
|
||||||
if (!graph_cache.contains(values))
|
auto [it, inserted] = graph_cache.try_emplace(values);
|
||||||
graph_cache[values] = buildGraph(values);
|
if (inserted)
|
||||||
return *graph_cache.at(values);
|
it->second = buildGraph(values);
|
||||||
|
|
||||||
|
return it->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,11 +21,14 @@ public:
|
|||||||
private:
|
private:
|
||||||
void addConstraints(const ConstraintsDescription & constraints_description);
|
void addConstraints(const ConstraintsDescription & constraints_description);
|
||||||
std::unique_ptr<ComparisonGraph> buildGraph(const std::vector<bool> & values) const;
|
std::unique_ptr<ComparisonGraph> buildGraph(const std::vector<bool> & values) const;
|
||||||
const ComparisonGraph & getGraph(const std::vector<bool> & values) const;
|
const ComparisonGraph * getGraph(const std::vector<bool> & values) const;
|
||||||
|
|
||||||
ASTPtr expression_ast;
|
ASTPtr expression_ast;
|
||||||
std::unique_ptr<CNFQuery> expression_cnf;
|
std::unique_ptr<CNFQuery> expression_cnf;
|
||||||
|
|
||||||
|
/// Part analysis can be done in parallel.
|
||||||
|
/// So, we have shared answer and graph cache.
|
||||||
|
mutable std::mutex cache_mutex;
|
||||||
mutable std::unordered_map<std::vector<bool>, std::unique_ptr<ComparisonGraph>> graph_cache;
|
mutable std::unordered_map<std::vector<bool>, std::unique_ptr<ComparisonGraph>> graph_cache;
|
||||||
mutable std::unordered_map<std::vector<bool>, bool> answer_cache;
|
mutable std::unordered_map<std::vector<bool>, bool> answer_cache;
|
||||||
|
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
OK
|
23
tests/queries/0_stateless/02150_index_hypothesis_race_long.sh
Executable file
23
tests/queries/0_stateless/02150_index_hypothesis_race_long.sh
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||||
|
# shellcheck source=../shell_config.sh
|
||||||
|
. "$CURDIR"/../shell_config.sh
|
||||||
|
|
||||||
|
$CLICKHOUSE_CLIENT -q "DROP TABLE IF EXISTS t_index_hypothesis"
|
||||||
|
|
||||||
|
$CLICKHOUSE_CLIENT -q "CREATE TABLE t_index_hypothesis (a UInt32, b UInt32, INDEX t a != b TYPE hypothesis GRANULARITY 1) ENGINE = MergeTree ORDER BY a"
|
||||||
|
|
||||||
|
$CLICKHOUSE_CLIENT -q "INSERT INTO t_index_hypothesis SELECT number, number + 1 FROM numbers(10000000)"
|
||||||
|
|
||||||
|
for _ in {0..30}; do
|
||||||
|
output=`$CLICKHOUSE_CLIENT -q "SELECT count() FROM t_index_hypothesis WHERE a = b"`
|
||||||
|
if [[ $output != "0" ]]; then
|
||||||
|
echo "output: $output, expected: 0"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo OK
|
||||||
|
|
||||||
|
$CLICKHOUSE_CLIENT -q "DROP TABLE t_index_hypothesis"
|
Loading…
Reference in New Issue
Block a user