diff --git a/src/Storages/MergeTree/MergeTreeIndexConditionBloomFilter.cpp b/src/Storages/MergeTree/MergeTreeIndexConditionBloomFilter.cpp index 69d63d0e80d..03bc9e4e046 100644 --- a/src/Storages/MergeTree/MergeTreeIndexConditionBloomFilter.cpp +++ b/src/Storages/MergeTree/MergeTreeIndexConditionBloomFilter.cpp @@ -324,14 +324,17 @@ bool MergeTreeIndexConditionBloomFilter::traverseASTIn( return false; } + static bool indexOfCanUseBloomFilter(const ASTPtr & parent) { if (!parent) return true; + /// `parent` is a function where `indexOf` is located. + /// Example: `indexOf(arr, x) = 1`, parent is a function named `equals`. if (const auto * function = parent->as()) { - if (function->name == "arrayElement") + if (function->name == "and") { return true; } @@ -342,23 +345,24 @@ static bool indexOfCanUseBloomFilter(const ASTPtr & parent) if (function->arguments->children.size() != 2) return false; + /// We don't allow constant expressions like `indexOf(arr, x) = 1 + 0` but it's neglible. if (const ASTLiteral * left = function->arguments->children[0]->as()) { - if (function->name == "equals" && left->value.get() != 0) - return true; - else if (function->name == "less" && left->value.get() >= 0) - return true; - else if (function->name == "lessOrEquals" && left->value.get() > 0) - return true; + if (function->name == "equals" && left->value.get() != 0) + return true; + else if (function->name == "less" && left->value.get() >= 0) + return true; + else if (function->name == "lessOrEquals" && left->value.get() > 0) + return true; } else if (const ASTLiteral * right = function->arguments->children[1]->as()) { - if (function->name == "equals" && right->value.get() != 0) - return true; - else if (function->name == "greater" && right->value.get() >= 0) - return true; - else if (function->name == "greaterOrEquals" && right->value.get() > 0) - return true; + if (function->name == "equals" && right->value.get() != 0) + return true; + else if (function->name == "greater" && right->value.get() >= 0) + return true; + else if (function->name == "greaterOrEquals" && right->value.get() > 0) + return true; } } } @@ -366,6 +370,7 @@ static bool indexOfCanUseBloomFilter(const ASTPtr & parent) return false; } + bool MergeTreeIndexConditionBloomFilter::traverseASTEquals( const String & function_name, const ASTPtr & key_ast, const DataTypePtr & value_type, const Field & value_field, RPNElement & out, const ASTPtr & parent) { @@ -380,6 +385,9 @@ bool MergeTreeIndexConditionBloomFilter::traverseASTEquals( if (!array_type) throw Exception("First argument for function " + function_name + " must be an array.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + /// We can treat `indexOf` function similar to `has`. + /// But it is little more cumbersome, compare: `has(arr, elem)` and `indexOf(arr, elem) != 0`. + /// The `parent` in this context is expected to be function `!=` (`notEquals`). if (function_name == "has" || indexOfCanUseBloomFilter(parent)) { out.function = RPNElement::FUNCTION_HAS;