mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-24 16:42:05 +00:00
Remove trailing zeros from Decimal serialization #15794
This commit is contained in:
parent
ef803f14a1
commit
60dccce818
@ -277,5 +277,4 @@ GTEST_TEST(WideInteger, DecimalFormatting)
|
||||
Int128 fractional = DecimalUtils::getFractionalPart(x, 2);
|
||||
|
||||
EXPECT_EQ(fractional, 40);
|
||||
EXPECT_EQ(decimalFractional(fractional, 2), "40");
|
||||
}
|
||||
|
@ -901,30 +901,63 @@ inline void writeText(const LocalDateTime & x, WriteBuffer & buf) { writeDateTim
|
||||
inline void writeText(const UUID & x, WriteBuffer & buf) { writeUUIDText(x, buf); }
|
||||
|
||||
template <typename T>
|
||||
String decimalFractional(const T & x, UInt32 scale)
|
||||
void writeDecimalFractional(const T & x, UInt32 scale, WriteBuffer & ostr)
|
||||
{
|
||||
/// If it's big integer, but the number of digits is small,
|
||||
/// use the implementation for smaller integers for more efficient arithmetic.
|
||||
|
||||
if constexpr (std::is_same_v<T, Int256>)
|
||||
{
|
||||
if (x <= std::numeric_limits<UInt32>::max())
|
||||
return decimalFractional(static_cast<UInt32>(x), scale);
|
||||
{
|
||||
writeDecimalFractional(static_cast<UInt32>(x), scale, ostr);
|
||||
return;
|
||||
}
|
||||
else if (x <= std::numeric_limits<UInt64>::max())
|
||||
return decimalFractional(static_cast<UInt64>(x), scale);
|
||||
{
|
||||
writeDecimalFractional(static_cast<UInt64>(x), scale, ostr);
|
||||
return;
|
||||
}
|
||||
else if (x <= std::numeric_limits<UInt128>::max())
|
||||
return decimalFractional(static_cast<UInt128>(x), scale);
|
||||
{
|
||||
writeDecimalFractional(static_cast<UInt128>(x), scale, ostr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, Int128>)
|
||||
{
|
||||
if (x <= std::numeric_limits<UInt32>::max())
|
||||
return decimalFractional(static_cast<UInt32>(x), scale);
|
||||
{
|
||||
writeDecimalFractional(static_cast<UInt32>(x), scale, ostr);
|
||||
return;
|
||||
}
|
||||
else if (x <= std::numeric_limits<UInt64>::max())
|
||||
return decimalFractional(static_cast<UInt64>(x), scale);
|
||||
{
|
||||
writeDecimalFractional(static_cast<UInt64>(x), scale, ostr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
String str(scale, '0');
|
||||
constexpr size_t max_digits = std::numeric_limits<T>::digits10;
|
||||
assert(scale <= max_digits);
|
||||
char buf[max_digits];
|
||||
memset(buf, '0', scale);
|
||||
|
||||
T value = x;
|
||||
for (Int32 pos = scale - 1; pos >= 0; --pos, value /= 10)
|
||||
str[pos] += static_cast<char>(value % 10);
|
||||
return str;
|
||||
Int32 last_nonzero_pos = 0;
|
||||
for (Int32 pos = scale - 1; pos >= 0; --pos)
|
||||
{
|
||||
auto remainder = value % 10;
|
||||
value /= 10;
|
||||
|
||||
if (remainder != 0 && last_nonzero_pos == 0)
|
||||
last_nonzero_pos = pos;
|
||||
|
||||
buf[pos] += static_cast<char>(remainder);
|
||||
}
|
||||
|
||||
writeChar('.', ostr);
|
||||
ostr.write(buf, last_nonzero_pos + 1);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -941,10 +974,9 @@ void writeText(Decimal<T> x, UInt32 scale, WriteBuffer & ostr)
|
||||
|
||||
if (scale)
|
||||
{
|
||||
writeChar('.', ostr);
|
||||
part = DecimalUtils::getFractionalPart(x, scale);
|
||||
String fractional = decimalFractional(part, scale);
|
||||
ostr.write(fractional.data(), scale);
|
||||
if (part)
|
||||
writeDecimalFractional(part, scale, ostr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,32 @@
|
||||
-- { echo }
|
||||
|
||||
SELECT 1.123::Decimal64(1);
|
||||
1.1
|
||||
SELECT 1.123::Decimal64(2);
|
||||
1.12
|
||||
SELECT 1.123::Decimal64(3);
|
||||
1.123
|
||||
SELECT 1.123::Decimal64(4);
|
||||
1.123
|
||||
SELECT 1.123::Decimal64(5);
|
||||
1.123
|
||||
SELECT 1.123::Decimal64(10);
|
||||
1.123
|
||||
SELECT 1::Decimal64(0);
|
||||
1
|
||||
SELECT 1::Decimal64(1);
|
||||
1
|
||||
SELECT 1::Decimal64(10);
|
||||
1
|
||||
SELECT 1.1234567::Decimal32(8);
|
||||
1.1234567
|
||||
SELECT 1.1234567890::Decimal64(10);
|
||||
1.123456789
|
||||
SELECT 1.1234567890::Decimal128(10);
|
||||
1.123456789
|
||||
SELECT 1.1234567890::Decimal256(10);
|
||||
1.123456789
|
||||
SELECT 1.123456789012345678901::Decimal256(20);
|
||||
1.1234567890123456789
|
||||
SELECT 1.123456789012345678901::Decimal256(22);
|
||||
1.123456789012345678901
|
@ -0,0 +1,18 @@
|
||||
-- { echo }
|
||||
|
||||
SELECT 1.123::Decimal64(1);
|
||||
SELECT 1.123::Decimal64(2);
|
||||
SELECT 1.123::Decimal64(3);
|
||||
SELECT 1.123::Decimal64(4);
|
||||
SELECT 1.123::Decimal64(5);
|
||||
SELECT 1.123::Decimal64(10);
|
||||
SELECT 1::Decimal64(0);
|
||||
SELECT 1::Decimal64(1);
|
||||
SELECT 1::Decimal64(10);
|
||||
|
||||
SELECT 1.1234567::Decimal32(8);
|
||||
SELECT 1.1234567890::Decimal64(10);
|
||||
SELECT 1.1234567890::Decimal128(10);
|
||||
SELECT 1.1234567890::Decimal256(10);
|
||||
SELECT 1.123456789012345678901::Decimal256(20);
|
||||
SELECT 1.123456789012345678901::Decimal256(22);
|
Loading…
Reference in New Issue
Block a user