Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rewrite multiple JOINs v2 #9739

Merged
merged 11 commits into from
Mar 22, 2020
2 changes: 1 addition & 1 deletion dbms/src/Common/ErrorCodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,7 @@ namespace ErrorCodes
extern const int CANNOT_PTHREAD_ATTR = 468;
extern const int VIOLATED_CONSTRAINT = 469;
extern const int QUERY_IS_NOT_SUPPORTED_IN_LIVE_VIEW = 470;
extern const int SETTINGS_ARE_NOT_SUPPORTED = 471;
extern const int INVALID_SETTING_VALUE = 471;
extern const int READONLY_SETTING = 472;
extern const int DEADLOCK_AVOIDED = 473;
extern const int INVALID_TEMPLATE_FORMAT = 474;
Expand Down
1 change: 1 addition & 0 deletions dbms/src/Core/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ struct Settings : public SettingsCollection<Settings>
M(SettingBool, partial_revokes, false, "Makes it possible to revoke privileges partially.", 0) \
M(SettingBool, 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(SettingBool, use_compact_format_in_distributed_parts_names, false, "Changes format of directories names for distributed table insert parts.", 0) \
M(SettingUInt64, multiple_joins_rewriter_version, 1, "1 or 2. Second rewriter version knows about table columns and keep not clashed names as is.", 0) \
\
/** Obsolete settings that do nothing but left for compatibility reasons. Remove each one after half a year of obsolescence. */ \
\
Expand Down
13 changes: 3 additions & 10 deletions dbms/src/Interpreters/CrossToInnerJoinVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include <Interpreters/CrossToInnerJoinVisitor.h>
#include <Interpreters/DatabaseAndTableWithAlias.h>
#include <Interpreters/IdentifierSemantic.h>
#include <Interpreters/QueryAliasesVisitor.h>
#include <Interpreters/misc.h>
#include <Parsers/ASTSelectQuery.h>
#include <Parsers/ASTSubquery.h>
Expand Down Expand Up @@ -95,7 +94,7 @@ class CheckExpressionVisitorData

CheckExpressionVisitorData(const std::vector<JoinedElement> & tables_,
const std::vector<TableWithColumnNamesAndTypes> & tables_with_columns,
Aliases && aliases_)
const Aliases & aliases_)
: joined_tables(tables_)
, tables(tables_with_columns)
, aliases(aliases_)
Expand Down Expand Up @@ -168,7 +167,7 @@ class CheckExpressionVisitorData
const std::vector<JoinedElement> & joined_tables;
const std::vector<TableWithColumnNamesAndTypes> & tables;
std::map<size_t, std::vector<ASTPtr>> asts_to_join_on;
Aliases aliases;
const Aliases & aliases;
bool ands_only;

size_t canMoveEqualsToJoinOn(const ASTFunction & node)
Expand Down Expand Up @@ -323,13 +322,7 @@ void CrossToInnerJoinMatcher::visit(ASTSelectQuery & select, ASTPtr &, Data & da
if (!select.where())
return;

Aliases aliases;
QueryAliasesVisitor::Data query_aliases_data{aliases};
if (ASTPtr with = select.with())
QueryAliasesVisitor(query_aliases_data).visit(with);
QueryAliasesVisitor(query_aliases_data).visit(select.select());

CheckExpressionVisitor::Data visitor_data{joined_tables, data.tables_with_columns, std::move(aliases)};
CheckExpressionVisitor::Data visitor_data{joined_tables, data.tables_with_columns, data.aliases};
CheckExpressionVisitor(visitor_data).visit(select.where());

if (visitor_data.complex())
Expand Down
2 changes: 2 additions & 0 deletions dbms/src/Interpreters/CrossToInnerJoinVisitor.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <Interpreters/InDepthNodeVisitor.h>
#include <Interpreters/Aliases.h>

namespace DB
{
Expand All @@ -15,6 +16,7 @@ class CrossToInnerJoinMatcher
struct Data
{
const std::vector<TableWithColumnNamesAndTypes> & tables_with_columns;
const Aliases & aliases;
const String current_database;
bool done = false;
};
Expand Down
19 changes: 16 additions & 3 deletions dbms/src/Interpreters/InterpreterSelectQuery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#include <Interpreters/AnalyzedJoin.h>
#include <Interpreters/Join.h>
#include <Interpreters/JoinedTables.h>
#include <Interpreters/QueryAliasesVisitor.h>

#include <Storages/MergeTree/MergeTreeData.h>
#include <Storages/MergeTree/MergeTreeWhereOptimizer.h>
Expand Down Expand Up @@ -115,6 +116,7 @@ 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.
Expand Down Expand Up @@ -264,13 +266,24 @@ InterpreterSelectQuery::InterpreterSelectQuery(
/// Rewrite JOINs
if (!has_input && joined_tables.tablesCount() > 1)
{
CrossToInnerJoinVisitor::Data cross_to_inner{joined_tables.tablesWithColumns(), context->getCurrentDatabase()};
ASTSelectQuery & select = getSelectQuery();

Aliases aliases;
if (ASTPtr with = select.with())
QueryAliasesNoSubqueriesVisitor(aliases).visit(with);
QueryAliasesNoSubqueriesVisitor(aliases).visit(select.select());

CrossToInnerJoinVisitor::Data cross_to_inner{joined_tables.tablesWithColumns(), aliases, context->getCurrentDatabase()};
CrossToInnerJoinVisitor(cross_to_inner).visit(query_ptr);

JoinToSubqueryTransformVisitor::Data join_to_subs_data{*context};
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{joined_tables.tablesWithColumns(), aliases, rewriter_version};
JoinToSubqueryTransformVisitor(join_to_subs_data).visit(query_ptr);

joined_tables.reset(getSelectQuery());
joined_tables.reset(select);
joined_tables.resolveTables();

if (storage && joined_tables.isLeftTableSubquery())
Expand Down