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
|
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,
|
template<typename BinaryOperation,
|
||||||
typename OpOverflowCheck,
|
typename OpOverflowCheck,
|
||||||
typename MultiplicationOverflowCheck>
|
typename MultiplicationOverflowCheck>
|
||||||
@ -115,7 +97,6 @@ namespace datatypes
|
|||||||
? r.s128Value : r.value;
|
? r.s128Value : r.value;
|
||||||
|
|
||||||
opOverflowCheck(lValue, rValue);
|
opOverflowCheck(lValue, rValue);
|
||||||
|
|
||||||
if (result.scale >= l.scale - r.scale)
|
if (result.scale >= l.scale - r.scale)
|
||||||
{
|
{
|
||||||
int128_t scaleMultiplier;
|
int128_t scaleMultiplier;
|
||||||
@ -213,7 +194,7 @@ namespace datatypes
|
|||||||
// rem carries the value's sign, but needs to be normalized.
|
// rem carries the value's sign, but needs to be normalized.
|
||||||
int64_t s = l.scale - r.scale;
|
int64_t s = l.scale - r.scale;
|
||||||
int128_t divisor;
|
int128_t divisor;
|
||||||
getScaleDivisor(divisor, abs(s));
|
getScaleDivisor(divisor, std::abs(s));
|
||||||
|
|
||||||
if (s < 0)
|
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
|
// @brief The class for Decimal related operations
|
||||||
// The class contains Decimal related operations are scale and
|
// The class contains Decimal related operations are scale and
|
||||||
// precision aware.
|
// precision aware.
|
||||||
|
@ -111,6 +111,11 @@ template<>
|
|||||||
struct is_uint128_t<uint128_t> {
|
struct is_uint128_t<uint128_t> {
|
||||||
static const bool value = true;
|
static const bool value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline int128_t abs(int128_t& x)
|
||||||
|
{
|
||||||
|
return (x >= 0) ? x : -x;
|
||||||
|
}
|
||||||
|
|
||||||
class TSInt128
|
class TSInt128
|
||||||
{
|
{
|
||||||
|
@ -2788,7 +2788,7 @@ void RowAggregationUM::calculateAvgColumns()
|
|||||||
uint32_t offset = fRow.getOffset(colOut);
|
uint32_t offset = fRow.getOffset(colOut);
|
||||||
uint32_t scale = fRow.getScale(colOut);
|
uint32_t scale = fRow.getScale(colOut);
|
||||||
// Get multiplied to deliver AVG with the scale closest
|
// Get multiplied to deliver AVG with the scale closest
|
||||||
// to the expected original scale + 4.
|
// to the expected original scale + 4.
|
||||||
// There is a counterpart in buildAggregateColumn.
|
// There is a counterpart in buildAggregateColumn.
|
||||||
datatypes::Decimal::setScalePrecision4Avg(precision, scale);
|
datatypes::Decimal::setScalePrecision4Avg(precision, scale);
|
||||||
int128_t* sumPnt = fRow.getBinaryField_offset<int128_t>(offset);
|
int128_t* sumPnt = fRow.getBinaryField_offset<int128_t>(offset);
|
||||||
@ -2800,8 +2800,22 @@ void RowAggregationUM::calculateAvgColumns()
|
|||||||
multOp(*sumPnt, datatypes::mcs_pow_10[scaleDiff], sum);
|
multOp(*sumPnt, datatypes::mcs_pow_10[scaleDiff], sum);
|
||||||
else
|
else
|
||||||
sum = *sumPnt;
|
sum = *sumPnt;
|
||||||
int128_t avg = sum / cnt;
|
datatypes::lldiv_t_128 avgAndRem = datatypes::lldiv128(sum, cnt);
|
||||||
fRow.setBinaryField_offset(&avg, sizeof(avg), offset);
|
// 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