From f209b5c2a9cdb29d646efdb2f8580c750cfb74c1 Mon Sep 17 00:00:00 2001 From: Dmitry Novik Date: Wed, 25 Oct 2023 14:39:50 +0200 Subject: [PATCH] Fix InDepthQueryTreeVisitorWithContext::visitChildren --- src/Analyzer/InDepthQueryTreeVisitor.h | 34 +++++++++++++++++--------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/Analyzer/InDepthQueryTreeVisitor.h b/src/Analyzer/InDepthQueryTreeVisitor.h index 59ee57996c4..b74486b1b04 100644 --- a/src/Analyzer/InDepthQueryTreeVisitor.h +++ b/src/Analyzer/InDepthQueryTreeVisitor.h @@ -99,7 +99,7 @@ using ConstInDepthQueryTreeVisitor = InDepthQueryTreeVisitor +template class InDepthQueryTreeVisitorWithContext { public: @@ -169,31 +169,43 @@ private: return *static_cast(this); } - bool shouldSkipSubtree( + void visitChildIfNeeded( VisitQueryTreeNodeType & parent, - VisitQueryTreeNodeType & child, - size_t subtree_index) + VisitQueryTreeNodeType & child) { bool need_visit_child = getDerived().needChildVisit(parent, child); if (!need_visit_child) - return true; + return; + // We do not visit ListNode with arguments of TableFunctionNode directly, because + // we need to know which arguments are in the unresolved state. + // It must be safe because we do not modify table function arguments list in any visitor. if (auto * table_function_node = parent->as()) { + if (child != table_function_node->getArgumentsNode()) + throw Exception(ErrorCodes::LOGICAL_ERROR, "TableFunctioNode is expected to have only one child node"); + const auto & unresolved_indexes = table_function_node->getUnresolvedArgumentIndexes(); - return std::find(unresolved_indexes.begin(), unresolved_indexes.end(), subtree_index) != unresolved_indexes.end(); + + size_t index = 0; + for (auto & argument : table_function_node->getArguments()) + { + if (std::find(unresolved_indexes.begin(), unresolved_indexes.end(), index) == unresolved_indexes.end()) + visit(argument); + ++index; + } + return; } - return false; + else + visit(child); } void visitChildren(VisitQueryTreeNodeType & expression) { - size_t index = 0; for (auto & child : expression->getChildren()) { - if (child && !shouldSkipSubtree(expression, child, index)) - visit(child); - ++index; + if (child) + visitChildIfNeeded(expression, child); } }