support IN in CrossToInnerJoin push down

This commit is contained in:
chertus 2019-05-23 19:01:17 +03:00
parent 15e31d5a8c
commit 333c9aeecc
3 changed files with 51 additions and 0 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;
@ -202,6 +209,26 @@ private:
}
return 0;
}
size_t checkIdentifier(const ASTIdentifier & identifier)
{
size_t best_match = 0;
size_t berst_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;
berst_table_pos = i;
}
}
if (best_match && tables[berst_table_pos].canAttachOnExpression())
return berst_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;