You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-08-01 06:46:55 +03:00
MCOL-4478 MCS now rounds the last digits of an avg() result for wide-DECIMAL argument
This commit is contained in:
@ -22,24 +22,6 @@
|
||||
|
||||
namespace datatypes
|
||||
{
|
||||
|
||||
struct lldiv_t_128
|
||||
{
|
||||
int128_t quot;
|
||||
int128_t rem;
|
||||
lldiv_t_128() : quot(0), rem(0) {}
|
||||
lldiv_t_128(const int128_t& a_quot, const int128_t& a_rem)
|
||||
: quot(a_quot), rem(a_rem) {}
|
||||
};
|
||||
|
||||
inline lldiv_t_128 lldiv128(const int128_t& dividend, const int128_t& divisor)
|
||||
{
|
||||
if (UNLIKELY(divisor == 0) || UNLIKELY(dividend == 0))
|
||||
return lldiv_t_128();
|
||||
|
||||
return lldiv_t_128(dividend / divisor, dividend % divisor);
|
||||
}
|
||||
|
||||
template<typename BinaryOperation,
|
||||
typename OpOverflowCheck,
|
||||
typename MultiplicationOverflowCheck>
|
||||
@ -115,7 +97,6 @@ namespace datatypes
|
||||
? r.s128Value : r.value;
|
||||
|
||||
opOverflowCheck(lValue, rValue);
|
||||
|
||||
if (result.scale >= l.scale - r.scale)
|
||||
{
|
||||
int128_t scaleMultiplier;
|
||||
@ -213,7 +194,7 @@ namespace datatypes
|
||||
// rem carries the value's sign, but needs to be normalized.
|
||||
int64_t s = l.scale - r.scale;
|
||||
int128_t divisor;
|
||||
getScaleDivisor(divisor, abs(s));
|
||||
getScaleDivisor(divisor, std::abs(s));
|
||||
|
||||
if (s < 0)
|
||||
{
|
||||
|
@ -161,6 +161,23 @@ inline void getScaleDivisor(T& divisor, const int8_t scale)
|
||||
}
|
||||
}
|
||||
|
||||
struct lldiv_t_128
|
||||
{
|
||||
int128_t quot;
|
||||
int128_t rem;
|
||||
lldiv_t_128() : quot(0), rem(0) {}
|
||||
lldiv_t_128(const int128_t& a_quot, const int128_t& a_rem)
|
||||
: quot(a_quot), rem(a_rem) {}
|
||||
};
|
||||
|
||||
inline lldiv_t_128 lldiv128(const int128_t& dividend, const int128_t& divisor)
|
||||
{
|
||||
if (UNLIKELY(divisor == 0) || UNLIKELY(dividend == 0))
|
||||
return lldiv_t_128();
|
||||
|
||||
return lldiv_t_128(dividend / divisor, dividend % divisor);
|
||||
}
|
||||
|
||||
// @brief The class for Decimal related operations
|
||||
// The class contains Decimal related operations are scale and
|
||||
// precision aware.
|
||||
|
@ -112,6 +112,11 @@ struct is_uint128_t<uint128_t> {
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
inline int128_t abs(int128_t& x)
|
||||
{
|
||||
return (x >= 0) ? x : -x;
|
||||
}
|
||||
|
||||
class TSInt128
|
||||
{
|
||||
public:
|
||||
|
@ -2800,8 +2800,22 @@ void RowAggregationUM::calculateAvgColumns()
|
||||
multOp(*sumPnt, datatypes::mcs_pow_10[scaleDiff], sum);
|
||||
else
|
||||
sum = *sumPnt;
|
||||
int128_t avg = sum / cnt;
|
||||
fRow.setBinaryField_offset(&avg, sizeof(avg), offset);
|
||||
datatypes::lldiv_t_128 avgAndRem = datatypes::lldiv128(sum, cnt);
|
||||
// Round the last digit
|
||||
if (datatypes::abs(avgAndRem.rem) * 2 >= (int128_t)cnt)
|
||||
{
|
||||
if (utils::is_negative(avgAndRem.rem))
|
||||
{
|
||||
avgAndRem.quot--;
|
||||
}
|
||||
else
|
||||
{
|
||||
avgAndRem.quot++;
|
||||
}
|
||||
}
|
||||
fRow.setBinaryField_offset(&avgAndRem.quot,
|
||||
sizeof(avgAndRem.quot),
|
||||
offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user