Fix lambda(tuple(x), x + 1) syntax in analyzer

This commit is contained in:
vdimir 2024-04-03 10:39:43 +00:00
parent f1345723d0
commit 71450c909a
No known key found for this signature in database
GPG Key ID: 6EE4CE2BEDC51862
7 changed files with 54 additions and 7 deletions

View File

@ -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 &>();

View File

@ -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");

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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")

View File

@ -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

View File

@ -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;