Improve implementation, add tests

This commit is contained in:
Dmitry Novik 2024-06-27 16:52:09 +02:00
parent 5ae3aba4e3
commit fba99d33bb
3 changed files with 123 additions and 5 deletions

View File

@ -2848,6 +2848,7 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi
if (function_in_arguments_nodes.size() != 2)
throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, "Function '{}' expects 2 arguments", function_name);
auto & in_first_argument = function_in_arguments_nodes[0];
auto & in_second_argument = function_in_arguments_nodes[1];
auto * table_node = in_second_argument->as<TableNode>();
auto * table_function_node = in_second_argument->as<TableFunctionNode>();
@ -2911,15 +2912,29 @@ ProjectionNames QueryAnalyzer::resolveFunction(QueryTreeNodePtr & node, Identifi
resolveExpressionNode(in_second_argument, scope, false /*allow_lambda_expression*/, true /*allow_table_expression*/);
/// Rewrite X in EXPR, where EXPR is a non-const expression, to has(EXPR, X).
if (auto * non_const_set_candidate = in_second_argument->as<FunctionNode>())
{
const auto & candidate_name = non_const_set_candidate->getFunctionName();
if (candidate_name == "array")
if (candidate_name == "array" && !isNullableOrLowCardinalityNullable(in_first_argument->getResultType()))
{
function_name = "has";
is_special_function_in = false;
auto & function_arguments = function_node.getArguments().getNodes();
std::swap(function_arguments[0], function_arguments[1]);
bool contains_nullable = false;
for (const auto & array_elem : non_const_set_candidate->getArguments())
{
if (isNullableOrLowCardinalityNullable(array_elem->getResultType()))
{
contains_nullable = true;
break;
}
}
if (!contains_nullable)
{
function_name = "has";
is_special_function_in = false;
auto & function_arguments = function_node.getArguments().getNodes();
std::swap(function_arguments[0], function_arguments[1]);
}
}
}
}

View File

@ -7,3 +7,59 @@
1
6
7
-- MORE CASES --
-- { echoOn }
SELECT null in [number % 3, number % 5] FROM numbers(2); -- { serverError UNSUPPORTED_METHOD }
SELECT null in [number % 3, number % 5, null] FROM numbers(2); -- { serverError UNSUPPORTED_METHOD }
SELECT 5 in [number % 3, number % 5, null] FROM numbers(2); -- { serverError UNSUPPORTED_METHOD }
SELECT (1, 2) in [number % 3, number % 5] FROM numbers(2); -- { serverError NO_COMMON_TYPE }
SELECT (1, 2) in (SELECT [0, 0] UNION ALL SELECT [1, 1]); -- { serverError TYPE_MISMATCH }
SELECT (1, 2) in [(number % 3, number % 5)] FROM numbers(2);
0
0
SELECT (1, 2) in (SELECT (0, 0)), (1, 2) in (SELECT (1, 1));
0 0
SELECT (1, 1) in [(number % 3, number % 5)] FROM numbers(2);
0
1
SELECT (1, 1) in (SELECT (0, 0)), (1, 1) in (SELECT (1, 1));
0 1
SELECT (1, null) in [(number % 3, number % 5)] FROM numbers(2);
0
0
SELECT (1, null) in (SELECT (0, 0::Nullable(Int))), (1, null) in (SELECT (1, 1::Nullable(Int)));
0 0
SELECT (1, null) in [(number % 3, number % 5), (1, null)] FROM numbers(2);
1
1
SELECT (1, null) in (SELECT (0, 0::Nullable(Int)) UNION ALL SELECT (1, null)), (1, null) in (SELECT (1, 1::Nullable(Int)) UNION ALL SELECT (1, null));
1 1
SELECT 'ANOTHER SETTING';
ANOTHER SETTING
set transform_null_in = 1;
SELECT null in [number % 3, number % 5] FROM numbers(2); -- { serverError UNSUPPORTED_METHOD }
SELECT null in [number % 3, number % 5, null] FROM numbers(2); -- { serverError UNSUPPORTED_METHOD }
SELECT 5 in [number % 3, number % 5, null] FROM numbers(2); -- { serverError UNSUPPORTED_METHOD }
SELECT (1, 2) in [number % 3, number % 5] FROM numbers(2); -- { serverError NO_COMMON_TYPE }
SELECT (1, 2) in (SELECT [0, 0] UNION ALL SELECT [1, 1]); -- { serverError TYPE_MISMATCH }
SELECT (1, 2) in [(number % 3, number % 5)] FROM numbers(2);
0
0
SELECT (1, 2) in (SELECT (0, 0)), (1, 2) in (SELECT (1, 1));
0 0
SELECT (1, 1) in [(number % 3, number % 5)] FROM numbers(2);
0
1
SELECT (1, 1) in (SELECT (0, 0)), (1, 1) in (SELECT (1, 1));
0 1
SELECT (1, null) in [(number % 3, number % 5)] FROM numbers(2);
0
0
SELECT (1, null) in (SELECT (0, 0::Nullable(Int))), (1, null) in (SELECT (1, 1::Nullable(Int)));
0 0
SELECT (1, null) in [(number % 3, number % 5), (1, null)] FROM numbers(2);
1
1
SELECT (1, null) in (SELECT (0, 0::Nullable(Int)) UNION ALL SELECT (1, null)), (1, null) in (SELECT (1, 1::Nullable(Int)) UNION ALL SELECT (1, null));
1 1

View File

@ -2,3 +2,50 @@ SELECT number FROM numbers(10) WHERE has([number % 3, number % 5], number % 2) O
SELECT '-- IN --';
SELECT number FROM numbers(10) WHERE number % 2 IN [number % 3, number % 5] ORDER BY number SETTINGS allow_experimental_analyzer = 1;
SELECT number FROM numbers(10) WHERE number % 2 IN [number % 3, number % 5] ORDER BY number SETTINGS allow_experimental_analyzer = 0; -- { serverError UNKNOWN_IDENTIFIER }
SELECT '-- MORE CASES --';
-- { echoOn }
SELECT null in [number % 3, number % 5] FROM numbers(2); -- { serverError UNSUPPORTED_METHOD }
SELECT null in [number % 3, number % 5, null] FROM numbers(2); -- { serverError UNSUPPORTED_METHOD }
SELECT 5 in [number % 3, number % 5, null] FROM numbers(2); -- { serverError UNSUPPORTED_METHOD }
SELECT (1, 2) in [number % 3, number % 5] FROM numbers(2); -- { serverError NO_COMMON_TYPE }
SELECT (1, 2) in (SELECT [0, 0] UNION ALL SELECT [1, 1]); -- { serverError TYPE_MISMATCH }
SELECT (1, 2) in [(number % 3, number % 5)] FROM numbers(2);
SELECT (1, 2) in (SELECT (0, 0)), (1, 2) in (SELECT (1, 1));
SELECT (1, 1) in [(number % 3, number % 5)] FROM numbers(2);
SELECT (1, 1) in (SELECT (0, 0)), (1, 1) in (SELECT (1, 1));
SELECT (1, null) in [(number % 3, number % 5)] FROM numbers(2);
SELECT (1, null) in (SELECT (0, 0::Nullable(Int))), (1, null) in (SELECT (1, 1::Nullable(Int)));
SELECT (1, null) in [(number % 3, number % 5), (1, null)] FROM numbers(2);
SELECT (1, null) in (SELECT (0, 0::Nullable(Int)) UNION ALL SELECT (1, null)), (1, null) in (SELECT (1, 1::Nullable(Int)) UNION ALL SELECT (1, null));
SELECT 'ANOTHER SETTING';
set transform_null_in = 1;
SELECT null in [number % 3, number % 5] FROM numbers(2); -- { serverError UNSUPPORTED_METHOD }
SELECT null in [number % 3, number % 5, null] FROM numbers(2); -- { serverError UNSUPPORTED_METHOD }
SELECT 5 in [number % 3, number % 5, null] FROM numbers(2); -- { serverError UNSUPPORTED_METHOD }
SELECT (1, 2) in [number % 3, number % 5] FROM numbers(2); -- { serverError NO_COMMON_TYPE }
SELECT (1, 2) in (SELECT [0, 0] UNION ALL SELECT [1, 1]); -- { serverError TYPE_MISMATCH }
SELECT (1, 2) in [(number % 3, number % 5)] FROM numbers(2);
SELECT (1, 2) in (SELECT (0, 0)), (1, 2) in (SELECT (1, 1));
SELECT (1, 1) in [(number % 3, number % 5)] FROM numbers(2);
SELECT (1, 1) in (SELECT (0, 0)), (1, 1) in (SELECT (1, 1));
SELECT (1, null) in [(number % 3, number % 5)] FROM numbers(2);
SELECT (1, null) in (SELECT (0, 0::Nullable(Int))), (1, null) in (SELECT (1, 1::Nullable(Int)));
SELECT (1, null) in [(number % 3, number % 5), (1, null)] FROM numbers(2);
SELECT (1, null) in (SELECT (0, 0::Nullable(Int)) UNION ALL SELECT (1, null)), (1, null) in (SELECT (1, 1::Nullable(Int)) UNION ALL SELECT (1, null));