mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-30 11:32:03 +00:00
Analyzer fix table functions with invalid arguments analysis
This commit is contained in:
parent
57b5d9852f
commit
05baf271f0
@ -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>();
|
||||
|
@ -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>();
|
||||
}
|
||||
|
||||
|
@ -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>())
|
||||
{
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user