fix float to decimal convert overflow

This commit is contained in:
dmitry kuzmin 2019-06-13 11:40:30 +03:00
parent ff594aaf1b
commit 89cc1440d8
2 changed files with 21 additions and 4 deletions

View File

@ -320,13 +320,26 @@ inline std::enable_if_t<IsDataTypeNumber<FromDataType> && IsDataTypeDecimal<ToDa
convertToDecimal(const typename FromDataType::FieldType & value, UInt32 scale)
{
using FromFieldType = typename FromDataType::FieldType;
using ToNativeType = typename ToDataType::FieldType::NativeType;
if constexpr (std::is_floating_point_v<FromFieldType>)
{
if (!std::isfinite(value))
throw Exception("Decimal convert overflow. Cannot convert infinity or NaN to decimal", ErrorCodes::DECIMAL_OVERFLOW);
return value * ToDataType::getScaleMultiplier(scale);
}
ToNativeType min_value, max_value;
if constexpr (std::is_same_v<ToNativeType, Int128>)
{
min_value = __int128(0x8000000000000000ll) << 64; // min __int128
max_value = (__int128(0x7fffffffffffffffll) << 64) + 0xffffffffffffffffll; // max __int128
}
else
{
min_value = std::numeric_limits<ToNativeType>::min();
max_value = std::numeric_limits<ToNativeType>::max();
}
ToNativeType converted_value = static_cast<ToNativeType>(value * ToDataType::getScaleMultiplier(scale));
if (converted_value == min_value || converted_value == max_value)
throw Exception("Decimal convert overflow", ErrorCodes::DECIMAL_OVERFLOW);
return converted_value;
}
else
{
if constexpr (std::is_same_v<FromFieldType, UInt64>)

View File

@ -250,3 +250,7 @@ SELECT CAST(1/0, 'Decimal(38, 2)'); -- { serverError 407 }
SELECT CAST(0/0, 'Decimal(9, 3)'); -- { serverError 407 }
SELECT CAST(0/0, 'Decimal(18, 4)'); -- { serverError 407 }
SELECT CAST(0/0, 'Decimal(38, 5)'); -- { serverError 407 }
select toDecimal32(10000.1, 6); -- { serverError 407 }
select toDecimal64(10000.1, 18); -- { serverError 407 }
select toDecimal128(1000000000000000000000.1, 18); -- { serverError 407 }