Handle CTEs more careafully

This commit is contained in:
Dmitry Novik 2024-01-26 14:23:19 +00:00
parent e38face46b
commit a9d2e13697

View File

@ -5730,6 +5730,8 @@ ProjectionNames QueryAnalyzer::resolveExpressionNode(QueryTreeNodePtr & node, Id
subquery_node = resolved_identifier_node->as<QueryNode>();
union_node = resolved_identifier_node->as<UnionNode>();
std::string_view cte_name = subquery_node ? subquery_node->getCTEName() : union_node->getCTEName();
if (subquery_node)
subquery_node->setIsCTE(false);
else
@ -5738,10 +5740,21 @@ ProjectionNames QueryAnalyzer::resolveExpressionNode(QueryTreeNodePtr & node, Id
IdentifierResolveScope subquery_scope(resolved_identifier_node, &scope /*parent_scope*/);
subquery_scope.subquery_depth = scope.subquery_depth + 1;
/// CTE is being resolved, it's required to forbid to resolve to it again
/// because recursive CTEs are not supported, e.g.:
///
/// WITH test1 AS (SELECT i + 1, j + 1 FROM test1) SELECT toInt64(4) i, toInt64(5) j FROM numbers(3) WHERE (i, j) IN test1;
///
/// In this example argument of function `in` is being resolve here. If CTE `test1` is not forbidden,
/// `test1` is resolved to CTE (not to the table) in `initializeQueryJoinTreeNode` function.
cte_in_resolve_process.insert(cte_name);
if (subquery_node)
resolveQuery(resolved_identifier_node, subquery_scope);
else
resolveUnion(resolved_identifier_node, subquery_scope);
cte_in_resolve_process.erase(cte_name);
}
}
}