diff --git a/src/Storages/MergeTree/MergeTreeIndexConditionBloomFilter.cpp b/src/Storages/MergeTree/MergeTreeIndexConditionBloomFilter.cpp index 03bc9e4e046..c709f8c3c99 100644 --- a/src/Storages/MergeTree/MergeTreeIndexConditionBloomFilter.cpp +++ b/src/Storages/MergeTree/MergeTreeIndexConditionBloomFilter.cpp @@ -1,17 +1,17 @@ -#include -#include -#include #include -#include -#include +#include #include #include #include -#include +#include +#include +#include +#include #include #include #include -#include +#include +#include #include #include @@ -106,11 +106,11 @@ bool MergeTreeIndexConditionBloomFilter::alwaysUnknownOrTrue() const rpn_stack.push_back(true); } else if (element.function == RPNElement::FUNCTION_EQUALS - || element.function == RPNElement::FUNCTION_NOT_EQUALS - || element.function == RPNElement::FUNCTION_HAS - || element.function == RPNElement::FUNCTION_IN - || element.function == RPNElement::FUNCTION_NOT_IN - || element.function == RPNElement::ALWAYS_FALSE) + || element.function == RPNElement::FUNCTION_NOT_EQUALS + || element.function == RPNElement::FUNCTION_HAS + || element.function == RPNElement::FUNCTION_IN + || element.function == RPNElement::FUNCTION_NOT_IN + || element.function == RPNElement::ALWAYS_FALSE) { rpn_stack.push_back(false); } @@ -338,7 +338,7 @@ static bool indexOfCanUseBloomFilter(const ASTPtr & parent) { return true; } - else if (function->name == "equals" + else if (function->name == "equals" /// notEquals is not applicable || function->name == "greater" || function->name == "greaterOrEquals" || function->name == "less" || function->name == "lessOrEquals") { @@ -346,24 +346,33 @@ static bool indexOfCanUseBloomFilter(const ASTPtr & parent) return false; /// We don't allow constant expressions like `indexOf(arr, x) = 1 + 0` but it's neglible. + + /// We should return true when the corresponding expression implies that the array contains the element. + /// Example: when `indexOf(arr, x)` > 10 is written, it means that arr definitely should contain the element + /// (at least at 11th position but it does not matter). + + bool reversed = false; + const ASTLiteral * constant = nullptr; + 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; + constant = left; + reversed = 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; + constant = right; } + else + return false; + + Field zero(0); + return (function->name == "equals" /// indexOf(...) = c, c != 0 + && !applyVisitor(FieldVisitorAccurateEquals(), constant->value, zero)) + || (function->name == (reversed ? "less" : "greater") /// indexOf(...) > c, c >= 0 + && !applyVisitor(FieldVisitorAccurateLess(), constant->value, zero)) + || (function->name == (reversed ? "lessOrEquals" : "greaterOrEquals") /// indexOf(...) >= c, c > 0 + && applyVisitor(FieldVisitorAccurateLess(), zero, constant->value)); } }