mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 08:32:02 +00:00
Added lambda tests
This commit is contained in:
parent
bd11c617b8
commit
9d4c508b39
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
25
tests/queries/0_stateless/02343_analyzer_lambdas.reference
Normal file
25
tests/queries/0_stateless/02343_analyzer_lambdas.reference
Normal 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
|
60
tests/queries/0_stateless/02343_analyzer_lambdas.sql
Normal file
60
tests/queries/0_stateless/02343_analyzer_lambdas.sql
Normal 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;
|
Loading…
Reference in New Issue
Block a user