Added lambda tests

This commit is contained in:
Maksim Kita 2022-07-14 14:06:25 +02:00
parent bd11c617b8
commit 9d4c508b39
4 changed files with 114 additions and 14 deletions

View File

@ -42,6 +42,10 @@ void ColumnNode::updateTreeHashImpl(HashState & hash_state) const
hash_state.update(column.name.size());
hash_state.update(column.name);
const auto & column_type_name = column.type->getName();
hash_state.update(column_type_name.size());
hash_state.update(column_type_name);
auto column_source_ptr = column_source.lock();
if (column_source_ptr)
column_source_ptr->updateTreeHashImpl(hash_state);

View File

@ -147,12 +147,16 @@ namespace ErrorCodes
*
* TODO: Add expression name into query tree node. Example: SELECT plus(1, 1). Result: SELECT 2. Expression name of constant node should be 2.
* TODO: Table identifiers with optional UUID.
* TODO: Table ALIAS columns
* TODO: Support STRICT except, replace matchers.
* TODO: Support multiple entities with same alias.
* TODO: Lookup functions arrayReduce(sum, [1, 2, 3]);
* TODO: SELECT (compound_expression).*, (compound_expression).COLUMNS are not supported on parser level.
* TODO: SELECT a.b.c.*, a.b.c.COLUMNS. Qualified matcher where identifier size is greater than 2 are not supported on parser level.
* TODO: CTE, JOIN, ARRAY JOIN, bulding sets, grouping, in.
* TODO: CTE
* TODO: JOIN, ARRAY JOIN
* TODO: bulding sets
* TODO: Special functions grouping, in.
*/
/// Identifier lookup context
@ -1222,6 +1226,9 @@ QueryTreeNodePtr QueryAnalyzer::resolveMatcher(QueryTreeNodePtr & matcher_node,
for (const auto & element_name : element_names)
{
if (!matcher_node_typed.isMatchingColumn(element_name))
continue;
auto tuple_element_function = std::make_shared<FunctionNode>("tupleElement");
tuple_element_function->getArguments().getNodes().push_back(expression_query_tree_node);
tuple_element_function->getArguments().getNodes().push_back(std::make_shared<ConstantNode>(element_name));
@ -1259,10 +1266,14 @@ QueryTreeNodePtr QueryAnalyzer::resolveMatcher(QueryTreeNodePtr & matcher_node,
*/
IQueryTreeNode * scope_node = scope.scope_node.get();
auto * scope_query_node = scope_node->as<QueryNode>();
while (scope.scope_node && !scope_query_node)
while (!scope_query_node)
{
if (scope.parent_scope)
scope_node = scope.parent_scope->scope_node.get();
if (!scope.parent_scope)
break;
scope_node = scope.parent_scope->scope_node.get();
scope_query_node = scope_node->as<QueryNode>();
}
/// If there are no parent scope that has tables or query scope does not have FROM section
@ -1683,11 +1694,11 @@ void QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, IdentifierResolveSc
for (auto & function_lambda_argument_index : function_lambda_arguments_indexes)
{
auto lambda_argument_clone = function_arguments[function_lambda_argument_index]->clone();
auto & lambda_argument_clone_typed = lambda_argument_clone->as<LambdaNode &>();
const auto & lambda_argument_clone_argument_names = lambda_argument_clone_typed.getArgumentNames();
auto lambda_to_resolve = function_arguments[function_lambda_argument_index]->clone();
auto & lambda_to_resolve_typed = lambda_to_resolve->as<LambdaNode &>();
size_t lambda_arguments_size = lambda_argument_clone_typed.getArguments().getNodes().size();
const auto & lambda_argument_names = lambda_to_resolve_typed.getArgumentNames();
size_t lambda_arguments_size = lambda_to_resolve_typed.getArguments().getNodes().size();
const auto * function_data_type = typeid_cast<const DataTypeFunction *>(argument_types[function_lambda_argument_index].get());
if (!function_data_type)
@ -1715,16 +1726,16 @@ void QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, IdentifierResolveSc
for (size_t i = 0; i < lambda_arguments_size; ++i)
{
const auto & argument_type = function_data_type_argument_types[i];
auto column_name_and_type = NameAndTypePair{lambda_argument_clone_argument_names[i], argument_type};
lambda_arguments.push_back(std::make_shared<ColumnNode>(std::move(column_name_and_type), lambda_argument_clone));
auto column_name_and_type = NameAndTypePair{lambda_argument_names[i], argument_type};
lambda_arguments.push_back(std::make_shared<ColumnNode>(std::move(column_name_and_type), lambda_to_resolve));
}
IdentifierResolveScope lambda_scope(lambda_argument_clone, &scope /*parent_scope*/);
resolveLambda(lambda_argument_clone, lambda_arguments, lambda_scope);
IdentifierResolveScope lambda_scope(lambda_to_resolve, &scope /*parent_scope*/);
resolveLambda(lambda_to_resolve, lambda_arguments, lambda_scope);
argument_types[function_lambda_argument_index] = std::make_shared<DataTypeFunction>(function_data_type_argument_types, lambda_argument_clone->getResultType());
argument_types[function_lambda_argument_index] = std::make_shared<DataTypeFunction>(function_data_type_argument_types, lambda_to_resolve->getResultType());
argument_columns[function_lambda_argument_index].type = argument_types[function_lambda_argument_index];
function_arguments[function_lambda_argument_index] = std::move(lambda_argument_clone);
function_arguments[function_lambda_argument_index] = std::move(lambda_to_resolve);
}
}

View File

@ -0,0 +1,25 @@
Standalone lambdas
2
1 \N [1,2,3]
1 \N [1,2,3]
1
0 Value
Lambda as function parameter
[2,3,4]
[2,3,4]
['1','2','3'] ['1','2','3']
['1','2','3'] ['1','2','3']
[0,0,0]
[1,2,3]
['1_0','2_0','3_0']
Lambda compound argument
(1,'Value') 1_Value
value_0_level_0_value_1_level_0
Lambda matcher
0
0 Value
Lambda untuple
(1,'Value') 1 Value
Lambda carrying
2 1
1 0

View File

@ -0,0 +1,60 @@
SET use_analyzer = 1;
DROP TABLE IF EXISTS test_table;
CREATE TABLE test_table
(
id UInt64,
value String
) ENGINE=TinyLog;
INSERT INTO test_table VALUES (0, 'Value');
SELECT 'Standalone lambdas';
WITH x -> x + 1 AS lambda SELECT lambda(1);
WITH x -> toString(x) AS lambda SELECT lambda(1), lambda(NULL), lambda([1,2,3]);
WITH x -> toString(x) AS lambda_1, lambda_1 AS lambda_2, lambda_2 AS lambda_3 SELECT lambda_1(1), lambda_2(NULL), lambda_3([1,2,3]);
WITH x -> x + 1 AS lambda SELECT lambda(id) FROM test_table;
WITH x -> toString(x) AS lambda SELECT lambda(id), lambda(value) FROM test_table;
SELECT 'Lambda as function parameter';
SELECT arrayMap(x -> x + 1, [1,2,3]);
WITH x -> x + 1 AS lambda SELECT arrayMap(lambda, [1,2,3]);
SELECT arrayMap((x -> toString(x)) as lambda, [1,2,3]), arrayMap(lambda, ['1','2','3']);
WITH x -> toString(x) AS lambda_1 SELECT arrayMap(lambda_1 AS lambda_2, [1,2,3]), arrayMap(lambda_2, ['1', '2', '3']);
SELECT arrayMap(x -> id, [1,2,3]) FROM test_table;
SELECT arrayMap(x -> x + id, [1,2,3]) FROM test_table;
SELECT arrayMap((x -> concat(concat(toString(x), '_'), toString(id))) as lambda, [1,2,3]) FROM test_table;
SELECT 'Lambda compound argument';
DROP TABLE IF EXISTS test_table_tuple;
CREATE TABLE test_table_tuple
(
id UInt64,
value Tuple(value_0_level_0 String, value_1_level_0 String)
) ENGINE=TinyLog;
INSERT INTO test_table_tuple VALUES (0, ('value_0_level_0', 'value_1_level_0'));
WITH x -> concat(concat(toString(x.id), '_'), x.value) AS lambda SELECT cast((1, 'Value'), 'Tuple (id UInt64, value String)') AS value, lambda(value);
WITH x -> concat(concat(x.value_0_level_0, '_'), x.value_1_level_0) AS lambda SELECT lambda(value) FROM test_table_tuple;
SELECT 'Lambda matcher';
WITH x -> * AS lambda SELECT lambda(1);
WITH x -> * AS lambda SELECT lambda(1) FROM test_table;
SELECT 'Lambda untuple';
WITH x -> untuple(x) AS lambda SELECT cast((1, 'Value'), 'Tuple (id UInt64, value String)') AS value, lambda(value);
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;
DROP TABLE test_table;