mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12:02 +00:00
Update CrossToInnerJoinVisitor, add tests to cross_to_inner_join
This commit is contained in:
parent
e052a5a05e
commit
946576017f
@ -124,6 +124,13 @@ void collectConjunctions(const ASTPtr & node, std::vector<ASTPtr> & members)
|
||||
members.push_back(node);
|
||||
}
|
||||
|
||||
std::vector<ASTPtr> collectConjunctions(const ASTPtr & node)
|
||||
{
|
||||
std::vector<ASTPtr> members;
|
||||
collectConjunctions(node, members);
|
||||
return members;
|
||||
}
|
||||
|
||||
std::optional<size_t> getIdentMembership(const ASTIdentifier & ident, const std::vector<TableWithColumnNamesAndTypes> & tables)
|
||||
{
|
||||
std::optional<size_t> table_pos = IdentifierSemantic::getMembership(ident);
|
||||
@ -169,20 +176,20 @@ bool isAllowedToRewriteCrossJoin(const ASTPtr & node, const Aliases & aliases)
|
||||
return node->as<ASTIdentifier>() || node->as<ASTLiteral>();
|
||||
}
|
||||
|
||||
bool canMoveExpressionToJoinOn(const ASTPtr & ast,
|
||||
const std::vector<JoinedElement> & joined_tables,
|
||||
const std::vector<TableWithColumnNamesAndTypes> & tables,
|
||||
const Aliases & aliases,
|
||||
std::map<size_t, std::vector<ASTPtr>> & asts_to_join_on)
|
||||
/// Return mapping table_no -> expression with expression that can be moved into JOIN ON section
|
||||
std::map<size_t, std::vector<ASTPtr>> moveExpressionToJoinOn(
|
||||
const ASTPtr & ast,
|
||||
const std::vector<JoinedElement> & joined_tables,
|
||||
const std::vector<TableWithColumnNamesAndTypes> & tables,
|
||||
const Aliases & aliases)
|
||||
{
|
||||
std::vector<ASTPtr> conjuncts;
|
||||
collectConjunctions(ast, conjuncts);
|
||||
for (const auto & node : conjuncts)
|
||||
std::map<size_t, std::vector<ASTPtr>> asts_to_join_on;
|
||||
for (const auto & node : collectConjunctions(ast))
|
||||
{
|
||||
if (const auto * func = node->as<ASTFunction>(); func && func->name == NameEquals::name)
|
||||
{
|
||||
if (!func->arguments || func->arguments->children.size() != 2)
|
||||
return false;
|
||||
return {};
|
||||
|
||||
/// Check if the identifiers are from different joined tables.
|
||||
/// If it's a self joint, tables should have aliases.
|
||||
@ -196,14 +203,14 @@ bool canMoveExpressionToJoinOn(const ASTPtr & ast,
|
||||
if (joined_tables[table_pos].canAttachOnExpression())
|
||||
asts_to_join_on[table_pos].push_back(node);
|
||||
else
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
if (!isAllowedToRewriteCrossJoin(node, aliases))
|
||||
return false;
|
||||
return {};
|
||||
}
|
||||
return true;
|
||||
return asts_to_join_on;
|
||||
}
|
||||
|
||||
ASTPtr makeOnExpression(const std::vector<ASTPtr> & expressions)
|
||||
@ -317,7 +324,6 @@ void CrossToInnerJoinMatcher::visit(ASTSelectQuery & select, ASTPtr &, Data & da
|
||||
}
|
||||
|
||||
/// COMMA to CROSS
|
||||
|
||||
if (num_comma)
|
||||
{
|
||||
for (auto & table : joined_tables)
|
||||
@ -325,22 +331,16 @@ void CrossToInnerJoinMatcher::visit(ASTSelectQuery & select, ASTPtr &, Data & da
|
||||
}
|
||||
|
||||
/// CROSS to INNER
|
||||
|
||||
if (select.where() && data.cross_to_inner_join_rewrite)
|
||||
if (data.cross_to_inner_join_rewrite && select.where())
|
||||
{
|
||||
std::map<size_t, std::vector<ASTPtr>> asts_to_join_on;
|
||||
bool can_move_where
|
||||
= canMoveExpressionToJoinOn(select.where(), joined_tables, data.tables_with_columns, data.aliases, asts_to_join_on);
|
||||
if (can_move_where)
|
||||
auto asts_to_join_on = moveExpressionToJoinOn(select.where(), joined_tables, data.tables_with_columns, data.aliases);
|
||||
for (size_t i = 1; i < joined_tables.size(); ++i)
|
||||
{
|
||||
for (size_t i = 1; i < joined_tables.size(); ++i)
|
||||
const auto & expr_it = asts_to_join_on.find(i);
|
||||
if (expr_it != asts_to_join_on.end())
|
||||
{
|
||||
const auto & expr_it = asts_to_join_on.find(i);
|
||||
if (expr_it != asts_to_join_on.end())
|
||||
{
|
||||
if (joined_tables[i].rewriteCrossToInner(makeOnExpression(expr_it->second)))
|
||||
data.done = true;
|
||||
}
|
||||
if (joined_tables[i].rewriteCrossToInner(makeOnExpression(expr_it->second)))
|
||||
data.done = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
0 0
|
||||
cross
|
||||
--- cross ---
|
||||
1 1 1 1
|
||||
1 1 1 2
|
||||
2 2 2 \N
|
||||
cross nullable
|
||||
--- cross nullable ---
|
||||
1 1 1 1
|
||||
2 2 1 2
|
||||
cross nullable vs not nullable
|
||||
--- cross nullable vs not nullable ---
|
||||
1 1 1 1
|
||||
2 2 1 2
|
||||
cross self
|
||||
--- cross self ---
|
||||
1 1 1 1
|
||||
2 2 2 2
|
||||
cross one table expr
|
||||
--- cross one table expr ---
|
||||
1 1 1 1
|
||||
1 1 1 2
|
||||
1 1 2 \N
|
||||
@ -21,20 +21,34 @@ cross one table expr
|
||||
2 2 1 2
|
||||
2 2 2 \N
|
||||
2 2 3 \N
|
||||
cross multiple ands
|
||||
--- cross multiple ands ---
|
||||
1 1 1 1
|
||||
cross and inside and
|
||||
--- cross and inside and ---
|
||||
1 1 1 1
|
||||
cross split conjunction
|
||||
--- cross split conjunction ---
|
||||
1 1 1 1
|
||||
comma
|
||||
--- and or ---
|
||||
1 1 1 1
|
||||
--- arithmetic expr ---
|
||||
2 2 1 2
|
||||
--- is null or ---
|
||||
1 1 1 2
|
||||
2 2 2 \N
|
||||
--- do not rewrite alias ---
|
||||
1
|
||||
1
|
||||
2
|
||||
--- comma ---
|
||||
1 1 1 1
|
||||
1 1 1 2
|
||||
2 2 2 \N
|
||||
comma nullable
|
||||
--- comma nullable ---
|
||||
1 1 1 1
|
||||
2 2 1 2
|
||||
cross
|
||||
--- comma and or ---
|
||||
1 1 1 1
|
||||
2 2 2 \N
|
||||
--- cross ---
|
||||
SELECT
|
||||
a,
|
||||
b,
|
||||
@ -43,7 +57,7 @@ SELECT
|
||||
FROM t1_00826
|
||||
ALL INNER JOIN t2_00826 ON a = t2_00826.a
|
||||
WHERE a = t2_00826.a
|
||||
cross nullable
|
||||
--- cross nullable ---
|
||||
SELECT
|
||||
a,
|
||||
b,
|
||||
@ -52,7 +66,7 @@ SELECT
|
||||
FROM t1_00826
|
||||
ALL INNER JOIN t2_00826 ON a = t2_00826.a
|
||||
WHERE a = t2_00826.a
|
||||
cross nullable vs not nullable
|
||||
--- cross nullable vs not nullable ---
|
||||
SELECT
|
||||
a,
|
||||
b,
|
||||
@ -61,7 +75,7 @@ SELECT
|
||||
FROM t1_00826
|
||||
ALL INNER JOIN t2_00826 ON a = t2_00826.b
|
||||
WHERE a = t2_00826.b
|
||||
cross self
|
||||
--- cross self ---
|
||||
SELECT
|
||||
a,
|
||||
b,
|
||||
@ -70,7 +84,7 @@ SELECT
|
||||
FROM t1_00826 AS x
|
||||
ALL INNER JOIN t1_00826 AS y ON (a = y.a) AND (b = y.b)
|
||||
WHERE (a = y.a) AND (b = y.b)
|
||||
cross one table expr
|
||||
--- cross one table expr ---
|
||||
SELECT
|
||||
a,
|
||||
b,
|
||||
@ -79,7 +93,7 @@ SELECT
|
||||
FROM t1_00826
|
||||
CROSS JOIN t2_00826
|
||||
WHERE a = b
|
||||
cross multiple ands
|
||||
--- cross multiple ands ---
|
||||
SELECT
|
||||
a,
|
||||
b,
|
||||
@ -88,7 +102,7 @@ SELECT
|
||||
FROM t1_00826
|
||||
ALL INNER JOIN t2_00826 ON (a = t2_00826.a) AND (b = t2_00826.b)
|
||||
WHERE (a = t2_00826.a) AND (b = t2_00826.b)
|
||||
cross and inside and
|
||||
--- cross and inside and ---
|
||||
SELECT
|
||||
a,
|
||||
b,
|
||||
@ -97,7 +111,7 @@ SELECT
|
||||
FROM t1_00826
|
||||
ALL INNER JOIN t2_00826 ON (a = t2_00826.a) AND (a = t2_00826.a) AND (a = t2_00826.a) AND (b = t2_00826.b)
|
||||
WHERE (a = t2_00826.a) AND ((a = t2_00826.a) AND ((a = t2_00826.a) AND (b = t2_00826.b)))
|
||||
cross split conjunction
|
||||
--- cross split conjunction ---
|
||||
SELECT
|
||||
a,
|
||||
b,
|
||||
@ -106,3 +120,62 @@ SELECT
|
||||
FROM t1_00826
|
||||
ALL INNER JOIN t2_00826 ON (a = t2_00826.a) AND (b = t2_00826.b)
|
||||
WHERE (a = t2_00826.a) AND (b = t2_00826.b) AND (a >= 1) AND (t2_00826.b > 0)
|
||||
--- and or ---
|
||||
SELECT
|
||||
a,
|
||||
b,
|
||||
t2_00826.a,
|
||||
t2_00826.b
|
||||
FROM t1_00826
|
||||
ALL INNER JOIN t2_00826 ON (a = t2_00826.a) AND (b = t2_00826.b)
|
||||
WHERE (a = t2_00826.a) AND (b = t2_00826.b) AND ((a >= 1) OR (t2_00826.b = 1))
|
||||
--- arithmetic expr ---
|
||||
SELECT
|
||||
a,
|
||||
b,
|
||||
t2_00826.a,
|
||||
t2_00826.b
|
||||
FROM t1_00826
|
||||
ALL INNER JOIN t2_00826 ON (a + 1) = (t2_00826.a + t2_00826.b)
|
||||
WHERE ((a + 1) = (t2_00826.a + t2_00826.b)) AND ((((a + b) + t2_00826.a) + t2_00826.b) > 5)
|
||||
--- is null or ---
|
||||
SELECT
|
||||
a,
|
||||
b,
|
||||
t2_00826.a,
|
||||
t2_00826.b
|
||||
FROM t1_00826
|
||||
ALL INNER JOIN t2_00826 ON b = t2_00826.a
|
||||
WHERE (b = t2_00826.a) AND (isNull(t2_00826.b) OR (t2_00826.b > t2_00826.a))
|
||||
--- do not rewrite alias ---
|
||||
SELECT a AS b
|
||||
FROM t1_00826
|
||||
CROSS JOIN t2_00826
|
||||
WHERE (b = t2_00826.a) AND (b > 0)
|
||||
--- comma ---
|
||||
SELECT
|
||||
a,
|
||||
b,
|
||||
t2_00826.a,
|
||||
t2_00826.b
|
||||
FROM t1_00826
|
||||
ALL INNER JOIN t2_00826 ON a = t2_00826.a
|
||||
WHERE a = t2_00826.a
|
||||
--- comma nullable ---
|
||||
SELECT
|
||||
a,
|
||||
b,
|
||||
t2_00826.a,
|
||||
t2_00826.b
|
||||
FROM t1_00826
|
||||
ALL INNER JOIN t2_00826 ON b = t2_00826.b
|
||||
WHERE b = t2_00826.b
|
||||
--- comma and or ---
|
||||
SELECT
|
||||
a,
|
||||
b,
|
||||
t2_00826.a,
|
||||
t2_00826.b
|
||||
FROM t1_00826
|
||||
ALL INNER JOIN t2_00826 ON a = t2_00826.a
|
||||
WHERE (a = t2_00826.a) AND (isNull(t2_00826.b) OR (t2_00826.b < 2))
|
||||
|
@ -12,46 +12,79 @@ INSERT INTO t1_00826 values (1,1), (2,2);
|
||||
INSERT INTO t2_00826 values (1,1), (1,2);
|
||||
INSERT INTO t2_00826 (a) values (2), (3);
|
||||
|
||||
SELECT 'cross';
|
||||
SELECT '--- cross ---';
|
||||
SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a;
|
||||
SELECT 'cross nullable';
|
||||
SELECT '--- cross nullable ---';
|
||||
SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.b = t2_00826.b;
|
||||
SELECT 'cross nullable vs not nullable';
|
||||
SELECT '--- cross nullable vs not nullable ---';
|
||||
SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.b;
|
||||
SELECT 'cross self';
|
||||
SELECT '--- cross self ---';
|
||||
SELECT * FROM t1_00826 x cross join t1_00826 y where x.a = y.a and x.b = y.b;
|
||||
SELECT 'cross one table expr';
|
||||
SELECT '--- cross one table expr ---';
|
||||
SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t1_00826.b order by (t1_00826.a, t2_00826.a, t2_00826.b);
|
||||
SELECT 'cross multiple ands';
|
||||
SELECT '--- cross multiple ands ---';
|
||||
SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a and t1_00826.b = t2_00826.b;
|
||||
SELECT 'cross and inside and';
|
||||
SELECT '--- cross and inside and ---';
|
||||
SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a and (t1_00826.b = t2_00826.b and 1);
|
||||
SELECT 'cross split conjunction';
|
||||
SELECT '--- cross split conjunction ---';
|
||||
SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a and t1_00826.b = t2_00826.b and t1_00826.a >= 1 and t2_00826.b = 1;
|
||||
|
||||
SELECT 'comma';
|
||||
SELECT '--- and or ---';
|
||||
SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a and t1_00826.b = t2_00826.b and (t1_00826.a >= 1 OR t2_00826.b = 1);
|
||||
|
||||
SELECT '--- arithmetic expr ---';
|
||||
SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a + 1 = t2_00826.a + t2_00826.b AND (t1_00826.a + t1_00826.b + t2_00826.a + t2_00826.b > 5);
|
||||
|
||||
SELECT '--- is null or ---';
|
||||
SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.b = t2_00826.a AND (t2_00826.b IS NULL OR t2_00826.b > t2_00826.a);
|
||||
|
||||
SELECT '--- do not rewrite alias ---';
|
||||
SELECT a as b FROM t1_00826 cross join t2_00826 where t1_00826.b = t2_00826.a AND b > 0;
|
||||
|
||||
SELECT '--- comma ---';
|
||||
SELECT * FROM t1_00826, t2_00826 where t1_00826.a = t2_00826.a;
|
||||
SELECT 'comma nullable';
|
||||
SELECT '--- comma nullable ---';
|
||||
SELECT * FROM t1_00826, t2_00826 where t1_00826.b = t2_00826.b;
|
||||
SELECT '--- comma and or ---';
|
||||
SELECT * FROM t1_00826, t2_00826 where t1_00826.a = t2_00826.a AND (t2_00826.b IS NULL OR t2_00826.b < 2);
|
||||
|
||||
|
||||
SELECT 'cross';
|
||||
SELECT '--- cross ---';
|
||||
EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a;
|
||||
SELECT 'cross nullable';
|
||||
SELECT '--- cross nullable ---';
|
||||
EXPLAIN SYNTAX SELECT * FROM t1_00826, t2_00826 where t1_00826.a = t2_00826.a;
|
||||
SELECT 'cross nullable vs not nullable';
|
||||
SELECT '--- cross nullable vs not nullable ---';
|
||||
EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.b;
|
||||
SELECT 'cross self';
|
||||
SELECT '--- cross self ---';
|
||||
EXPLAIN SYNTAX SELECT * FROM t1_00826 x cross join t1_00826 y where x.a = y.a and x.b = y.b;
|
||||
SELECT 'cross one table expr';
|
||||
SELECT '--- cross one table expr ---';
|
||||
EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t1_00826.b;
|
||||
SELECT 'cross multiple ands';
|
||||
SELECT '--- cross multiple ands ---';
|
||||
EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a and t1_00826.b = t2_00826.b;
|
||||
SELECT 'cross and inside and';
|
||||
SELECT '--- cross and inside and ---';
|
||||
EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a and (t1_00826.a = t2_00826.a and (t1_00826.a = t2_00826.a and t1_00826.b = t2_00826.b));
|
||||
|
||||
SELECT 'cross split conjunction';
|
||||
SELECT '--- cross split conjunction ---';
|
||||
EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a and t1_00826.b = t2_00826.b and t1_00826.a >= 1 and t2_00826.b > 0;
|
||||
|
||||
SELECT '--- and or ---';
|
||||
EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a = t2_00826.a and t1_00826.b = t2_00826.b and (t1_00826.a >= 1 OR t2_00826.b = 1);
|
||||
|
||||
SELECT '--- arithmetic expr ---';
|
||||
EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.a + 1 = t2_00826.a + t2_00826.b AND (t1_00826.a + t1_00826.b + t2_00826.a + t2_00826.b > 5);
|
||||
|
||||
SELECT '--- is null or ---';
|
||||
EXPLAIN SYNTAX SELECT * FROM t1_00826 cross join t2_00826 where t1_00826.b = t2_00826.a AND (t2_00826.b IS NULL OR t2_00826.b > t2_00826.a);
|
||||
|
||||
SELECT '--- do not rewrite alias ---';
|
||||
EXPLAIN SYNTAX SELECT a as b FROM t1_00826 cross join t2_00826 where t1_00826.b = t2_00826.a AND b > 0;
|
||||
|
||||
SELECT '--- comma ---';
|
||||
EXPLAIN SYNTAX SELECT * FROM t1_00826, t2_00826 where t1_00826.a = t2_00826.a;
|
||||
SELECT '--- comma nullable ---';
|
||||
EXPLAIN SYNTAX SELECT * FROM t1_00826, t2_00826 where t1_00826.b = t2_00826.b;
|
||||
SELECT '--- comma and or ---';
|
||||
EXPLAIN SYNTAX SELECT * FROM t1_00826, t2_00826 where t1_00826.a = t2_00826.a AND (t2_00826.b IS NULL OR t2_00826.b < 2);
|
||||
|
||||
DROP TABLE t1_00826;
|
||||
DROP TABLE t2_00826;
|
||||
|
@ -19,10 +19,3 @@ SELECT
|
||||
FROM n
|
||||
ALL INNER JOIN r ON k = r.k
|
||||
WHERE (k = r.k) AND (name NOT LIKE \'A%\')
|
||||
SELECT
|
||||
k,
|
||||
r.k,
|
||||
name
|
||||
FROM n
|
||||
ALL INNER JOIN r ON (k + 1) = (r.k + 1)
|
||||
WHERE ((k + 1) = (r.k + 1)) AND ((name = \'A\') OR (name = \'AA\'))
|
||||
|
@ -9,7 +9,6 @@ SET enable_optimize_predicate_expression = 0;
|
||||
EXPLAIN SYNTAX SELECT * FROM n, r WHERE n.k = r.k AND r.name = 'A';
|
||||
EXPLAIN SYNTAX SELECT * FROM n, r WHERE n.k = r.k AND r.name LIKE 'A%';
|
||||
EXPLAIN SYNTAX SELECT * FROM n, r WHERE n.k = r.k AND r.name NOT LIKE 'A%';
|
||||
EXPLAIN SYNTAX SELECT * FROM n, r WHERE n.k + 1 = r.k + 1 AND (r.name = 'A' OR r.name = 'AA');
|
||||
|
||||
DROP TABLE n;
|
||||
DROP TABLE r;
|
||||
|
Loading…
Reference in New Issue
Block a user