mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
Merge pull request #65755 from ClickHouse/backport/24.3/64517
Backport #64517 to 24.3: Fixing aliases for GLOBAL IN
This commit is contained in:
commit
cfa4e62b77
@ -6534,6 +6534,7 @@ ProjectionNames QueryAnalyzer::resolveExpressionNode(QueryTreeNodePtr & node, Id
|
|||||||
scope.scope_node->formatASTForErrorMessage());
|
scope.scope_node->formatASTForErrorMessage());
|
||||||
|
|
||||||
auto & table_node = node->as<TableNode &>();
|
auto & table_node = node->as<TableNode &>();
|
||||||
|
if (result_projection_names.empty())
|
||||||
result_projection_names.push_back(table_node.getStorageID().getFullNameNotQuoted());
|
result_projection_names.push_back(table_node.getStorageID().getFullNameNotQuoted());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -8242,7 +8243,10 @@ void QueryAnalyzer::resolveQuery(const QueryTreeNodePtr & query_node, Identifier
|
|||||||
{
|
{
|
||||||
auto node = node_with_duplicated_alias;
|
auto node = node_with_duplicated_alias;
|
||||||
auto node_alias = node->getAlias();
|
auto node_alias = node->getAlias();
|
||||||
resolveExpressionNode(node, scope, true /*allow_lambda_expression*/, false /*allow_table_expression*/);
|
|
||||||
|
/// Add current alias to non cached set, because in case of cyclic alias identifier should not be substituted from cache.
|
||||||
|
/// See 02896_cyclic_aliases_crash.
|
||||||
|
resolveExpressionNode(node, scope, true /*allow_lambda_expression*/, true /*allow_table_expression*/);
|
||||||
|
|
||||||
bool has_node_in_alias_table = false;
|
bool has_node_in_alias_table = false;
|
||||||
|
|
||||||
@ -8251,7 +8255,16 @@ void QueryAnalyzer::resolveQuery(const QueryTreeNodePtr & query_node, Identifier
|
|||||||
{
|
{
|
||||||
has_node_in_alias_table = true;
|
has_node_in_alias_table = true;
|
||||||
|
|
||||||
if (!it->second->isEqual(*node))
|
bool matched = it->second->isEqual(*node);
|
||||||
|
if (!matched)
|
||||||
|
/// Table expression could be resolved as scalar subquery,
|
||||||
|
/// but for duplicating alias we allow table expression to be returned.
|
||||||
|
/// So, check constant node source expression as well.
|
||||||
|
if (const auto * constant_node = it->second->as<ConstantNode>())
|
||||||
|
if (const auto & source_expression = constant_node->getSourceExpression())
|
||||||
|
matched = source_expression->isEqual(*node);
|
||||||
|
|
||||||
|
if (!matched)
|
||||||
throw Exception(ErrorCodes::MULTIPLE_EXPRESSIONS_FOR_ALIAS,
|
throw Exception(ErrorCodes::MULTIPLE_EXPRESSIONS_FOR_ALIAS,
|
||||||
"Multiple expressions {} and {} for alias {}. In scope {}",
|
"Multiple expressions {} and {} for alias {}. In scope {}",
|
||||||
node->formatASTForErrorMessage(),
|
node->formatASTForErrorMessage(),
|
||||||
|
@ -320,6 +320,8 @@ QueryTreeNodePtr buildQueryTreeForShard(const PlannerContextPtr & planner_contex
|
|||||||
auto replacement_map = visitor.getReplacementMap();
|
auto replacement_map = visitor.getReplacementMap();
|
||||||
const auto & global_in_or_join_nodes = visitor.getGlobalInOrJoinNodes();
|
const auto & global_in_or_join_nodes = visitor.getGlobalInOrJoinNodes();
|
||||||
|
|
||||||
|
QueryTreeNodePtrWithHashMap<TableNodePtr> global_in_temporary_tables;
|
||||||
|
|
||||||
for (const auto & global_in_or_join_node : global_in_or_join_nodes)
|
for (const auto & global_in_or_join_node : global_in_or_join_nodes)
|
||||||
{
|
{
|
||||||
if (auto * join_node = global_in_or_join_node.query_node->as<JoinNode>())
|
if (auto * join_node = global_in_or_join_node.query_node->as<JoinNode>())
|
||||||
@ -364,15 +366,19 @@ QueryTreeNodePtr buildQueryTreeForShard(const PlannerContextPtr & planner_contex
|
|||||||
if (in_function_node_type != QueryTreeNodeType::QUERY && in_function_node_type != QueryTreeNodeType::UNION && in_function_node_type != QueryTreeNodeType::TABLE)
|
if (in_function_node_type != QueryTreeNodeType::QUERY && in_function_node_type != QueryTreeNodeType::UNION && in_function_node_type != QueryTreeNodeType::TABLE)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
auto & temporary_table_expression_node = global_in_temporary_tables[in_function_subquery_node];
|
||||||
|
if (!temporary_table_expression_node)
|
||||||
|
{
|
||||||
auto subquery_to_execute = in_function_subquery_node;
|
auto subquery_to_execute = in_function_subquery_node;
|
||||||
if (subquery_to_execute->as<TableNode>())
|
if (subquery_to_execute->as<TableNode>())
|
||||||
subquery_to_execute = buildSubqueryToReadColumnsFromTableExpression(std::move(subquery_to_execute), planner_context->getQueryContext());
|
subquery_to_execute = buildSubqueryToReadColumnsFromTableExpression(subquery_to_execute, planner_context->getQueryContext());
|
||||||
|
|
||||||
auto temporary_table_expression_node = executeSubqueryNode(subquery_to_execute,
|
temporary_table_expression_node = executeSubqueryNode(subquery_to_execute,
|
||||||
planner_context->getMutableQueryContext(),
|
planner_context->getMutableQueryContext(),
|
||||||
global_in_or_join_node.subquery_depth);
|
global_in_or_join_node.subquery_depth);
|
||||||
|
}
|
||||||
|
|
||||||
in_function_subquery_node = std::move(temporary_table_expression_node);
|
replacement_map.emplace(in_function_subquery_node.get(), temporary_table_expression_node);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,4 @@
|
|||||||
|
1 1
|
||||||
|
1
|
||||||
|
1 1
|
||||||
|
1
|
@ -0,0 +1,6 @@
|
|||||||
|
SET allow_experimental_analyzer=1;
|
||||||
|
SELECT 1 GLOBAL IN (SELECT 1) AS s, s FROM remote('127.0.0.{2,3}', system.one) GROUP BY 1;
|
||||||
|
SELECT 1 GLOBAL IN (SELECT 1) AS s FROM remote('127.0.0.{2,3}', system.one) GROUP BY 1;
|
||||||
|
|
||||||
|
SELECT 1 GLOBAL IN (SELECT 1) AS s, s FROM remote('127.0.0.{1,3}', system.one) GROUP BY 1;
|
||||||
|
SELECT 1 GLOBAL IN (SELECT 1) AS s FROM remote('127.0.0.{1,3}', system.one) GROUP BY 1;
|
Loading…
Reference in New Issue
Block a user