diff --git a/src/AggregateFunctions/AggregateFunctionAny.cpp b/src/AggregateFunctions/AggregateFunctionAny.cpp index d210c85768b..f727ab04aa9 100644 --- a/src/AggregateFunctions/AggregateFunctionAny.cpp +++ b/src/AggregateFunctions/AggregateFunctionAny.cpp @@ -24,8 +24,9 @@ private: SerializationPtr serialization; public: - explicit AggregateFunctionAny(const DataTypePtr & type) - : IAggregateFunctionDataHelper>({type}, {}, type), serialization(type->getDefaultSerialization()) + explicit AggregateFunctionAny(const DataTypes & argument_types_) + : IAggregateFunctionDataHelper>(argument_types_, {}, argument_types_[0]) + , serialization(this->result_type->getDefaultSerialization()) { } @@ -179,7 +180,8 @@ public: AggregateFunctionPtr createAggregateFunctionAny(const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) { - return AggregateFunctionPtr(createAggregateFunctionSingleValue(name, argument_types, parameters, settings)); + return AggregateFunctionPtr( + createAggregateFunctionSingleValue(name, argument_types, parameters, settings)); } @@ -190,9 +192,9 @@ private: SerializationPtr serialization; public: - explicit AggregateFunctionAnyLast(const DataTypePtr & type) - : IAggregateFunctionDataHelper>({type}, {}, type) - , serialization(type->getDefaultSerialization()) + explicit AggregateFunctionAnyLast(const DataTypes & argument_types_) + : IAggregateFunctionDataHelper>(argument_types_, {}, argument_types_[0]) + , serialization(this->result_type->getDefaultSerialization()) { } @@ -348,7 +350,8 @@ public: AggregateFunctionPtr createAggregateFunctionAnyLast( const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) { - return AggregateFunctionPtr(createAggregateFunctionSingleValue(name, argument_types, parameters, settings)); + return AggregateFunctionPtr( + createAggregateFunctionSingleValue(name, argument_types, parameters, settings)); } } diff --git a/src/AggregateFunctions/AggregateFunctionAnyHeavy.cpp b/src/AggregateFunctions/AggregateFunctionAnyHeavy.cpp index 4f270085ec8..4f4d4a19cba 100644 --- a/src/AggregateFunctions/AggregateFunctionAnyHeavy.cpp +++ b/src/AggregateFunctions/AggregateFunctionAnyHeavy.cpp @@ -27,7 +27,7 @@ struct AggregateFunctionAnyHeavyData using Self = AggregateFunctionAnyHeavyData; private: - SingleValueDataBase::memory_block v_data; + SingleValueDataBaseMemoryBlock v_data; UInt64 counter = 0; public: diff --git a/src/AggregateFunctions/AggregateFunctionSingleValueOrNull.cpp b/src/AggregateFunctions/AggregateFunctionSingleValueOrNull.cpp index 0608df0a476..b14af34c5fc 100644 --- a/src/AggregateFunctions/AggregateFunctionSingleValueOrNull.cpp +++ b/src/AggregateFunctions/AggregateFunctionSingleValueOrNull.cpp @@ -28,7 +28,7 @@ struct AggregateFunctionSingleValueOrNullData using Self = AggregateFunctionSingleValueOrNullData; private: - SingleValueDataBase::memory_block v_data; + SingleValueDataBaseMemoryBlock v_data; bool first_value = true; bool is_null = false; diff --git a/src/AggregateFunctions/AggregateFunctionsArgMinArgMax.cpp b/src/AggregateFunctions/AggregateFunctionsArgMinArgMax.cpp index a8d8433ff87..f287ec557fd 100644 --- a/src/AggregateFunctions/AggregateFunctionsArgMinArgMax.cpp +++ b/src/AggregateFunctions/AggregateFunctionsArgMinArgMax.cpp @@ -22,63 +22,56 @@ extern const int LOGICAL_ERROR; namespace { +template struct AggregateFunctionArgMinMaxData { private: - SingleValueDataBase::memory_block r_data; - SingleValueDataBase::memory_block v_data; + SingleValueDataBaseMemoryBlock result_data; + ValueType value_data; public: - SingleValueDataBase & result() { return r_data.get(); } - const SingleValueDataBase & result() const { return r_data.get(); } - SingleValueDataBase & value() { return v_data.get(); } - const SingleValueDataBase & value() const { return v_data.get(); } + SingleValueDataBase & result() { return result_data.get(); } + const SingleValueDataBase & result() const { return result_data.get(); } + ValueType & value() { return value_data; } + const ValueType & value() const { return value_data; } [[noreturn]] explicit AggregateFunctionArgMinMaxData() { throw Exception(ErrorCodes::LOGICAL_ERROR, "AggregateFunctionArgMinMaxData initialized empty"); } - explicit AggregateFunctionArgMinMaxData(TypeIndex result_type, TypeIndex value_type) + explicit AggregateFunctionArgMinMaxData(TypeIndex result_type) : value_data() { - generateSingleValueFromTypeIndex(result_type, r_data); - generateSingleValueFromTypeIndex(value_type, v_data); + generateSingleValueFromTypeIndex(result_type, result_data); } - ~AggregateFunctionArgMinMaxData() - { - result().~SingleValueDataBase(); - value().~SingleValueDataBase(); - } + ~AggregateFunctionArgMinMaxData() { result().~SingleValueDataBase(); } }; static_assert( - sizeof(AggregateFunctionArgMinMaxData) == 2 * SingleValueDataBase::MAX_STORAGE_SIZE, + sizeof(AggregateFunctionArgMinMaxData) <= 2 * SingleValueDataBase::MAX_STORAGE_SIZE, "Incorrect size of AggregateFunctionArgMinMaxData struct"); /// Returns the first arg value found for the minimum/maximum value. Example: argMin(arg, value). -template +template class AggregateFunctionArgMinMax final - : public IAggregateFunctionDataHelper> + : public IAggregateFunctionDataHelper, AggregateFunctionArgMinMax> { private: const DataTypePtr & type_val; const SerializationPtr serialization_res; const SerializationPtr serialization_val; - const TypeIndex result_type_index; - const TypeIndex value_type_index; - using Base = IAggregateFunctionDataHelper>; + using Base = IAggregateFunctionDataHelper, AggregateFunctionArgMinMax>; public: - AggregateFunctionArgMinMax(const DataTypePtr & type_res_, const DataTypePtr & type_val_) - : Base({type_res_, type_val_}, {}, type_res_) + AggregateFunctionArgMinMax(const DataTypes & argument_types_) + : Base(argument_types_, {}, argument_types_[0]) , type_val(this->argument_types[1]) - , serialization_res(type_res_->getDefaultSerialization()) - , serialization_val(type_val->getDefaultSerialization()) - , result_type_index(WhichDataType(type_res_).idx) - , value_type_index(WhichDataType(type_val_).idx) + , serialization_res(this->argument_types[0]->getDefaultSerialization()) + , serialization_val(this->argument_types[1]->getDefaultSerialization()) + , result_type_index(WhichDataType(this->argument_types[0]).idx) { if (!type_val->isComparable()) throw Exception( @@ -90,7 +83,7 @@ public: void create(AggregateDataPtr __restrict place) const override /// NOLINT { - new (place) AggregateFunctionArgMinMaxData(result_type_index, value_type_index); + new (place) AggregateFunctionArgMinMaxData(result_type_index); } String getName() const override @@ -214,7 +207,7 @@ public: bool allocatesMemoryInArena() const override { - return singleValueTypeAllocatesMemoryInArena(result_type_index) || singleValueTypeAllocatesMemoryInArena(value_type_index); + return singleValueTypeAllocatesMemoryInArena(result_type_index) || ValueData::allocatesMemoryInArena(); } void insertResultInto(AggregateDataPtr __restrict place, IColumn & to, Arena *) const override @@ -224,16 +217,11 @@ public: }; template -AggregateFunctionPtr -createAggregateFunctionArgMinMax(const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings *) +AggregateFunctionPtr createAggregateFunctionArgMinMax( + const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) { - assertNoParameters(name, parameters); - assertBinary(name, argument_types); - - const DataTypePtr & res_type = argument_types[0]; - const DataTypePtr & val_type = argument_types[1]; - - return AggregateFunctionPtr(new AggregateFunctionArgMinMax(res_type, val_type)); + return AggregateFunctionPtr(createAggregateFunctionSingleValue( + name, argument_types, parameters, settings)); } } diff --git a/src/AggregateFunctions/AggregateFunctionsMinMax.cpp b/src/AggregateFunctions/AggregateFunctionsMinMax.cpp index 6d094b7f980..03e21c15a75 100644 --- a/src/AggregateFunctions/AggregateFunctionsMinMax.cpp +++ b/src/AggregateFunctions/AggregateFunctionsMinMax.cpp @@ -25,15 +25,15 @@ private: SerializationPtr serialization; public: - explicit AggregateFunctionMinMax(const DataTypePtr & type) - : IAggregateFunctionDataHelper>({type}, {}, type) - , serialization(type->getDefaultSerialization()) + explicit AggregateFunctionMinMax(const DataTypes & argument_types_) + : IAggregateFunctionDataHelper>(argument_types_, {}, argument_types_[0]) + , serialization(this->result_type->getDefaultSerialization()) { - if (!type->isComparable()) + if (!this->result_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(), + this->result_type->getName(), getName()); } @@ -189,7 +189,7 @@ AggregateFunctionPtr createAggregateFunctionMinMax( const std::string & name, const DataTypes & argument_types, const Array & parameters, const Settings * settings) { return AggregateFunctionPtr( - createAggregateFunctionSingleValue(name, argument_types, parameters, settings)); + createAggregateFunctionSingleValue(name, argument_types, parameters, settings)); } } diff --git a/src/AggregateFunctions/Combinators/AggregateFunctionCombinatorsArgMinArgMax.cpp b/src/AggregateFunctions/Combinators/AggregateFunctionCombinatorsArgMinArgMax.cpp index 6f579872278..71c2bab6f6b 100644 --- a/src/AggregateFunctions/Combinators/AggregateFunctionCombinatorsArgMinArgMax.cpp +++ b/src/AggregateFunctions/Combinators/AggregateFunctionCombinatorsArgMinArgMax.cpp @@ -16,7 +16,7 @@ namespace struct AggregateFunctionCombinatorArgMinArgMaxData { private: - SingleValueDataBase::memory_block v_data; + SingleValueDataBaseMemoryBlock v_data; public: explicit AggregateFunctionCombinatorArgMinArgMaxData(TypeIndex value_type) { generateSingleValueFromTypeIndex(value_type, v_data); } @@ -93,7 +93,7 @@ public: size_t sizeOfData() const override { return key_offset + sizeof(Key); } - size_t alignOfData() const override { return std::max(nested_function->alignOfData(), alignof(SingleValueDataBase::memory_block)); } + size_t alignOfData() const override { return std::max(nested_function->alignOfData(), alignof(SingleValueDataBaseMemoryBlock)); } void create(AggregateDataPtr __restrict place) const override { diff --git a/src/AggregateFunctions/SingleValueData.cpp b/src/AggregateFunctions/SingleValueData.cpp index 3eb9571b370..066d0dec306 100644 --- a/src/AggregateFunctions/SingleValueData.cpp +++ b/src/AggregateFunctions/SingleValueData.cpp @@ -1380,13 +1380,14 @@ bool SingleValueDataGeneric::setIfGreater(const SingleValueDataBase & other, Are return false; } -void generateSingleValueFromTypeIndex(TypeIndex idx, SingleValueDataBase::memory_block & data) +void generateSingleValueFromTypeIndex(TypeIndex idx, SingleValueDataBaseMemoryBlock & data) { #define DISPATCH(TYPE) \ if (idx == TypeIndex::TYPE) \ { \ - static_assert(sizeof(SingleValueDataNumeric) <= SingleValueDataBase::MAX_STORAGE_SIZE); \ - new (data.memory) SingleValueDataNumeric; \ + static_assert(sizeof(SingleValueDataNumeric) <= sizeof(SingleValueDataBaseMemoryBlock::memory)); \ + static_assert(alignof(SingleValueDataNumeric) <= alignof(SingleValueDataBaseMemoryBlock)); \ + new (&data.memory) SingleValueDataNumeric; \ return; \ } @@ -1395,24 +1396,28 @@ void generateSingleValueFromTypeIndex(TypeIndex idx, SingleValueDataBase::memory if (idx == TypeIndex::Date) { - static_assert(sizeof(SingleValueDataFixed) <= SingleValueDataBase::MAX_STORAGE_SIZE); - new (data.memory) SingleValueDataNumeric; + static_assert(sizeof(SingleValueDataNumeric) <= sizeof(SingleValueDataBaseMemoryBlock::memory)); + static_assert(alignof(SingleValueDataNumeric) <= alignof(SingleValueDataBaseMemoryBlock)); + new (&data.memory) SingleValueDataNumeric; return; } if (idx == TypeIndex::DateTime) { - static_assert(sizeof(SingleValueDataFixed) <= SingleValueDataBase::MAX_STORAGE_SIZE); - new (data.memory) SingleValueDataNumeric; + static_assert(sizeof(SingleValueDataNumeric) <= sizeof(SingleValueDataBaseMemoryBlock::memory)); + static_assert(alignof(SingleValueDataNumeric) <= alignof(SingleValueDataBaseMemoryBlock)); + new (&data.memory) SingleValueDataNumeric; return; } if (idx == TypeIndex::String) { - static_assert(sizeof(SingleValueDataString) <= SingleValueDataBase::MAX_STORAGE_SIZE); - new (data.memory) SingleValueDataString; + static_assert(sizeof(SingleValueDataString) <= sizeof(SingleValueDataBaseMemoryBlock::memory)); + static_assert(alignof(SingleValueDataString) <= alignof(SingleValueDataBaseMemoryBlock)); + new (&data.memory) SingleValueDataString; return; } - static_assert(sizeof(SingleValueDataGeneric) <= SingleValueDataBase::MAX_STORAGE_SIZE); - new (data.memory) SingleValueDataGeneric; + static_assert(sizeof(SingleValueDataGeneric) <= sizeof(SingleValueDataBaseMemoryBlock::memory)); + static_assert(alignof(SingleValueDataGeneric) <= alignof(SingleValueDataBaseMemoryBlock)); + new (&data.memory) SingleValueDataGeneric; } bool singleValueTypeAllocatesMemoryInArena(TypeIndex idx) diff --git a/src/AggregateFunctions/SingleValueData.h b/src/AggregateFunctions/SingleValueData.h index 923c986923c..d2ed55d6ff3 100644 --- a/src/AggregateFunctions/SingleValueData.h +++ b/src/AggregateFunctions/SingleValueData.h @@ -21,19 +21,9 @@ struct SingleValueDataBase static constexpr int nan_direction_hint = 1; /// Any subclass (numeric, string, generic) must be smaller than MAX_STORAGE_SIZE /// We use this knowledge to create composite data classes that use them directly by reserving a 'memory_block' - /// For example argMin holds 2 of these objects + /// For example argMin holds 1 of these (for the result), while keeping a template for the value static constexpr UInt32 MAX_STORAGE_SIZE = 64; - /// Helper to allocate enough memory to store any derived class and subclasses will be misaligned - /// alignas is necessary as otherwise alignof(memory_block) == 1 - struct alignas(MAX_STORAGE_SIZE) memory_block - { - char memory[SingleValueDataBase::MAX_STORAGE_SIZE]; - SingleValueDataBase & get() { return *reinterpret_cast(memory); } - const SingleValueDataBase & get() const { return *reinterpret_cast(memory); } - }; - static_assert(alignof(memory_block) == SingleValueDataBase::MAX_STORAGE_SIZE); - virtual ~SingleValueDataBase() { } virtual bool has() const = 0; virtual void insertResultInto(IColumn &) const = 0; @@ -353,37 +343,52 @@ public: static_assert(sizeof(SingleValueDataGeneric) <= SingleValueDataBase::MAX_STORAGE_SIZE, "Incorrect size of SingleValueDataGeneric struct"); /// min, max, any, anyLast, anyHeavy, etc... -template