From 1950bc4cd4a88b1feb29e965e516797c37fffd37 Mon Sep 17 00:00:00 2001 From: Marina Fathouat Date: Fri, 17 Nov 2023 17:32:33 +0100 Subject: [PATCH 001/223] Hello from Marina --- src/Interpreters/loadMetadata.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Interpreters/loadMetadata.cpp b/src/Interpreters/loadMetadata.cpp index 3612dbfdc4e..dfa0a129773 100644 --- a/src/Interpreters/loadMetadata.cpp +++ b/src/Interpreters/loadMetadata.cpp @@ -221,13 +221,23 @@ void loadMetadata(ContextMutablePtr context, const String & default_database_nam databases.emplace(default_database_name, std::filesystem::path(path) / escapeForFileName(default_database_name)); } + bool has_ordinary_databases=false; TablesLoader::Databases loaded_databases; for (const auto & [name, db_path] : databases) { loadDatabase(context, name, db_path, has_force_restore_data_flag); loaded_databases.insert({name, DatabaseCatalog::instance().getDatabase(name)}); - } + }autodatabase=DatabaseCatalog::instance().getDatabase(name); + if (database->getEngineName()=="Ordinary") + + has_ordinary_databases = true; + loaded_databases.insert({name,database}) + + +if( has_ordinary_databases) + context->addWarningMessage("Server Has Databases with Ordinary Engine which is not optimal. \n " + "To convert this database to a new Atomic engine, please create a flag named `convert_ordinary_to_atomic` in flags directory"); auto mode = getLoadingStrictnessLevel(/* attach */ true, /* force_attach */ true, has_force_restore_data_flag); TablesLoader loader{context, std::move(loaded_databases), mode}; loader.loadTables(); From 31526d73235ae9a66845f337df77bc317d5eb564 Mon Sep 17 00:00:00 2001 From: shabroo <114589608+shabroo@users.noreply.github.com> Date: Fri, 17 Nov 2023 17:54:56 +0100 Subject: [PATCH 002/223] Me again! My first attempt at a contribution --- src/Interpreters/loadMetadata.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/Interpreters/loadMetadata.cpp b/src/Interpreters/loadMetadata.cpp index dfa0a129773..5b0666abfb4 100644 --- a/src/Interpreters/loadMetadata.cpp +++ b/src/Interpreters/loadMetadata.cpp @@ -221,23 +221,24 @@ void loadMetadata(ContextMutablePtr context, const String & default_database_nam databases.emplace(default_database_name, std::filesystem::path(path) / escapeForFileName(default_database_name)); } - bool has_ordinary_databases=false; + bool has_ordinary_databases = false; TablesLoader::Databases loaded_databases; for (const auto & [name, db_path] : databases) { loadDatabase(context, name, db_path, has_force_restore_data_flag); loaded_databases.insert({name, DatabaseCatalog::instance().getDatabase(name)}); - }autodatabase=DatabaseCatalog::instance().getDatabase(name); + auto database = DatabaseCatalog::instance().getDatabase(name); - if (database->getEngineName()=="Ordinary") + if (database->getEngineName() == "Ordinary") + has_ordinary_databases = true; + + loaded_databases.insert({name,database}); + } - has_ordinary_databases = true; - loaded_databases.insert({name,database}) - - -if( has_ordinary_databases) - context->addWarningMessage("Server Has Databases with Ordinary Engine which is not optimal. \n " - "To convert this database to a new Atomic engine, please create a flag named `convert_ordinary_to_atomic` in flags directory"); + if (has_ordinary_databases) + context->addWarningMessage("Server Has Databases with Ordinary Engine which is not optimal. \n " + "To convert this database to a new Atomic engine, please create a flag named `convert_ordinary_to_atomic` in flags directory"); + auto mode = getLoadingStrictnessLevel(/* attach */ true, /* force_attach */ true, has_force_restore_data_flag); TablesLoader loader{context, std::move(loaded_databases), mode}; loader.loadTables(); From 36709f2c024b8826bbcfd117543f3ef9b0a6e1d3 Mon Sep 17 00:00:00 2001 From: Nikita Mikhaylov Date: Fri, 17 Nov 2023 20:21:20 +0100 Subject: [PATCH 003/223] Update src/Interpreters/loadMetadata.cpp Co-authored-by: Nikolay Degterinsky <43110995+evillique@users.noreply.github.com> --- src/Interpreters/loadMetadata.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Interpreters/loadMetadata.cpp b/src/Interpreters/loadMetadata.cpp index 5b0666abfb4..76b2377be19 100644 --- a/src/Interpreters/loadMetadata.cpp +++ b/src/Interpreters/loadMetadata.cpp @@ -226,8 +226,10 @@ void loadMetadata(ContextMutablePtr context, const String & default_database_nam for (const auto & [name, db_path] : databases) { loadDatabase(context, name, db_path, has_force_restore_data_flag); - loaded_databases.insert({name, DatabaseCatalog::instance().getDatabase(name)}); + auto database = DatabaseCatalog::instance().getDatabase(name); + loaded_databases.insert({name, database}); + if (database->getEngineName() == "Ordinary") has_ordinary_databases = true; From aba54eeebcceee4b56ebe9ef5b68b2f1188ee62f Mon Sep 17 00:00:00 2001 From: shabroo <114589608+shabroo@users.noreply.github.com> Date: Mon, 20 Nov 2023 21:30:34 +0100 Subject: [PATCH 004/223] Update loadMetadata.cpp Fixing use of capitals in user message "Server has databases with Ordinary engine, which is not optimal." --- src/Interpreters/loadMetadata.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Interpreters/loadMetadata.cpp b/src/Interpreters/loadMetadata.cpp index 76b2377be19..48c4f13c026 100644 --- a/src/Interpreters/loadMetadata.cpp +++ b/src/Interpreters/loadMetadata.cpp @@ -238,7 +238,7 @@ void loadMetadata(ContextMutablePtr context, const String & default_database_nam } if (has_ordinary_databases) - context->addWarningMessage("Server Has Databases with Ordinary Engine which is not optimal. \n " + context->addWarningMessage("Server has databases with Ordinary engine, which is not optimal. \n " "To convert this database to a new Atomic engine, please create a flag named `convert_ordinary_to_atomic` in flags directory"); auto mode = getLoadingStrictnessLevel(/* attach */ true, /* force_attach */ true, has_force_restore_data_flag); From 600d293b6c49628a3c24a9afdccf09545491c158 Mon Sep 17 00:00:00 2001 From: shabroo <114589608+shabroo@users.noreply.github.com> Date: Wed, 22 Nov 2023 21:31:02 +0100 Subject: [PATCH 005/223] Update loadMetadata.cpp removed space at the beginning of the line --- src/Interpreters/loadMetadata.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Interpreters/loadMetadata.cpp b/src/Interpreters/loadMetadata.cpp index 48c4f13c026..16cf84da672 100644 --- a/src/Interpreters/loadMetadata.cpp +++ b/src/Interpreters/loadMetadata.cpp @@ -239,7 +239,7 @@ void loadMetadata(ContextMutablePtr context, const String & default_database_nam if (has_ordinary_databases) context->addWarningMessage("Server has databases with Ordinary engine, which is not optimal. \n " - "To convert this database to a new Atomic engine, please create a flag named `convert_ordinary_to_atomic` in flags directory"); + "To convert this database to a new Atomic engine, please create a flag named `convert_ordinary_to_atomic` in flags directory"); auto mode = getLoadingStrictnessLevel(/* attach */ true, /* force_attach */ true, has_force_restore_data_flag); TablesLoader loader{context, std::move(loaded_databases), mode}; From b3cd4069b701bee4c3107de09edf54561f6284e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Mar=C3=ADn?= Date: Mon, 8 Jan 2024 22:20:36 +0100 Subject: [PATCH 006/223] Reimplement AggregateFunctionMin --- .../AggregateFunctionAny.cpp | 486 +++--- .../AggregateFunctionMax.cpp | 448 ++--- .../AggregateFunctionMin.cpp | 420 +++-- .../AggregateFunctionMinMaxAny.h | 1449 ----------------- .../AggregateFunctionSingleValueOrNull.cpp | 24 +- .../AggregateFunctionArgMinMax.cpp | 150 +- src/AggregateFunctions/HelpersMinMaxAny.h | 160 +- src/AggregateFunctions/SingleValueData.cpp | 476 ++++++ src/AggregateFunctions/SingleValueData.h | 723 ++++++++ src/Common/findExtreme.cpp | 119 +- src/Common/findExtreme.h | 14 +- 11 files changed, 2137 insertions(+), 2332 deletions(-) delete mode 100644 src/AggregateFunctions/AggregateFunctionMinMaxAny.h create mode 100644 src/AggregateFunctions/SingleValueData.cpp create mode 100644 src/AggregateFunctions/SingleValueData.h diff --git a/src/AggregateFunctions/AggregateFunctionAny.cpp b/src/AggregateFunctions/AggregateFunctionAny.cpp index a6010ff07c3..7a81cf53bfc 100644 --- a/src/AggregateFunctions/AggregateFunctionAny.cpp +++ b/src/AggregateFunctions/AggregateFunctionAny.cpp @@ -8,250 +8,250 @@ namespace DB { struct Settings; - -namespace ErrorCodes +// +//namespace ErrorCodes +//{ +// extern const int INCORRECT_DATA; +// extern const int LOGICAL_ERROR; +//} +// +//namespace +//{ +//struct AggregateFunctionAnyRespectNullsData +//{ +// enum Status : UInt8 +// { +// NotSet = 1, +// SetNull = 2, +// SetOther = 3 +// }; +// +// Status status = Status::NotSet; +// Field value; +// +// bool isSet() const { return status != Status::NotSet; } +// void setNull() { status = Status::SetNull; } +// void setOther() { status = Status::SetOther; } +//}; +// +//template +//class AggregateFunctionAnyRespectNulls final +// : public IAggregateFunctionDataHelper> +//{ +//public: +// using Data = AggregateFunctionAnyRespectNullsData; +// +// SerializationPtr serialization; +// const bool returns_nullable_type = false; +// +// explicit AggregateFunctionAnyRespectNulls(const DataTypePtr & type) +// : IAggregateFunctionDataHelper>({type}, {}, type) +// , serialization(type->getDefaultSerialization()) +// , returns_nullable_type(type->isNullable()) +// { +// } +// +// String getName() const override +// { +// if constexpr (First) +// return "any_respect_nulls"; +// else +// return "anyLast_respect_nulls"; +// } +// +// bool allocatesMemoryInArena() const override { return false; } +// +// void addNull(AggregateDataPtr __restrict place) const +// { +// chassert(returns_nullable_type); +// auto & d = this->data(place); +// if (First && d.isSet()) +// return; +// d.setNull(); +// } +// +// void add(AggregateDataPtr __restrict place, const IColumn ** columns, size_t row_num, Arena *) const override +// { +// if (columns[0]->isNullable()) +// { +// if (columns[0]->isNullAt(row_num)) +// return addNull(place); +// } +// auto & d = this->data(place); +// if (First && d.isSet()) +// return; +// d.setOther(); +// columns[0]->get(row_num, d.value); +// } +// +// void addManyDefaults(AggregateDataPtr __restrict place, const IColumn ** columns, size_t, Arena * arena) const override +// { +// if (columns[0]->isNullable()) +// addNull(place); +// else +// add(place, columns, 0, arena); +// } +// +// void addBatchSinglePlace( +// size_t row_begin, size_t row_end, AggregateDataPtr place, const IColumn ** columns, Arena * arena, ssize_t if_argument_pos) +// const override +// { +// if (if_argument_pos >= 0) +// { +// const auto & flags = assert_cast(*columns[if_argument_pos]).getData(); +// size_t size = row_end - row_begin; +// for (size_t i = 0; i < size; ++i) +// { +// size_t pos = First ? row_begin + i : row_end - 1 - i; +// if (flags[pos]) +// { +// add(place, columns, pos, arena); +// break; +// } +// } +// } +// else if (row_begin < row_end) +// { +// size_t pos = First ? row_begin : row_end - 1; +// add(place, columns, pos, arena); +// } +// } +// +// void addBatchSinglePlaceNotNull( +// size_t, size_t, AggregateDataPtr __restrict, const IColumn **, const UInt8 *, Arena *, ssize_t) const override +// { +// /// This should not happen since it means somebody else has preprocessed the data (NULLs or IFs) and might +// /// have discarded values that we need (NULLs) +// throw DB::Exception(ErrorCodes::LOGICAL_ERROR, "AggregateFunctionAnyRespectNulls::addBatchSinglePlaceNotNull called"); +// } +// +// void merge(AggregateDataPtr __restrict place, ConstAggregateDataPtr rhs, Arena *) const override +// { +// auto & d = this->data(place); +// if (First && d.isSet()) +// return; +// +// auto & other = this->data(rhs); +// if (other.isSet()) +// { +// d.status = other.status; +// d.value = other.value; +// } +// } +// +// void serialize(ConstAggregateDataPtr __restrict place, WriteBuffer & buf, std::optional /* version */) const override +// { +// auto & d = this->data(place); +// UInt8 k = d.status; +// +// writeBinaryLittleEndian(k, buf); +// if (k == Data::Status::SetOther) +// serialization->serializeBinary(d.value, buf, {}); +// } +// +// void deserialize(AggregateDataPtr place, ReadBuffer & buf, std::optional /* version */, Arena *) const override +// { +// auto & d = this->data(place); +// UInt8 k = Data::Status::NotSet; +// readBinaryLittleEndian(k, buf); +// d.status = static_cast(k); +// if (d.status == Data::Status::NotSet) +// return; +// else if (d.status == Data::Status::SetNull) +// { +// if (!returns_nullable_type) +// throw Exception(ErrorCodes::INCORRECT_DATA, "Incorrect type (NULL) in non-nullable {}State", getName()); +// return; +// } +// else if (d.status == Data::Status::SetOther) +// serialization->deserializeBinary(d.value, buf, {}); +// else +// throw Exception(ErrorCodes::INCORRECT_DATA, "Incorrect type ({}) in {}State", static_cast(k), getName()); +// } +// +// void insertResultInto(AggregateDataPtr __restrict place, IColumn & to, Arena *) const override +// { +// auto & d = this->data(place); +// if (d.status == Data::Status::SetOther) +// to.insert(d.value); +// else +// to.insertDefault(); +// } +// +// AggregateFunctionPtr getOwnNullAdapter( +// const AggregateFunctionPtr & original_function, +// const DataTypes & /*arguments*/, +// const Array & /*params*/, +// const AggregateFunctionProperties & /*properties*/) const override +// { +// return original_function; +// } +//}; +// +// +//template +//IAggregateFunction * createAggregateFunctionSingleValueRespectNulls( +// const String & name, const DataTypes & argument_types, const Array & parameters, const Settings *) +//{ +// assertNoParameters(name, parameters); +// assertUnary(name, argument_types); +// +// return new AggregateFunctionAnyRespectNulls(argument_types[0]); +//} +// +//AggregateFunctionPtr createAggregateFunctionAny(const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) +//{ +// return AggregateFunctionPtr(createAggregateFunctionSingleValue(name, argument_types, parameters, settings)); +//} +// +//AggregateFunctionPtr createAggregateFunctionAnyRespectNulls( +// const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) +//{ +// return AggregateFunctionPtr(createAggregateFunctionSingleValueRespectNulls(name, argument_types, parameters, settings)); +//} +// +//AggregateFunctionPtr createAggregateFunctionAnyLast(const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) +//{ +// return AggregateFunctionPtr(createAggregateFunctionSingleValue(name, argument_types, parameters, settings)); +//} +// +//AggregateFunctionPtr createAggregateFunctionAnyLastRespectNulls( +// const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) +//{ +// return AggregateFunctionPtr(createAggregateFunctionSingleValueRespectNulls(name, argument_types, parameters, settings)); +//} +// +//AggregateFunctionPtr createAggregateFunctionAnyHeavy(const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) +//{ +// return AggregateFunctionPtr(createAggregateFunctionSingleValue(name, argument_types, parameters, settings)); +//} +// +//} +// +void registerAggregateFunctionsAny(AggregateFunctionFactory &) { - extern const int INCORRECT_DATA; - extern const int LOGICAL_ERROR; -} - -namespace -{ -struct AggregateFunctionAnyRespectNullsData -{ - enum Status : UInt8 - { - NotSet = 1, - SetNull = 2, - SetOther = 3 - }; - - Status status = Status::NotSet; - Field value; - - bool isSet() const { return status != Status::NotSet; } - void setNull() { status = Status::SetNull; } - void setOther() { status = Status::SetOther; } -}; - -template -class AggregateFunctionAnyRespectNulls final - : public IAggregateFunctionDataHelper> -{ -public: - using Data = AggregateFunctionAnyRespectNullsData; - - SerializationPtr serialization; - const bool returns_nullable_type = false; - - explicit AggregateFunctionAnyRespectNulls(const DataTypePtr & type) - : IAggregateFunctionDataHelper>({type}, {}, type) - , serialization(type->getDefaultSerialization()) - , returns_nullable_type(type->isNullable()) - { - } - - String getName() const override - { - if constexpr (First) - return "any_respect_nulls"; - else - return "anyLast_respect_nulls"; - } - - bool allocatesMemoryInArena() const override { return false; } - - void addNull(AggregateDataPtr __restrict place) const - { - chassert(returns_nullable_type); - auto & d = this->data(place); - if (First && d.isSet()) - return; - d.setNull(); - } - - void add(AggregateDataPtr __restrict place, const IColumn ** columns, size_t row_num, Arena *) const override - { - if (columns[0]->isNullable()) - { - if (columns[0]->isNullAt(row_num)) - return addNull(place); - } - auto & d = this->data(place); - if (First && d.isSet()) - return; - d.setOther(); - columns[0]->get(row_num, d.value); - } - - void addManyDefaults(AggregateDataPtr __restrict place, const IColumn ** columns, size_t, Arena * arena) const override - { - if (columns[0]->isNullable()) - addNull(place); - else - add(place, columns, 0, arena); - } - - void addBatchSinglePlace( - size_t row_begin, size_t row_end, AggregateDataPtr place, const IColumn ** columns, Arena * arena, ssize_t if_argument_pos) - const override - { - if (if_argument_pos >= 0) - { - const auto & flags = assert_cast(*columns[if_argument_pos]).getData(); - size_t size = row_end - row_begin; - for (size_t i = 0; i < size; ++i) - { - size_t pos = First ? row_begin + i : row_end - 1 - i; - if (flags[pos]) - { - add(place, columns, pos, arena); - break; - } - } - } - else if (row_begin < row_end) - { - size_t pos = First ? row_begin : row_end - 1; - add(place, columns, pos, arena); - } - } - - void addBatchSinglePlaceNotNull( - size_t, size_t, AggregateDataPtr __restrict, const IColumn **, const UInt8 *, Arena *, ssize_t) const override - { - /// This should not happen since it means somebody else has preprocessed the data (NULLs or IFs) and might - /// have discarded values that we need (NULLs) - throw DB::Exception(ErrorCodes::LOGICAL_ERROR, "AggregateFunctionAnyRespectNulls::addBatchSinglePlaceNotNull called"); - } - - void merge(AggregateDataPtr __restrict place, ConstAggregateDataPtr rhs, Arena *) const override - { - auto & d = this->data(place); - if (First && d.isSet()) - return; - - auto & other = this->data(rhs); - if (other.isSet()) - { - d.status = other.status; - d.value = other.value; - } - } - - void serialize(ConstAggregateDataPtr __restrict place, WriteBuffer & buf, std::optional /* version */) const override - { - auto & d = this->data(place); - UInt8 k = d.status; - - writeBinaryLittleEndian(k, buf); - if (k == Data::Status::SetOther) - serialization->serializeBinary(d.value, buf, {}); - } - - void deserialize(AggregateDataPtr place, ReadBuffer & buf, std::optional /* version */, Arena *) const override - { - auto & d = this->data(place); - UInt8 k = Data::Status::NotSet; - readBinaryLittleEndian(k, buf); - d.status = static_cast(k); - if (d.status == Data::Status::NotSet) - return; - else if (d.status == Data::Status::SetNull) - { - if (!returns_nullable_type) - throw Exception(ErrorCodes::INCORRECT_DATA, "Incorrect type (NULL) in non-nullable {}State", getName()); - return; - } - else if (d.status == Data::Status::SetOther) - serialization->deserializeBinary(d.value, buf, {}); - else - throw Exception(ErrorCodes::INCORRECT_DATA, "Incorrect type ({}) in {}State", static_cast(k), getName()); - } - - void insertResultInto(AggregateDataPtr __restrict place, IColumn & to, Arena *) const override - { - auto & d = this->data(place); - if (d.status == Data::Status::SetOther) - to.insert(d.value); - else - to.insertDefault(); - } - - AggregateFunctionPtr getOwnNullAdapter( - const AggregateFunctionPtr & original_function, - const DataTypes & /*arguments*/, - const Array & /*params*/, - const AggregateFunctionProperties & /*properties*/) const override - { - return original_function; - } -}; - - -template -IAggregateFunction * createAggregateFunctionSingleValueRespectNulls( - const String & name, const DataTypes & argument_types, const Array & parameters, const Settings *) -{ - assertNoParameters(name, parameters); - assertUnary(name, argument_types); - - return new AggregateFunctionAnyRespectNulls(argument_types[0]); -} - -AggregateFunctionPtr createAggregateFunctionAny(const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) -{ - return AggregateFunctionPtr(createAggregateFunctionSingleValue(name, argument_types, parameters, settings)); -} - -AggregateFunctionPtr createAggregateFunctionAnyRespectNulls( - const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) -{ - return AggregateFunctionPtr(createAggregateFunctionSingleValueRespectNulls(name, argument_types, parameters, settings)); -} - -AggregateFunctionPtr createAggregateFunctionAnyLast(const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) -{ - return AggregateFunctionPtr(createAggregateFunctionSingleValue(name, argument_types, parameters, settings)); -} - -AggregateFunctionPtr createAggregateFunctionAnyLastRespectNulls( - const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) -{ - return AggregateFunctionPtr(createAggregateFunctionSingleValueRespectNulls(name, argument_types, parameters, settings)); -} - -AggregateFunctionPtr createAggregateFunctionAnyHeavy(const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) -{ - return AggregateFunctionPtr(createAggregateFunctionSingleValue(name, argument_types, parameters, settings)); -} - -} - -void registerAggregateFunctionsAny(AggregateFunctionFactory & factory) -{ - AggregateFunctionProperties default_properties = {.returns_default_when_only_null = false, .is_order_dependent = true}; - AggregateFunctionProperties default_properties_for_respect_nulls - = {.returns_default_when_only_null = false, .is_order_dependent = true, .is_window_function = true}; - - factory.registerFunction("any", {createAggregateFunctionAny, default_properties}); - factory.registerAlias("any_value", "any", AggregateFunctionFactory::CaseInsensitive); - factory.registerAlias("first_value", "any", AggregateFunctionFactory::CaseInsensitive); - - factory.registerFunction("any_respect_nulls", {createAggregateFunctionAnyRespectNulls, default_properties_for_respect_nulls}); - 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, default_properties}); - factory.registerAlias("last_value", "anyLast", AggregateFunctionFactory::CaseInsensitive); - - factory.registerFunction("anyLast_respect_nulls", {createAggregateFunctionAnyLastRespectNulls, default_properties_for_respect_nulls}); - factory.registerAlias("last_value_respect_nulls", "anyLast_respect_nulls", AggregateFunctionFactory::CaseInsensitive); - - factory.registerFunction("anyHeavy", {createAggregateFunctionAnyHeavy, default_properties}); - - factory.registerNullsActionTransformation("any", "any_respect_nulls"); - factory.registerNullsActionTransformation("anyLast", "anyLast_respect_nulls"); + // AggregateFunctionProperties default_properties = {.returns_default_when_only_null = false, .is_order_dependent = true}; + // AggregateFunctionProperties default_properties_for_respect_nulls + // = {.returns_default_when_only_null = false, .is_order_dependent = true, .is_window_function = true}; + // + // factory.registerFunction("any", {createAggregateFunctionAny, default_properties}); + // factory.registerAlias("any_value", "any", AggregateFunctionFactory::CaseInsensitive); + // factory.registerAlias("first_value", "any", AggregateFunctionFactory::CaseInsensitive); + // + // factory.registerFunction("any_respect_nulls", {createAggregateFunctionAnyRespectNulls, default_properties_for_respect_nulls}); + // 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, default_properties}); + // factory.registerAlias("last_value", "anyLast", AggregateFunctionFactory::CaseInsensitive); + // + // factory.registerFunction("anyLast_respect_nulls", {createAggregateFunctionAnyLastRespectNulls, default_properties_for_respect_nulls}); + // factory.registerAlias("last_value_respect_nulls", "anyLast_respect_nulls", AggregateFunctionFactory::CaseInsensitive); + // + // factory.registerFunction("anyHeavy", {createAggregateFunctionAnyHeavy, default_properties}); + // + // factory.registerNullsActionTransformation("any", "any_respect_nulls"); + // factory.registerNullsActionTransformation("anyLast", "anyLast_respect_nulls"); } } diff --git a/src/AggregateFunctions/AggregateFunctionMax.cpp b/src/AggregateFunctions/AggregateFunctionMax.cpp index e9cd651b8db..692426ded0e 100644 --- a/src/AggregateFunctions/AggregateFunctionMax.cpp +++ b/src/AggregateFunctions/AggregateFunctionMax.cpp @@ -8,231 +8,231 @@ namespace DB { struct Settings; -namespace +//namespace +//{ +// +//template +//class AggregateFunctionsSingleValueMax final : public AggregateFunctionsSingleValue +//{ +// using Parent = AggregateFunctionsSingleValue; +// +//public: +// explicit AggregateFunctionsSingleValueMax(const DataTypePtr & type) : Parent(type) { } +// +// /// Specializations for native numeric types +// void addBatchSinglePlace( +// size_t row_begin, +// size_t row_end, +// AggregateDataPtr __restrict place, +// const IColumn ** __restrict columns, +// Arena * arena, +// ssize_t if_argument_pos) const override; +// +// void addBatchSinglePlaceNotNull( +// size_t row_begin, +// size_t row_end, +// AggregateDataPtr __restrict place, +// const IColumn ** __restrict columns, +// const UInt8 * __restrict null_map, +// Arena * arena, +// ssize_t if_argument_pos) const override; +//}; +// +//// NOLINTBEGIN(bugprone-macro-parentheses) +//#define SPECIALIZE(TYPE) \ +//template <> \ +//void AggregateFunctionsSingleValueMax>>::addBatchSinglePlace( \ +// size_t row_begin, \ +// size_t row_end, \ +// AggregateDataPtr __restrict place, \ +// const IColumn ** __restrict columns, \ +// Arena *, \ +// ssize_t if_argument_pos) const \ +//{ \ +// const auto & column = assert_cast>::ColVecType &>(*columns[0]); \ +// std::optional opt; \ +// if (if_argument_pos >= 0) \ +// { \ +// const auto & flags = assert_cast(*columns[if_argument_pos]).getData(); \ +// opt = findExtremeMaxIf(column.getData().data(), flags.data(), row_begin, row_end); \ +// } \ +// else \ +// opt = findExtremeMax(column.getData().data(), row_begin, row_end); \ +// if (opt.has_value()) \ +// this->data(place).changeIfGreater(opt.value()); \ +//} +//// NOLINTEND(bugprone-macro-parentheses) +// +//FOR_BASIC_NUMERIC_TYPES(SPECIALIZE) +//#undef SPECIALIZE +// +//template +//void AggregateFunctionsSingleValueMax::addBatchSinglePlace( +// size_t row_begin, +// size_t row_end, +// AggregateDataPtr __restrict place, +// const IColumn ** __restrict columns, +// Arena * arena, +// ssize_t if_argument_pos) const +//{ +// if constexpr (!is_any_of) +// { +// /// Leave other numeric types (large integers, decimals, etc) to keep doing the comparison as it's +// /// faster than doing a permutation +// return Parent::addBatchSinglePlace(row_begin, row_end, place, columns, arena, if_argument_pos); +// } +// +// constexpr int nan_direction_hint = 1; +// auto const & column = *columns[0]; +// if (if_argument_pos >= 0) +// { +// size_t index = row_begin; +// const auto & if_flags = assert_cast(*columns[if_argument_pos]).getData(); +// while (if_flags[index] == 0 && index < row_end) +// index++; +// if (index >= row_end) +// return; +// +// for (size_t i = index + 1; i < row_end; i++) +// { +// if ((if_flags[i] != 0) && (column.compareAt(i, index, column, nan_direction_hint) > 0)) +// index = i; +// } +// this->data(place).changeIfGreater(column, index, arena); +// } +// else +// { +// if (row_begin >= row_end) +// return; +// +// /// TODO: Introduce row_begin and row_end to getPermutation +// if (row_begin != 0 || row_end != column.size()) +// { +// size_t index = row_begin; +// for (size_t i = index + 1; i < row_end; i++) +// { +// if (column.compareAt(i, index, column, nan_direction_hint) > 0) +// index = i; +// } +// this->data(place).changeIfGreater(column, index, arena); +// } +// else +// { +// constexpr IColumn::PermutationSortDirection direction = IColumn::PermutationSortDirection::Descending; +// constexpr IColumn::PermutationSortStability stability = IColumn::PermutationSortStability::Unstable; +// IColumn::Permutation permutation; +// constexpr UInt64 limit = 1; +// column.getPermutation(direction, stability, limit, nan_direction_hint, permutation); +// this->data(place).changeIfGreater(column, permutation[0], arena); +// } +// } +//} +// +//// NOLINTBEGIN(bugprone-macro-parentheses) +//#define SPECIALIZE(TYPE) \ +//template <> \ +//void AggregateFunctionsSingleValueMax>>::addBatchSinglePlaceNotNull( \ +// size_t row_begin, \ +// size_t row_end, \ +// AggregateDataPtr __restrict place, \ +// const IColumn ** __restrict columns, \ +// const UInt8 * __restrict null_map, \ +// Arena *, \ +// ssize_t if_argument_pos) const \ +//{ \ +// const auto & column = assert_cast>::ColVecType &>(*columns[0]); \ +// std::optional opt; \ +// if (if_argument_pos >= 0) \ +// { \ +// const auto * if_flags = assert_cast(*columns[if_argument_pos]).getData().data(); \ +// auto final_flags = std::make_unique(row_end); \ +// for (size_t i = row_begin; i < row_end; ++i) \ +// final_flags[i] = (!null_map[i]) & !!if_flags[i]; \ +// opt = findExtremeMaxIf(column.getData().data(), final_flags.get(), row_begin, row_end); \ +// } \ +// else \ +// opt = findExtremeMaxNotNull(column.getData().data(), null_map, row_begin, row_end); \ +// if (opt.has_value()) \ +// this->data(place).changeIfGreater(opt.value()); \ +//} +//// NOLINTEND(bugprone-macro-parentheses) +// +//FOR_BASIC_NUMERIC_TYPES(SPECIALIZE) +//#undef SPECIALIZE +// +//template +//void AggregateFunctionsSingleValueMax::addBatchSinglePlaceNotNull( +// size_t row_begin, +// size_t row_end, +// AggregateDataPtr __restrict place, +// const IColumn ** __restrict columns, +// const UInt8 * __restrict null_map, +// Arena * arena, +// ssize_t if_argument_pos) const +//{ +// if constexpr (!is_any_of) +// { +// /// Leave other numeric types (large integers, decimals, etc) to keep doing the comparison as it's +// /// faster than doing a permutation +// return Parent::addBatchSinglePlaceNotNull(row_begin, row_end, place, columns, null_map, arena, if_argument_pos); +// } +// +// constexpr int nan_direction_hint = 1; +// auto const & column = *columns[0]; +// if (if_argument_pos >= 0) +// { +// size_t index = row_begin; +// const auto & if_flags = assert_cast(*columns[if_argument_pos]).getData(); +// while ((if_flags[index] == 0 || null_map[index] != 0) && (index < row_end)) +// index++; +// if (index >= row_end) +// return; +// +// for (size_t i = index + 1; i < row_end; i++) +// { +// if ((if_flags[i] != 0) && (null_map[i] == 0) && (column.compareAt(i, index, column, nan_direction_hint) > 0)) +// index = i; +// } +// this->data(place).changeIfGreater(column, index, arena); +// } +// else +// { +// size_t index = row_begin; +// while ((null_map[index] != 0) && (index < row_end)) +// index++; +// if (index >= row_end) +// return; +// +// for (size_t i = index + 1; i < row_end; i++) +// { +// if ((null_map[i] == 0) && (column.compareAt(i, index, column, nan_direction_hint) > 0)) +// index = i; +// } +// this->data(place).changeIfGreater(column, index, arena); +// } +//} +// +//AggregateFunctionPtr createAggregateFunctionMax( +// const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) +//{ +// return AggregateFunctionPtr(createAggregateFunctionSingleValue(name, argument_types, parameters, settings)); +//} +// +//AggregateFunctionPtr createAggregateFunctionArgMax( +// const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) +//{ +// return AggregateFunctionPtr(createAggregateFunctionArgMinMax(name, argument_types, parameters, settings)); +//} +// +//} +// +void registerAggregateFunctionsMax(AggregateFunctionFactory &) { - -template -class AggregateFunctionsSingleValueMax final : public AggregateFunctionsSingleValue -{ - using Parent = AggregateFunctionsSingleValue; - -public: - explicit AggregateFunctionsSingleValueMax(const DataTypePtr & type) : Parent(type) { } - - /// Specializations for native numeric types - void addBatchSinglePlace( - size_t row_begin, - size_t row_end, - AggregateDataPtr __restrict place, - const IColumn ** __restrict columns, - Arena * arena, - ssize_t if_argument_pos) const override; - - void addBatchSinglePlaceNotNull( - size_t row_begin, - size_t row_end, - AggregateDataPtr __restrict place, - const IColumn ** __restrict columns, - const UInt8 * __restrict null_map, - Arena * arena, - ssize_t if_argument_pos) const override; -}; - -// NOLINTBEGIN(bugprone-macro-parentheses) -#define SPECIALIZE(TYPE) \ -template <> \ -void AggregateFunctionsSingleValueMax>>::addBatchSinglePlace( \ - size_t row_begin, \ - size_t row_end, \ - AggregateDataPtr __restrict place, \ - const IColumn ** __restrict columns, \ - Arena *, \ - ssize_t if_argument_pos) const \ -{ \ - const auto & column = assert_cast>::ColVecType &>(*columns[0]); \ - std::optional opt; \ - if (if_argument_pos >= 0) \ - { \ - const auto & flags = assert_cast(*columns[if_argument_pos]).getData(); \ - opt = findExtremeMaxIf(column.getData().data(), flags.data(), row_begin, row_end); \ - } \ - else \ - opt = findExtremeMax(column.getData().data(), row_begin, row_end); \ - if (opt.has_value()) \ - this->data(place).changeIfGreater(opt.value()); \ -} -// NOLINTEND(bugprone-macro-parentheses) - -FOR_BASIC_NUMERIC_TYPES(SPECIALIZE) -#undef SPECIALIZE - -template -void AggregateFunctionsSingleValueMax::addBatchSinglePlace( - size_t row_begin, - size_t row_end, - AggregateDataPtr __restrict place, - const IColumn ** __restrict columns, - Arena * arena, - ssize_t if_argument_pos) const -{ - if constexpr (!is_any_of) - { - /// Leave other numeric types (large integers, decimals, etc) to keep doing the comparison as it's - /// faster than doing a permutation - return Parent::addBatchSinglePlace(row_begin, row_end, place, columns, arena, if_argument_pos); - } - - constexpr int nan_direction_hint = 1; - auto const & column = *columns[0]; - if (if_argument_pos >= 0) - { - size_t index = row_begin; - const auto & if_flags = assert_cast(*columns[if_argument_pos]).getData(); - while (if_flags[index] == 0 && index < row_end) - index++; - if (index >= row_end) - return; - - for (size_t i = index + 1; i < row_end; i++) - { - if ((if_flags[i] != 0) && (column.compareAt(i, index, column, nan_direction_hint) > 0)) - index = i; - } - this->data(place).changeIfGreater(column, index, arena); - } - else - { - if (row_begin >= row_end) - return; - - /// TODO: Introduce row_begin and row_end to getPermutation - if (row_begin != 0 || row_end != column.size()) - { - size_t index = row_begin; - for (size_t i = index + 1; i < row_end; i++) - { - if (column.compareAt(i, index, column, nan_direction_hint) > 0) - index = i; - } - this->data(place).changeIfGreater(column, index, arena); - } - else - { - constexpr IColumn::PermutationSortDirection direction = IColumn::PermutationSortDirection::Descending; - constexpr IColumn::PermutationSortStability stability = IColumn::PermutationSortStability::Unstable; - IColumn::Permutation permutation; - constexpr UInt64 limit = 1; - column.getPermutation(direction, stability, limit, nan_direction_hint, permutation); - this->data(place).changeIfGreater(column, permutation[0], arena); - } - } -} - -// NOLINTBEGIN(bugprone-macro-parentheses) -#define SPECIALIZE(TYPE) \ -template <> \ -void AggregateFunctionsSingleValueMax>>::addBatchSinglePlaceNotNull( \ - size_t row_begin, \ - size_t row_end, \ - AggregateDataPtr __restrict place, \ - const IColumn ** __restrict columns, \ - const UInt8 * __restrict null_map, \ - Arena *, \ - ssize_t if_argument_pos) const \ -{ \ - const auto & column = assert_cast>::ColVecType &>(*columns[0]); \ - std::optional opt; \ - if (if_argument_pos >= 0) \ - { \ - const auto * if_flags = assert_cast(*columns[if_argument_pos]).getData().data(); \ - auto final_flags = std::make_unique(row_end); \ - for (size_t i = row_begin; i < row_end; ++i) \ - final_flags[i] = (!null_map[i]) & !!if_flags[i]; \ - opt = findExtremeMaxIf(column.getData().data(), final_flags.get(), row_begin, row_end); \ - } \ - else \ - opt = findExtremeMaxNotNull(column.getData().data(), null_map, row_begin, row_end); \ - if (opt.has_value()) \ - this->data(place).changeIfGreater(opt.value()); \ -} -// NOLINTEND(bugprone-macro-parentheses) - -FOR_BASIC_NUMERIC_TYPES(SPECIALIZE) -#undef SPECIALIZE - -template -void AggregateFunctionsSingleValueMax::addBatchSinglePlaceNotNull( - size_t row_begin, - size_t row_end, - AggregateDataPtr __restrict place, - const IColumn ** __restrict columns, - const UInt8 * __restrict null_map, - Arena * arena, - ssize_t if_argument_pos) const -{ - if constexpr (!is_any_of) - { - /// Leave other numeric types (large integers, decimals, etc) to keep doing the comparison as it's - /// faster than doing a permutation - return Parent::addBatchSinglePlaceNotNull(row_begin, row_end, place, columns, null_map, arena, if_argument_pos); - } - - constexpr int nan_direction_hint = 1; - auto const & column = *columns[0]; - if (if_argument_pos >= 0) - { - size_t index = row_begin; - const auto & if_flags = assert_cast(*columns[if_argument_pos]).getData(); - while ((if_flags[index] == 0 || null_map[index] != 0) && (index < row_end)) - index++; - if (index >= row_end) - return; - - for (size_t i = index + 1; i < row_end; i++) - { - if ((if_flags[i] != 0) && (null_map[i] == 0) && (column.compareAt(i, index, column, nan_direction_hint) > 0)) - index = i; - } - this->data(place).changeIfGreater(column, index, arena); - } - else - { - size_t index = row_begin; - while ((null_map[index] != 0) && (index < row_end)) - index++; - if (index >= row_end) - return; - - for (size_t i = index + 1; i < row_end; i++) - { - if ((null_map[i] == 0) && (column.compareAt(i, index, column, nan_direction_hint) > 0)) - index = i; - } - this->data(place).changeIfGreater(column, index, arena); - } -} - -AggregateFunctionPtr createAggregateFunctionMax( - const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) -{ - return AggregateFunctionPtr(createAggregateFunctionSingleValue(name, argument_types, parameters, settings)); -} - -AggregateFunctionPtr createAggregateFunctionArgMax( - const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) -{ - return AggregateFunctionPtr(createAggregateFunctionArgMinMax(name, argument_types, parameters, settings)); -} - -} - -void registerAggregateFunctionsMax(AggregateFunctionFactory & factory) -{ - factory.registerFunction("max", createAggregateFunctionMax, AggregateFunctionFactory::CaseInsensitive); - - /// The functions below depend on the order of data. - AggregateFunctionProperties properties = { .returns_default_when_only_null = false, .is_order_dependent = true }; - factory.registerFunction("argMax", { createAggregateFunctionArgMax, properties }); + // factory.registerFunction("max", createAggregateFunctionMax, AggregateFunctionFactory::CaseInsensitive); + // + // /// The functions below depend on the order of data. + // AggregateFunctionProperties properties = { .returns_default_when_only_null = false, .is_order_dependent = true }; + // factory.registerFunction("argMax", { createAggregateFunctionArgMax, properties }); } } diff --git a/src/AggregateFunctions/AggregateFunctionMin.cpp b/src/AggregateFunctions/AggregateFunctionMin.cpp index d767bd5c563..a4f05378079 100644 --- a/src/AggregateFunctions/AggregateFunctionMin.cpp +++ b/src/AggregateFunctions/AggregateFunctionMin.cpp @@ -13,12 +13,34 @@ namespace { template -class AggregateFunctionsSingleValueMin final : public AggregateFunctionsSingleValue +class AggregateFunctionMin final : public IAggregateFunctionDataHelper> { - using Parent = AggregateFunctionsSingleValue; +private: + SerializationPtr serialization; public: - explicit AggregateFunctionsSingleValueMin(const DataTypePtr & type) : Parent(type) { } + explicit AggregateFunctionMin(const DataTypePtr & type) + : IAggregateFunctionDataHelper>({type}, {}, type), serialization(type->getDefaultSerialization()) + { + if (!type->isComparable()) + throw Exception( + ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Illegal type {} of argument of aggregate function {} because the values of that data type are not comparable", + type->getName(), + getName()); + } + + String getName() const override { return "min"; } + + void add(AggregateDataPtr __restrict place, const IColumn ** columns, size_t row_num, Arena * arena) const override + { + this->data(place).setIfSmaller(*columns[0], row_num, arena); + } + + void addManyDefaults(AggregateDataPtr __restrict place, const IColumn ** columns, size_t, Arena * arena) const override + { + this->data(place).setIfSmaller(*columns[0], 0, arena); + } /// Specializations for native numeric types void addBatchSinglePlace( @@ -27,7 +49,18 @@ public: AggregateDataPtr __restrict place, const IColumn ** __restrict columns, Arena * arena, - ssize_t if_argument_pos) const override; + ssize_t if_argument_pos) const override + { + if (if_argument_pos >= 0) + { + const auto & if_map = assert_cast(*columns[if_argument_pos]).getData(); + this->data(place).setSmallestNotNullIf(*columns[0], nullptr, if_map.data(), row_begin, row_end, arena); + } + else + { + this->data(place).setSmallest(*columns[0], row_begin, row_end, arena); + } + } void addBatchSinglePlaceNotNull( size_t row_begin, @@ -36,205 +69,236 @@ public: const IColumn ** __restrict columns, const UInt8 * __restrict null_map, Arena * arena, - ssize_t if_argument_pos) const override; -}; - -// NOLINTBEGIN(bugprone-macro-parentheses) -#define SPECIALIZE(TYPE) \ - template <> \ - void AggregateFunctionsSingleValueMin>>::addBatchSinglePlace( \ - size_t row_begin, \ - size_t row_end, \ - AggregateDataPtr __restrict place, \ - const IColumn ** __restrict columns, \ - Arena *, \ - ssize_t if_argument_pos) const \ - { \ - const auto & column = assert_cast>::ColVecType &>(*columns[0]); \ - std::optional opt; \ - if (if_argument_pos >= 0) \ - { \ - const auto & flags = assert_cast(*columns[if_argument_pos]).getData(); \ - opt = findExtremeMinIf(column.getData().data(), flags.data(), row_begin, row_end); \ - } \ - else \ - opt = findExtremeMin(column.getData().data(), row_begin, row_end); \ - if (opt.has_value()) \ - this->data(place).changeIfLess(opt.value()); \ - } -// NOLINTEND(bugprone-macro-parentheses) - -FOR_BASIC_NUMERIC_TYPES(SPECIALIZE) -#undef SPECIALIZE - -template -void AggregateFunctionsSingleValueMin::addBatchSinglePlace( - size_t row_begin, - size_t row_end, - AggregateDataPtr __restrict place, - const IColumn ** __restrict columns, - Arena * arena, - ssize_t if_argument_pos) const -{ - if constexpr (!is_any_of) + ssize_t if_argument_pos) const override { - /// Leave other numeric types (large integers, decimals, etc) to keep doing the comparison as it's - /// faster than doing a permutation - return Parent::addBatchSinglePlace(row_begin, row_end, place, columns, arena, if_argument_pos); - } - - constexpr int nan_direction_hint = 1; - auto const & column = *columns[0]; - if (if_argument_pos >= 0) - { - size_t index = row_begin; - const auto & if_flags = assert_cast(*columns[if_argument_pos]).getData(); - while (if_flags[index] == 0 && index < row_end) - index++; - if (index >= row_end) - return; - - for (size_t i = index + 1; i < row_end; i++) + if (if_argument_pos >= 0) { - if ((if_flags[i] != 0) && (column.compareAt(i, index, column, nan_direction_hint) < 0)) - index = i; - } - this->data(place).changeIfLess(column, index, arena); - } - else - { - if (row_begin >= row_end) - return; - - /// TODO: Introduce row_begin and row_end to getPermutation - if (row_begin != 0 || row_end != column.size()) - { - size_t index = row_begin; - for (size_t i = index + 1; i < row_end; i++) - { - if (column.compareAt(i, index, column, nan_direction_hint) < 0) - index = i; - } - this->data(place).changeIfLess(column, index, arena); + const auto & if_map = assert_cast(*columns[if_argument_pos]).getData(); + this->data(place).setSmallestNotNullIf(*columns[0], null_map, if_map.data(), row_begin, row_end, arena); } else { - constexpr IColumn::PermutationSortDirection direction = IColumn::PermutationSortDirection::Ascending; - constexpr IColumn::PermutationSortStability stability = IColumn::PermutationSortStability::Unstable; - IColumn::Permutation permutation; - constexpr UInt64 limit = 1; - column.getPermutation(direction, stability, limit, nan_direction_hint, permutation); - this->data(place).changeIfLess(column, permutation[0], arena); + this->data(place).setSmallestNotNullIf(*columns[0], null_map, nullptr, row_begin, row_end, arena); } } -} -// NOLINTBEGIN(bugprone-macro-parentheses) -#define SPECIALIZE(TYPE) \ - template <> \ - void AggregateFunctionsSingleValueMin>>::addBatchSinglePlaceNotNull( \ - size_t row_begin, \ - size_t row_end, \ - AggregateDataPtr __restrict place, \ - const IColumn ** __restrict columns, \ - const UInt8 * __restrict null_map, \ - Arena *, \ - ssize_t if_argument_pos) const \ - { \ - const auto & column = assert_cast>::ColVecType &>(*columns[0]); \ - std::optional opt; \ - if (if_argument_pos >= 0) \ - { \ - const auto * if_flags = assert_cast(*columns[if_argument_pos]).getData().data(); \ - auto final_flags = std::make_unique(row_end); \ - for (size_t i = row_begin; i < row_end; ++i) \ - final_flags[i] = (!null_map[i]) & !!if_flags[i]; \ - opt = findExtremeMinIf(column.getData().data(), final_flags.get(), row_begin, row_end); \ - } \ - else \ - opt = findExtremeMinNotNull(column.getData().data(), null_map, row_begin, row_end); \ - if (opt.has_value()) \ - this->data(place).changeIfLess(opt.value()); \ - } -// NOLINTEND(bugprone-macro-parentheses) - -FOR_BASIC_NUMERIC_TYPES(SPECIALIZE) -#undef SPECIALIZE - -template -void AggregateFunctionsSingleValueMin::addBatchSinglePlaceNotNull( - size_t row_begin, - size_t row_end, - AggregateDataPtr __restrict place, - const IColumn ** __restrict columns, - const UInt8 * __restrict null_map, - Arena * arena, - ssize_t if_argument_pos) const -{ - if constexpr (!is_any_of) + void merge(AggregateDataPtr __restrict place, ConstAggregateDataPtr rhs, Arena * arena) const override { - /// Leave other numeric types (large integers, decimals, etc) to keep doing the comparison as it's - /// faster than doing a permutation - return Parent::addBatchSinglePlaceNotNull(row_begin, row_end, place, columns, null_map, arena, if_argument_pos); + this->data(place).setIfSmaller(this->data(rhs), arena); } - constexpr int nan_direction_hint = 1; - auto const & column = *columns[0]; - if (if_argument_pos >= 0) + void serialize(ConstAggregateDataPtr __restrict place, WriteBuffer & buf, std::optional /* version */) const override { - size_t index = row_begin; - const auto & if_flags = assert_cast(*columns[if_argument_pos]).getData(); - while ((if_flags[index] == 0 || null_map[index] != 0) && (index < row_end)) - index++; - if (index >= row_end) - return; - - for (size_t i = index + 1; i < row_end; i++) - { - if ((if_flags[i] != 0) && (null_map[index] == 0) && (column.compareAt(i, index, column, nan_direction_hint) < 0)) - index = i; - } - this->data(place).changeIfLess(column, index, arena); + this->data(place).write(buf, *serialization); } - else + + void deserialize(AggregateDataPtr place, ReadBuffer & buf, std::optional /* version */, Arena * arena) const override { - size_t index = row_begin; - while ((null_map[index] != 0) && (index < row_end)) - index++; - if (index >= row_end) - return; - - for (size_t i = index + 1; i < row_end; i++) - { - if ((null_map[i] == 0) && (column.compareAt(i, index, column, nan_direction_hint) < 0)) - index = i; - } - this->data(place).changeIfLess(column, index, arena); + this->data(place).read(buf, *serialization, arena); } -} -AggregateFunctionPtr createAggregateFunctionMin( - const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) + bool allocatesMemoryInArena() const override { return Data::allocatesMemoryInArena(); } + + void insertResultInto(AggregateDataPtr __restrict place, IColumn & to, Arena *) const override + { + this->data(place).insertResultInto(to); + } +}; + +//// NOLINTBEGIN(bugprone-macro-parentheses) +//#define SPECIALIZE(TYPE) \ +// template <> \ +// void AggregateFunctionsSingleValueMin>::addBatchSinglePlace( \ +// size_t row_begin, \ +// size_t row_end, \ +// AggregateDataPtr __restrict place, \ +// const IColumn ** __restrict columns, \ +// Arena *, \ +// ssize_t if_argument_pos) const \ +// { \ +// const auto & column = assert_cast>::ColVecType &>(*columns[0]); \ +// std::optional opt; \ +// if (if_argument_pos >= 0) \ +// { \ +// const auto & flags = assert_cast(*columns[if_argument_pos]).getData(); \ +// opt = findExtremeMinIf(column.getData().data(), flags.data(), row_begin, row_end); \ +// } \ +// else \ +// opt = findExtremeMin(column.getData().data(), row_begin, row_end); \ +// if (opt.has_value()) \ +// this->data(place).setIfSmaller(opt.value()); \ +// } +//// NOLINTEND(bugprone-macro-parentheses) +// +//FOR_BASIC_NUMERIC_TYPES(SPECIALIZE) +//#undef SPECIALIZE +// +//template +//void AggregateFunctionsSingleValueMin::addBatchSinglePlace( +// size_t row_begin, +// size_t row_end, +// AggregateDataPtr __restrict place, +// const IColumn ** __restrict columns, +// Arena * arena, +// ssize_t if_argument_pos) const +//{ +//// if constexpr (!is_any_of) +//// { +//// /// Leave other numeric types (large integers, decimals, etc) to keep doing the comparison as it's +//// /// faster than doing a permutation +//// return Parent::addBatchSinglePlace(row_begin, row_end, place, columns, arena, if_argument_pos); +//// } +// +// constexpr int nan_direction_hint = 1; +// auto const & column = *columns[0]; +// if (if_argument_pos >= 0) +// { +// size_t index = row_begin; +// const auto & if_flags = assert_cast(*columns[if_argument_pos]).getData(); +// while (if_flags[index] == 0 && index < row_end) +// index++; +// if (index >= row_end) +// return; +// +// for (size_t i = index + 1; i < row_end; i++) +// { +// if ((if_flags[i] != 0) && (column.compareAt(i, index, column, nan_direction_hint) < 0)) +// index = i; +// } +// this->data(place).setIfSmaller(column, index, arena); +// } +// else +// { +// if (row_begin >= row_end) +// return; +// +// /// TODO: Introduce row_begin and row_end to getPermutation +// if (row_begin != 0 || row_end != column.size()) +// { +// size_t index = row_begin; +// for (size_t i = index + 1; i < row_end; i++) +// { +// if (column.compareAt(i, index, column, nan_direction_hint) < 0) +// index = i; +// } +// this->data(place).setIfSmaller(column, index, arena); +// } +// else +// { +// constexpr IColumn::PermutationSortDirection direction = IColumn::PermutationSortDirection::Ascending; +// constexpr IColumn::PermutationSortStability stability = IColumn::PermutationSortStability::Unstable; +// IColumn::Permutation permutation; +// constexpr UInt64 limit = 1; +// column.getPermutation(direction, stability, limit, nan_direction_hint, permutation); +// this->data(place).setIfSmaller(column, permutation[0], arena); +// } +// } +//} +// +//// NOLINTBEGIN(bugprone-macro-parentheses) +//#define SPECIALIZE(TYPE) \ +// template <> \ +// void AggregateFunctionsSingleValueMin>>::addBatchSinglePlaceNotNull( \ +// size_t row_begin, \ +// size_t row_end, \ +// AggregateDataPtr __restrict place, \ +// const IColumn ** __restrict columns, \ +// const UInt8 * __restrict null_map, \ +// Arena *, \ +// ssize_t if_argument_pos) const \ +// { \ +// const auto & column = assert_cast>::ColVecType &>(*columns[0]); \ +// std::optional opt; \ +// if (if_argument_pos >= 0) \ +// { \ +// const auto * if_flags = assert_cast(*columns[if_argument_pos]).getData().data(); \ +// auto final_flags = std::make_unique(row_end); \ +// for (size_t i = row_begin; i < row_end; ++i) \ +// final_flags[i] = (!null_map[i]) & !!if_flags[i]; \ +// opt = findExtremeMinIf(column.getData().data(), final_flags.get(), row_begin, row_end); \ +// } \ +// else \ +// opt = findExtremeMinNotNull(column.getData().data(), null_map, row_begin, row_end); \ +// if (opt.has_value()) \ +// this->data(place).setIfSmaller(opt.value()); \ +// } +//// NOLINTEND(bugprone-macro-parentheses) +// +//FOR_BASIC_NUMERIC_TYPES(SPECIALIZE) +//#undef SPECIALIZE +// +//template +//void AggregateFunctionsSingleValueMin::addBatchSinglePlaceNotNull( +// size_t row_begin, +// size_t row_end, +// AggregateDataPtr __restrict place, +// const IColumn ** __restrict columns, +// const UInt8 * __restrict null_map, +// Arena * arena, +// ssize_t if_argument_pos) const +//{ +//// if constexpr (!is_any_of) +//// { +//// /// Leave other numeric types (large integers, decimals, etc) to keep doing the comparison as it's +//// /// faster than doing a permutation +//// return Parent::addBatchSinglePlaceNotNull(row_begin, row_end, place, columns, null_map, arena, if_argument_pos); +//// } +// +// constexpr int nan_direction_hint = 1; +// auto const & column = *columns[0]; +// if (if_argument_pos >= 0) +// { +// size_t index = row_begin; +// const auto & if_flags = assert_cast(*columns[if_argument_pos]).getData(); +// while ((if_flags[index] == 0 || null_map[index] != 0) && (index < row_end)) +// index++; +// if (index >= row_end) +// return; +// +// for (size_t i = index + 1; i < row_end; i++) +// { +// if ((if_flags[i] != 0) && (null_map[index] == 0) && (column.compareAt(i, index, column, nan_direction_hint) < 0)) +// index = i; +// } +// this->data(place).setIfSmaller(column, index, arena); +// } +// else +// { +// size_t index = row_begin; +// while ((null_map[index] != 0) && (index < row_end)) +// index++; +// if (index >= row_end) +// return; +// +// for (size_t i = index + 1; i < row_end; i++) +// { +// if ((null_map[i] == 0) && (column.compareAt(i, index, column, nan_direction_hint) < 0)) +// index = i; +// } +// this->data(place).setIfSmaller(column, index, arena); +// } +//} + +AggregateFunctionPtr +createAggregateFunctionMin(const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) { - return AggregateFunctionPtr(createAggregateFunctionSingleValue( - name, argument_types, parameters, settings)); -} - -AggregateFunctionPtr createAggregateFunctionArgMin( - const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) -{ - return AggregateFunctionPtr(createAggregateFunctionArgMinMax(name, argument_types, parameters, settings)); + return AggregateFunctionPtr(createAggregateFunctionSingleValue(name, argument_types, parameters, settings)); } +//AggregateFunctionPtr createAggregateFunctionArgMin( +// const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) +//{ +// return AggregateFunctionPtr(createAggregateFunctionArgMinMax(name, argument_types, parameters, settings)); +//} } void registerAggregateFunctionsMin(AggregateFunctionFactory & factory) { factory.registerFunction("min", createAggregateFunctionMin, AggregateFunctionFactory::CaseInsensitive); - /// The functions below depend on the order of data. - AggregateFunctionProperties properties = { .returns_default_when_only_null = false, .is_order_dependent = true }; - factory.registerFunction("argMin", { createAggregateFunctionArgMin, properties }); + // /// The functions below depend on the order of data. + // AggregateFunctionProperties properties = { .returns_default_when_only_null = false, .is_order_dependent = true }; + // factory.registerFunction("argMin", { createAggregateFunctionArgMin, properties }); } } diff --git a/src/AggregateFunctions/AggregateFunctionMinMaxAny.h b/src/AggregateFunctions/AggregateFunctionMinMaxAny.h deleted file mode 100644 index dec70861543..00000000000 --- a/src/AggregateFunctions/AggregateFunctionMinMaxAny.h +++ /dev/null @@ -1,1449 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "config.h" - -#if USE_EMBEDDED_COMPILER -# include -# include -#endif - -namespace DB -{ -struct Settings; - -namespace ErrorCodes -{ - extern const int ILLEGAL_TYPE_OF_ARGUMENT; - extern const int NOT_IMPLEMENTED; - extern const int TOO_LARGE_STRING_SIZE; - extern const int LOGICAL_ERROR; -} - -/** Aggregate functions that store one of passed values. - * For example: min, max, any, anyLast. - */ - - -/// For numeric values. -template -struct SingleValueDataFixed -{ - using Self = SingleValueDataFixed; - using ColVecType = ColumnVectorOrDecimal; - - bool has_value = false; /// We need to remember if at least one value has been passed. This is necessary for AggregateFunctionIf. - T value = T{}; - - static constexpr bool result_is_nullable = false; - static constexpr bool should_skip_null_arguments = true; - static constexpr bool is_any = false; - - bool has() const - { - return has_value; - } - - void insertResultInto(IColumn & to) const - { - if (has()) - assert_cast(to).getData().push_back(value); - else - assert_cast(to).insertDefault(); - } - - void write(WriteBuffer & buf, const ISerialization & /*serialization*/) const - { - writeBinary(has(), buf); - if (has()) - writeBinaryLittleEndian(value, buf); - } - - void read(ReadBuffer & buf, const ISerialization & /*serialization*/, Arena *) - { - readBinary(has_value, buf); - if (has()) - readBinaryLittleEndian(value, buf); - } - - - void change(const IColumn & column, size_t row_num, Arena *) - { - has_value = true; - value = assert_cast(column).getData()[row_num]; - } - - /// Assuming to.has() - void change(const Self & to, Arena *) - { - has_value = true; - value = to.value; - } - - bool changeFirstTime(const IColumn & column, size_t row_num, Arena * arena) - { - if (!has()) - { - change(column, row_num, arena); - return true; - } - else - return false; - } - - bool changeFirstTime(const Self & to, Arena * arena) - { - if (!has() && to.has()) - { - change(to, arena); - return true; - } - else - return false; - } - - bool changeEveryTime(const IColumn & column, size_t row_num, Arena * arena) - { - change(column, row_num, arena); - return true; - } - - bool changeEveryTime(const Self & to, Arena * arena) - { - if (to.has()) - { - change(to, arena); - return true; - } - else - return false; - } - - bool changeIfLess(const IColumn & column, size_t row_num, Arena * arena) - { - if (!has() || assert_cast(column).getData()[row_num] < value) - { - change(column, row_num, arena); - return true; - } - else - return false; - } - - bool changeIfLess(const Self & to, Arena * arena) - { - if (to.has() && (!has() || to.value < value)) - { - change(to, arena); - return true; - } - else - return false; - } - - void changeIfLess(T from) - { - if (!has() || from < value) - { - has_value = true; - value = from; - } - } - - bool changeIfGreater(const IColumn & column, size_t row_num, Arena * arena) - { - if (!has() || assert_cast(column).getData()[row_num] > value) - { - change(column, row_num, arena); - return true; - } - else - return false; - } - - bool changeIfGreater(const Self & to, Arena * arena) - { - if (to.has() && (!has() || to.value > value)) - { - change(to, arena); - return true; - } - else - return false; - } - - void changeIfGreater(T & from) - { - if (!has() || from > value) - { - has_value = true; - value = from; - } - } - - bool isEqualTo(const Self & to) const - { - return has() && to.value == value; - } - - bool isEqualTo(const IColumn & column, size_t row_num) const - { - return has() && assert_cast(column).getData()[row_num] == value; - } - - static bool allocatesMemoryInArena() - { - return false; - } - -#if USE_EMBEDDED_COMPILER - - static constexpr bool is_compilable = true; - - static llvm::Value * getValuePtrFromAggregateDataPtr(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr) - { - llvm::IRBuilder<> & b = static_cast &>(builder); - - static constexpr size_t value_offset_from_structure = offsetof(SingleValueDataFixed, value); - auto * value_ptr = b.CreateConstInBoundsGEP1_64(b.getInt8Ty(), aggregate_data_ptr, value_offset_from_structure); - - return value_ptr; - } - - static llvm::Value * getValueFromAggregateDataPtr(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr) - { - llvm::IRBuilder<> & b = static_cast &>(builder); - - auto * type = toNativeType(builder); - auto * value_ptr = getValuePtrFromAggregateDataPtr(builder, aggregate_data_ptr); - - return b.CreateLoad(type, value_ptr); - } - - static void compileChange(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr, llvm::Value * value_to_check) - { - llvm::IRBuilder<> & b = static_cast &>(builder); - - auto * has_value_ptr = aggregate_data_ptr; - b.CreateStore(b.getInt1(true), has_value_ptr); - - auto * value_ptr = getValuePtrFromAggregateDataPtr(b, aggregate_data_ptr); - b.CreateStore(value_to_check, value_ptr); - } - - static void compileChangeMerge(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_dst_ptr, llvm::Value * aggregate_data_src_ptr) - { - auto * value_src = getValueFromAggregateDataPtr(builder, aggregate_data_src_ptr); - - compileChange(builder, aggregate_data_dst_ptr, value_src); - } - - static void compileChangeFirstTime(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr, llvm::Value * value_to_check) - { - llvm::IRBuilder<> & b = static_cast &>(builder); - - auto * has_value_ptr = aggregate_data_ptr; - auto * has_value_value = b.CreateLoad(b.getInt1Ty(), has_value_ptr); - - auto * head = b.GetInsertBlock(); - - auto * join_block = llvm::BasicBlock::Create(head->getContext(), "join_block", head->getParent()); - auto * if_should_change = llvm::BasicBlock::Create(head->getContext(), "if_should_change", head->getParent()); - auto * if_should_not_change = llvm::BasicBlock::Create(head->getContext(), "if_should_not_change", head->getParent()); - - b.CreateCondBr(has_value_value, if_should_not_change, if_should_change); - - b.SetInsertPoint(if_should_not_change); - b.CreateBr(join_block); - - b.SetInsertPoint(if_should_change); - compileChange(builder, aggregate_data_ptr, value_to_check); - b.CreateBr(join_block); - - b.SetInsertPoint(join_block); - } - - static void compileChangeFirstTimeMerge(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_dst_ptr, llvm::Value * aggregate_data_src_ptr) - { - llvm::IRBuilder<> & b = static_cast &>(builder); - - auto * has_value_dst_ptr = aggregate_data_dst_ptr; - auto * has_value_dst = b.CreateLoad(b.getInt1Ty(), has_value_dst_ptr); - - auto * has_value_src_ptr = aggregate_data_src_ptr; - auto * has_value_src = b.CreateLoad(b.getInt1Ty(), has_value_src_ptr); - - auto * head = b.GetInsertBlock(); - - auto * join_block = llvm::BasicBlock::Create(head->getContext(), "join_block", head->getParent()); - auto * if_should_change = llvm::BasicBlock::Create(head->getContext(), "if_should_change", head->getParent()); - auto * if_should_not_change = llvm::BasicBlock::Create(head->getContext(), "if_should_not_change", head->getParent()); - - b.CreateCondBr(b.CreateAnd(b.CreateNot(has_value_dst), has_value_src), if_should_change, if_should_not_change); - - b.SetInsertPoint(if_should_change); - compileChangeMerge(builder, aggregate_data_dst_ptr, aggregate_data_src_ptr); - b.CreateBr(join_block); - - b.SetInsertPoint(if_should_not_change); - b.CreateBr(join_block); - - b.SetInsertPoint(join_block); - } - - static void compileChangeEveryTime(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr, llvm::Value * value_to_check) - { - compileChange(builder, aggregate_data_ptr, value_to_check); - } - - static void compileChangeEveryTimeMerge(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_dst_ptr, llvm::Value * aggregate_data_src_ptr) - { - llvm::IRBuilder<> & b = static_cast &>(builder); - - auto * has_value_src_ptr = aggregate_data_src_ptr; - auto * has_value_src = b.CreateLoad(b.getInt1Ty(), has_value_src_ptr); - - auto * head = b.GetInsertBlock(); - - auto * join_block = llvm::BasicBlock::Create(head->getContext(), "join_block", head->getParent()); - auto * if_should_change = llvm::BasicBlock::Create(head->getContext(), "if_should_change", head->getParent()); - auto * if_should_not_change = llvm::BasicBlock::Create(head->getContext(), "if_should_not_change", head->getParent()); - - b.CreateCondBr(has_value_src, if_should_change, if_should_not_change); - - b.SetInsertPoint(if_should_change); - compileChangeMerge(builder, aggregate_data_dst_ptr, aggregate_data_src_ptr); - b.CreateBr(join_block); - - b.SetInsertPoint(if_should_not_change); - b.CreateBr(join_block); - - b.SetInsertPoint(join_block); - } - - template - static void compileChangeComparison(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr, llvm::Value * value_to_check) - { - llvm::IRBuilder<> & b = static_cast &>(builder); - - auto * has_value_ptr = aggregate_data_ptr; - auto * has_value_value = b.CreateLoad(b.getInt1Ty(), has_value_ptr); - - auto * value = getValueFromAggregateDataPtr(b, aggregate_data_ptr); - - auto * head = b.GetInsertBlock(); - - auto * join_block = llvm::BasicBlock::Create(head->getContext(), "join_block", head->getParent()); - auto * if_should_change = llvm::BasicBlock::Create(head->getContext(), "if_should_change", head->getParent()); - auto * if_should_not_change = llvm::BasicBlock::Create(head->getContext(), "if_should_not_change", head->getParent()); - - auto is_signed = std::numeric_limits::is_signed; - - llvm::Value * should_change_after_comparison = nullptr; - - if constexpr (is_less) - { - if (value_to_check->getType()->isIntegerTy()) - should_change_after_comparison = is_signed ? b.CreateICmpSLT(value_to_check, value) : b.CreateICmpULT(value_to_check, value); - else - should_change_after_comparison = b.CreateFCmpOLT(value_to_check, value); - } - else - { - if (value_to_check->getType()->isIntegerTy()) - should_change_after_comparison = is_signed ? b.CreateICmpSGT(value_to_check, value) : b.CreateICmpUGT(value_to_check, value); - else - should_change_after_comparison = b.CreateFCmpOGT(value_to_check, value); - } - - b.CreateCondBr(b.CreateOr(b.CreateNot(has_value_value), should_change_after_comparison), if_should_change, if_should_not_change); - - b.SetInsertPoint(if_should_change); - compileChange(builder, aggregate_data_ptr, value_to_check); - b.CreateBr(join_block); - - b.SetInsertPoint(if_should_not_change); - b.CreateBr(join_block); - - b.SetInsertPoint(join_block); - } - - template - static void compileChangeComparisonMerge(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_dst_ptr, llvm::Value * aggregate_data_src_ptr) - { - llvm::IRBuilder<> & b = static_cast &>(builder); - - auto * has_value_dst_ptr = aggregate_data_dst_ptr; - auto * has_value_dst = b.CreateLoad(b.getInt1Ty(), has_value_dst_ptr); - - auto * value_dst = getValueFromAggregateDataPtr(b, aggregate_data_dst_ptr); - - auto * has_value_src_ptr = aggregate_data_src_ptr; - auto * has_value_src = b.CreateLoad(b.getInt1Ty(), has_value_src_ptr); - - auto * value_src = getValueFromAggregateDataPtr(b, aggregate_data_src_ptr); - - auto * head = b.GetInsertBlock(); - - auto * join_block = llvm::BasicBlock::Create(head->getContext(), "join_block", head->getParent()); - auto * if_should_change = llvm::BasicBlock::Create(head->getContext(), "if_should_change", head->getParent()); - auto * if_should_not_change = llvm::BasicBlock::Create(head->getContext(), "if_should_not_change", head->getParent()); - - auto is_signed = std::numeric_limits::is_signed; - - llvm::Value * should_change_after_comparison = nullptr; - - if constexpr (is_less) - { - if (value_src->getType()->isIntegerTy()) - should_change_after_comparison = is_signed ? b.CreateICmpSLT(value_src, value_dst) : b.CreateICmpULT(value_src, value_dst); - else - should_change_after_comparison = b.CreateFCmpOLT(value_src, value_dst); - } - else - { - if (value_src->getType()->isIntegerTy()) - should_change_after_comparison = is_signed ? b.CreateICmpSGT(value_src, value_dst) : b.CreateICmpUGT(value_src, value_dst); - else - should_change_after_comparison = b.CreateFCmpOGT(value_src, value_dst); - } - - b.CreateCondBr(b.CreateAnd(has_value_src, b.CreateOr(b.CreateNot(has_value_dst), should_change_after_comparison)), if_should_change, if_should_not_change); - - b.SetInsertPoint(if_should_change); - compileChangeMerge(builder, aggregate_data_dst_ptr, aggregate_data_src_ptr); - b.CreateBr(join_block); - - b.SetInsertPoint(if_should_not_change); - b.CreateBr(join_block); - - b.SetInsertPoint(join_block); - } - - static void compileChangeIfLess(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr, llvm::Value * value_to_check) - { - static constexpr bool is_less = true; - compileChangeComparison(builder, aggregate_data_ptr, value_to_check); - } - - static void compileChangeIfLessMerge(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_dst_ptr, llvm::Value * aggregate_data_src_ptr) - { - static constexpr bool is_less = true; - compileChangeComparisonMerge(builder, aggregate_data_dst_ptr, aggregate_data_src_ptr); - } - - static void compileChangeIfGreater(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr, llvm::Value * value_to_check) - { - static constexpr bool is_less = false; - compileChangeComparison(builder, aggregate_data_ptr, value_to_check); - } - - static void compileChangeIfGreaterMerge(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_dst_ptr, llvm::Value * aggregate_data_src_ptr) - { - static constexpr bool is_less = false; - compileChangeComparisonMerge(builder, aggregate_data_dst_ptr, aggregate_data_src_ptr); - } - - static llvm::Value * compileGetResult(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr) - { - return getValueFromAggregateDataPtr(builder, aggregate_data_ptr); - } - -#endif -}; - -struct Compatibility -{ - /// Old versions used to store terminating null-character in SingleValueDataString. - /// Then -WithTerminatingZero methods were removed from IColumn interface, - /// because these methods are quite dangerous and easy to misuse. It introduced incompatibility. - /// See https://github.com/ClickHouse/ClickHouse/pull/41431 and https://github.com/ClickHouse/ClickHouse/issues/42916 - /// Here we keep these functions for compatibility. - /// It's safe because there's no way unsanitized user input (without \0 at the end) can reach these functions. - - static StringRef getDataAtWithTerminatingZero(const ColumnString & column, size_t n) - { - auto res = column.getDataAt(n); - /// ColumnString always reserves extra byte for null-character after string. - /// But getDataAt returns StringRef without the null-character. Let's add it. - chassert(res.data[res.size] == '\0'); - ++res.size; - return res; - } - - static void insertDataWithTerminatingZero(ColumnString & column, const char * pos, size_t length) - { - /// String already has terminating null-character. - /// But insertData will add another one unconditionally. Trim existing null-character to avoid duplication. - chassert(0 < length); - chassert(pos[length - 1] == '\0'); - column.insertData(pos, length - 1); - } -}; - -/** For strings. Short strings are stored in the object itself, and long strings are allocated separately. - * NOTE It could also be suitable for arrays of numbers. - */ -struct SingleValueDataString -{ -private: - using Self = SingleValueDataString; - - /// 0 size indicates that there is no value. Empty string must has terminating '\0' and, therefore, size of empty string is 1 - UInt32 size = 0; - UInt32 capacity = 0; /// power of two or zero - char * large_data; - -public: - static constexpr UInt32 AUTOMATIC_STORAGE_SIZE = 64; - static constexpr UInt32 MAX_SMALL_STRING_SIZE = AUTOMATIC_STORAGE_SIZE - sizeof(size) - sizeof(capacity) - sizeof(large_data); - static constexpr UInt32 MAX_STRING_SIZE = std::numeric_limits::max(); - -private: - char small_data[MAX_SMALL_STRING_SIZE]; /// Including the terminating zero. - -public: - static constexpr bool result_is_nullable = false; - static constexpr bool should_skip_null_arguments = true; - static constexpr bool is_any = false; - - bool has() const - { - return size; - } - -private: - char * getDataMutable() - { - return size <= MAX_SMALL_STRING_SIZE ? small_data : large_data; - } - - const char * getData() const - { - const char * data_ptr = size <= MAX_SMALL_STRING_SIZE ? small_data : large_data; - /// It must always be terminated with null-character - chassert(0 < size); - chassert(data_ptr[size - 1] == '\0'); - return data_ptr; - } - - StringRef getStringRef() const - { - return StringRef(getData(), size); - } - -public: - void insertResultInto(IColumn & to) const - { - if (has()) - Compatibility::insertDataWithTerminatingZero(assert_cast(to), getData(), size); - else - assert_cast(to).insertDefault(); - } - - void write(WriteBuffer & buf, const ISerialization & /*serialization*/) const - { - if (unlikely(MAX_STRING_SIZE < size)) - throw Exception(ErrorCodes::LOGICAL_ERROR, "String size is too big ({}), it's a bug", size); - - /// For serialization we use signed Int32 (for historical reasons), -1 means "no value" - Int32 size_to_write = size ? size : -1; - writeBinaryLittleEndian(size_to_write, buf); - if (has()) - buf.write(getData(), size); - } - - void allocateLargeDataIfNeeded(UInt32 size_to_reserve, Arena * arena) - { - if (capacity < size_to_reserve) - { - if (unlikely(MAX_STRING_SIZE < size_to_reserve)) - throw Exception(ErrorCodes::TOO_LARGE_STRING_SIZE, "String size is too big ({}), maximum: {}", - size_to_reserve, MAX_STRING_SIZE); - - size_t rounded_capacity = roundUpToPowerOfTwoOrZero(size_to_reserve); - chassert(rounded_capacity <= MAX_STRING_SIZE + 1); /// rounded_capacity <= 2^31 - capacity = static_cast(rounded_capacity); - - /// Don't free large_data here. - large_data = arena->alloc(capacity); - } - } - - void read(ReadBuffer & buf, const ISerialization & /*serialization*/, Arena * arena) - { - /// For serialization we use signed Int32 (for historical reasons), -1 means "no value" - Int32 rhs_size_signed; - readBinaryLittleEndian(rhs_size_signed, buf); - - if (rhs_size_signed < 0) - { - /// Don't free large_data here. - size = 0; - return; - } - - UInt32 rhs_size = rhs_size_signed; - if (rhs_size <= MAX_SMALL_STRING_SIZE) - { - /// Don't free large_data here. - size = rhs_size; - buf.readStrict(small_data, size); - } - else - { - /// Reserve one byte more for null-character - allocateLargeDataIfNeeded(rhs_size + 1, arena); - size = rhs_size; - buf.readStrict(large_data, size); - } - - /// Check if the string we read is null-terminated (getDataMutable does not have the assertion) - if (0 < size && getDataMutable()[size - 1] == '\0') - return; - - /// It's not null-terminated, but it must be (for historical reasons). There are two variants: - /// - The value was serialized by one of the incompatible versions of ClickHouse. We had some range of versions - /// that used to serialize SingleValueDataString without terminating '\0'. Let's just append it. - /// - An attacker sent crafted data. Sanitize it and append '\0'. - /// In all other cases the string must be already null-terminated. - - /// NOTE We cannot add '\0' unconditionally, because it will be duplicated. - /// NOTE It's possible that a string that actually ends with '\0' was written by one of the incompatible versions. - /// Unfortunately, we cannot distinguish it from normal string written by normal version. - /// So such strings will be trimmed. - - if (size == MAX_SMALL_STRING_SIZE) - { - /// Special case: We have to move value to large_data - allocateLargeDataIfNeeded(size + 1, arena); - memcpy(large_data, small_data, size); - } - - /// We have enough space to append - ++size; - getDataMutable()[size - 1] = '\0'; - } - - /// Assuming to.has() - void changeImpl(StringRef value, Arena * arena) - { - if (unlikely(MAX_STRING_SIZE < value.size)) - throw Exception(ErrorCodes::TOO_LARGE_STRING_SIZE, "String size is too big ({}), maximum: {}", - value.size, MAX_STRING_SIZE); - - UInt32 value_size = static_cast(value.size); - - if (value_size <= MAX_SMALL_STRING_SIZE) - { - /// Don't free large_data here. - size = value_size; - - if (size > 0) - memcpy(small_data, value.data, size); - } - else - { - allocateLargeDataIfNeeded(value_size, arena); - size = value_size; - memcpy(large_data, value.data, size); - } - } - - void change(const IColumn & column, size_t row_num, Arena * arena) - { - changeImpl(Compatibility::getDataAtWithTerminatingZero(assert_cast(column), row_num), arena); - } - - void change(const Self & to, Arena * arena) - { - changeImpl(to.getStringRef(), arena); - } - - bool changeFirstTime(const IColumn & column, size_t row_num, Arena * arena) - { - if (!has()) - { - change(column, row_num, arena); - return true; - } - else - return false; - } - - bool changeFirstTime(const Self & to, Arena * arena) - { - if (!has() && to.has()) - { - change(to, arena); - return true; - } - else - return false; - } - - bool changeEveryTime(const IColumn & column, size_t row_num, Arena * arena) - { - change(column, row_num, arena); - return true; - } - - bool changeEveryTime(const Self & to, Arena * arena) - { - if (to.has()) - { - change(to, arena); - return true; - } - else - return false; - } - - bool changeIfLess(const IColumn & column, size_t row_num, Arena * arena) - { - if (!has() || Compatibility::getDataAtWithTerminatingZero(assert_cast(column), row_num) < getStringRef()) - { - change(column, row_num, arena); - return true; - } - else - return false; - } - - bool changeIfLess(const Self & to, Arena * arena) - { - if (to.has() && (!has() || to.getStringRef() < getStringRef())) - { - change(to, arena); - return true; - } - else - return false; - } - - bool changeIfGreater(const IColumn & column, size_t row_num, Arena * arena) - { - if (!has() || Compatibility::getDataAtWithTerminatingZero(assert_cast(column), row_num) > getStringRef()) - { - change(column, row_num, arena); - return true; - } - else - return false; - } - - bool changeIfGreater(const Self & to, Arena * arena) - { - if (to.has() && (!has() || to.getStringRef() > getStringRef())) - { - change(to, arena); - return true; - } - else - return false; - } - - bool isEqualTo(const Self & to) const - { - return has() && to.getStringRef() == getStringRef(); - } - - bool isEqualTo(const IColumn & column, size_t row_num) const - { - return has() && Compatibility::getDataAtWithTerminatingZero(assert_cast(column), row_num) == getStringRef(); - } - - static bool allocatesMemoryInArena() - { - return true; - } - -#if USE_EMBEDDED_COMPILER - - static constexpr bool is_compilable = false; - -#endif - -}; - -static_assert( - sizeof(SingleValueDataString) == SingleValueDataString::AUTOMATIC_STORAGE_SIZE, - "Incorrect size of SingleValueDataString struct"); - - -/// For any other value types. -struct SingleValueDataGeneric -{ -private: - using Self = SingleValueDataGeneric; - Field value; - -public: - static constexpr bool result_is_nullable = false; - static constexpr bool should_skip_null_arguments = true; - static constexpr bool is_any = false; - - bool has() const { return !value.isNull(); } - - void insertResultInto(IColumn & to) const - { - if (has()) - to.insert(value); - else - to.insertDefault(); - } - - void write(WriteBuffer & buf, const ISerialization & serialization) const - { - if (!value.isNull()) - { - writeBinary(true, buf); - serialization.serializeBinary(value, buf, {}); - } - else - writeBinary(false, buf); - } - - void read(ReadBuffer & buf, const ISerialization & serialization, Arena *) - { - bool is_not_null; - readBinary(is_not_null, buf); - - if (is_not_null) - serialization.deserializeBinary(value, buf, {}); - } - - void change(const IColumn & column, size_t row_num, Arena *) { column.get(row_num, value); } - - void change(const Self & to, Arena *) { value = to.value; } - - bool changeFirstTime(const IColumn & column, size_t row_num, Arena * arena) - { - if (!has()) - { - change(column, row_num, arena); - return true; - } - else - return false; - } - - bool changeFirstTime(const Self & to, Arena * arena) - { - if (!has() && to.has()) - { - change(to, arena); - return true; - } - else - return false; - } - - bool changeEveryTime(const IColumn & column, size_t row_num, Arena * arena) - { - change(column, row_num, arena); - return true; - } - - bool changeEveryTime(const Self & to, Arena * arena) - { - if (to.has()) - { - change(to, arena); - return true; - } - else - return false; - } - - bool changeIfLess(const IColumn & column, size_t row_num, Arena * arena) - { - if (!has()) - { - change(column, row_num, arena); - return true; - } - else - { - Field new_value; - column.get(row_num, new_value); - if (new_value < value) - { - value = new_value; - return true; - } - else - return false; - } - } - - bool changeIfLess(const Self & to, Arena * arena) - { - if (!to.has()) - return false; - if (!has() || to.value < value) - { - change(to, arena); - return true; - } - else - return false; - } - - bool changeIfGreater(const IColumn & column, size_t row_num, Arena * arena) - { - if (!has()) - { - change(column, row_num, arena); - return true; - } - else - { - Field new_value; - column.get(row_num, new_value); - if (new_value > value) - { - value = new_value; - return true; - } - else - return false; - } - } - - bool changeIfGreater(const Self & to, Arena * arena) - { - if (!to.has()) - return false; - if (!has() || to.value > value) - { - change(to, arena); - return true; - } - else - return false; - } - - bool isEqualTo(const IColumn & column, size_t row_num) const { return has() && value == column[row_num]; } - - bool isEqualTo(const Self & to) const { return has() && to.value == value; } - - static bool allocatesMemoryInArena() - { - return false; - } - -#if USE_EMBEDDED_COMPILER - - static constexpr bool is_compilable = false; - -#endif - -}; - - -/** What is the difference between the aggregate functions min, max, any, anyLast - * (the condition that the stored value is replaced by a new one, - * as well as, of course, the name). - */ - -template -struct AggregateFunctionMinData : Data -{ - using Self = AggregateFunctionMinData; - using Impl = Data; - - bool changeIfBetter(const IColumn & column, size_t row_num, Arena * arena) { return this->changeIfLess(column, row_num, arena); } - bool changeIfBetter(const Self & to, Arena * arena) { return this->changeIfLess(to, arena); } - void addManyDefaults(const IColumn & column, size_t /*length*/, Arena * arena) { this->changeIfLess(column, 0, arena); } - - static const char * name() { return "min"; } - -#if USE_EMBEDDED_COMPILER - - static constexpr bool is_compilable = Data::is_compilable; - - static void compileChangeIfBetter(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr, llvm::Value * value_to_check) - { - Data::compileChangeIfLess(builder, aggregate_data_ptr, value_to_check); - } - - static void compileChangeIfBetterMerge(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_dst_ptr, llvm::Value * aggregate_data_src_ptr) - { - Data::compileChangeIfLessMerge(builder, aggregate_data_dst_ptr, aggregate_data_src_ptr); - } - -#endif -}; - -template -struct AggregateFunctionMaxData : Data -{ - using Self = AggregateFunctionMaxData; - using Impl = Data; - - bool changeIfBetter(const IColumn & column, size_t row_num, Arena * arena) { return this->changeIfGreater(column, row_num, arena); } - bool changeIfBetter(const Self & to, Arena * arena) { return this->changeIfGreater(to, arena); } - void addManyDefaults(const IColumn & column, size_t /*length*/, Arena * arena) { this->changeIfGreater(column, 0, arena); } - - static const char * name() { return "max"; } - -#if USE_EMBEDDED_COMPILER - - static constexpr bool is_compilable = Data::is_compilable; - - static void compileChangeIfBetter(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr, llvm::Value * value_to_check) - { - Data::compileChangeIfGreater(builder, aggregate_data_ptr, value_to_check); - } - - static void compileChangeIfBetterMerge(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_dst_ptr, llvm::Value * aggregate_data_src_ptr) - { - Data::compileChangeIfGreaterMerge(builder, aggregate_data_dst_ptr, aggregate_data_src_ptr); - } - -#endif -}; - -template -struct AggregateFunctionAnyData : Data -{ - using Self = AggregateFunctionAnyData; - static constexpr bool is_any = true; - - bool changeIfBetter(const IColumn & column, size_t row_num, Arena * arena) { return this->changeFirstTime(column, row_num, arena); } - 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"; } - -#if USE_EMBEDDED_COMPILER - - static constexpr bool is_compilable = Data::is_compilable; - - static void compileChangeIfBetter(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr, llvm::Value * value_to_check) - { - Data::compileChangeFirstTime(builder, aggregate_data_ptr, value_to_check); - } - - static void compileChangeIfBetterMerge(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_dst_ptr, llvm::Value * aggregate_data_src_ptr) - { - Data::compileChangeFirstTimeMerge(builder, aggregate_data_dst_ptr, aggregate_data_src_ptr); - } - -#endif -}; - -template -struct AggregateFunctionAnyLastData : Data -{ - using Self = AggregateFunctionAnyLastData; - - bool changeIfBetter(const IColumn & column, size_t row_num, Arena * arena) { return this->changeEveryTime(column, row_num, arena); } - 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"; } - -#if USE_EMBEDDED_COMPILER - - static constexpr bool is_compilable = Data::is_compilable; - - static void compileChangeIfBetter(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr, llvm::Value * value_to_check) - { - Data::compileChangeEveryTime(builder, aggregate_data_ptr, value_to_check); - } - - static void compileChangeIfBetterMerge(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_dst_ptr, llvm::Value * aggregate_data_src_ptr) - { - Data::compileChangeEveryTimeMerge(builder, aggregate_data_dst_ptr, aggregate_data_src_ptr); - } - -#endif -}; - - -/** The aggregate function 'singleValueOrNull' is used to implement subquery operators, - * such as x = ALL (SELECT ...) - * It checks if there is only one unique non-NULL value in the data. - * If there is only one unique value - returns it. - * If there are zero or at least two distinct values - returns NULL. - */ -template -struct AggregateFunctionSingleValueOrNullData : Data -{ - using Self = AggregateFunctionSingleValueOrNullData; - - static constexpr bool result_is_nullable = true; - - bool first_value = true; - bool is_null = false; - - void changeIfBetter(const IColumn & column, size_t row_num, Arena * arena) - { - if (first_value) - { - first_value = false; - this->change(column, row_num, arena); - } - else if (!this->isEqualTo(column, row_num)) - { - is_null = true; - } - } - - void changeIfBetter(const Self & to, Arena * arena) - { - if (!to.has()) - return; - - if (first_value && !to.first_value) - { - first_value = false; - this->change(to, arena); - } - else if (!this->isEqualTo(to)) - { - is_null = true; - } - } - - void addManyDefaults(const IColumn & column, size_t /*length*/, Arena * arena) { this->changeIfBetter(column, 0, arena); } - - void insertResultInto(IColumn & to) const - { - if (is_null || first_value) - { - to.insertDefault(); - } - else - { - ColumnNullable & col = typeid_cast(to); - col.getNullMapColumn().insertDefault(); - this->Data::insertResultInto(col.getNestedColumn()); - } - } - - static const char * name() { return "singleValueOrNull"; } - -#if USE_EMBEDDED_COMPILER - - static constexpr bool is_compilable = false; - -#endif -}; - -/** Implement 'heavy hitters' algorithm. - * Selects most frequent value if its frequency is more than 50% in each thread of execution. - * Otherwise, selects some arbitrary value. - * http://www.cs.umd.edu/~samir/498/karp.pdf - */ -template -struct AggregateFunctionAnyHeavyData : Data -{ - UInt64 counter = 0; - - using Self = AggregateFunctionAnyHeavyData; - - bool changeIfBetter(const IColumn & column, size_t row_num, Arena * arena) - { - if (this->isEqualTo(column, row_num)) - { - ++counter; - } - else - { - if (counter == 0) - { - this->change(column, row_num, arena); - ++counter; - return true; - } - else - --counter; - } - return false; - } - - bool changeIfBetter(const Self & to, Arena * arena) - { - if (!to.has()) - return false; - - if (this->isEqualTo(to)) - { - counter += to.counter; - } - else - { - if ((!this->has() && to.has()) || counter < to.counter) - { - this->change(to, arena); - return true; - } - else - counter -= to.counter; - } - return false; - } - - void addManyDefaults(const IColumn & column, size_t length, Arena * arena) - { - for (size_t i = 0; i < length; ++i) - changeIfBetter(column, 0, arena); - } - - void write(WriteBuffer & buf, const ISerialization & serialization) const - { - Data::write(buf, serialization); - writeBinaryLittleEndian(counter, buf); - } - - void read(ReadBuffer & buf, const ISerialization & serialization, Arena * arena) - { - Data::read(buf, serialization, arena); - readBinaryLittleEndian(counter, buf); - } - - static const char * name() { return "anyHeavy"; } - -#if USE_EMBEDDED_COMPILER - - static constexpr bool is_compilable = false; - -#endif - -}; - - -template -class AggregateFunctionsSingleValue : public IAggregateFunctionDataHelper> -{ - static constexpr bool is_any = Data::is_any; - -private: - SerializationPtr serialization; - -public: - explicit AggregateFunctionsSingleValue(const DataTypePtr & type) - : IAggregateFunctionDataHelper>({type}, {}, createResultType(type)) - , serialization(type->getDefaultSerialization()) - { - if (StringRef(Data::name()) == StringRef("min") - || StringRef(Data::name()) == StringRef("max")) - { - if (!type->isComparable()) - throw Exception( - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, - "Illegal type {} of argument of aggregate function {} because the values of that data type are not comparable", - type->getName(), - Data::name()); - } - } - - String getName() const override { return Data::name(); } - - static DataTypePtr createResultType(const DataTypePtr & type_) - { - if constexpr (Data::result_is_nullable) - return makeNullable(type_); - return type_; - } - - void add(AggregateDataPtr __restrict place, const IColumn ** columns, size_t row_num, Arena * arena) const override - { - this->data(place).changeIfBetter(*columns[0], row_num, arena); - } - - void addManyDefaults( - AggregateDataPtr __restrict place, - const IColumn ** columns, - size_t length, - Arena * arena) const override - { - this->data(place).addManyDefaults(*columns[0], length, arena); - } - - void addBatchSinglePlace( - size_t row_begin, - size_t row_end, - AggregateDataPtr place, - const IColumn ** columns, - Arena * arena, - ssize_t if_argument_pos) const override - { - if constexpr (is_any) - if (this->data(place).has()) - return; - if (if_argument_pos >= 0) - { - const auto & flags = assert_cast(*columns[if_argument_pos]).getData(); - for (size_t i = row_begin; i < row_end; ++i) - { - if (flags[i]) - { - this->data(place).changeIfBetter(*columns[0], i, arena); - if constexpr (is_any) - break; - } - } - } - else - { - for (size_t i = row_begin; i < row_end; ++i) - { - this->data(place).changeIfBetter(*columns[0], i, arena); - if constexpr (is_any) - break; - } - } - } - - void addBatchSinglePlaceNotNull( /// NOLINT - size_t row_begin, - size_t row_end, - AggregateDataPtr place, - const IColumn ** columns, - const UInt8 * null_map, - Arena * arena, - ssize_t if_argument_pos = -1) const override - { - if constexpr (is_any) - if (this->data(place).has()) - return; - - if (if_argument_pos >= 0) - { - const auto & flags = assert_cast(*columns[if_argument_pos]).getData(); - for (size_t i = row_begin; i < row_end; ++i) - { - if (!null_map[i] && flags[i]) - { - this->data(place).changeIfBetter(*columns[0], i, arena); - if constexpr (is_any) - break; - } - } - } - else - { - for (size_t i = row_begin; i < row_end; ++i) - { - if (!null_map[i]) - { - this->data(place).changeIfBetter(*columns[0], i, arena); - if constexpr (is_any) - break; - } - } - } - } - - void merge(AggregateDataPtr __restrict place, ConstAggregateDataPtr rhs, Arena * arena) const override - { - this->data(place).changeIfBetter(this->data(rhs), arena); - } - - void serialize(ConstAggregateDataPtr __restrict place, WriteBuffer & buf, std::optional /* version */) const override - { - this->data(place).write(buf, *serialization); - } - - void deserialize(AggregateDataPtr place, ReadBuffer & buf, std::optional /* version */, Arena * arena) const override - { - this->data(place).read(buf, *serialization, arena); - } - - bool allocatesMemoryInArena() const override - { - return Data::allocatesMemoryInArena(); - } - - void insertResultInto(AggregateDataPtr __restrict place, IColumn & to, Arena *) const override - { - this->data(place).insertResultInto(to); - } - - AggregateFunctionPtr getOwnNullAdapter( - const AggregateFunctionPtr & original_function, - const DataTypes & /*arguments*/, - const Array & /*params*/, - const AggregateFunctionProperties & /*properties*/) const override - { - if (Data::result_is_nullable && !Data::should_skip_null_arguments) - return original_function; - return nullptr; - } - -#if USE_EMBEDDED_COMPILER - - bool isCompilable() const override - { - if constexpr (!Data::is_compilable) - return false; - - return canBeNativeType(*this->argument_types[0]); - } - - - void compileCreate(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr) const override - { - llvm::IRBuilder<> & b = static_cast &>(builder); - - b.CreateMemSet(aggregate_data_ptr, llvm::ConstantInt::get(b.getInt8Ty(), 0), this->sizeOfData(), llvm::assumeAligned(this->alignOfData())); - } - - void compileAdd(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr, const ValuesWithType & arguments) const override - { - if constexpr (Data::is_compilable) - { - Data::compileChangeIfBetter(builder, aggregate_data_ptr, arguments[0].value); - } - else - { - throw Exception(ErrorCodes::NOT_IMPLEMENTED, "{} is not JIT-compilable", getName()); - } - } - - void compileMerge(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_dst_ptr, llvm::Value * aggregate_data_src_ptr) const override - { - if constexpr (Data::is_compilable) - { - Data::compileChangeIfBetterMerge(builder, aggregate_data_dst_ptr, aggregate_data_src_ptr); - } - else - { - throw Exception(ErrorCodes::NOT_IMPLEMENTED, "{} is not JIT-compilable", getName()); - } - } - - llvm::Value * compileGetResult(llvm::IRBuilderBase & builder, llvm::Value * aggregate_data_ptr) const override - { - if constexpr (Data::is_compilable) - { - return Data::compileGetResult(builder, aggregate_data_ptr); - } - else - { - throw Exception(ErrorCodes::NOT_IMPLEMENTED, "{} is not JIT-compilable", getName()); - } - } - -#endif -}; - -} diff --git a/src/AggregateFunctions/AggregateFunctionSingleValueOrNull.cpp b/src/AggregateFunctions/AggregateFunctionSingleValueOrNull.cpp index cd897dfcf6e..71ab5c59820 100644 --- a/src/AggregateFunctions/AggregateFunctionSingleValueOrNull.cpp +++ b/src/AggregateFunctions/AggregateFunctionSingleValueOrNull.cpp @@ -8,19 +8,19 @@ namespace DB { struct Settings; -namespace +//namespace +//{ +// +//AggregateFunctionPtr createAggregateFunctionSingleValueOrNull(const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) +//{ +// return AggregateFunctionPtr(createAggregateFunctionSingleValue(name, argument_types, parameters, settings)); +//} +// +//} +// +void registerAggregateFunctionSingleValueOrNull(AggregateFunctionFactory &) { - -AggregateFunctionPtr createAggregateFunctionSingleValueOrNull(const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) -{ - return AggregateFunctionPtr(createAggregateFunctionSingleValue(name, argument_types, parameters, settings)); -} - -} - -void registerAggregateFunctionSingleValueOrNull(AggregateFunctionFactory & factory) -{ - factory.registerFunction("singleValueOrNull", createAggregateFunctionSingleValueOrNull); + // factory.registerFunction("singleValueOrNull", createAggregateFunctionSingleValueOrNull); } diff --git a/src/AggregateFunctions/Combinators/AggregateFunctionArgMinMax.cpp b/src/AggregateFunctions/Combinators/AggregateFunctionArgMinMax.cpp index 38e19a0b8da..946b4a07a9a 100644 --- a/src/AggregateFunctions/Combinators/AggregateFunctionArgMinMax.cpp +++ b/src/AggregateFunctions/Combinators/AggregateFunctionArgMinMax.cpp @@ -1,7 +1,7 @@ #include "AggregateFunctionArgMinMax.h" #include "AggregateFunctionCombinatorFactory.h" -#include +#include #include #include #include @@ -13,81 +13,81 @@ namespace ErrorCodes { extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH; } - -namespace +// +//namespace +//{ +//template