mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-26 17:41:59 +00:00
check the result of conversion for decimal IN float
This commit is contained in:
parent
4b0ac268e8
commit
215acf5e5b
@ -91,15 +91,35 @@ static size_t getTypeDepth(const DataTypePtr & type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static bool decimalEqualsFloat(Field field, Float64 float_value)
|
||||
{
|
||||
auto decimal_field = field.get<DecimalField<T>>();
|
||||
auto decimal_to_float = DecimalUtils::convertTo<Float64>(decimal_field.getValue(), decimal_field.getScale());
|
||||
return decimal_to_float == float_value;
|
||||
}
|
||||
|
||||
/// Applies stricter rules than convertFieldToType:
|
||||
/// Doesn't allow :
|
||||
/// - loss of precision with `Decimals`
|
||||
/// - loss of precision converting to Decimal
|
||||
static bool convertFieldToTypeStrict(const Field & from_value, const IDataType & to_type, Field & result_value)
|
||||
{
|
||||
result_value = convertFieldToType(from_value, to_type);
|
||||
if (Field::isDecimal(from_value.getType()) && Field::isDecimal(result_value.getType()))
|
||||
return applyVisitor(FieldVisitorAccurateEquals{}, from_value, result_value);
|
||||
|
||||
if (from_value.getType() == Field::Types::Float64 && Field::isDecimal(result_value.getType()))
|
||||
{
|
||||
/// Convert back to Float64 and compare
|
||||
if (result_value.getType() == Field::Types::Decimal32)
|
||||
return decimalEqualsFloat<Decimal32>(result_value, from_value.get<Float64>());
|
||||
if (result_value.getType() == Field::Types::Decimal64)
|
||||
return decimalEqualsFloat<Decimal64>(result_value, from_value.get<Float64>());
|
||||
if (result_value.getType() == Field::Types::Decimal128)
|
||||
return decimalEqualsFloat<Decimal128>(result_value, from_value.get<Float64>());
|
||||
if (result_value.getType() == Field::Types::Decimal256)
|
||||
return decimalEqualsFloat<Decimal256>(result_value, from_value.get<Float64>());
|
||||
throw Exception(ErrorCodes::LOGICAL_ERROR, "Unknown decimal type {}", result_value.getTypeName());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -112,15 +112,16 @@ Field convertDecimalToDecimalType(const Field & from, const DataTypeDecimal<T> &
|
||||
template <typename From, typename T>
|
||||
Field convertFloatToDecimalType(const Field & from, const DataTypeDecimal<T> & type)
|
||||
{
|
||||
From dValue = from.get<From>();
|
||||
if (!type.canStoreWhole(dValue))
|
||||
From value = from.get<From>();
|
||||
if (!type.canStoreWhole(value))
|
||||
throw Exception("Number is too big to place in " + type.getName(), ErrorCodes::ARGUMENT_OUT_OF_BOUND);
|
||||
|
||||
String sValue = convertFieldToString(from);
|
||||
int fromScale = sValue.length()- sValue.find('.') - 1;
|
||||
//String sValue = convertFieldToString(from);
|
||||
//int fromScale = sValue.length()- sValue.find('.') - 1;
|
||||
UInt32 scale = type.getScale();
|
||||
|
||||
auto scaledValue = convertToDecimal<DataTypeNumber<From>, DataTypeDecimal<T>>(dValue, fromScale);
|
||||
return DecimalField<T>(scaledValue, fromScale);
|
||||
auto scaled_value = convertToDecimal<DataTypeNumber<From>, DataTypeDecimal<T>>(value, scale);
|
||||
return DecimalField<T>(scaled_value, scale);
|
||||
}
|
||||
|
||||
template <typename To>
|
||||
|
@ -18,3 +18,4 @@
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
|
Loading…
Reference in New Issue
Block a user