Analyzer fix table functions with invalid arguments analysis

This commit is contained in:
Maksim Kita 2023-02-16 11:31:24 +01:00
parent 57b5d9852f
commit 05baf271f0
6 changed files with 51 additions and 8 deletions

View File

@ -23,6 +23,11 @@ public:
: context(std::move(context_))
{}
static bool needChildVisit(QueryTreeNodePtr &, QueryTreeNodePtr & child)
{
return child->getNodeType() != QueryTreeNodeType::TABLE_FUNCTION;
}
void visitImpl(QueryTreeNodePtr & node) const
{
auto * function_node = node->as<FunctionNode>();

View File

@ -18,8 +18,11 @@ public:
using Base = InDepthQueryTreeVisitorWithContext<OptimizeGroupByFunctionKeysVisitor>;
using Base::Base;
static bool needChildVisit(QueryTreeNodePtr & /*parent*/, QueryTreeNodePtr & child)
static bool needChildVisit(QueryTreeNodePtr & parent, QueryTreeNodePtr & child)
{
if (parent->getNodeType() == QueryTreeNodeType::TABLE_FUNCTION)
return false;
return !child->as<FunctionNode>();
}

View File

@ -1072,6 +1072,12 @@ public:
break;
}
case QueryTreeNodeType::TABLE_FUNCTION:
{
QueryExpressionsAliasVisitor expressions_alias_visitor(scope);
resolveTableFunction(node, scope, expressions_alias_visitor, false /*nested_table_function*/);
break;
}
default:
{
throw Exception(ErrorCodes::BAD_ARGUMENTS,
@ -5902,7 +5908,27 @@ void QueryAnalyzer::resolveTableFunction(QueryTreeNodePtr & table_function_node,
}
}
resolveExpressionNode(table_function_argument, scope, false /*allow_lambda_expression*/, false /*allow_table_expression*/);
/** Table functions arguments can contain expressions with invalid identifiers.
* We cannot skip analysis for such arguments, because some table functions cannot provide
* information if analysis for argument should be skipped until other arguments will be resolved.
*
* Example: SELECT key from remote('127.0.0.{1,2}', view(select number AS key from numbers(2)), key);
* Example: SELECT id from remote('127.0.0.{1,2}', 'default', 'test_table', id);
*/
try
{
resolveExpressionNode(table_function_argument, scope, false /*allow_lambda_expression*/, false /*allow_table_expression*/);
}
catch (const Exception & exception)
{
if (exception.code() == ErrorCodes::UNKNOWN_IDENTIFIER)
{
result_table_function_arguments.push_back(table_function_argument);
continue;
}
throw;
}
if (auto * expression_list = table_function_argument->as<ListNode>())
{

View File

@ -336,6 +336,7 @@ ASTPtr QueryNode::toASTImpl() const
{
auto settings_query = std::make_shared<ASTSetQuery>();
settings_query->changes = settings_changes;
settings_query->is_standalone = false;
select_query->setExpression(ASTSelectQuery::Expression::SETTINGS, std::move(settings_query));
}

View File

@ -13,6 +13,7 @@
#include <Parsers/ASTSelectQuery.h>
#include <Parsers/ASTTablesInSelectQuery.h>
#include <Parsers/ASTIdentifier.h>
#include <Parsers/ASTQueryParameter.h>
#include <Parsers/ASTAsterisk.h>
#include <Parsers/ASTQualifiedAsterisk.h>
#include <Parsers/ASTColumnsMatcher.h>
@ -61,6 +62,7 @@ namespace ErrorCodes
extern const int EXPECTED_ALL_OR_ANY;
extern const int NOT_IMPLEMENTED;
extern const int BAD_ARGUMENTS;
extern const int UNKNOWN_QUERY_PARAMETER;
}
namespace
@ -540,6 +542,11 @@ QueryTreeNodePtr QueryTreeBuilder::buildExpression(const ASTPtr & expression, co
result = std::move(query_node);
}
else if (const auto * select_with_union_query = expression->as<ASTSelectWithUnionQuery>())
{
auto query_node = buildSelectWithUnionExpression(expression, false /*is_subquery*/, {} /*cte_name*/, context);
result = std::move(query_node);
}
else if (const auto * with_element = expression->as<ASTWithElement>())
{
auto with_element_subquery = with_element->subquery->as<ASTSubquery &>().children.at(0);
@ -588,6 +595,12 @@ QueryTreeNodePtr QueryTreeBuilder::buildExpression(const ASTPtr & expression, co
auto column_transformers = buildColumnTransformers(qualified_columns_list_matcher->transformers, context);
result = std::make_shared<MatcherNode>(Identifier(qualified_identifier.name_parts), std::move(column_list_identifiers), std::move(column_transformers));
}
else if (const auto * query_parameter = expression->as<ASTQueryParameter>())
{
throw Exception(ErrorCodes::UNKNOWN_QUERY_PARAMETER,
"Query parameter {} was not set",
backQuote(query_parameter->name));
}
else
{
throw Exception(ErrorCodes::UNSUPPORTED_METHOD,

View File

@ -678,13 +678,8 @@ QueryTreeNodePtr buildQueryTreeDistributedTableReplacedWithLocalTable(const Sele
table_function_node->getArgumentsNode() = remote_table_function_node.getArgumentsNode();
QueryAnalysisPass query_analysis_pass;
query_analysis_pass.run(table_function_node->getArgumentsNode(), query_context);
query_analysis_pass.run(table_function_node, query_context);
auto remote_table_function_to_resolve = table_function_node->toAST();
TableFunctionPtr table_function_ptr = TableFunctionFactory::instance().get(remote_table_function_to_resolve, query_context);
auto table_function_storage = table_function_ptr->execute(remote_table_function_to_resolve, query_context, table_function_ptr->getName());
table_function_node->resolve(std::move(table_function_ptr), std::move(table_function_storage), query_context);
replacement_table_expression = std::move(table_function_node);
}
else