2018-11-02 18:53:23 +00:00
|
|
|
#include <Interpreters/AnalyzedJoin.h>
|
|
|
|
#include <Interpreters/DatabaseAndTableWithAlias.h>
|
|
|
|
#include <Interpreters/InterpreterSelectWithUnionQuery.h>
|
|
|
|
|
|
|
|
#include <Parsers/ASTExpressionList.h>
|
|
|
|
#include <Parsers/ASTTablesInSelectQuery.h>
|
|
|
|
#include <Parsers/ASTSelectQuery.h>
|
|
|
|
|
|
|
|
#include <Storages/IStorage.h>
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
|
|
|
|
2019-02-13 15:18:02 +00:00
|
|
|
void AnalyzedJoin::addUsingKey(const ASTPtr & ast)
|
|
|
|
{
|
|
|
|
key_names_left.push_back(ast->getColumnName());
|
|
|
|
key_names_right.push_back(ast->getAliasOrColumnName());
|
|
|
|
|
|
|
|
key_asts_left.push_back(ast);
|
|
|
|
key_asts_right.push_back(ast);
|
2019-07-30 18:39:37 +00:00
|
|
|
|
|
|
|
auto & right_key = key_names_right.back();
|
|
|
|
if (renames.count(right_key))
|
|
|
|
right_key = renames[right_key];
|
2019-02-13 15:18:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void AnalyzedJoin::addOnKeys(ASTPtr & left_table_ast, ASTPtr & right_table_ast)
|
|
|
|
{
|
2019-05-13 18:58:15 +00:00
|
|
|
with_using = false;
|
2019-02-13 15:18:02 +00:00
|
|
|
key_names_left.push_back(left_table_ast->getColumnName());
|
|
|
|
key_names_right.push_back(right_table_ast->getAliasOrColumnName());
|
|
|
|
|
|
|
|
key_asts_left.push_back(left_table_ast);
|
|
|
|
key_asts_right.push_back(right_table_ast);
|
|
|
|
}
|
|
|
|
|
2019-05-13 18:58:15 +00:00
|
|
|
/// @return how many times right key appears in ON section.
|
|
|
|
size_t AnalyzedJoin::rightKeyInclusion(const String & name) const
|
|
|
|
{
|
|
|
|
if (with_using)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
size_t count = 0;
|
|
|
|
for (const auto & key_name : key_names_right)
|
|
|
|
if (name == key_name)
|
|
|
|
++count;
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
2019-07-30 18:39:37 +00:00
|
|
|
void AnalyzedJoin::deduplicateAndQualifyColumnNames(const NameSet & left_table_columns, const String & right_table_prefix)
|
|
|
|
{
|
|
|
|
NameSet joined_columns;
|
|
|
|
NamesAndTypesList dedup_columns;
|
|
|
|
|
|
|
|
for (auto & column : columns_from_joined_table)
|
|
|
|
{
|
|
|
|
if (joined_columns.count(column.name))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
joined_columns.insert(column.name);
|
|
|
|
|
|
|
|
dedup_columns.push_back(column);
|
|
|
|
auto & inserted = dedup_columns.back();
|
|
|
|
|
|
|
|
if (left_table_columns.count(column.name))
|
|
|
|
inserted.name = right_table_prefix + column.name;
|
|
|
|
|
|
|
|
original_names[inserted.name] = column.name;
|
|
|
|
if (inserted.name != column.name)
|
|
|
|
renames[column.name] = inserted.name;
|
|
|
|
}
|
|
|
|
|
|
|
|
columns_from_joined_table.swap(dedup_columns);
|
|
|
|
}
|
|
|
|
|
|
|
|
NameSet AnalyzedJoin::getQualifiedColumnsSet() const
|
2019-01-30 15:51:39 +00:00
|
|
|
{
|
2019-07-30 18:39:37 +00:00
|
|
|
NameSet out;
|
|
|
|
for (const auto & names : original_names)
|
|
|
|
out.insert(names.first);
|
|
|
|
return out;
|
2018-11-02 18:53:23 +00:00
|
|
|
}
|
|
|
|
|
2019-07-30 18:39:37 +00:00
|
|
|
NameSet AnalyzedJoin::getOriginalColumnsSet() const
|
2018-11-02 18:53:23 +00:00
|
|
|
{
|
2019-07-30 18:39:37 +00:00
|
|
|
NameSet out;
|
|
|
|
for (const auto & names : original_names)
|
|
|
|
out.insert(names.second);
|
|
|
|
return out;
|
|
|
|
}
|
2018-11-02 18:53:23 +00:00
|
|
|
|
2019-08-01 19:56:29 +00:00
|
|
|
std::unordered_map<String, String> AnalyzedJoin::getOriginalColumnsMap(const NameSet & required_columns) const
|
2019-07-30 18:39:37 +00:00
|
|
|
{
|
2019-08-01 19:56:29 +00:00
|
|
|
std::unordered_map<String, String> out;
|
2019-07-30 18:39:37 +00:00
|
|
|
for (const auto & column : required_columns)
|
2019-02-13 19:00:52 +00:00
|
|
|
{
|
2019-07-30 18:39:37 +00:00
|
|
|
auto it = original_names.find(column);
|
|
|
|
if (it != original_names.end())
|
2019-08-01 19:56:29 +00:00
|
|
|
out.insert(*it);
|
2019-02-13 19:00:52 +00:00
|
|
|
}
|
2019-07-30 18:39:37 +00:00
|
|
|
return out;
|
2018-11-02 18:53:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NamesAndTypesList getNamesAndTypeListFromTableExpression(const ASTTableExpression & table_expression, const Context & context)
|
|
|
|
{
|
|
|
|
NamesAndTypesList names_and_type_list;
|
|
|
|
if (table_expression.subquery)
|
|
|
|
{
|
|
|
|
const auto & subquery = table_expression.subquery->children.at(0);
|
|
|
|
names_and_type_list = InterpreterSelectWithUnionQuery::getSampleBlock(subquery, context).getNamesAndTypesList();
|
|
|
|
}
|
|
|
|
else if (table_expression.table_function)
|
|
|
|
{
|
|
|
|
const auto table_function = table_expression.table_function;
|
|
|
|
auto query_context = const_cast<Context *>(&context.getQueryContext());
|
|
|
|
const auto & function_storage = query_context->executeTableFunction(table_function);
|
|
|
|
names_and_type_list = function_storage->getSampleBlockNonMaterialized().getNamesAndTypesList();
|
|
|
|
}
|
|
|
|
else if (table_expression.database_and_table_name)
|
|
|
|
{
|
2019-01-14 18:15:04 +00:00
|
|
|
DatabaseAndTableWithAlias database_table(table_expression.database_and_table_name);
|
2018-11-02 18:53:23 +00:00
|
|
|
const auto & table = context.getTable(database_table.database, database_table.table);
|
|
|
|
names_and_type_list = table->getSampleBlockNonMaterialized().getNamesAndTypesList();
|
|
|
|
}
|
|
|
|
|
|
|
|
return names_and_type_list;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|