提交 c6a50834 编写于 作者: G Guillaume Tassery

Fix comparison of UInt128 to Float64

上级 b9073492
......@@ -307,11 +307,11 @@ template class ColumnVector<UInt8>;
template class ColumnVector<UInt16>;
template class ColumnVector<UInt32>;
template class ColumnVector<UInt64>;
template class ColumnVector<UInt128>;
template class ColumnVector<Int8>;
template class ColumnVector<Int16>;
template class ColumnVector<Int32>;
template class ColumnVector<Int64>;
template class ColumnVector<Float32>;
template class ColumnVector<Float64>;
template class ColumnVector<UUID>;
}
......@@ -29,15 +29,15 @@ struct UInt128
explicit UInt128(const UInt64 low, const UInt64 high) : low(low), high(high) { }
bool inline operator== (const UInt128 rhs) const { return std::tie(low, high) == std::tie(rhs.low, rhs.high); }
bool inline operator!= (const UInt128 rhs) const { return !(*this == rhs); }
bool inline operator!= (const UInt128 rhs) const { return !operator==(rhs); }
bool inline operator< (const UInt128 rhs) const { return std::tie(low, high) < std::tie(rhs.low, rhs.high); }
bool inline operator<= (const UInt128 rhs) const { return !(rhs < *this); }
bool inline operator> (const UInt128 rhs) const { return rhs < *this; }
bool inline operator>= (const UInt128 rhs) const { return !(*this < rhs); }
bool inline operator<= (const UInt128 rhs) const { return !rhs.operator<(*this); }
bool inline operator> (const UInt128 rhs) const { return rhs.operator<(*this); }
bool inline operator>= (const UInt128 rhs) const { return !operator<(rhs); }
/** Type stored in the database will contain no more than 64 bits at the moment, don't need
* to check the `high` element
/** Types who are stored at the moment in the database have no more than 64bits and can be handle
* inside an unique UInt64.
*/
template<typename T> bool inline operator== (const T rhs) const { return *this == UInt128(0, rhs); }
template<typename T> bool inline operator!= (const T rhs) const { return *this != UInt128(0, rhs); }
......@@ -62,6 +62,9 @@ template<typename T> bool inline operator> (T a, const UInt128 b) { return b.lo
template<typename T> bool inline operator<= (T a, const UInt128 b) { return b.low != 0 || a <= static_cast<T>(b.high); }
template<typename T> bool inline operator< (T a, const UInt128 b) { return b.low != 0 || a < static_cast<T>(b.high); }
template <> struct IsNumber<UInt128> { static constexpr bool value = true; };
template <> struct TypeName<UInt128> { static std::string get() { return "UInt128"; } };
struct UInt128Hash
{
size_t operator()(UInt128 x) const
......@@ -199,4 +202,15 @@ template <> struct is_unsigned<DB::UInt128>
{
static constexpr bool value = true;
};
template <> struct is_integral<DB::UInt128>
{
static constexpr bool value = true;
};
// Operator +, -, /, *, % aren't implemented so it's not an arithmetic type
template <> struct is_arithmetic<DB::UInt128>
{
static constexpr bool value = false;
};
}
......@@ -31,7 +31,7 @@ using DB::UInt64;
// Case 1. Is pair of floats or pair of ints or pair of uints
template <typename A, typename B>
using is_safe_conversion = std::integral_constant<bool, (std::is_floating_point<A>::value && std::is_floating_point<B>::value)
|| ((std::is_integral<A>::value || std::is_same<A, DB::UInt128>::value) && (std::is_integral<B>::value || std::is_same<B, DB::UInt128>::value) && !(std::is_signed<A>::value ^ std::is_signed<B>::value))>;
|| (std::is_integral<A>::value && std::is_integral<B>::value && !(std::is_signed<A>::value ^ std::is_signed<B>::value))>;
template <typename A, typename B>
using bool_if_safe_conversion = std::enable_if_t<is_safe_conversion<A, B>::value, bool>;
template <typename A, typename B>
......@@ -41,8 +41,8 @@ using bool_if_not_safe_conversion = std::enable_if_t<!is_safe_conversion<A, B>::
/// Case 2. Are params IntXX and UIntYY ?
template <typename TInt, typename TUInt>
using is_any_int_vs_uint = std::integral_constant<bool,
std::is_integral<TInt>::value && (std::is_integral<TUInt>::value || std::is_same<TUInt, DB::UInt128>::value) &&
std::is_signed<TInt>::value && (std::is_unsigned<TUInt>::value || std::is_same<TUInt, DB::UInt128>::value)>;
std::is_integral<TInt>::value && std::is_integral<TUInt>::value &&
std::is_signed<TInt>::value && std::is_unsigned<TUInt>::value>;
// Case 2a. Are params IntXX and UIntYY and sizeof(IntXX) >= sizeof(UIntYY) (in such case will use accurate compare)
......@@ -112,7 +112,7 @@ inline bool_if_gt_int_vs_uint<TInt, TUInt> equalsOpTmpl(TUInt a, TInt b)
// Case 3a. Comparison via conversion to double.
template <typename TAInt, typename TAFloat>
using bool_if_double_can_be_used = std::enable_if_t<
std::is_integral<TAInt>::value && (sizeof(TAInt) <= 4 || sizeof(DB::UInt128) == sizeof(TAInt)) && std::is_floating_point<TAFloat>::value,
std::is_integral<TAInt>::value && (sizeof(TAInt) <= 4) && std::is_floating_point<TAFloat>::value,
bool>;
template <typename TAInt, typename TAFloat>
......@@ -228,13 +228,13 @@ inline bool greaterOp<DB::UInt64, DB::Float32>(DB::UInt64 u, DB::Float32 f)
template<>
inline bool greaterOp<DB::Float64, DB::UInt128>(DB::Float64 f, DB::UInt128 u)
{
return f > u && greaterOp(f, static_cast<UInt64>(u));
return u.low == 0 && greaterOp(f, u.high);
}
template<>
inline bool greaterOp<DB::UInt128, DB::Float64>(DB::UInt128 u, DB::Float64 f)
{
return u > f && greaterOp(static_cast<UInt64>(u), f);
return u.low != 0 || greaterOp(u.high, f);
}
template<>
......@@ -312,7 +312,7 @@ inline bool equalsOp<DB::Int64, DB::Float32>(DB::Int64 u, DB::Float32 f)
template<>
inline bool equalsOp<DB::UInt128, DB::Float64>(DB::UInt128 u, DB::Float64 f)
{
return u == f && equalsOp(static_cast<UInt64>(u), f);
return u.low == 0 && equalsOp(static_cast<UInt64>(u.high), f);
}
template<>
......@@ -324,7 +324,7 @@ inline bool equalsOp<DB::UInt128, DB::Float32>(DB::UInt128 u, DB::Float32 f)
template<>
inline bool equalsOp<DB::Float64, DB::UInt128>(DB::Float64 f, DB::UInt128 u)
{
return f == u && equalsOp(f, static_cast<UInt64>(u));
return equalsOp(u, f);
}
template<>
......
......@@ -7,7 +7,4 @@ namespace DB
using UUID = DB::UInt128;
template <> struct IsNumber<UUID> { static constexpr bool value = true; };
template <> struct TypeName<UUID> { static std::string get() { return "UUID"; } };
}
......@@ -23,13 +23,13 @@ void DataTypeNumberBase<T>::serializeTextEscaped(const IColumn & column, size_t
template <typename T>
static void readTextUnsafeIfIntegral(typename std::enable_if<std::is_integral<T>::value, T>::type & x, ReadBuffer & istr)
static void readTextUnsafeIfIntegral(typename std::enable_if<std::is_integral<T>::value && std::is_arithmetic<T>::value, T>::type & x, ReadBuffer & istr)
{
readIntTextUnsafe(x, istr);
}
template <typename T>
static void readTextUnsafeIfIntegral(typename std::enable_if<!std::is_integral<T>::value, T>::type & x, ReadBuffer & istr)
static void readTextUnsafeIfIntegral(typename std::enable_if<!std::is_integral<T>::value || !std::is_arithmetic<T>::value, T>::type & x, ReadBuffer & istr)
{
readText(x, istr);
}
......
......@@ -14,7 +14,8 @@ class DataTypeUUID final : public DataTypeNumberBase<UInt128>
public:
bool behavesAsNumber() const override { return false; }
std::string getName() const override { return "UUID"; }
DataTypePtr clone() const override { return std::make_shared<DataTypeUUID>(); }
void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr) const override;
......
......@@ -17,6 +17,7 @@ using DataTypeUInt8 = DataTypeNumber<UInt8>;
using DataTypeUInt16 = DataTypeNumber<UInt16>;
using DataTypeUInt32 = DataTypeNumber<UInt32>;
using DataTypeUInt64 = DataTypeNumber<UInt64>;
using DataTypeUInt128 = DataTypeNumber<UInt128>;
using DataTypeInt8 = DataTypeNumber<Int8>;
using DataTypeInt16 = DataTypeNumber<Int16>;
using DataTypeInt32 = DataTypeNumber<Int32>;
......
......@@ -175,7 +175,7 @@ DataTypePtr FieldToDataType::operator() (Array & x) const
return wrap_into_array(std::make_shared<DataTypeString>());
if (has_uint128)
return wrap_into_array(std::make_shared<DataTypeUUID>());
return wrap_into_array(std::make_shared<DataTypeUInt128>());
if (has_float && max_bits == 64)
throw Exception("Incompatible types Float64 and UInt64/Int64 of elements of array", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
......
......@@ -132,7 +132,6 @@ namespace
static_cast<const Poco::MongoDB::ConcreteElement<Poco::Timestamp> &>(value).value().epochTime());
break;
}
}
}
}
......
......@@ -605,7 +605,7 @@ inline void readUUIDText(UUID & uuid, ReadBuffer & buf)
throw Exception(std::string("Cannot parse uuid ") + s, ErrorCodes::CANNOT_PARSE_UUID);
}
parseUUID((const UInt8 *)s, uuid);
parseUUID(reinterpret_cast<const UInt8 *>(s), uuid);
}
......
......@@ -481,7 +481,7 @@ inline void writeUUIDText(const UUID & uuid, WriteBuffer & buf)
{
char s[36];
formatUUID(uuid, (UInt8 *)s);
formatUUID(uuid, reinterpret_cast<UInt8 *>(s));
buf.write(s, sizeof(s));
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册