ClickHouse/dbms/src/AggregateFunctions/AggregateFunctionAvg.h

112 lines
3.5 KiB
C++
Raw Normal View History

2011-09-26 04:00:46 +00:00
#pragma once
#include <IO/WriteHelpers.h>
#include <IO/ReadHelpers.h>
2011-09-26 04:00:46 +00:00
#include <DataTypes/DataTypesNumber.h>
2018-09-12 13:27:32 +00:00
#include <DataTypes/DataTypesDecimal.h>
#include <Columns/ColumnsNumber.h>
2011-09-26 04:00:46 +00:00
#include <AggregateFunctions/IAggregateFunction.h>
2011-09-26 04:00:46 +00:00
namespace DB
{
namespace ErrorCodes
{
extern const int LOGICAL_ERROR;
}
2011-09-26 04:00:46 +00:00
template <typename T>
struct AggregateFunctionAvgData
2011-09-26 04:00:46 +00:00
{
T sum = 0;
UInt64 count = 0;
template <typename ResultT>
2018-12-27 00:51:14 +00:00
ResultT NO_SANITIZE_UNDEFINED result() const
{
if constexpr (std::is_floating_point_v<ResultT>)
if constexpr (std::numeric_limits<ResultT>::is_iec559)
return static_cast<ResultT>(sum) / count; /// allow division by zero
if (!count)
throw Exception("AggregateFunctionAvg with zero values", ErrorCodes::LOGICAL_ERROR);
return static_cast<ResultT>(sum) / count;
}
};
2017-03-09 00:56:38 +00:00
/// Calculates arithmetic mean of numbers.
2018-09-12 13:27:32 +00:00
template <typename T, typename Data>
class AggregateFunctionAvg final : public IAggregateFunctionDataHelper<Data, AggregateFunctionAvg<T, Data>>
{
public:
2018-09-12 13:27:32 +00:00
using ResultType = std::conditional_t<IsDecimalNumber<T>, Decimal128, Float64>;
using ResultDataType = std::conditional_t<IsDecimalNumber<T>, DataTypeDecimal<Decimal128>, DataTypeNumber<Float64>>;
using ColVecType = std::conditional_t<IsDecimalNumber<T>, ColumnDecimal<T>, ColumnVector<T>>;
using ColVecResult = std::conditional_t<IsDecimalNumber<T>, ColumnDecimal<Decimal128>, ColumnVector<Float64>>;
/// ctor for native types
AggregateFunctionAvg(const DataTypes & argument_types_)
: IAggregateFunctionDataHelper<Data, AggregateFunctionAvg<T, Data>>(argument_types_, {})
2019-02-12 09:31:20 +00:00
, scale(0)
2018-09-12 13:27:32 +00:00
{}
/// ctor for Decimals
AggregateFunctionAvg(const IDataType & data_type, const DataTypes & argument_types_)
: IAggregateFunctionDataHelper<Data, AggregateFunctionAvg<T, Data>>(argument_types_, {})
2019-02-11 19:26:32 +00:00
, scale(getDecimalScale(data_type))
2018-09-12 13:27:32 +00:00
{}
String getName() const override { return "avg"; }
DataTypePtr getReturnType() const override
{
2018-09-12 13:27:32 +00:00
if constexpr (IsDecimalNumber<T>)
return std::make_shared<ResultDataType>(ResultDataType::maxPrecision(), scale);
else
return std::make_shared<ResultDataType>();
}
void add(AggregateDataPtr place, const IColumn ** columns, size_t row_num, Arena *) const override
{
2018-09-12 13:27:32 +00:00
const auto & column = static_cast<const ColVecType &>(*columns[0]);
this->data(place).sum += column.getData()[row_num];
++this->data(place).count;
}
2017-12-01 21:51:50 +00:00
void merge(AggregateDataPtr place, ConstAggregateDataPtr rhs, Arena *) const override
{
this->data(place).sum += this->data(rhs).sum;
this->data(place).count += this->data(rhs).count;
}
void serialize(ConstAggregateDataPtr place, WriteBuffer & buf) const override
{
writeBinary(this->data(place).sum, buf);
writeVarUInt(this->data(place).count, buf);
}
void deserialize(AggregateDataPtr place, ReadBuffer & buf, Arena *) const override
{
readBinary(this->data(place).sum, buf);
readVarUInt(this->data(place).count, buf);
}
void insertResultInto(ConstAggregateDataPtr place, IColumn & to) const override
{
2018-09-12 13:27:32 +00:00
auto & column = static_cast<ColVecResult &>(to);
column.getData().push_back(this->data(place).template result<ResultType>());
}
const char * getHeaderFilePath() const override { return __FILE__; }
2018-09-12 13:27:32 +00:00
private:
UInt32 scale;
2011-09-26 04:00:46 +00:00
};
2011-09-26 04:00:46 +00:00
}