#pragma once #include #include #include #include #include #include #include #include #include #include namespace DB { class IColumn; /// For the case where there is one numeric key. /// FieldType is UInt8/16/32/64 for any type with corresponding bit width. template struct AggregationMethodOneNumber { using Data = TData; using Key = typename Data::key_type; using Mapped = typename Data::mapped_type; Data data; AggregationMethodOneNumber() = default; explicit AggregationMethodOneNumber(size_t size_hint) : data(size_hint) { } template explicit AggregationMethodOneNumber(const Other & other) : data(other.data) { } /// To use one `Method` in different threads, use different `State`. template using StateImpl = ColumnsHashing::HashMethodOneNumber< typename Data::value_type, Mapped, FieldType, use_cache && consecutive_keys_optimization, /*need_offset=*/ false, nullable>; using State = StateImpl; using StateNoCache = StateImpl; /// Use optimization for low cardinality. static const bool low_cardinality_optimization = false; static const bool one_key_nullable_optimization = nullable; /// Shuffle key columns before `insertKeyIntoColumns` call if needed. std::optional shuffleKeyColumns(std::vector &, const Sizes &) { return {}; } // Insert the key from the hash table into columns. static void insertKeyIntoColumns(const Key & key, std::vector & key_columns, const Sizes & /*key_sizes*/); }; /// For the case where there is one string key. template struct AggregationMethodString { using Data = TData; using Key = typename Data::key_type; using Mapped = typename Data::mapped_type; Data data; AggregationMethodString() = default; template explicit AggregationMethodString(const Other & other) : data(other.data) { } explicit AggregationMethodString(size_t size_hint) : data(size_hint) { } template using StateImpl = ColumnsHashing::HashMethodString; using State = StateImpl; using StateNoCache = StateImpl; static const bool low_cardinality_optimization = false; static const bool one_key_nullable_optimization = false; std::optional shuffleKeyColumns(std::vector &, const Sizes &) { return {}; } static void insertKeyIntoColumns(StringRef key, std::vector & key_columns, const Sizes &) { static_cast(key_columns[0])->insertData(key.data, key.size); } }; /// Same as above but without cache template struct AggregationMethodStringNoCache { using Data = TData; using Key = typename Data::key_type; using Mapped = typename Data::mapped_type; Data data; AggregationMethodStringNoCache() = default; explicit AggregationMethodStringNoCache(size_t size_hint) : data(size_hint) { } template explicit AggregationMethodStringNoCache(const Other & other) : data(other.data) { } template using StateImpl = ColumnsHashing::HashMethodString; using State = StateImpl; using StateNoCache = StateImpl; static const bool low_cardinality_optimization = false; static const bool one_key_nullable_optimization = nullable; std::optional shuffleKeyColumns(std::vector &, const Sizes &) { return {}; } static void insertKeyIntoColumns(StringRef key, std::vector & key_columns, const Sizes &); }; /// For the case where there is one fixed-length string key. template struct AggregationMethodFixedString { using Data = TData; using Key = typename Data::key_type; using Mapped = typename Data::mapped_type; Data data; AggregationMethodFixedString() = default; explicit AggregationMethodFixedString(size_t size_hint) : data(size_hint) { } template explicit AggregationMethodFixedString(const Other & other) : data(other.data) { } template using StateImpl = ColumnsHashing::HashMethodFixedString; using State = StateImpl; using StateNoCache = StateImpl; static const bool low_cardinality_optimization = false; static const bool one_key_nullable_optimization = false; std::optional shuffleKeyColumns(std::vector &, const Sizes &) { return {}; } static void insertKeyIntoColumns(StringRef key, std::vector & key_columns, const Sizes &); }; /// Same as above but without cache template struct AggregationMethodFixedStringNoCache { using Data = TData; using Key = typename Data::key_type; using Mapped = typename Data::mapped_type; Data data; AggregationMethodFixedStringNoCache() = default; explicit AggregationMethodFixedStringNoCache(size_t size_hint) : data(size_hint) { } template explicit AggregationMethodFixedStringNoCache(const Other & other) : data(other.data) { } template using StateImpl = ColumnsHashing::HashMethodFixedString; using State = StateImpl; using StateNoCache = StateImpl; static const bool low_cardinality_optimization = false; static const bool one_key_nullable_optimization = nullable; std::optional shuffleKeyColumns(std::vector &, const Sizes &) { return {}; } static void insertKeyIntoColumns(StringRef key, std::vector & key_columns, const Sizes &); }; /// Single low cardinality column. template struct AggregationMethodSingleLowCardinalityColumn : public SingleColumnMethod { using Base = SingleColumnMethod; using Data = typename Base::Data; using Key = typename Base::Key; using Mapped = typename Base::Mapped; using Base::data; template using BaseStateImpl = typename Base::template StateImpl; AggregationMethodSingleLowCardinalityColumn() = default; template explicit AggregationMethodSingleLowCardinalityColumn(const Other & other) : Base(other) {} template using StateImpl = ColumnsHashing::HashMethodSingleLowCardinalityColumn, Mapped, use_cache>; using State = StateImpl; using StateNoCache = StateImpl; static const bool low_cardinality_optimization = true; std::optional shuffleKeyColumns(std::vector &, const Sizes &) { return {}; } static void insertKeyIntoColumns(const Key & key, std::vector & key_columns_low_cardinality, const Sizes & /*key_sizes*/); }; /// For the case where all keys are of fixed length, and they fit in N (for example, 128) bits. template struct AggregationMethodKeysFixed { using Data = TData; using Key = typename Data::key_type; using Mapped = typename Data::mapped_type; static constexpr bool has_nullable_keys = has_nullable_keys_; static constexpr bool has_low_cardinality = has_low_cardinality_; Data data; AggregationMethodKeysFixed() = default; explicit AggregationMethodKeysFixed(size_t size_hint) : data(size_hint) { } template explicit AggregationMethodKeysFixed(const Other & other) : data(other.data) { } template using StateImpl = ColumnsHashing::HashMethodKeysFixed< typename Data::value_type, Key, Mapped, has_nullable_keys, has_low_cardinality, use_cache && consecutive_keys_optimization>; using State = StateImpl; using StateNoCache = StateImpl; static const bool low_cardinality_optimization = false; static const bool one_key_nullable_optimization = false; std::optional shuffleKeyColumns(std::vector & key_columns, const Sizes & key_sizes) { return State::shuffleKeyColumns(key_columns, key_sizes); } static void insertKeyIntoColumns(const Key & key, std::vector & key_columns, const Sizes & key_sizes); }; /** Aggregates by concatenating serialized key values. * The serialized value differs in that it uniquely allows to deserialize it, having only the position with which it starts. * That is, for example, for strings, it contains first the serialized length of the string, and then the bytes. * Therefore, when aggregating by several strings, there is no ambiguity. */ template struct AggregationMethodSerialized { using Data = TData; using Key = typename Data::key_type; using Mapped = typename Data::mapped_type; Data data; AggregationMethodSerialized() = default; explicit AggregationMethodSerialized(size_t size_hint) : data(size_hint) { } template explicit AggregationMethodSerialized(const Other & other) : data(other.data) { } template using StateImpl = ColumnsHashing::HashMethodSerialized; using State = StateImpl; using StateNoCache = StateImpl; static const bool low_cardinality_optimization = false; static const bool one_key_nullable_optimization = false; std::optional shuffleKeyColumns(std::vector &, const Sizes &) { return {}; } static void insertKeyIntoColumns(StringRef key, std::vector & key_columns, const Sizes &); }; template using AggregationMethodNullableSerialized = AggregationMethodSerialized; template using AggregationMethodPreallocSerialized = AggregationMethodSerialized; template using AggregationMethodNullablePreallocSerialized = AggregationMethodSerialized; }