#pragma once #include #include #include #include #include #include #include namespace DB { struct AggregateDescription { AggregateFunctionPtr function; ColumnNumbers arguments; Names argument_names; /// Используются, если arguments не заданы. String column_name; /// Какое имя использовать для столбца со значениями агрегатной функции }; typedef std::vector AggregateDescriptions; /// Для агрегации по md5. struct UInt128 { UInt64 first; UInt64 second; bool operator== (const UInt128 rhs) const { return first == rhs.first && second == rhs.second; } }; struct UInt128Hash { size_t operator()(UInt128 x) const { return x.first ^ x.second; } }; /// Немного быстрее стандартного struct StringHash { size_t operator()(const String & x) const { return CityHash64(x.data(), x.size()); } }; /// Разные структуры данных, которые могут использоваться для агрегации typedef std::map AggregatedData; typedef AggregateFunctions AggregatedDataWithoutKey; typedef std::tr1::unordered_map AggregatedDataWithUInt64Key; typedef std::tr1::unordered_map AggregatedDataWithStringKey; typedef std::tr1::unordered_map, UInt128Hash> AggregatedDataHashed; struct AggregatedDataVariants { /// Наиболее общий вариант. Самый медленный. На данный момент, не используется. AggregatedData generic; /// Специализация для случая, когда ключи отсутствуют. AggregatedDataWithoutKey without_key; /// Специализация для случая, когда есть один числовой ключ (не с плавающей запятой). AggregatedDataWithUInt64Key key64; /// Специализация для случая, когда есть один строковый ключ. AggregatedDataWithStringKey key_string; /** Агрегирует по 128 битному хэшу от ключа. * Если все ключи фиксированной длины, влезающие целиком в 128 бит, то укладывает их без изменений в 128 бит. * Иначе - вычисляет md5 от набора из всех ключей. */ AggregatedDataHashed hashed; }; /** Агрегирует поток блоков. */ class Aggregator { public: Aggregator(const ColumnNumbers & keys_, AggregateDescriptions & aggregates_) : keys(keys_), aggregates(aggregates_) {}; Aggregator(const Names & key_names_, AggregateDescriptions & aggregates_) : key_names(key_names_), aggregates(aggregates_) {}; void execute(BlockInputStreamPtr stream, AggregatedDataVariants & result); /// Получить пример блока, описывающего результат. Следует вызывать только после execute. Block getSampleBlock() { return sample; } private: ColumnNumbers keys; Names key_names; AggregateDescriptions aggregates; Block sample; }; }