mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 16:42:05 +00:00
Fix lambda(tuple(x), x + 1) syntax in analyzer
This commit is contained in:
parent
f1345723d0
commit
71450c909a
@ -558,7 +558,7 @@ QueryTreeNodePtr QueryTreeBuilder::buildExpression(const ASTPtr & expression, co
|
||||
}
|
||||
else if (const auto * function = expression->as<ASTFunction>())
|
||||
{
|
||||
if (function->is_lambda_function)
|
||||
if (function->is_lambda_function || isASTLambdaFunction(*function))
|
||||
{
|
||||
const auto & lambda_arguments_and_expression = function->arguments->as<ASTExpressionList &>().children;
|
||||
auto & lambda_arguments_tuple = lambda_arguments_and_expression.at(0)->as<ASTFunction &>();
|
||||
|
@ -1130,12 +1130,11 @@ void ActionsMatcher::visit(const ASTFunction & node, const ASTPtr & ast, Data &
|
||||
const auto * query_parameter = child->as<ASTQueryParameter>();
|
||||
if (function && function->name == "lambda")
|
||||
{
|
||||
if (!isASTLambdaFunction(*function))
|
||||
throw Exception(ErrorCodes::SYNTAX_ERROR, "Lambda function definition expects two arguments, first argument must be a tuple of arguments");
|
||||
|
||||
/// If the argument is a lambda expression, just remember its approximate type.
|
||||
if (function->arguments->children.size() != 2)
|
||||
throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, "lambda requires two arguments");
|
||||
|
||||
const auto * lambda_args_tuple = function->arguments->children.at(0)->as<ASTFunction>();
|
||||
|
||||
if (!lambda_args_tuple || lambda_args_tuple->name != "tuple")
|
||||
throw Exception(ErrorCodes::TYPE_MISMATCH, "First argument of lambda must be a tuple");
|
||||
|
||||
|
@ -793,4 +793,15 @@ bool tryGetFunctionNameInto(const IAST * ast, String & name)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isASTLambdaFunction(const ASTFunction & function)
|
||||
{
|
||||
if (function.name == "lambda" && function.arguments && function.arguments->children.size() == 2)
|
||||
{
|
||||
const auto * lambda_args_tuple = function.arguments->children.at(0)->as<ASTFunction>();
|
||||
return lambda_args_tuple && lambda_args_tuple->name == "tuple";
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -111,4 +111,7 @@ inline String getFunctionName(const ASTPtr & ast) { return getFunctionName(ast.g
|
||||
inline std::optional<String> tryGetFunctionName(const ASTPtr & ast) { return tryGetFunctionName(ast.get()); }
|
||||
inline bool tryGetFunctionNameInto(const ASTPtr & ast, String & name) { return tryGetFunctionNameInto(ast.get(), name); }
|
||||
|
||||
/// Checks if function is a lambda function definition `lambda((x, y), x + y)`
|
||||
bool isASTLambdaFunction(const ASTFunction & function);
|
||||
|
||||
}
|
||||
|
@ -1545,8 +1545,8 @@ bool ParserColumnsTransformers::parseImpl(Pos & pos, ASTPtr & node, Expected & e
|
||||
{
|
||||
if (auto * func = lambda->as<ASTFunction>(); func && func->name == "lambda")
|
||||
{
|
||||
if (func->arguments->children.size() != 2)
|
||||
throw Exception(ErrorCodes::SYNTAX_ERROR, "lambda requires two arguments");
|
||||
if (!isASTLambdaFunction(*func))
|
||||
throw Exception(ErrorCodes::SYNTAX_ERROR, "Lambda function definition expects two arguments, first argument must be a tuple of arguments");
|
||||
|
||||
const auto * lambda_args_tuple = func->arguments->children.at(0)->as<ASTFunction>();
|
||||
if (!lambda_args_tuple || lambda_args_tuple->name != "tuple")
|
||||
|
@ -27,3 +27,11 @@ Lambda untuple
|
||||
Lambda carrying
|
||||
2 1
|
||||
1 0
|
||||
Lambda legacy syntax
|
||||
[2,3,4]
|
||||
[2,3,4]
|
||||
[2,3,4]
|
||||
['hello','world']
|
||||
[2,3,4]
|
||||
[2,3,4] 2
|
||||
[2,3,4] 2 1
|
||||
|
@ -65,5 +65,31 @@ SELECT 'Lambda carrying';
|
||||
WITH (functor, x) -> functor(x) AS lambda, x -> x + 1 AS functor_1, x -> toString(x) AS functor_2 SELECT lambda(functor_1, 1), lambda(functor_2, 1);
|
||||
WITH (functor, x) -> functor(x) AS lambda, x -> x + 1 AS functor_1, x -> toString(x) AS functor_2 SELECT lambda(functor_1, id), lambda(functor_2, id) FROM test_table;
|
||||
|
||||
|
||||
SELECT 'Lambda legacy syntax';
|
||||
|
||||
SELECT arrayMap(lambda(tuple(x), x + 1), [1, 2, 3]);
|
||||
|
||||
WITH 222 AS lambda
|
||||
SELECT arrayMap(lambda(tuple(x), x + 1), [1, 2, 3]);
|
||||
|
||||
SELECT arrayMap(lambda((x,), x + 1), [1, 2, 3]);
|
||||
|
||||
SELECT arraySort(lambda((x, y), y), ['world', 'hello'], [2, 1]);
|
||||
|
||||
WITH 222 AS lambda
|
||||
SELECT arrayMap(lambda((x, ), x + 1), [1, 2, 3]);
|
||||
|
||||
WITH x -> x + 1 AS lambda
|
||||
SELECT arrayMap(lambda(tuple(x), x + 1), [1, 2, 3]), lambda(1);
|
||||
|
||||
-- lambda(tuple(x), x + 1) parsed as lambda definion but not as call of lambda defined in WITH
|
||||
WITH (x, y) -> y AS lambda
|
||||
SELECT arrayMap(lambda(tuple(x), x + 1), [1, 2, 3]), lambda(tuple(x), x + 1), 1 AS x; -- { serverError BAD_ARGUMENTS }
|
||||
|
||||
WITH (x, y) -> y AS lambda2
|
||||
SELECT arrayMap(lambda(tuple(x), x + 1), [1, 2, 3]), lambda2(tuple(x), x + 1), 1 AS x;
|
||||
|
||||
|
||||
DROP TABLE test_table_tuple;
|
||||
DROP TABLE test_table;
|
||||
|
Loading…
Reference in New Issue
Block a user