ClickHouse/dbms/include/DB/AggregateFunctions/IAggregateFunction.h

153 lines
6.9 KiB
C++
Raw Normal View History

2011-09-19 03:40:05 +00:00
#pragma once
2011-12-19 08:06:31 +00:00
#include <memory>
2011-09-19 03:40:05 +00:00
#include <DB/Core/Row.h>
#include <DB/DataTypes/IDataType.h>
#include <DB/Common/typeid_cast.h>
2011-09-19 03:40:05 +00:00
namespace DB
{
namespace ErrorCodes
{
extern const int AGGREGATE_FUNCTION_DOESNT_ALLOW_PARAMETERS;
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
2016-01-12 02:21:15 +00:00
extern const int ILLEGAL_TYPE_OF_ARGUMENT;
extern const int ARGUMENT_OUT_OF_BOUND;
}
using AggregateDataPtr = char *;
using ConstAggregateDataPtr = const char *;
2011-09-19 03:40:05 +00:00
/** Интерфейс для агрегатных функций.
* Экземпляры классов с этим интерфейсом не содержат самих данных для агрегации,
* а содержат лишь метаданные (описание) агрегатной функции,
* а также методы для создания, удаления и работы с данными.
* Данные, получающиеся во время агрегации (промежуточные состояния вычислений), хранятся в других объектах
* (которые могут быть созданы в каком-нибудь пуле),
* а IAggregateFunction - внешний интерфейс для манипулирования ими.
2011-09-19 03:40:05 +00:00
*/
class IAggregateFunction
{
public:
/// Получить основное имя функции.
virtual String getName() const = 0;
/** Указать типы аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
* Необходимо вызывать перед остальными вызовами.
*/
virtual void setArguments(const DataTypes & arguments) = 0;
/** Указать параметры - для параметрических агрегатных функций.
* Если параметры не предусмотрены или переданные параметры недопустимы - кинуть исключение.
* Если параметры есть - необходимо вызывать перед остальными вызовами, иначе - не вызывать.
*/
virtual void setParameters(const Array & params)
{
throw Exception("Aggregate function " + getName() + " doesn't allow parameters.",
ErrorCodes::AGGREGATE_FUNCTION_DOESNT_ALLOW_PARAMETERS);
}
2011-09-19 03:40:05 +00:00
/// Получить тип результата.
virtual DataTypePtr getReturnType() const = 0;
virtual ~IAggregateFunction() {};
/** Функции по работе с данными. */
/** Создать пустые данные для агрегации с помощью placement new в заданном месте.
* Вы должны будете уничтожить их с помощью метода destroy.
*/
virtual void create(AggregateDataPtr place) const = 0;
/// Уничтожить данные для агрегации.
2014-05-23 00:35:14 +00:00
virtual void destroy(AggregateDataPtr place) const noexcept = 0;
/// Уничтожать данные не обязательно.
virtual bool hasTrivialDestructor() const = 0;
/// Получить sizeof структуры с данными.
virtual size_t sizeOfData() const = 0;
2013-02-09 02:20:26 +00:00
/// Как должна быть выровнена структура с данными. NOTE: Сейчас не используется (структуры с состоянием агрегации кладутся без выравнивания).
virtual size_t alignOfData() const = 0;
/// Добавить значение. columns - столбцы, содержащие аргументы, row_num - номер строки в столбцах.
virtual void add(AggregateDataPtr place, const IColumn ** columns, size_t row_num) const = 0;
2011-09-19 03:40:05 +00:00
/// Объединить состояние с другим состоянием.
virtual void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs) const = 0;
2011-09-19 03:40:05 +00:00
2014-06-03 20:29:04 +00:00
/// Сериализовать состояние (например, для передачи по сети).
virtual void serialize(ConstAggregateDataPtr place, WriteBuffer & buf) const = 0;
2011-09-19 03:40:05 +00:00
2016-03-12 04:01:03 +00:00
/// Десериализовать состояние. Вызывается для пустого (только что созданного) состояния.
virtual void deserialize(AggregateDataPtr place, ReadBuffer & buf) const = 0;
2011-09-19 03:40:05 +00:00
/// Вставить результат в столбец.
virtual void insertResultInto(ConstAggregateDataPtr place, IColumn & to) const = 0;
2014-05-21 13:27:40 +00:00
2014-06-03 20:29:04 +00:00
/** Возвращает true для агрегатных функций типа -State.
* Они выполняются как другие агрегатные функции, но не финализируются (возвращают состояние агрегации, которое может быть объединено с другим).
*/
virtual bool isState() const { return false; }
/** Внутренний цикл, использующий указатель на функцию, получается лучше, чем использующий виртуальную функцию.
* Причина в том, что в случае виртуальных функций, GCC 5.1.2 генерирует код,
* который на каждой итерации цикла заново грузит из памяти в регистр адрес функции (значение по смещению в таблице виртуальных функций).
* Это даёт падение производительности на простых запросах в районе 12%.
* После появления более хороших компиляторов, код можно будет убрать.
*/
using AddFunc = void (*)(const IAggregateFunction *, AggregateDataPtr, const IColumn **, size_t);
virtual AddFunc getAddressOfAddFunction() const = 0;
};
/// Реализует несколько методов. T - тип структуры с данными для агрегации.
template <typename T>
class IAggregateFunctionHelper : public IAggregateFunction
{
protected:
using Data = T;
static Data & data(AggregateDataPtr place) { return *reinterpret_cast<Data*>(place); }
static const Data & data(ConstAggregateDataPtr place) { return *reinterpret_cast<const Data*>(place); }
public:
2015-11-11 02:04:23 +00:00
void create(AggregateDataPtr place) const override
{
new (place) Data;
}
2015-11-11 02:04:23 +00:00
void destroy(AggregateDataPtr place) const noexcept override
{
data(place).~Data();
}
2015-11-11 02:04:23 +00:00
bool hasTrivialDestructor() const override
{
return __has_trivial_destructor(Data);
}
2015-11-11 02:04:23 +00:00
size_t sizeOfData() const override
{
return sizeof(Data);
}
2013-02-09 02:20:26 +00:00
/// NOTE: Сейчас не используется (структуры с состоянием агрегации кладутся без выравнивания).
2015-11-11 02:04:23 +00:00
size_t alignOfData() const override
{
return __alignof__(Data);
}
2011-09-19 03:40:05 +00:00
};
using AggregateFunctionPtr = std::shared_ptr<IAggregateFunction>;
2011-09-19 03:40:05 +00:00
}