Merge branch 'indexOf_bloomfilter' of github.com:achimbab/ClickHouse into achimbab-indexOf_bloomfilter

This commit is contained in:
Alexey Milovidov 2020-11-08 16:19:57 +03:00
commit 44b363d16b

View File

@ -324,14 +324,17 @@ bool MergeTreeIndexConditionBloomFilter::traverseASTIn(
return false; return false;
} }
static bool indexOfCanUseBloomFilter(const ASTPtr & parent) static bool indexOfCanUseBloomFilter(const ASTPtr & parent)
{ {
if (!parent) if (!parent)
return true; 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<ASTFunction>()) if (const auto * function = parent->as<ASTFunction>())
{ {
if (function->name == "arrayElement") if (function->name == "and")
{ {
return true; return true;
} }
@ -342,23 +345,24 @@ static bool indexOfCanUseBloomFilter(const ASTPtr & parent)
if (function->arguments->children.size() != 2) if (function->arguments->children.size() != 2)
return false; 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<ASTLiteral>()) if (const ASTLiteral * left = function->arguments->children[0]->as<ASTLiteral>())
{ {
if (function->name == "equals" && left->value.get<Int64>() != 0) if (function->name == "equals" && left->value.get<Int64>() != 0)
return true; return true;
else if (function->name == "less" && left->value.get<Int64>() >= 0) else if (function->name == "less" && left->value.get<Int64>() >= 0)
return true; return true;
else if (function->name == "lessOrEquals" && left->value.get<Int64>() > 0) else if (function->name == "lessOrEquals" && left->value.get<Int64>() > 0)
return true; return true;
} }
else if (const ASTLiteral * right = function->arguments->children[1]->as<ASTLiteral>()) else if (const ASTLiteral * right = function->arguments->children[1]->as<ASTLiteral>())
{ {
if (function->name == "equals" && right->value.get<Int64>() != 0) if (function->name == "equals" && right->value.get<Int64>() != 0)
return true; return true;
else if (function->name == "greater" && right->value.get<Int64>() >= 0) else if (function->name == "greater" && right->value.get<Int64>() >= 0)
return true; return true;
else if (function->name == "greaterOrEquals" && right->value.get<Int64>() > 0) else if (function->name == "greaterOrEquals" && right->value.get<Int64>() > 0)
return true; return true;
} }
} }
} }
@ -366,6 +370,7 @@ static bool indexOfCanUseBloomFilter(const ASTPtr & parent)
return false; return false;
} }
bool MergeTreeIndexConditionBloomFilter::traverseASTEquals( bool MergeTreeIndexConditionBloomFilter::traverseASTEquals(
const String & function_name, const ASTPtr & key_ast, const DataTypePtr & value_type, const Field & value_field, RPNElement & out, const ASTPtr & parent) 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) if (!array_type)
throw Exception("First argument for function " + function_name + " must be an array.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); 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)) if (function_name == "has" || indexOfCanUseBloomFilter(parent))
{ {
out.function = RPNElement::FUNCTION_HAS; out.function = RPNElement::FUNCTION_HAS;