MergeTreeWhereOptimizer::tryAnalyzeTuple, fix fuzz

This commit is contained in:
vdimir 2021-09-28 16:41:50 +03:00
parent e326b12a37
commit 64ffacd9e0
No known key found for this signature in database
GPG Key ID: 9B404D301C0CC7EB
3 changed files with 76 additions and 54 deletions

View File

@ -119,6 +119,45 @@ static bool isConditionGood(const ASTPtr & condition)
return false;
}
bool MergeTreeWhereOptimizer::tryAnalyzeTuple(Conditions & res, const ASTFunction * func, bool is_final) const
{
if (!func || func->name != "equals" || func->arguments->children.empty())
return false;
const auto * func_tuple = func->arguments->children[0]->as<ASTFunction>();
if (!func_tuple || func_tuple->name != "tuple")
return false;
if (func->arguments->children.size() <= 1)
return false;
Tuple tuple;
{
const auto * value_tuple = func->arguments->children[1]->as<ASTLiteral>();
if (!value_tuple || !value_tuple->value.tryGet<Tuple>(tuple))
return false;
}
int index = 0;
for (const auto & child : func_tuple->arguments->children)
{
std::shared_ptr<IAST> fetch_sign_column = nullptr;
/// tuple in tuple like (a, (b, c)) = (1, (2, 3))
if (const auto * child_func = child->as<ASTFunction>(); child_func && child_func->name == "tuple")
fetch_sign_column = std::make_shared<ASTFunction>(*child_func);
else if (const auto * child_ident = child->as<ASTIdentifier>())
fetch_sign_column = std::make_shared<ASTIdentifier>(child_ident->name());
else
return false;
ASTPtr fetch_sign_value = std::make_shared<ASTLiteral>(tuple.at(index));
ASTPtr func_node = makeASTFunction("equals", fetch_sign_column, fetch_sign_value);
analyzeImpl(res, func_node, is_final);
index++;
}
return true;
}
void MergeTreeWhereOptimizer::analyzeImpl(Conditions & res, const ASTPtr & node, bool is_final) const
{
@ -129,35 +168,9 @@ void MergeTreeWhereOptimizer::analyzeImpl(Conditions & res, const ASTPtr & node,
for (const auto & elem : func->arguments->children)
analyzeImpl(res, elem, is_final);
}
else
else if (tryAnalyzeTuple(res, func, is_final))
{
ASTFunction * func_tuple = nullptr;
if (func && func->name == "equals")
func_tuple = func->arguments->children[0]->as<ASTFunction>();
if (func_tuple && func_tuple->name == "tuple")
{
const auto * value_tuple = func->arguments->children[1]->as<ASTLiteral>();
auto & tuple = value_tuple->value.safeGet<Tuple>();
int index = 0;
for (auto child : func_tuple->arguments->children)
{
const auto * child_func = child->as<ASTFunction>();
const auto & fetch_sign_value = std::make_shared<ASTLiteral>(tuple.at(index));
std::shared_ptr<IAST> fetch_sign_column = nullptr;
// tuple in tuple like (a, (b,c)) = (1, (2,3))
if (child_func && child_func->name == "tuple")
fetch_sign_column = std::make_shared<ASTFunction>(*child_func);
else
fetch_sign_column = std::make_shared<ASTIdentifier>(child->as<ASTIdentifier>()->name());
auto func_node = makeASTFunction("equals", fetch_sign_column, fetch_sign_value);
analyzeImpl(res, func_node, is_final);
index++;
}
/// analyzed
}
else
{
@ -184,8 +197,6 @@ void MergeTreeWhereOptimizer::analyzeImpl(Conditions & res, const ASTPtr & node,
res.emplace_back(std::move(cond));
}
}
}
/// Transform conjunctions chain in WHERE expression to Conditions list.

View File

@ -70,6 +70,7 @@ private:
using Conditions = std::list<Condition>;
bool tryAnalyzeTuple(Conditions & res, const ASTFunction * func, bool is_final) const;
void analyzeImpl(Conditions & res, const ASTPtr & node, bool is_final) const;
/// Transform conjunctions chain in WHERE expression to Conditions list.

View File

@ -1,14 +1,24 @@
DROP TABLE IF EXISTS test_tuple_filter;
CREATE TABLE test_tuple_filter (id UInt32, value String, log_date Date) Engine=MergeTree() ORDER BY id PARTITION BY log_date settings index_granularity=3;
CREATE TABLE test_tuple_filter (id UInt32, value String, log_date Date) Engine=MergeTree() ORDER BY id PARTITION BY log_date SETTINGS index_granularity = 3;
insert into test_tuple_filter values (1, 'A','2021-01-01'),(2,'B','2021-01-01'),(3,'C','2021-01-01'),(4,'D','2021-01-02'),(5,'E','2021-01-02');
INSERT INTO test_tuple_filter VALUES (1, 'A','2021-01-01'),(2,'B','2021-01-01'),(3,'C','2021-01-01'),(4,'D','2021-01-02'),(5,'E','2021-01-02');
set force_primary_key=1;
SET force_primary_key = 1;
SELECT * FROM test_tuple_filter WHERE (id, value) = (1, 'A');
set force_index_by_date=1;
set force_primary_key=0;
SET force_index_by_date = 1;
SET force_primary_key = 0;
SELECT * FROM test_tuple_filter WHERE (log_date, value) = ('2021-01-01', 'A');
SET force_index_by_date = 0;
SET force_primary_key = 0;
SELECT * FROM test_tuple_filter WHERE tuple(id) = tuple(1) FORMAT Null;
SELECT * FROM test_tuple_filter WHERE (log_date, value) = tuple('2021-01-01'); -- { serverError 43 }
SELECT * FROM test_tuple_filter WHERE (id, value) = tuple(1); -- { serverError 43 }
SELECT * FROM test_tuple_filter WHERE tuple(id, value) = tuple(value, id); -- { serverError 386 }
SELECT * FROM test_tuple_filter WHERE equals((id, value)); -- { serverError 42 }
DROP TABLE IF EXISTS test_tuple_filter;