Merge pull request #5396 from 4ertus2/ast

Support IN in CrossToInnerJoin push down predicates
This commit is contained in:
alexey-milovidov 2019-05-25 14:07:45 +03:00 committed by GitHub
commit 9e24c8d19a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 52 additions and 1 deletions

View File

@ -4,6 +4,7 @@
#include <Interpreters/CrossToInnerJoinVisitor.h>
#include <Interpreters/DatabaseAndTableWithAlias.h>
#include <Interpreters/IdentifierSemantic.h>
#include <Interpreters/QueryNormalizer.h> // for functionIsInOperator
#include <Parsers/ASTSelectQuery.h>
#include <Parsers/ASTTablesInSelectQuery.h>
#include <Parsers/ASTIdentifier.h>
@ -120,6 +121,12 @@ public:
{
/// leave other comparisons as is
}
else if (functionIsInOperator(node.name)) /// IN, NOT IN
{
if (auto ident = node.arguments->children.at(0)->as<ASTIdentifier>())
if (size_t min_table = checkIdentifier(*ident))
asts_to_join_on[min_table].push_back(ast);
}
else
{
ands_only = false;
@ -173,7 +180,7 @@ private:
/// @return table position to attach expression to or 0.
size_t checkIdentifiers(const ASTIdentifier & left, const ASTIdentifier & right)
{
/// {best_match, berst_table_pos}
/// {best_match, best_table_pos}
std::pair<size_t, size_t> left_best{0, 0};
std::pair<size_t, size_t> right_best{0, 0};
@ -202,6 +209,26 @@ private:
}
return 0;
}
size_t checkIdentifier(const ASTIdentifier & identifier)
{
size_t best_match = 0;
size_t best_table_pos = 0;
for (size_t i = 0; i < tables.size(); ++i)
{
size_t match = IdentifierSemantic::canReferColumnToTable(identifier, tables[i].table);
if (match > best_match)
{
best_match = match;
best_table_pos = i;
}
}
if (best_match && tables[best_table_pos].canAttachOnExpression())
return best_table_pos;
return 0;
}
};
using CheckExpressionMatcher = OneTypeMatcher<CheckExpressionVisitorData, false>;

View File

@ -0,0 +1,3 @@
1
2
3

View File

@ -0,0 +1,21 @@
drop table if exists test1;
drop table if exists test2;
drop table if exists test3;
create table test1 (id UInt64, code String) engine = Memory;
create table test3 (id UInt64, code String) engine = Memory;
create table test2 (id UInt64, code String, test1_id UInt64, test3_id UInt64) engine = Memory;
insert into test1 (id, code) select number, toString(number) FROM numbers(100000);
insert into test3 (id, code) select number, toString(number) FROM numbers(100000);
insert into test2 (id, code, test1_id, test3_id) select number, toString(number), number, number FROM numbers(100000);
select test2.id
from test1, test2, test3
where test1.code in ('1', '2', '3')
and test2.test1_id = test1.id
and test2.test3_id = test3.id;
drop table test1;
drop table test2;
drop table test3;