#pragma once #include #include #include #include #include #include #include #include #define AGGREGATE_FUNCTION_GROUP_ARRAY_UNIQ_MAX_SIZE 0xFFFFFF namespace DB { template struct AggregateFunctionGroupUniqArrayData { /// При создании, хэш-таблица должна быть небольшой. using Set = HashSet< T, DefaultHash, HashTableGrower<4>, HashTableAllocatorWithStackMemory >; Set value; }; /// Складывает все значения в хэш-множество. Возвращает массив уникальных значений. Реализована для числовых типов. template class AggregateFunctionGroupUniqArray : public IUnaryAggregateFunction, AggregateFunctionGroupUniqArray> { private: using State = AggregateFunctionGroupUniqArrayData; public: String getName() const override { return "groupUniqArray"; } DataTypePtr getReturnType() const override { return std::make_shared(std::make_shared::Type>()); } void setArgument(const DataTypePtr & argument) { } void addImpl(AggregateDataPtr place, const IColumn & column, size_t row_num, Arena *) const { this->data(place).value.insert(static_cast &>(column).getData()[row_num]); } void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs) const override { this->data(place).value.merge(this->data(rhs).value); } void serialize(ConstAggregateDataPtr place, WriteBuffer & buf) const override { const typename State::Set & set = this->data(place).value; size_t size = set.size(); writeVarUInt(size, buf); for (auto it = set.begin(); it != set.end(); ++it) writeIntBinary(*it, buf); } void deserialize(AggregateDataPtr place, ReadBuffer & buf) const override { this->data(place).value.read(buf); } void insertResultInto(ConstAggregateDataPtr place, IColumn & to) const override { ColumnArray & arr_to = static_cast(to); ColumnArray::Offsets_t & offsets_to = arr_to.getOffsets(); const typename State::Set & set = this->data(place).value; size_t size = set.size(); offsets_to.push_back((offsets_to.size() == 0 ? 0 : offsets_to.back()) + size); typename ColumnVector::Container_t & data_to = static_cast &>(arr_to.getData()).getData(); size_t old_size = data_to.size(); data_to.resize(old_size + size); size_t i = 0; for (auto it = set.begin(); it != set.end(); ++it, ++i) data_to[old_size + i] = *it; } }; #undef AGGREGATE_FUNCTION_GROUP_ARRAY_UNIQ_MAX_SIZE }