Remove multiple_joins_rewriter v1 (#15472)

This commit is contained in:
Artem Zuikov 2020-09-30 23:11:49 +03:00 committed by GitHub
parent 0ac18a382f
commit 0f6a6453fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 14 additions and 774 deletions

View File

@ -368,7 +368,6 @@ class IColumn;
\
M(Bool, deduplicate_blocks_in_dependent_materialized_views, false, "Should deduplicate blocks for materialized views if the block is not a duplicate for the table. Use true to always deduplicate in dependent tables.", 0) \
M(Bool, use_compact_format_in_distributed_parts_names, false, "Changes format of directories names for distributed table insert parts.", 0) \
M(UInt64, multiple_joins_rewriter_version, 2, "1 or 2. Second rewriter version knows about table columns and keep not clashed names as is.", 0) \
M(Bool, validate_polygons, true, "Throw exception if polygon is invalid in function pointInPolygon (e.g. self-tangent, self-intersecting). If the setting is false, the function will accept invalid polygons but may silently return wrong result.", 0) \
M(UInt64, max_parser_depth, DBMS_DEFAULT_MAX_PARSER_DEPTH, "Maximum parser depth (recursion depth of recursive descend parser).", 0) \
M(Seconds, temporary_live_view_timeout, DEFAULT_TEMPORARY_LIVE_VIEW_TIMEOUT_SEC, "Timeout after which temporary live view is deleted.", 0) \
@ -399,6 +398,7 @@ class IColumn;
M(UInt64, mark_cache_min_lifetime, 0, "Obsolete setting, does nothing. Will be removed after 2020-05-31", 0) \
M(Bool, partial_merge_join, false, "Obsolete. Use join_algorithm='prefer_partial_merge' instead.", 0) \
M(UInt64, max_memory_usage_for_all_queries, 0, "Obsolete. Will be removed after 2020-10-20", 0) \
M(UInt64, multiple_joins_rewriter_version, 0, "Obsolete setting, does nothing. Will be removed after 2021-03-31", 0) \
\
M(Bool, force_optimize_skip_unused_shards_no_nested, false, "Obsolete setting, does nothing. Will be removed after 2020-12-01. Use force_optimize_skip_unused_shards_nesting instead.", 0) \
M(Bool, experimental_use_processors, true, "Obsolete setting, does nothing. Will be removed after 2020-11-29.", 0) \

View File

@ -1,41 +0,0 @@
#pragma once
#include <unordered_map>
#include <Parsers/ASTAsterisk.h>
#include <Parsers/ASTQualifiedAsterisk.h>
#include <Parsers/ASTColumnsMatcher.h>
namespace DB
{
struct AsteriskSemanticImpl
{
using RevertedAliases = std::unordered_map<String, std::vector<String>>;
using RevertedAliasesPtr = std::shared_ptr<RevertedAliases>;
RevertedAliasesPtr aliases; /// map of aliases that should be set in phase of * expanding.
};
struct AsteriskSemantic
{
using RevertedAliases = AsteriskSemanticImpl::RevertedAliases;
using RevertedAliasesPtr = AsteriskSemanticImpl::RevertedAliasesPtr;
static void setAliases(ASTAsterisk & node, const RevertedAliasesPtr & aliases) { node.semantic = makeSemantic(aliases); }
static void setAliases(ASTQualifiedAsterisk & node, const RevertedAliasesPtr & aliases) { node.semantic = makeSemantic(aliases); }
static void setAliases(ASTColumnsMatcher & node, const RevertedAliasesPtr & aliases) { node.semantic = makeSemantic(aliases); }
static RevertedAliasesPtr getAliases(const ASTAsterisk & node) { return node.semantic ? node.semantic->aliases : nullptr; }
static RevertedAliasesPtr getAliases(const ASTQualifiedAsterisk & node) { return node.semantic ? node.semantic->aliases : nullptr; }
static RevertedAliasesPtr getAliases(const ASTColumnsMatcher & node) { return node.semantic ? node.semantic->aliases : nullptr; }
private:
static std::shared_ptr<AsteriskSemanticImpl> makeSemantic(const RevertedAliasesPtr & aliases)
{
return std::make_shared<AsteriskSemanticImpl>(AsteriskSemanticImpl{aliases});
}
};
}

View File

@ -93,7 +93,6 @@ namespace ErrorCodes
extern const int PARAMETER_OUT_OF_BOUND;
extern const int INVALID_LIMIT_EXPRESSION;
extern const int INVALID_WITH_FILL_EXPRESSION;
extern const int INVALID_SETTING_VALUE;
}
/// Assumes `storage` is set and the table filter (row-level security) is not empty.
@ -190,7 +189,7 @@ static Context getSubqueryContext(const Context & context)
return subquery_context;
}
static void rewriteMultipleJoins(ASTPtr & query, const TablesWithColumns & tables, const String & database, const Settings & settings)
static void rewriteMultipleJoins(ASTPtr & query, const TablesWithColumns & tables, const String & database)
{
ASTSelectQuery & select = query->as<ASTSelectQuery &>();
@ -202,11 +201,7 @@ static void rewriteMultipleJoins(ASTPtr & query, const TablesWithColumns & table
CrossToInnerJoinVisitor::Data cross_to_inner{tables, aliases, database};
CrossToInnerJoinVisitor(cross_to_inner).visit(query);
size_t rewriter_version = settings.multiple_joins_rewriter_version;
if (!rewriter_version || rewriter_version > 2)
throw Exception("Bad multiple_joins_rewriter_version setting value: " + settings.multiple_joins_rewriter_version.toString(),
ErrorCodes::INVALID_SETTING_VALUE);
JoinToSubqueryTransformVisitor::Data join_to_subs_data{tables, aliases, rewriter_version};
JoinToSubqueryTransformVisitor::Data join_to_subs_data{tables, aliases};
JoinToSubqueryTransformVisitor(join_to_subs_data).visit(query);
}
@ -271,7 +266,7 @@ InterpreterSelectQuery::InterpreterSelectQuery(
/// Rewrite JOINs
if (!has_input && joined_tables.tablesCount() > 1)
{
rewriteMultipleJoins(query_ptr, joined_tables.tablesWithColumns(), context->getCurrentDatabase(), settings);
rewriteMultipleJoins(query_ptr, joined_tables.tablesWithColumns(), context->getCurrentDatabase());
joined_tables.reset(getSelectQuery());
joined_tables.resolveTables();

View File

@ -2,7 +2,6 @@
#include <Core/NamesAndTypes.h>
#include <Interpreters/JoinToSubqueryTransformVisitor.h>
#include <Interpreters/IdentifierSemantic.h>
#include <Interpreters/AsteriskSemantic.h>
#include <Interpreters/DatabaseAndTableWithAlias.h>
#include <Interpreters/RequiredSourceColumnsVisitor.h>
#include <Parsers/ASTSelectQuery.h>
@ -11,6 +10,8 @@
#include <Parsers/ASTIdentifier.h>
#include <Parsers/ASTExpressionList.h>
#include <Parsers/ASTFunction.h>
#include <Parsers/ASTAsterisk.h>
#include <Parsers/ASTQualifiedAsterisk.h>
#include <Parsers/ParserTablesInSelectQuery.h>
#include <Parsers/ExpressionListParsers.h>
#include <Parsers/parseQuery.h>
@ -127,169 +128,6 @@ private:
}
};
/// Find columns with aliases to push them into rewritten subselects.
/// Normalize table aliases: table_name.column_name -> table_alias.column_name
/// Make aliases maps (alias -> column_name, column_name -> alias)
struct ColumnAliasesMatcher
{
using Visitor = ConstInDepthNodeVisitor<ColumnAliasesMatcher, true>;
struct Data
{
const std::vector<DatabaseAndTableWithAlias> tables;
bool public_names;
AsteriskSemantic::RevertedAliases rev_aliases; /// long_name -> aliases
std::unordered_map<String, String> aliases; /// alias -> long_name
std::vector<std::pair<ASTIdentifier *, bool>> compound_identifiers;
std::set<String> allowed_long_names; /// original names allowed as aliases '--t.x as t.x' (select expressions only).
bool inside_function = false;
explicit Data(const std::vector<DatabaseAndTableWithAlias> && tables_)
: tables(tables_)
, public_names(false)
{}
void replaceIdentifiersWithAliases()
{
String hide_prefix = "--"; /// @note restriction: user should not use aliases like `--table.column`
for (auto & [identifier, is_public] : compound_identifiers)
{
String long_name = identifier->name;
auto it = rev_aliases.find(long_name);
if (it == rev_aliases.end())
{
bool last_table = false;
{
if (auto best_table_pos = IdentifierSemantic::chooseTable(*identifier, tables))
last_table = (*best_table_pos + 1 == tables.size());
}
if (!last_table)
{
String alias = hide_prefix + long_name;
aliases[alias] = long_name;
rev_aliases[long_name].push_back(alias);
IdentifierSemantic::coverName(*identifier, alias);
if (is_public)
{
identifier->setAlias(long_name);
allowed_long_names.insert(long_name);
}
}
else if (is_public)
identifier->setAlias(long_name); /// prevent crop long to short name
}
else
{
if (it->second.empty())
throw Exception("No alias for '" + long_name + "'", ErrorCodes::LOGICAL_ERROR);
if (is_public && allowed_long_names.count(long_name))
; /// leave original name unchanged for correct output
else
IdentifierSemantic::coverName(*identifier, it->second[0]);
}
}
}
};
static bool needChildVisit(const ASTPtr & node, const ASTPtr &)
{
/// Do not go into subqueries. Function visits children itself.
if (node->as<ASTSubquery>() ||
node->as<ASTFunction>())
return false;
return !node->as<ASTQualifiedAsterisk>();
}
static void visit(const ASTPtr & ast, Data & data)
{
if (auto * t = ast->as<ASTIdentifier>())
visit(*t, ast, data);
else if (auto * f = ast->as<ASTFunction>())
visit(*f, ast, data);
/// Do not allow asterisks but ignore them inside functions. I.e. allow 'count(*)'.
if (!data.inside_function && (ast->as<ASTAsterisk>() || ast->as<ASTQualifiedAsterisk>()))
throw Exception("Multiple JOIN do not support asterisks for complex queries yet", ErrorCodes::NOT_IMPLEMENTED);
}
static void visit(const ASTFunction &, const ASTPtr & ast, Data & data)
{
/// Grandchild case: Function -> (ExpressionList) -> Asterisk
data.inside_function = true;
Visitor visitor(data);
for (auto & child : ast->children)
visitor.visit(child);
data.inside_function = false;
}
static void visit(const ASTIdentifier & const_node, const ASTPtr &, Data & data)
{
ASTIdentifier & node = const_cast<ASTIdentifier &>(const_node); /// we know it's not const
if (node.isShort())
return;
bool last_table = false;
String long_name;
if (auto table_pos = IdentifierSemantic::chooseTable(node, data.tables))
{
const auto & table = data.tables[*table_pos];
IdentifierSemantic::setColumnLongName(node, table); /// table_name.column_name -> table_alias.column_name
long_name = node.name;
if (&table == &data.tables.back())
last_table = true;
}
if (long_name.empty())
throw Exception("Cannot refer column '" + node.name + "' to table", ErrorCodes::AMBIGUOUS_COLUMN_NAME);
String alias = node.tryGetAlias();
if (!alias.empty())
{
data.aliases[alias] = long_name;
data.rev_aliases[long_name].push_back(alias);
if (!last_table)
{
IdentifierSemantic::coverName(node, alias);
node.setAlias({});
}
}
else if (node.compound())
data.compound_identifiers.emplace_back(&node, data.public_names);
}
};
/// Attach additional semantic info to generated selects.
struct AppendSemanticVisitorData
{
using TypeToVisit = ASTSelectQuery;
AsteriskSemantic::RevertedAliasesPtr rev_aliases = {};
bool done = false;
void visit(ASTSelectQuery & select, ASTPtr &)
{
if (done || !rev_aliases || !select.select())
return;
for (auto & child : select.select()->children)
{
if (auto * node = child->as<ASTAsterisk>())
AsteriskSemantic::setAliases(*node, rev_aliases);
if (auto * node = child->as<ASTQualifiedAsterisk>())
AsteriskSemantic::setAliases(*node, rev_aliases);
}
done = true;
}
};
/// Replaces table elements with pair.
struct RewriteTablesVisitorData
{
@ -371,9 +209,6 @@ bool needRewrite(ASTSelectQuery & select, std::vector<const ASTTableExpression *
using RewriteMatcher = OneTypeMatcher<RewriteTablesVisitorData>;
using RewriteVisitor = InDepthNodeVisitor<RewriteMatcher, true>;
using ExtractAsterisksVisitor = ConstInDepthNodeVisitor<ExtractAsterisksMatcher, true>;
using ColumnAliasesVisitor = ColumnAliasesMatcher::Visitor;
using AppendSemanticMatcher = OneTypeMatcher<AppendSemanticVisitorData>;
using AppendSemanticVisitor = InDepthNodeVisitor<AppendSemanticMatcher, true>;
/// V2 specific visitors
@ -718,12 +553,7 @@ bool JoinToSubqueryTransformMatcher::needChildVisit(ASTPtr & node, const ASTPtr
void JoinToSubqueryTransformMatcher::visit(ASTPtr & ast, Data & data)
{
if (auto * t = ast->as<ASTSelectQuery>())
{
if (data.version == 1)
visitV1(*t, ast, data);
else
visitV2(*t, ast, data);
}
visit(*t, ast, data);
}
/// The reason for V2: not to alias columns without clashes.
@ -733,7 +563,7 @@ void JoinToSubqueryTransformMatcher::visit(ASTPtr & ast, Data & data)
/// 3. Rewrite multiple JOINs with subqueries:
/// SELECT ... FROM (SELECT `--.s`.*, ... FROM (...) AS `--.s` JOIN tableY ON ...) AS `--.s` JOIN tableZ ON ...'
/// 4. Push down expressions of aliases used in ON section into expression list of first reletad subquery
void JoinToSubqueryTransformMatcher::visitV2(ASTSelectQuery & select, ASTPtr & ast, Data & data)
void JoinToSubqueryTransformMatcher::visit(ASTSelectQuery & select, ASTPtr & ast, Data & data)
{
std::vector<const ASTTableExpression *> table_expressions;
if (!needRewrite<2>(select, table_expressions))
@ -855,89 +685,6 @@ void JoinToSubqueryTransformMatcher::visitV2(ASTSelectQuery & select, ASTPtr & a
data.done = true;
}
void JoinToSubqueryTransformMatcher::visitV1(ASTSelectQuery & select, ASTPtr &, Data & data)
{
using RevertedAliases = AsteriskSemantic::RevertedAliases;
std::vector<const ASTTableExpression *> table_expressions;
if (!needRewrite(select, table_expressions))
return;
if (table_expressions.size() != data.tables.size())
throw Exception("Inconsistent tables count in JOIN rewriter", ErrorCodes::LOGICAL_ERROR);
bool has_subquery = false;
for (const auto & expr : table_expressions)
if (expr->subquery)
has_subquery = true;
if (!has_subquery)
{
ExtractAsterisksVisitor::Data asterisks_data(data.tables);
ExtractAsterisksVisitor(asterisks_data).visit(select.select());
if (asterisks_data.new_select_expression_list)
select.setExpression(ASTSelectQuery::Expression::SELECT, std::move(asterisks_data.new_select_expression_list));
}
ColumnAliasesVisitor::Data aliases_data(getDatabaseAndTables(select, ""));
if (select.select())
{
/// TODO: there's a bug here. We need to publish only top-level ASTIdentifiers but visitor extracts all.
aliases_data.public_names = true;
ColumnAliasesVisitor(aliases_data).visit(select.select());
aliases_data.public_names = false;
}
if (select.where())
ColumnAliasesVisitor(aliases_data).visit(select.where());
if (select.prewhere())
ColumnAliasesVisitor(aliases_data).visit(select.prewhere());
if (select.orderBy())
ColumnAliasesVisitor(aliases_data).visit(select.orderBy());
if (select.groupBy())
ColumnAliasesVisitor(aliases_data).visit(select.groupBy());
if (select.having())
ColumnAliasesVisitor(aliases_data).visit(select.having());
/// JOIN sections
for (auto & child : select.tables()->children)
{
auto * table = child->as<ASTTablesInSelectQueryElement>();
if (table->table_join)
{
auto & join = table->table_join->as<ASTTableJoin &>();
if (join.on_expression)
ColumnAliasesVisitor(aliases_data).visit(join.on_expression);
}
}
aliases_data.replaceIdentifiersWithAliases();
auto rev_aliases = std::make_shared<RevertedAliases>();
rev_aliases->swap(aliases_data.rev_aliases);
auto & src_tables = select.tables()->children;
ASTPtr left_table = src_tables[0];
static ASTPtr subquery_template = makeSubqueryTemplate();
for (size_t i = 1; i < src_tables.size() - 1; ++i)
{
left_table = replaceJoin(left_table, src_tables[i], subquery_template->clone());
if (!left_table)
throw Exception("Cannot replace tables with subselect", ErrorCodes::LOGICAL_ERROR);
/// attach data to generated asterisk
AppendSemanticVisitor::Data semantic_data{rev_aliases, false};
AppendSemanticVisitor(semantic_data).visit(left_table);
}
/// replace tables in select with generated two-table join
RewriteVisitor::Data visitor_data{left_table, src_tables.back()};
RewriteVisitor(visitor_data).visit(select.refTables());
data.done = true;
}
ASTPtr JoinToSubqueryTransformMatcher::replaceJoin(ASTPtr ast_left, ASTPtr ast_right, ASTPtr subquery_template)
{
const auto * left = ast_left->as<ASTTablesInSelectQueryElement>();

View File

@ -20,7 +20,6 @@ public:
{
const std::vector<TableWithColumnNamesAndTypes> & tables;
const Aliases & aliases;
size_t version = 1;
bool done = false;
};
@ -43,10 +42,7 @@ private:
/// TablesInSelectQueryElement [source1]
/// TablesInSelectQueryElement [source2]
///
static void visitV1(ASTSelectQuery & select, ASTPtr & ast, Data & data);
/// V2 uses information about tables' columns to rewrite queries.
static void visitV2(ASTSelectQuery & select, ASTPtr & ast, Data & data);
static void visit(ASTSelectQuery & select, ASTPtr & ast, Data & data);
/// @return combined TablesInSelectQueryElement or nullptr if cannot rewrite
static ASTPtr replaceJoin(ASTPtr left, ASTPtr right, ASTPtr subquery_template);

View File

@ -2,7 +2,6 @@
#include <Interpreters/TranslateQualifiedNamesVisitor.h>
#include <Interpreters/IdentifierSemantic.h>
#include <Interpreters/AsteriskSemantic.h>
#include <Common/typeid_cast.h>
#include <Common/StringUtils/StringUtils.h>
@ -174,24 +173,10 @@ void TranslateQualifiedNamesMatcher::visit(ASTSelectQuery & select, const ASTPtr
Visitor(data).visit(select.refHaving());
}
static void addIdentifier(ASTs & nodes, const DatabaseAndTableWithAlias & table, const String & column_name,
AsteriskSemantic::RevertedAliasesPtr aliases)
static void addIdentifier(ASTs & nodes, const DatabaseAndTableWithAlias & table, const String & column_name)
{
String table_name = table.getQualifiedNamePrefix(false);
auto identifier = std::make_shared<ASTIdentifier>(std::vector<String>{table_name, column_name});
bool added = false;
if (aliases && aliases->count(identifier->name))
{
for (const String & alias : (*aliases)[identifier->name])
{
nodes.push_back(identifier->clone());
nodes.back()->setAlias(alias);
added = true;
}
}
if (!added)
nodes.emplace_back(identifier);
}
@ -237,7 +222,7 @@ void TranslateQualifiedNamesMatcher::visit(ASTExpressionList & node, const ASTPt
{
if (first_table || !data.join_using_columns.count(column.name))
{
addIdentifier(node.children, table.table, column.name, AsteriskSemantic::getAliases(*asterisk));
addIdentifier(node.children, table.table, column.name);
}
}
@ -264,7 +249,7 @@ void TranslateQualifiedNamesMatcher::visit(ASTExpressionList & node, const ASTPt
{
if (asterisk_pattern->isColumnMatching(column.name) && (first_table || !data.join_using_columns.count(column.name)))
{
addIdentifier(node.children, table.table, column.name, AsteriskSemantic::getAliases(*asterisk_pattern));
addIdentifier(node.children, table.table, column.name);
}
}
@ -287,7 +272,7 @@ void TranslateQualifiedNamesMatcher::visit(ASTExpressionList & node, const ASTPt
{
for (const auto & column : table.columns)
{
addIdentifier(node.children, table.table, column.name, AsteriskSemantic::getAliases(*qualified_asterisk));
addIdentifier(node.children, table.table, column.name);
}
break;
}

View File

@ -6,9 +6,6 @@
namespace DB
{
struct AsteriskSemantic;
struct AsteriskSemanticImpl;
/** SELECT * is expanded to all visible columns of the source table.
* Optional transformers can be attached to further manipulate these expanded columns.
*/
@ -21,11 +18,6 @@ public:
protected:
void formatImpl(const FormatSettings & settings, FormatState &, FormatStateStacked) const override;
private:
std::shared_ptr<AsteriskSemanticImpl> semantic; /// pimpl
friend struct AsteriskSemantic;
};
}

View File

@ -6,9 +6,6 @@
namespace DB
{
struct AsteriskSemantic;
struct AsteriskSemanticImpl;
/** Something like t.*
* It will have qualifier as its child ASTIdentifier.
* Optional transformers can be attached to further manipulate these expanded columns.
@ -27,11 +24,6 @@ public:
protected:
void formatImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override;
private:
std::shared_ptr<AsteriskSemanticImpl> semantic; /// pimpl
friend struct AsteriskSemantic;
};
}

View File

@ -31,18 +31,6 @@ y.b: 0
│ 1 │ 1 │ 1 │
│ 2 │ 2 │ 2 │
└─────┴─────┴─────┘
┌─s.a─┬─s.a─┬─s_b─┬─s_b─┐
│ 1 │ 1 │ 1 │ 1 │
│ 0 │ 0 │ 0 │ 0 │
└─────┴─────┴─────┴─────┘
┌─y.a─┬─y.a─┬─y_b─┬─y_b─┐
│ 1 │ 1 │ 1 │ 1 │
│ 0 │ 0 │ 0 │ 0 │
└─────┴─────┴─────┴─────┘
┌─t_a─┬─t_a─┬─s_a─┬─s_a─┬─y_a─┬─y_a─┐
│ 1 │ 1 │ 1 │ 1 │ 1 │ 1 │
│ 2 │ 2 │ 0 │ 0 │ 0 │ 0 │
└─────┴─────┴─────┴─────┴─────┴─────┘
┌─s.a─┬─s.a─┬─s_b─┬─s.b─┐
│ 1 │ 1 │ 1 │ 1 │
│ 0 │ 0 │ 0 │ 0 │

View File

@ -39,28 +39,6 @@ left join y on y.b = s.b
order by t.a
format PrettyCompactNoEscapes;
set multiple_joins_rewriter_version = 1;
select s.a, s.a, s.b as s_b, s.b from t
left join s on s.a = t.a
left join y on s.b = y.b
order by t.a
format PrettyCompactNoEscapes;
select y.a, y.a, y.b as y_b, y.b from t
left join s on s.a = t.a
left join y on y.b = s.b
order by t.a
format PrettyCompactNoEscapes;
select t.a, t.a as t_a, s.a, s.a as s_a, y.a, y.a as y_a from t
left join s on t.a = s.a
left join y on y.b = s.b
order by t.a
format PrettyCompactNoEscapes;
set multiple_joins_rewriter_version = 2;
select s.a, s.a, s.b as s_b, s.b from t
left join s on s.a = t.a
left join y on s.b = y.b

View File

@ -1,292 +0,0 @@
SELECT a
FROM t1_00849
CROSS JOIN t2_00849
SELECT a
FROM t1_00849
ALL INNER JOIN t2_00849 ON a = t2_00849.a
WHERE a = t2_00849.a
SELECT a
FROM t1_00849
ALL INNER JOIN t2_00849 ON b = t2_00849.b
WHERE b = t2_00849.b
SELECT `--t1_00849.a` AS `t1_00849.a`
FROM
(
SELECT
a AS `--t1_00849.a`,
b,
t2_00849.a AS `--t2_00849.a`,
t2_00849.b
FROM t1_00849
ALL INNER JOIN t2_00849 ON `--t1_00849.a` = `--t2_00849.a`
) AS `--.s`
ALL INNER JOIN t3_00849 ON `--t1_00849.a` = a
WHERE (`--t1_00849.a` = `--t2_00849.a`) AND (`--t1_00849.a` = a)
SELECT `--t1_00849.a` AS `t1_00849.a`
FROM
(
SELECT
a AS `--t1_00849.a`,
b AS `--t1_00849.b`,
t2_00849.a,
t2_00849.b AS `--t2_00849.b`
FROM t1_00849
ALL INNER JOIN t2_00849 ON `--t1_00849.b` = `--t2_00849.b`
) AS `--.s`
ALL INNER JOIN t3_00849 ON `--t1_00849.b` = b
WHERE (`--t1_00849.b` = `--t2_00849.b`) AND (`--t1_00849.b` = b)
SELECT `--t1_00849.a` AS `t1_00849.a`
FROM
(
SELECT
`--t1_00849.a`,
b,
`--t2_00849.a`,
`t2_00849.b`,
a AS `--t3_00849.a`,
t3_00849.b
FROM
(
SELECT
a AS `--t1_00849.a`,
b,
t2_00849.a AS `--t2_00849.a`,
t2_00849.b
FROM t1_00849
ALL INNER JOIN t2_00849 ON `--t1_00849.a` = `--t2_00849.a`
) AS `--.s`
ALL INNER JOIN t3_00849 ON `--t1_00849.a` = `--t3_00849.a`
) AS `--.s`
ALL INNER JOIN t4_00849 ON `--t1_00849.a` = a
WHERE (`--t1_00849.a` = `--t2_00849.a`) AND (`--t1_00849.a` = `--t3_00849.a`) AND (`--t1_00849.a` = a)
SELECT `--t1_00849.a` AS `t1_00849.a`
FROM
(
SELECT
`--t1_00849.a`,
`--t1_00849.b`,
`t2_00849.a`,
`--t2_00849.b`,
a,
b AS `--t3_00849.b`
FROM
(
SELECT
a AS `--t1_00849.a`,
b AS `--t1_00849.b`,
t2_00849.a,
t2_00849.b AS `--t2_00849.b`
FROM t1_00849
ALL INNER JOIN t2_00849 ON `--t1_00849.b` = `--t2_00849.b`
) AS `--.s`
ALL INNER JOIN t3_00849 ON `--t1_00849.b` = `--t3_00849.b`
) AS `--.s`
ALL INNER JOIN t4_00849 ON `--t1_00849.b` = b
WHERE (`--t1_00849.b` = `--t2_00849.b`) AND (`--t1_00849.b` = `--t3_00849.b`) AND (`--t1_00849.b` = b)
SELECT `--t1_00849.a` AS `t1_00849.a`
FROM
(
SELECT
`--t1_00849.a`,
b,
`--t2_00849.a`,
`t2_00849.b`,
a AS `--t3_00849.a`,
t3_00849.b
FROM
(
SELECT
a AS `--t1_00849.a`,
b,
t2_00849.a AS `--t2_00849.a`,
t2_00849.b
FROM t1_00849
ALL INNER JOIN t2_00849 ON `--t2_00849.a` = `--t1_00849.a`
) AS `--.s`
ALL INNER JOIN t3_00849 ON `--t2_00849.a` = `--t3_00849.a`
) AS `--.s`
ALL INNER JOIN t4_00849 ON `--t2_00849.a` = a
WHERE (`--t2_00849.a` = `--t1_00849.a`) AND (`--t2_00849.a` = `--t3_00849.a`) AND (`--t2_00849.a` = a)
SELECT `--t1_00849.a` AS `t1_00849.a`
FROM
(
SELECT
`--t1_00849.a`,
b,
`--t2_00849.a`,
`t2_00849.b`,
a AS `--t3_00849.a`,
t3_00849.b
FROM
(
SELECT
a AS `--t1_00849.a`,
b,
t2_00849.a AS `--t2_00849.a`,
t2_00849.b
FROM t1_00849
CROSS JOIN t2_00849
) AS `--.s`
ALL INNER JOIN t3_00849 ON (`--t3_00849.a` = `--t1_00849.a`) AND (`--t3_00849.a` = `--t2_00849.a`)
) AS `--.s`
ALL INNER JOIN t4_00849 ON `--t3_00849.a` = a
WHERE (`--t3_00849.a` = `--t1_00849.a`) AND (`--t3_00849.a` = `--t2_00849.a`) AND (`--t3_00849.a` = a)
SELECT `--t1_00849.a` AS `t1_00849.a`
FROM
(
SELECT
`--t1_00849.a`,
b,
`--t2_00849.a`,
`t2_00849.b`,
a AS `--t3_00849.a`,
t3_00849.b
FROM
(
SELECT
a AS `--t1_00849.a`,
b,
t2_00849.a AS `--t2_00849.a`,
t2_00849.b
FROM t1_00849
CROSS JOIN t2_00849
) AS `--.s`
CROSS JOIN t3_00849
) AS `--.s`
ALL INNER JOIN t4_00849 ON (a = `--t1_00849.a`) AND (a = `--t2_00849.a`) AND (a = `--t3_00849.a`)
WHERE (a = `--t1_00849.a`) AND (a = `--t2_00849.a`) AND (a = `--t3_00849.a`)
SELECT `--t1_00849.a` AS `t1_00849.a`
FROM
(
SELECT
`--t1_00849.a`,
b,
`--t2_00849.a`,
`t2_00849.b`,
a AS `--t3_00849.a`,
t3_00849.b
FROM
(
SELECT
a AS `--t1_00849.a`,
b,
t2_00849.a AS `--t2_00849.a`,
t2_00849.b
FROM t1_00849
ALL INNER JOIN t2_00849 ON `--t1_00849.a` = `--t2_00849.a`
) AS `--.s`
ALL INNER JOIN t3_00849 ON `--t2_00849.a` = `--t3_00849.a`
) AS `--.s`
ALL INNER JOIN t4_00849 ON `--t3_00849.a` = a
WHERE (`--t1_00849.a` = `--t2_00849.a`) AND (`--t2_00849.a` = `--t3_00849.a`) AND (`--t3_00849.a` = a)
SELECT `--t1_00849.a` AS `t1_00849.a`
FROM
(
SELECT
`--t1_00849.a`,
b,
`t2_00849.a`,
`t2_00849.b`,
a,
t3_00849.b
FROM
(
SELECT
a AS `--t1_00849.a`,
b,
t2_00849.a,
t2_00849.b
FROM t1_00849
CROSS JOIN t2_00849
) AS `--.s`
CROSS JOIN t3_00849
) AS `--.s`
CROSS JOIN t4_00849
SELECT `--t1_00849.a` AS `t1_00849.a`
FROM
(
SELECT
`--t1_00849.a`,
b,
`t2_00849.a`,
`t2_00849.b`,
a,
t3_00849.b
FROM
(
SELECT
a AS `--t1_00849.a`,
b,
t2_00849.a,
t2_00849.b
FROM t1_00849
CROSS JOIN t2_00849
) AS `--.s`
CROSS JOIN t3_00849
) AS `--.s`
CROSS JOIN t4_00849
SELECT `--t1_00849.a` AS `t1_00849.a`
FROM
(
SELECT
a AS `--t1_00849.a`,
b,
t2_00849.a,
t2_00849.b
FROM t1_00849
CROSS JOIN t2_00849
) AS `--.s`
CROSS JOIN t3_00849
SELECT `--t1_00849.a` AS `t1_00849.a`
FROM
(
SELECT
a AS `--t1_00849.a`,
b,
t2_00849.a AS `--t2_00849.a`,
t2_00849.b
FROM t1_00849
ALL INNER JOIN t2_00849 ON `--t1_00849.a` = `--t2_00849.a`
) AS `--.s`
CROSS JOIN t3_00849
SELECT * FROM t1, t2
1 1 1 1
1 1 1 \N
2 2 1 1
2 2 1 \N
3 3 1 1
3 3 1 \N
4 4 1 1
4 4 1 \N
SELECT * FROM t1, t2 WHERE t1.a = t2.a
1 1 1 1
1 1 1 \N
SELECT t1.a, t2.a FROM t1, t2 WHERE t1.b = t2.b
1 1
SELECT t1.a, t2.b, t3.b FROM t1, t2, t3 WHERE t1.a = t2.a AND t1.a = t3.a
1 1 1
1 1 \N
1 \N 1
1 \N \N
SELECT t1.a, t2.b, t3.b FROM t1, t2, t3 WHERE t1.b = t2.b AND t1.b = t3.b
1 1 1
SELECT t1.a, t2.b, t3.b, t4.b FROM t1, t2, t3, t4 WHERE t1.a = t2.a AND t1.a = t3.a AND t1.a = t4.a
1 1 1 1
1 1 1 \N
1 1 \N 1
1 1 \N \N
1 \N 1 1
1 \N 1 \N
1 \N \N 1
1 \N \N \N
SELECT t1.a, t2.b, t3.b, t4.b FROM t1, t2, t3, t4 WHERE t1.b = t2.b AND t1.b = t3.b AND t1.b = t4.b
1 1 1 1
SELECT t1.a, t2.b, t3.b, t4.b FROM t1, t2, t3, t4 WHERE t1.a = t2.a AND t2.a = t3.a AND t3.a = t4.a
1 1 1 1
1 1 1 \N
1 1 \N 1
1 1 \N \N
1 \N 1 1
1 \N 1 \N
1 \N \N 1
1 \N \N \N

View File

@ -1,69 +0,0 @@
SET enable_debug_queries = 1;
SET enable_optimize_predicate_expression = 0;
SET multiple_joins_rewriter_version = 1;
DROP TABLE IF EXISTS t1_00849;
DROP TABLE IF EXISTS t2_00849;
DROP TABLE IF EXISTS t3_00849;
DROP TABLE IF EXISTS t4_00849;
CREATE TABLE t1_00849 (a UInt32, b Nullable(Int32)) ENGINE = Memory;
CREATE TABLE t2_00849 (a UInt32, b Nullable(Int32)) ENGINE = Memory;
CREATE TABLE t3_00849 (a UInt32, b Nullable(Int32)) ENGINE = Memory;
CREATE TABLE t4_00849 (a UInt32, b Nullable(Int32)) ENGINE = Memory;
ANALYZE SELECT t1_00849.a FROM t1_00849, t2_00849;
ANALYZE SELECT t1_00849.a FROM t1_00849, t2_00849 WHERE t1_00849.a = t2_00849.a;
ANALYZE SELECT t1_00849.a FROM t1_00849, t2_00849 WHERE t1_00849.b = t2_00849.b;
ANALYZE SELECT t1_00849.a FROM t1_00849, t2_00849, t3_00849 WHERE t1_00849.a = t2_00849.a AND t1_00849.a = t3_00849.a;
ANALYZE SELECT t1_00849.a FROM t1_00849, t2_00849, t3_00849 WHERE t1_00849.b = t2_00849.b AND t1_00849.b = t3_00849.b;
ANALYZE SELECT t1_00849.a FROM t1_00849, t2_00849, t3_00849, t4_00849 WHERE t1_00849.a = t2_00849.a AND t1_00849.a = t3_00849.a AND t1_00849.a = t4_00849.a;
ANALYZE SELECT t1_00849.a FROM t1_00849, t2_00849, t3_00849, t4_00849 WHERE t1_00849.b = t2_00849.b AND t1_00849.b = t3_00849.b AND t1_00849.b = t4_00849.b;
ANALYZE SELECT t1_00849.a FROM t1_00849, t2_00849, t3_00849, t4_00849 WHERE t2_00849.a = t1_00849.a AND t2_00849.a = t3_00849.a AND t2_00849.a = t4_00849.a;
ANALYZE SELECT t1_00849.a FROM t1_00849, t2_00849, t3_00849, t4_00849 WHERE t3_00849.a = t1_00849.a AND t3_00849.a = t2_00849.a AND t3_00849.a = t4_00849.a;
ANALYZE SELECT t1_00849.a FROM t1_00849, t2_00849, t3_00849, t4_00849 WHERE t4_00849.a = t1_00849.a AND t4_00849.a = t2_00849.a AND t4_00849.a = t3_00849.a;
ANALYZE SELECT t1_00849.a FROM t1_00849, t2_00849, t3_00849, t4_00849 WHERE t1_00849.a = t2_00849.a AND t2_00849.a = t3_00849.a AND t3_00849.a = t4_00849.a;
ANALYZE SELECT t1_00849.a FROM t1_00849, t2_00849, t3_00849, t4_00849;
ANALYZE SELECT t1_00849.a FROM t1_00849 CROSS JOIN t2_00849 CROSS JOIN t3_00849 CROSS JOIN t4_00849;
ANALYZE SELECT t1_00849.a FROM t1_00849, t2_00849 CROSS JOIN t3_00849;
ANALYZE SELECT t1_00849.a FROM t1_00849 JOIN t2_00849 USING a CROSS JOIN t3_00849; -- { serverError 48 }
ANALYZE SELECT t1_00849.a FROM t1_00849 JOIN t2_00849 ON t1_00849.a = t2_00849.a CROSS JOIN t3_00849;
INSERT INTO t1_00849 values (1,1), (2,2), (3,3), (4,4);
INSERT INTO t2_00849 values (1,1), (1, Null);
INSERT INTO t3_00849 values (1,1), (1, Null);
INSERT INTO t4_00849 values (1,1), (1, Null);
SELECT 'SELECT * FROM t1, t2';
SELECT * FROM t1_00849, t2_00849
ORDER BY t1_00849.a, t2_00849.b;
SELECT 'SELECT * FROM t1, t2 WHERE t1.a = t2.a';
SELECT * FROM t1_00849, t2_00849 WHERE t1_00849.a = t2_00849.a
ORDER BY t1_00849.a, t2_00849.b;
SELECT 'SELECT t1.a, t2.a FROM t1, t2 WHERE t1.b = t2.b';
SELECT t1_00849.a, t2_00849.b FROM t1_00849, t2_00849 WHERE t1_00849.b = t2_00849.b;
SELECT 'SELECT t1.a, t2.b, t3.b FROM t1, t2, t3 WHERE t1.a = t2.a AND t1.a = t3.a';
SELECT t1_00849.a, t2_00849.b, t3_00849.b FROM t1_00849, t2_00849, t3_00849
WHERE t1_00849.a = t2_00849.a AND t1_00849.a = t3_00849.a
ORDER BY t2_00849.b, t3_00849.b;
SELECT 'SELECT t1.a, t2.b, t3.b FROM t1, t2, t3 WHERE t1.b = t2.b AND t1.b = t3.b';
SELECT t1_00849.a, t2_00849.b, t3_00849.b FROM t1_00849, t2_00849, t3_00849 WHERE t1_00849.b = t2_00849.b AND t1_00849.b = t3_00849.b;
SELECT 'SELECT t1.a, t2.b, t3.b, t4.b FROM t1, t2, t3, t4 WHERE t1.a = t2.a AND t1.a = t3.a AND t1.a = t4.a';
SELECT t1_00849.a, t2_00849.b, t3_00849.b, t4_00849.b FROM t1_00849, t2_00849, t3_00849, t4_00849
WHERE t1_00849.a = t2_00849.a AND t1_00849.a = t3_00849.a AND t1_00849.a = t4_00849.a
ORDER BY t2_00849.b, t3_00849.b, t4_00849.b;
SELECT 'SELECT t1.a, t2.b, t3.b, t4.b FROM t1, t2, t3, t4 WHERE t1.b = t2.b AND t1.b = t3.b AND t1.b = t4.b';
SELECT t1_00849.a, t2_00849.b, t3_00849.b, t4_00849.b FROM t1_00849, t2_00849, t3_00849, t4_00849
WHERE t1_00849.b = t2_00849.b AND t1_00849.b = t3_00849.b AND t1_00849.b = t4_00849.b;
SELECT 'SELECT t1.a, t2.b, t3.b, t4.b FROM t1, t2, t3, t4 WHERE t1.a = t2.a AND t2.a = t3.a AND t3.a = t4.a';
SELECT t1_00849.a, t2_00849.b, t3_00849.b, t4_00849.b FROM t1_00849, t2_00849, t3_00849, t4_00849
WHERE t1_00849.a = t2_00849.a AND t2_00849.a = t3_00849.a AND t3_00849.a = t4_00849.a
ORDER BY t2_00849.b, t3_00849.b, t4_00849.b;
DROP TABLE t1_00849;
DROP TABLE t2_00849;
DROP TABLE t3_00849;
DROP TABLE t4_00849;

View File

@ -1,6 +1,5 @@
SET enable_debug_queries = 1;
SET enable_optimize_predicate_expression = 0;
SET multiple_joins_rewriter_version = 2;
DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t2;

View File

@ -4,14 +4,6 @@ select t1.* from system.one t1 join system.one t2 on t1.dummy = t2.dummy join sy
select t2.*, t3.* from system.one t1 join system.one t2 on t1.dummy = t2.dummy join system.one t3 ON t1.dummy = t3.dummy;
select t1.dummy, t2.*, t3.dummy from system.one t1 join system.one t2 on t1.dummy = t2.dummy join system.one t3 ON t1.dummy = t3.dummy;
set multiple_joins_rewriter_version = 1;
select t1.dummy, t2.*, t3.dummy from (select * from system.one) t1
join system.one t2 on t1.dummy = t2.dummy
join system.one t3 ON t1.dummy = t3.dummy; -- { serverError 48 }
set multiple_joins_rewriter_version = 2;
select t1.dummy, t2.*, t3.dummy from (select * from system.one) t1
join system.one t2 on t1.dummy = t2.dummy
join system.one t3 ON t1.dummy = t3.dummy;

View File

@ -1,20 +1,3 @@
SET multiple_joins_rewriter_version = 2;
SELECT count(*)
FROM numbers(2) AS n1, numbers(3) AS n2, numbers(4) AS n3
WHERE (n1.number = n2.number) AND (n2.number = n3.number);
SELECT count(*) c FROM (
SELECT count(*), count(*) as c
FROM numbers(2) AS n1, numbers(3) AS n2, numbers(4) AS n3
WHERE (n1.number = n2.number) AND (n2.number = n3.number)
AND (SELECT count(*) FROM numbers(1)) = 1
)
WHERE (SELECT count(*) FROM numbers(2)) = 2
HAVING c IN(SELECT count(*) c FROM numbers(1));
SET multiple_joins_rewriter_version = 1;
SELECT count(*)
FROM numbers(2) AS n1, numbers(3) AS n2, numbers(4) AS n3
WHERE (n1.number = n2.number) AND (n2.number = n3.number);

View File

@ -11,7 +11,6 @@ INSERT INTO t1 (id, value1) VALUES (1, 'val11');
INSERT INTO t2 (id, value2) VALUES (1, 'val21');
INSERT INTO t3 (id, value3) VALUES (1, 'val31');
SET multiple_joins_rewriter_version = 2;
SET enable_optimize_predicate_expression = 1;
SELECT t1.id, t2.id as id, t3.id as value

View File

@ -1,5 +1,3 @@
set multiple_joins_rewriter_version = 2;
select
arrayMap(x, y -> floor((y - x) / x, 3), l, r) diff_percent,
test, query