Fix for column aliases that use other aliases

This commit is contained in:
Dmitry Novik 2023-06-16 18:49:59 +00:00
parent 55b81a5a5e
commit 6489922dc1
2 changed files with 33 additions and 14 deletions

View File

@ -1099,7 +1099,6 @@ public:
{
if (table_expression)
{
LOG_DEBUG(&Poco::Logger::get("resolve"), "Table expression: {}", table_expression->dumpTree());
scope.expression_join_tree_node = table_expression;
validateTableExpressionModifiers(scope.expression_join_tree_node, scope);
initializeTableExpressionData(scope.expression_join_tree_node, scope);
@ -1109,7 +1108,6 @@ public:
resolveExpressionNodeList(node, scope, false /*allow_lambda_expression*/, false /*allow_table_expression*/);
else
resolveExpressionNode(node, scope, false /*allow_lambda_expression*/, false /*allow_table_expression*/);
LOG_DEBUG(&Poco::Logger::get("resolve"), "Result: {}", node->dumpTree());
break;
}
@ -2681,7 +2679,6 @@ QueryTreeNodePtr QueryAnalyzer::tryResolveIdentifierFromAliases(const Identifier
*/
QueryTreeNodePtr QueryAnalyzer::tryResolveIdentifierFromTableColumns(const IdentifierLookup & identifier_lookup, IdentifierResolveScope & scope)
{
LOG_DEBUG(&Poco::Logger::get("tryResolveIdentifierFromTableColumns"), "{} {}", scope.column_name_to_column_node.size(), !identifier_lookup.isExpressionLookup());
if (scope.column_name_to_column_node.empty() || !identifier_lookup.isExpressionLookup())
return {};
@ -2841,14 +2838,11 @@ QueryTreeNodePtr QueryAnalyzer::tryResolveIdentifierFromTableExpression(const Id
QueryTreeNodePtr result_expression;
bool match_full_identifier = false;
LOG_DEBUG(&Poco::Logger::get("resolve_identifier_from_storage_or_throw"), "Looking for id: {}", identifier_without_column_qualifier.getFullName());
auto it = table_expression_data.column_name_to_column_node.find(identifier_without_column_qualifier.getFullName());
if (it != table_expression_data.column_name_to_column_node.end())
{
match_full_identifier = true;
result_expression = it->second;
LOG_DEBUG(&Poco::Logger::get("resolve_identifier_from_storage_or_throw"), "Found: {}", result_expression->dumpTree());
}
else
{
@ -5397,7 +5391,6 @@ ProjectionNames QueryAnalyzer::resolveExpressionNode(QueryTreeNodePtr & node, Id
auto unresolved_identifier = identifier_node.getIdentifier();
auto resolve_identifier_expression_result = tryResolveIdentifier({unresolved_identifier, IdentifierLookupContext::EXPRESSION}, scope);
auto resolved_identifier_node = resolve_identifier_expression_result.resolved_identifier;
LOG_DEBUG(&Poco::Logger::get("resolveExpressionNode"), "Resolved: {}", resolved_identifier_node ? resolved_identifier_node->dumpTree() : "Not resolved");
if (resolved_identifier_node && result_projection_names.empty() &&
(resolve_identifier_expression_result.isResolvedFromJoinTree() || resolve_identifier_expression_result.isResolvedFromExpressionArguments()))
@ -5479,7 +5472,6 @@ ProjectionNames QueryAnalyzer::resolveExpressionNode(QueryTreeNodePtr & node, Id
}
node = std::move(resolved_identifier_node);
LOG_DEBUG(&Poco::Logger::get("resolveExpressionNode"), "Result node: {}", node ? node->dumpTree() : "Not resolved");
if (node->getNodeType() == QueryTreeNodeType::LIST)
{
@ -6183,7 +6175,6 @@ void QueryAnalyzer::initializeTableExpressionData(const QueryTreeNodePtr & table
table_expression_data.should_qualify_columns = false;
}
LOG_DEBUG(&Poco::Logger::get("Analyzer"), "Table data: {}", table_expression_data.dump());
scope.table_expression_node_to_data.emplace(table_expression_node, std::move(table_expression_data));
}

View File

@ -34,6 +34,7 @@
#include "Analyzer/IQueryTreeNode.h"
#include "Analyzer/Identifier.h"
#include "Analyzer/IdentifierNode.h"
#include "Analyzer/InDepthQueryTreeVisitor.h"
#include "Analyzer/Passes/QueryAnalysisPass.h"
#include "Analyzer/QueryTreeBuilder.h"
#include "Core/NamesAndTypes.h"
@ -564,6 +565,26 @@ void ReadFromMerge::initializePipeline(QueryPipelineBuilder & pipeline, const Bu
pipeline.addResources(std::move(resources));
}
namespace
{
class ApplyAliasColumnExpressionsVisitor : public InDepthQueryTreeVisitor<ApplyAliasColumnExpressionsVisitor>
{
public:
ApplyAliasColumnExpressionsVisitor() = default;
void visitImpl(QueryTreeNodePtr & node)
{
if (auto * column = node->as<ColumnNode>();
column != nullptr && column->hasExpression())
{
node = column->getExpressionOrThrow();
}
}
};
}
SelectQueryInfo ReadFromMerge::getModifiedQueryInfo(const ContextPtr & modified_context,
const StorageWithLockAndName & storage_with_lock_and_name,
const StorageSnapshotPtr & storage_snapshot,
@ -611,23 +632,28 @@ SelectQueryInfo ReadFromMerge::getModifiedQueryInfo(const ContextPtr & modified_
QueryTreeNodePtr column_node;
if (is_alias)
{
// column_node = buildQueryTree(column_default->expression, modified_context);
column_node = std::make_shared<IdentifierNode>(Identifier{column});
QueryTreeNodePtr fake_node = std::make_shared<IdentifierNode>(Identifier{column});
LOG_DEBUG(&Poco::Logger::get("getModifiedQueryInfo"), "QT before: {}\n{}", column_node->dumpTree(), modified_query_info.table_expression->dumpTree());
LOG_DEBUG(&Poco::Logger::get("getModifiedQueryInfo"), "QT before: {}\n{}", fake_node->dumpTree(), modified_query_info.table_expression->dumpTree());
QueryAnalysisPass query_analysis_pass(modified_query_info.table_expression);
query_analysis_pass.run(column_node, modified_context);
query_analysis_pass.run(fake_node, modified_context);
auto * resolved_column = fake_node->as<ColumnNode>();
column_node = fake_node;
ApplyAliasColumnExpressionsVisitor visitor;
visitor.visit(column_node);
LOG_DEBUG(&Poco::Logger::get("getModifiedQueryInfo"), "QT after: {}", column_node->dumpTree());
auto * resolved_column = column_node->as<ColumnNode>();
if (!resolved_column || !resolved_column->getExpression())
throw Exception(ErrorCodes::LOGICAL_ERROR, "Alias column is not resolved");
column_node = resolved_column->getExpression();
column_name_to_node.emplace(column, column_node);
aliases.push_back({ .name = column, .type = resolved_column->getResultType(), .expression = column_node->toAST() });
}
@ -1095,6 +1121,8 @@ void ReadFromMerge::convertingSourceStream(
std::move(convert_actions_dag),
ExpressionActionsSettings::fromContext(local_context, CompileExpressions::yes));
LOG_DEBUG(&Poco::Logger::get("convertingSourceStream"), "The header: {}", builder.getHeader().dumpStructure());
builder.addSimpleTransform([&](const Block & stream_header)
{
return std::make_shared<ExpressionTransform>(stream_header, actions);