提交 f3dcc2ef 编写于 作者: Z zhang2014

ISSUES-3145 support qualified asterisk

上级 65f7c390
......@@ -358,10 +358,11 @@ void ExpressionAnalyzer::translateQualifiedNamesImpl(ASTPtr & ast, const std::ve
&& ((!table_names.table.empty() && ident->name == table_names.table)
|| (!table_names.alias.empty() && ident->name == table_names.alias))))
{
/// Replace to plain asterisk.
ast = std::make_shared<ASTAsterisk>();
return;
}
}
throw Exception("Unknown qualified identifier: " + ident->getAliasOrColumnName(), ErrorCodes::UNKNOWN_IDENTIFIER);
}
else if (auto * join = typeid_cast<ASTTableJoin *>(ast.get()))
{
......@@ -862,6 +863,43 @@ static NamesAndTypesList::iterator findColumn(const String & name, NamesAndTypes
[&](const NamesAndTypesList::value_type & val) { return val.name == name; });
}
static void getTableExpressions(const ASTPtr & node, std::vector<ASTTableExpression> & table_expressions)
{
if (ASTTableExpression * table_expression = typeid_cast<ASTTableExpression *>(node.get()))
{
table_expressions.emplace_back(*table_expression);
return;
}
for (const auto & child : node->children)
getTableExpressions(child, table_expressions);
}
static 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)
{
const auto & identifier = static_cast<const ASTIdentifier &>(*table_expression.database_and_table_name);
auto database_table = getDatabaseAndTableNameFromIdentifier(identifier);
const auto & table = context.getTable(database_table.first, database_table.second);
names_and_type_list = table->getSampleBlockNonMaterialized().getNamesAndTypesList();
}
return names_and_type_list;
}
void ExpressionAnalyzer::normalizeTree()
{
......@@ -879,7 +917,21 @@ void ExpressionAnalyzer::normalizeTree()
if (all_columns_name.empty())
throw Exception("Logical error: an asterisk cannot be replaced with empty columns.", ErrorCodes::LOGICAL_ERROR);
QueryNormalizer(query, aliases, settings, all_columns_name).perform();
TableNamesAndColumnsName table_names_nad_columns_name;
if (select_query && select_query->tables && !select_query->tables->children.empty())
{
std::vector<ASTTableExpression> tables_expression;
getTableExpressions(select_query->tables, tables_expression);
for (const auto & table_expression : tables_expression)
{
const auto table_name = getTableNameWithAliasFromTableExpression(table_expression, context);
NamesAndTypesList names_and_types = getNamesAndTypeListFromTableExpression(table_expression, context);
table_names_nad_columns_name.emplace_back(std::pair(table_name, names_and_types.getNames()));
}
}
QueryNormalizer(query, aliases, settings, all_columns_name, table_names_nad_columns_name).perform();
}
......@@ -2274,30 +2326,9 @@ NamesAndTypesList ExpressionAnalyzer::AnalyzedJoin::getColumnsFromJoinedTable(co
{
if (const ASTTablesInSelectQueryElement * node = select_query_with_join->join())
{
Block nested_result_sample;
const auto & table_expression = static_cast<const ASTTableExpression &>(*node->table_expression);
if (table_expression.subquery)
{
const auto & subquery = table_expression.subquery->children.at(0);
nested_result_sample = InterpreterSelectWithUnionQuery::getSampleBlock(subquery, context);
}
else if (table_expression.table_function)
{
const auto table_function = table_expression.table_function;
auto query_context = const_cast<Context *>(&context.getQueryContext());
const auto & join_storage = query_context->executeTableFunction(table_function);
nested_result_sample = join_storage->getSampleBlockNonMaterialized();
}
else if (table_expression.database_and_table_name)
{
const auto & identifier = static_cast<const ASTIdentifier &>(*table_expression.database_and_table_name);
auto database_table = getDatabaseAndTableNameFromIdentifier(identifier);
const auto & table = context.getTable(database_table.first, database_table.second);
nested_result_sample = table->getSampleBlockNonMaterialized();
}
columns_from_joined_table = nested_result_sample.getNamesAndTypesList();
columns_from_joined_table = getNamesAndTypeListFromTableExpression(table_expression, context);
}
}
......
......@@ -303,7 +303,7 @@ ASTs PredicateExpressionsOptimizer::getSelectQueryProjectionColumns(ASTPtr & ast
/// first should normalize query tree.
std::unordered_map<String, ASTPtr> aliases;
getQueryAliases(ast, aliases, 0);
QueryNormalizer(ast, aliases, settings, {}).perform();
QueryNormalizer(ast, aliases, settings, {}, {}).perform();
ASTs projection_columns;
auto select_query = static_cast<ASTSelectQuery *>(ast.get());
......
......@@ -8,6 +8,8 @@
#include <Common/StringUtils/StringUtils.h>
#include <Common/typeid_cast.h>
#include <Poco/String.h>
#include <Parsers/ASTQualifiedAsterisk.h>
#include <iostream>
namespace DB
{
......@@ -29,9 +31,11 @@ bool functionIsInOrGlobalInOperator(const String & name)
}
QueryNormalizer::QueryNormalizer(
ASTPtr & query, const QueryNormalizer::Aliases & aliases, const Settings & settings, const Names & all_columns_name)
: query(query), aliases(aliases), settings(settings), all_columns_name(all_columns_name)
QueryNormalizer::QueryNormalizer(ASTPtr & query, const QueryNormalizer::Aliases & aliases,
const Settings & settings, const Names & all_columns_name,
const TableNamesAndColumnsName & table_names_and_columns_name)
: query(query), aliases(aliases), settings(settings), all_columns_name(all_columns_name),
table_names_and_columns_name(table_names_and_columns_name)
{
}
......@@ -154,6 +158,31 @@ void QueryNormalizer::performImpl(ASTPtr & ast, MapOfASTs & finished_asts, SetOf
for (size_t idx = 0; idx < all_columns_name.size(); idx++)
asts.insert(asts.begin() + idx + i, std::make_shared<ASTIdentifier>(all_columns_name[idx]));
}
else if (typeid_cast<ASTQualifiedAsterisk *>(asts[i].get()) && !table_names_and_columns_name.empty())
{
ASTQualifiedAsterisk * qualified_asterisk = static_cast<ASTQualifiedAsterisk *>(asts[i].get());
ASTIdentifier * identifier = typeid_cast<ASTIdentifier *>(qualified_asterisk->children[0].get());
size_t num_components = identifier->children.size();
for (const auto table_name_and_names : table_names_and_columns_name)
{
const auto table_name = table_name_and_names.first;
const auto table_all_columns_name = table_name_and_names.second;
if ((num_components == 2
&& !table_name.database.empty()
&& static_cast<const ASTIdentifier &>(*identifier->children[0]).name == table_name.database
&& static_cast<const ASTIdentifier &>(*identifier->children[1]).name == table_name.table)
|| (num_components == 0
&& ((!table_name.table.empty() && identifier->name == table_name.table)
|| (!table_name.alias.empty() && identifier->name == table_name.alias))))
{
asts.erase(asts.begin() + i);
for (size_t idx = 0; idx < table_all_columns_name.size(); idx++)
asts.insert(asts.begin() + idx + i, std::make_shared<ASTIdentifier>(table_all_columns_name[idx]));
}
}
}
}
}
else if (ASTTablesInSelectQueryElement * tables_elem = typeid_cast<ASTTablesInSelectQueryElement *>(ast.get()))
......
#pragma once
#include <Parsers/IAST.h>
#include "Settings.h"
#include <Interpreters/Settings.h>
#include <Interpreters/evaluateQualified.h>
namespace DB
{
using TableNameAndColumnsName = std::pair<DatabaseAndTableWithAlias, Names>;
using TableNamesAndColumnsName = std::vector<TableNameAndColumnsName>;
class QueryNormalizer
{
public:
using Aliases = std::unordered_map<String, ASTPtr>;
QueryNormalizer(ASTPtr & query, const Aliases & aliases, const Settings & settings, const Names & all_columns_name);
QueryNormalizer(ASTPtr & query, const Aliases & aliases, const Settings & settings, const Names & all_columns_name,
const TableNamesAndColumnsName & table_names_and_columns_name);
void perform();
......@@ -23,8 +28,9 @@ private:
const Aliases & aliases;
const Settings & settings;
const Names & all_columns_name;
const std::vector<std::pair<DatabaseAndTableWithAlias, Names>> & table_names_and_columns_name;
void performImpl(ASTPtr &ast, MapOfASTs &finished_asts, SetOfASTs &current_asts, std::string current_alias, size_t level);
void performImpl(ASTPtr & ast, MapOfASTs & finished_asts, SetOfASTs & current_asts, std::string current_alias, size_t level);
};
}
1 2
1 2 3 1 4 5
1 2 1 3 1 2 1 3
1 2 1 3 1 2 1 3 3
1 2 1 3 1 3
1 2 1 3 1 3 3
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册