some mote ExpressionAnalyzer refactoring

This commit is contained in:
chertus 2019-02-06 17:48:05 +03:00
parent 1f95bf18e4
commit 9a8db441c3
5 changed files with 61 additions and 57 deletions

View File

@ -9,6 +9,7 @@
#include <Parsers/ASTSelectQuery.h>
#include <Storages/IStorage.h>
#include <DataTypes/DataTypeNullable.h>
namespace DB
{
@ -51,24 +52,13 @@ ExpressionActionsPtr AnalyzedJoin::createJoinedBlockActions(
return analyzer.getActions(false);
}
NameSet AnalyzedJoin::getRequiredColumnsFromJoinedTable(const JoinedColumnsList & columns_added_by_join,
const ExpressionActionsPtr & joined_block_actions) const
Names AnalyzedJoin::getOriginalColumnNames(const NameSet & required_columns_from_joined_table) const
{
NameSet required_columns_from_joined_table;
auto required_action_columns = joined_block_actions->getRequiredColumns();
required_columns_from_joined_table.insert(required_action_columns.begin(), required_action_columns.end());
auto sample = joined_block_actions->getSampleBlock();
for (auto & column : key_names_right)
if (!sample.has(column))
required_columns_from_joined_table.insert(column);
for (auto & column : columns_added_by_join)
if (!sample.has(column.name_and_type.name))
required_columns_from_joined_table.insert(column.name_and_type.name);
return required_columns_from_joined_table;
Names original_columns;
for (const auto & column : columns_from_joined_table)
if (required_columns_from_joined_table.count(column.name_and_type.name))
original_columns.emplace_back(column.original_name);
return original_columns;
}
const JoinedColumnsList & AnalyzedJoin::getColumnsFromJoinedTable(
@ -104,6 +94,30 @@ const JoinedColumnsList & AnalyzedJoin::getColumnsFromJoinedTable(
return columns_from_joined_table;
}
void AnalyzedJoin::calculateAvailableJoinedColumns(
const NameSet & source_columns, const Context & context, const ASTSelectQuery * select_query_with_join, bool make_nullable)
{
const auto & columns = getColumnsFromJoinedTable(source_columns, context, select_query_with_join);
NameSet joined_columns;
for (auto & column : columns)
{
auto & column_name = column.name_and_type.name;
auto & column_type = column.name_and_type.type;
auto & original_name = column.original_name;
{
if (joined_columns.count(column_name)) /// Duplicate columns in the subquery for JOIN do not make sense.
continue;
joined_columns.insert(column_name);
auto type = make_nullable ? makeNullable(column_type) : column_type;
available_joined_columns.emplace_back(NameAndTypePair(column_name, std::move(type)), original_name);
}
}
}
NamesAndTypesList getNamesAndTypeListFromTableExpression(const ASTTableExpression & table_expression, const Context & context)
{

View File

@ -66,13 +66,15 @@ struct AnalyzedJoin
const ASTSelectQuery * select_query_with_join,
const Context & context) const;
/// Columns which will be used in query from joined table.
NameSet getRequiredColumnsFromJoinedTable(const JoinedColumnsList & columns_added_by_join,
const ExpressionActionsPtr & joined_block_actions) const;
Names getOriginalColumnNames(const NameSet & required_columns) const;
const JoinedColumnsList & getColumnsFromJoinedTable(const NameSet & source_columns,
const Context & context,
const ASTSelectQuery * select_query_with_join);
void calculateAvailableJoinedColumns(const NameSet & source_columns,
const Context & context,
const ASTSelectQuery * select_query_with_join,
bool make_nullable);
};
struct ASTTableExpression;

View File

@ -510,6 +510,17 @@ void ExpressionAnalyzer::addJoinAction(ExpressionActionsPtr & actions, bool only
columns_added_by_join_list));
}
static void appendRequiredColumns(NameSet & required_columns, const Block & sample, const AnalyzedJoin & analyzed_join)
{
for (auto & column : analyzed_join.key_names_right)
if (!sample.has(column))
required_columns.insert(column);
for (auto & column : analyzed_join.columns_from_joined_table)
if (!sample.has(column.name_and_type.name))
required_columns.insert(column.name_and_type.name);
}
bool ExpressionAnalyzer::appendJoin(ExpressionActionsChain & chain, bool only_types)
{
assertSelect();
@ -566,6 +577,11 @@ bool ExpressionAnalyzer::appendJoin(ExpressionActionsChain & chain, bool only_ty
if (!subquery_for_set.join)
{
auto & analyzed_join = analyzedJoin();
/// Actions which need to be calculated on joined block.
ExpressionActionsPtr joined_block_actions =
analyzed_join.createJoinedBlockActions(columns_added_by_join, select_query, context);
/** For GLOBAL JOINs (in the case, for example, of the push method for executing GLOBAL subqueries), the following occurs
* - in the addExternalStorage function, the JOIN (SELECT ...) subquery is replaced with JOIN _data1,
* in the subquery_for_set object this subquery is exposed as source and the temporary table _data1 as the `table`.
@ -582,15 +598,15 @@ bool ExpressionAnalyzer::appendJoin(ExpressionActionsChain & chain, bool only_ty
else if (table_to_join.database_and_table_name)
table = table_to_join.database_and_table_name;
const JoinedColumnsList & columns_from_joined_table = analyzedJoin().columns_from_joined_table;
Names action_columns = joined_block_actions->getRequiredColumns();
NameSet required_columns(action_columns.begin(), action_columns.end());
Names original_columns;
for (const auto & column : columns_from_joined_table)
if (required_columns_from_joined_table.count(column.name_and_type.name))
original_columns.emplace_back(column.original_name);
appendRequiredColumns(required_columns, joined_block_actions->getSampleBlock(), analyzed_join);
Names original_columns = analyzed_join.getOriginalColumnNames(required_columns);
auto interpreter = interpretSubquery(table, context, subquery_depth, original_columns);
subquery_for_set.makeSource(interpreter, columns_from_joined_table, required_columns_from_joined_table);
subquery_for_set.makeSource(interpreter, analyzed_join.columns_from_joined_table, required_columns);
}
Block sample_block = subquery_for_set.renamedSampleBlock();
@ -1038,9 +1054,6 @@ void ExpressionAnalyzer::collectUsedColumns()
required.swap(fixed_required);
}
joined_block_actions = analyzed_join.createJoinedBlockActions(columns_added_by_join, select_query, context);
required_columns_from_joined_table = analyzed_join.getRequiredColumnsFromJoinedTable(columns_added_by_join, joined_block_actions);
}
if (columns_context.has_array_join)

View File

@ -67,12 +67,6 @@ struct ExpressionAnalyzerData
/// Columns will be added to block by join.
JoinedColumnsList columns_added_by_join; /// Subset of analyzed_join.available_joined_columns
/// Actions which need to be calculated on joined block.
ExpressionActionsPtr joined_block_actions;
/// Columns which will be used in query from joined table. Duplicate names are qualified.
NameSet required_columns_from_joined_table;
protected:
ExpressionAnalyzerData(const NamesAndTypesList & source_columns_,
const NameSet & required_result_columns_,

View File

@ -22,7 +22,6 @@
#include <Parsers/queryToString.h>
#include <DataTypes/NestedUtils.h>
#include <DataTypes/DataTypeNullable.h>
#include <Common/typeid_cast.h>
#include <Core/NamesAndTypes.h>
@ -641,29 +640,11 @@ void collectJoinedColumns(AnalyzedJoin & analyzed_join, const ASTSelectQuery * s
else if (table_join.on_expression)
collectJoinedColumnsFromJoinOnExpr(analyzed_join, select_query, source_columns, context);
auto & columns_from_joined_table = analyzed_join.getColumnsFromJoinedTable(source_columns, context, select_query);
NameSet joined_columns;
auto & settings = context.getSettingsRef();
bool make_nullable = settings.join_use_nulls && (table_join.kind == ASTTableJoin::Kind::Left ||
table_join.kind == ASTTableJoin::Kind::Full);
for (auto & column : columns_from_joined_table)
{
auto & column_name = column.name_and_type.name;
auto & column_type = column.name_and_type.type;
auto & original_name = column.original_name;
{
if (joined_columns.count(column_name)) /// Duplicate columns in the subquery for JOIN do not make sense.
continue;
joined_columns.insert(column_name);
bool make_nullable = settings.join_use_nulls && (table_join.kind == ASTTableJoin::Kind::Left ||
table_join.kind == ASTTableJoin::Kind::Full);
auto type = make_nullable ? makeNullable(column_type) : column_type;
analyzed_join.available_joined_columns.emplace_back(NameAndTypePair(column_name, std::move(type)), original_name);
}
}
analyzed_join.calculateAvailableJoinedColumns(source_columns, context, select_query, make_nullable);
}
}