Analyzer aggregate function lambda crash fix

This commit is contained in:
Maksim Kita 2022-12-09 18:26:12 +01:00
parent 17c557648e
commit 407f8ae224
4 changed files with 34 additions and 10 deletions

View File

@ -7,6 +7,11 @@
namespace DB
{
namespace ErrorCodes
{
extern const int UNSUPPORTED_METHOD;
}
class IFunctionOverloadResolver;
using FunctionOverloadResolverPtr = std::shared_ptr<IFunctionOverloadResolver>;
@ -189,6 +194,11 @@ public:
DataTypePtr getResultType() const override
{
if (!result_type)
throw Exception(ErrorCodes::UNSUPPORTED_METHOD,
"Function node with name '{}' is not resolved",
function_name);
return result_type;
}

View File

@ -3983,7 +3983,7 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi
const auto * constant_node = parameter_node->as<ConstantNode>();
if (!constant_node)
throw Exception(ErrorCodes::BAD_ARGUMENTS,
"Parameter for function {} expected to have constant value. Actual {}. In scope {}",
"Parameter for function '{}' expected to have constant value. Actual {}. In scope {}",
function_name,
parameter_node->formatASTForErrorMessage(),
scope.scope_node->formatASTForErrorMessage());
@ -4079,7 +4079,7 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi
{
auto & function_in_arguments_nodes = function_node.getArguments().getNodes();
if (function_in_arguments_nodes.size() != 2)
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Function {} expects 2 arguments", function_name);
throw Exception(ErrorCodes::BAD_ARGUMENTS, "Function '{}' expects 2 arguments", function_name);
auto & in_second_argument = function_in_arguments_nodes[1];
auto * table_node = in_second_argument->as<TableNode>();
@ -4169,8 +4169,8 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi
if (!argument_column.type)
throw Exception(ErrorCodes::LOGICAL_ERROR,
"Function {} argument is not resolved. In scope {}",
function_node.getFunctionName(),
"Function '{}' argument is not resolved. In scope {}",
function_name,
scope.scope_node->formatASTForErrorMessage());
const auto * constant_node = function_argument->as<ConstantNode>();
@ -4220,7 +4220,7 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi
auto * lambda_expression = lambda_expression_untyped->as<LambdaNode>();
if (!lambda_expression)
throw Exception(ErrorCodes::LOGICAL_ERROR,
"Function identifier {} must be resolved as lambda. Actual {}. In scope {}",
"Function identifier '{}' must be resolved as lambda. Actual {}. In scope {}",
function_node.getFunctionName(),
lambda_expression_untyped->formatASTForErrorMessage(),
scope.scope_node->formatASTForErrorMessage());
@ -4253,7 +4253,7 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi
const auto * tuple_data_type = typeid_cast<const DataTypeTuple *>(result_type.get());
if (!tuple_data_type)
throw Exception(ErrorCodes::UNSUPPORTED_METHOD,
"Function untuple argument must be have compound type. Actual type {}. In scope {}",
"Function 'untuple' argument must have compound type. Actual type {}. In scope {}",
result_type->getName(),
scope.scope_node->formatASTForErrorMessage());
@ -4311,7 +4311,7 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi
{
if (!AggregateFunctionFactory::instance().isAggregateFunctionName(function_name))
{
std::string error_message = fmt::format("Aggregate function with name {} does not exists. In scope {}",
std::string error_message = fmt::format("Aggregate function with name '{}' does not exists. In scope {}",
function_name,
scope.scope_node->formatASTForErrorMessage());
@ -4319,6 +4319,11 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi
throw Exception(ErrorCodes::UNKNOWN_AGGREGATE_FUNCTION, error_message);
}
if (!function_lambda_arguments_indexes.empty())
throw Exception(ErrorCodes::UNSUPPORTED_METHOD,
"Window function '{}' does not support lambda arguments",
function_name);
AggregateFunctionProperties properties;
auto aggregate_function = AggregateFunctionFactory::instance().get(function_name, argument_types, parameters, properties);
@ -4368,12 +4373,17 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi
auto hints = name_prompter.getHints(function_name, possible_function_names);
throw Exception(ErrorCodes::UNKNOWN_FUNCTION,
"Function with name {} does not exists. In scope {}{}",
"Function with name '{}' does not exists. In scope {}{}",
function_name,
scope.scope_node->formatASTForErrorMessage(),
getHintsErrorMessageSuffix(hints));
}
if (!function_lambda_arguments_indexes.empty())
throw Exception(ErrorCodes::UNSUPPORTED_METHOD,
"Aggregate function '{}' does not support lambda arguments",
function_name);
AggregateFunctionProperties properties;
auto aggregate_function = AggregateFunctionFactory::instance().get(function_name, argument_types, parameters, properties);
function_node.resolveAsAggregateFunction(aggregate_function, aggregate_function->getReturnType());
@ -4404,7 +4414,7 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi
const auto * function_data_type = typeid_cast<const DataTypeFunction *>(argument_types[function_lambda_argument_index].get());
if (!function_data_type)
throw Exception(ErrorCodes::LOGICAL_ERROR,
"Function {} expected function data type for lambda argument with index {}. Actual {}. In scope {}",
"Function '{}' expected function data type for lambda argument with index {}. Actual {}. In scope {}",
function_name,
function_lambda_argument_index,
argument_types[function_lambda_argument_index]->getName(),
@ -4414,7 +4424,7 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi
size_t function_data_type_arguments_size = function_data_type_argument_types.size();
if (function_data_type_arguments_size != lambda_arguments_size)
throw Exception(ErrorCodes::LOGICAL_ERROR,
"Function {} function data type for lambda argument with index {} arguments size mismatch. Actual {}. Expected {}. In scope {}",
"Function '{}' function data type for lambda argument with index {} arguments size mismatch. Actual {}. Expected {}. In scope {}",
function_name,
function_data_type_arguments_size,
lambda_arguments_size,

View File

@ -0,0 +1,4 @@
SET allow_experimental_analyzer = 1;
SELECT count((t, x_0, x_1) -> ((key_2, x_0, x_1) IN (NULL, NULL, '0.3'))) FROM numbers(10); -- { serverError 1 }
SELECT count((t, x_0, x_1) -> ((key_2, x_0, x_1) IN (NULL, NULL, '0.3'))) OVER (PARTITION BY id) FROM numbers(10); -- { serverError 1 }