Separate first_value and first_value_respect_nulls states

This commit is contained in:
Raúl Marín 2023-11-22 13:08:45 +01:00
parent b10e46b2bc
commit a3e342a477
6 changed files with 70 additions and 31 deletions

View File

@ -50,22 +50,19 @@ void registerAggregateFunctionsAny(AggregateFunctionFactory & factory)
factory.registerFunction("any", { createAggregateFunctionAny, properties });
factory.registerAlias("any_value", "any", AggregateFunctionFactory::CaseInsensitive);
factory.registerAlias("first_value", "any", AggregateFunctionFactory::CaseInsensitive);
factory.registerFunction("any_respect_nulls", {createAggregateFunctionNullableAny<true>, properties});
factory.registerAlias("any_value_respect_nulls", "any_respect_nulls", AggregateFunctionFactory::CaseInsensitive);
factory.registerAlias("first_value_respect_nulls", "any_respect_nulls", AggregateFunctionFactory::CaseInsensitive);
factory.registerFunction("anyLast", { createAggregateFunctionAnyLast, properties });
factory.registerFunction("anyHeavy", { createAggregateFunctionAnyHeavy, properties });
factory.registerAlias("last_value", "anyLast", AggregateFunctionFactory::CaseInsensitive);
// Synonyms for use as window functions.
factory.registerFunction("first_value",
{ createAggregateFunctionAny, properties },
AggregateFunctionFactory::CaseInsensitive);
factory.registerFunction("first_value_respect_nulls",
{ createAggregateFunctionNullableAny<true>, properties },
AggregateFunctionFactory::CaseInsensitive);
factory.registerFunction("last_value",
{ createAggregateFunctionAnyLast, properties },
AggregateFunctionFactory::CaseInsensitive);
factory.registerFunction("last_value_respect_nulls",
{ createAggregateFunctionNullableAnyLast<true>, properties },
AggregateFunctionFactory::CaseInsensitive);
factory.registerFunction("anyLast_respect_nulls", {createAggregateFunctionNullableAnyLast<true>, properties});
factory.registerAlias("last_value_respect_nulls", "anyLast_respect_nulls", AggregateFunctionFactory::CaseInsensitive);
factory.registerFunction("anyHeavy", {createAggregateFunctionAnyHeavy, properties});
}
}

View File

@ -1084,7 +1084,7 @@ struct AggregateFunctionMaxData : Data
#endif
};
template <typename Data>
template <typename Data, bool RespectNulls = false>
struct AggregateFunctionAnyData : Data
{
using Self = AggregateFunctionAnyData;
@ -1094,7 +1094,13 @@ struct AggregateFunctionAnyData : Data
bool changeIfBetter(const Self & to, Arena * arena) { return this->changeFirstTime(to, arena); }
void addManyDefaults(const IColumn & column, size_t /*length*/, Arena * arena) { this->changeFirstTime(column, 0, arena); }
static const char * name() { return "any"; }
static const char * name()
{
if constexpr (RespectNulls)
return "any_respect_nulls";
else
return "any";
}
#if USE_EMBEDDED_COMPILER
@ -1113,7 +1119,7 @@ struct AggregateFunctionAnyData : Data
#endif
};
template <typename Data>
template <typename Data, bool RespectNulls = false>
struct AggregateFunctionAnyLastData : Data
{
using Self = AggregateFunctionAnyLastData;
@ -1122,7 +1128,13 @@ struct AggregateFunctionAnyLastData : Data
bool changeIfBetter(const Self & to, Arena * arena) { return this->changeEveryTime(to, arena); }
void addManyDefaults(const IColumn & column, size_t /*length*/, Arena * arena) { this->changeEveryTime(column, 0, arena); }
static const char * name() { return "anyLast"; }
static const char * name()
{
if constexpr (RespectNulls)
return "anyLast_respect_nulls";
else
return "anyLast";
}
#if USE_EMBEDDED_COMPILER

View File

@ -14,8 +14,9 @@ namespace DB
struct Settings;
/// min, max, any, anyLast, anyHeavy, etc...
template <template <typename> class AggregateFunctionTemplate, template <typename> class Data>
static IAggregateFunction * createAggregateFunctionSingleValue(const String & name, const DataTypes & argument_types, const Array & parameters, const Settings *)
template <template <typename> class AggregateFunctionTemplate, template <typename, bool...> class Data>
static IAggregateFunction *
createAggregateFunctionSingleValue(const String & name, const DataTypes & argument_types, const Array & parameters, const Settings *)
{
assertNoParameters(name, parameters);
assertUnary(name, argument_types);
@ -47,8 +48,9 @@ static IAggregateFunction * createAggregateFunctionSingleValue(const String & na
return new AggregateFunctionTemplate<Data<SingleValueDataGeneric<>>>(argument_type);
}
template <template <typename> class AggregateFunctionTemplate, template <typename> class Data, bool RespectNulls = false>
static IAggregateFunction * createAggregateFunctionSingleNullableValue(const String & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings)
template <template <typename> class AggregateFunctionTemplate, template <typename, bool> class Data, bool RespectNulls = false>
static IAggregateFunction * createAggregateFunctionSingleNullableValue(
const String & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings)
{
assertNoParameters(name, parameters);
assertUnary(name, argument_types);
@ -63,7 +65,7 @@ static IAggregateFunction * createAggregateFunctionSingleNullableValue(const Str
}
else
{
return new AggregateFunctionTemplate<Data<SingleValueDataGeneric<true>>>(argument_type);
return new AggregateFunctionTemplate<Data<SingleValueDataGeneric<true>, RespectNulls>>(argument_type);
}
UNREACHABLE();
}

View File

@ -1138,7 +1138,8 @@ public:
{
nulls_action = NullsAction::IGNORE_NULLS;
}
function_node->name = transformFunctionNameForRepectNulls(function_node->name, nulls_action);
if (nulls_action == NullsAction::RESPECT_NULLS)
function_node->name = transformFunctionNameForRespectNulls(function_node->name, nulls_action);
if (over.ignore(pos, expected))
{
@ -1179,11 +1180,14 @@ private:
RESPECT_NULLS = 1,
IGNORE_NULLS = 2,
};
static String transformFunctionNameForRepectNulls(const String & original_function_name, NullsAction nulls_action)
static String transformFunctionNameForRespectNulls(const String & original_function_name, NullsAction nulls_action)
{
static std::unordered_map<String, std::vector<String>> renamed_functions_with_nulls = {
{"first_value", {"first_value", "first_value_respect_nulls", "first_value"}},
{"last_value", {"last_value", "last_value_respect_nulls", "last_value"}},
static std::unordered_map<String, String> renamed_functions_with_nulls = {
{"any", "any_respect_nulls"},
{"any_value", "any_respect_nulls"},
{"first_value", "any_respect_nulls"},
{"anyLast", "anyLast_respect_nulls"},
{"last_value", "anyLast_respect_nulls"},
};
auto it = renamed_functions_with_nulls.find(original_function_name);
if (it == renamed_functions_with_nulls.end())
@ -1191,10 +1195,9 @@ private:
if (nulls_action == NullsAction::EMPTY)
return original_function_name;
else
throw Exception(
ErrorCodes::SYNTAX_ERROR, "Function {} does not support RESPECT NULLS or IGNORE NULLS", original_function_name);
throw Exception(ErrorCodes::NOT_IMPLEMENTED, "Function {} does not support RESPECT NULLS", original_function_name);
}
return it->second[nulls_action];
return it->second;
}
};

View File

@ -0,0 +1,10 @@
AggregateFunction(any_respect_nulls, UInt8) AggregateFunction(anyLast_respect_nulls, UInt8)
0
\N
0
\N
0
\N
4
\N
\N

View File

@ -0,0 +1,15 @@
SELECT toTypeName(first_value_respect_nullsState(dummy)), toTypeName(last_value_respect_nullsState(dummy)) from system.one;
SELECT first_value_respect_nullsMerge(t) FROM (Select first_value_respect_nullsState(dummy) as t FROM system.one);
SELECT first_value_respect_nullsMerge(t) FROM (Select first_value_respect_nullsState(NULL::Nullable(UInt8)) as t FROM system.one);
SELECT first_value_respect_nullsMerge(t) FROM (Select first_value_respect_nullsState(number) as t FROM numbers(5));
SELECT first_value_respect_nullsMerge(t) FROM (Select first_value_respect_nullsState(NULL::Nullable(UInt8)) as t FROM numbers(5));
SELECT last_value_respect_nullsMerge(t) FROM (Select last_value_respect_nullsState(dummy) as t FROM system.one);
SELECT last_value_respect_nullsMerge(t) FROM (Select last_value_respect_nullsState(NULL::Nullable(UInt8)) as t FROM system.one);
SELECT last_value_respect_nullsMerge(t) FROM (Select last_value_respect_nullsState(number) as t FROM numbers(5));
SELECT last_value_respect_nullsMerge(t) FROM (Select last_value_respect_nullsState(NULL::Nullable(UInt8)) as t FROM numbers(5));
SELECT first_value_respect_nullsMerge(t) FROM (Select first_valueState(number) as t from numbers(0)); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
SELECT first_value_respect_nullsMerge(CAST(unhex('00'), 'AggregateFunction(any, UInt64)')); -- { serverError ILLEGAL_TYPE_OF_ARGUMENT }
SELECT first_value_respect_nullsMerge(CAST(unhex('00'), 'AggregateFunction(any_respect_nulls, UInt64)'));