Fix OrderByLimitByDuplicateEliminationPass with IGNORE NULLS

This commit is contained in:
vdimir 2024-08-12 15:40:03 +00:00
parent 0aa30b10d5
commit 848285eabc
No known key found for this signature in database
GPG Key ID: 6EE4CE2BEDC51862
4 changed files with 63 additions and 3 deletions

View File

@ -88,6 +88,7 @@ void FunctionNode::resolveAsFunction(FunctionBasePtr function_value)
function_name = function_value->getName(); function_name = function_value->getName();
function = std::move(function_value); function = std::move(function_value);
kind = FunctionKind::ORDINARY; kind = FunctionKind::ORDINARY;
nulls_action = NullsAction::EMPTY;
} }
void FunctionNode::resolveAsAggregateFunction(AggregateFunctionPtr aggregate_function_value) void FunctionNode::resolveAsAggregateFunction(AggregateFunctionPtr aggregate_function_value)
@ -95,6 +96,12 @@ void FunctionNode::resolveAsAggregateFunction(AggregateFunctionPtr aggregate_fun
function_name = aggregate_function_value->getName(); function_name = aggregate_function_value->getName();
function = std::move(aggregate_function_value); function = std::move(aggregate_function_value);
kind = FunctionKind::AGGREGATE; kind = FunctionKind::AGGREGATE;
/** When the function is resolved, we do not need the nulls action anymore.
* The only thing that the nulls action does is map from one function to another.
* Thus, the nulls action is encoded in the function name and does not make sense anymore.
* Keeping the nulls action may lead to incorrect comparison of functions, e.g., count() and count() IGNORE NULLS are the same function.
*/
nulls_action = NullsAction::EMPTY;
} }
void FunctionNode::resolveAsWindowFunction(AggregateFunctionPtr window_function_value) void FunctionNode::resolveAsWindowFunction(AggregateFunctionPtr window_function_value)

View File

@ -81,10 +81,9 @@ QueryTreeNodePtr createResolvedFunction(const ContextPtr & context, const String
} }
FunctionNodePtr createResolvedAggregateFunction( FunctionNodePtr createResolvedAggregateFunction(
const String & name, const QueryTreeNodePtr & argument, const Array & parameters = {}, NullsAction action = NullsAction::EMPTY) const String & name, const QueryTreeNodePtr & argument, const Array & parameters = {})
{ {
auto function_node = std::make_shared<FunctionNode>(name); auto function_node = std::make_shared<FunctionNode>(name);
function_node->setNullsAction(action);
if (!parameters.empty()) if (!parameters.empty())
{ {
@ -96,7 +95,7 @@ FunctionNodePtr createResolvedAggregateFunction(
function_node->getArguments().getNodes() = { argument }; function_node->getArguments().getNodes() = { argument };
AggregateFunctionProperties properties; AggregateFunctionProperties properties;
auto aggregate_function = AggregateFunctionFactory::instance().get(name, action, {argument->getResultType()}, parameters, properties); auto aggregate_function = AggregateFunctionFactory::instance().get(name, NullsAction::EMPTY, {argument->getResultType()}, parameters, properties);
function_node->resolveAsAggregateFunction(std::move(aggregate_function)); function_node->resolveAsAggregateFunction(std::move(aggregate_function));
return function_node; return function_node;

View File

@ -0,0 +1,51 @@
#!/usr/bin/env -S ${HOME}/clickhouse-client --queries-file
DROP TABLE IF EXISTS with_fill_date__fuzz_0;
CREATE TABLE with_fill_date__fuzz_0
(
`d` Date,
`d32` Nullable(Int32),
`d33` Int32
)
ENGINE = Memory;
INSERT INTO with_fill_date__fuzz_0 VALUES (toDate('2020-03-03'), 1, 3), (toDate('2020-03-03'), NULL, 3), (toDate('2020-02-05'), 1, 1);
SELECT count()
FROM with_fill_date__fuzz_0
ORDER BY
count(),
count() IGNORE NULLS,
max(d)
WITH FILL STEP toIntervalDay(10)
;
SELECT count()
FROM with_fill_date__fuzz_0
ORDER BY
any(d32) RESPECT NULLS,
any_respect_nulls(d32),
max(d)
WITH FILL STEP toIntervalDay(10)
;
SELECT count()
FROM with_fill_date__fuzz_0
ORDER BY
any(d32),
any(d32) IGNORE NULLS,
any(d32) RESPECT NULLS,
any_respect_nulls(d32) IGNORE NULLS,
any_respect_nulls(d32),
sum(d33),
sum(d33) IGNORE NULLS,
max(d)
WITH FILL STEP toIntervalDay(10)
;