#pragma once #include #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int BAD_TYPE_OF_FIELD; } /** More precise comparison, used for index. * Differs from Field::operator< and Field::operator== in that it also compares values of different types. * Comparison rules are same as in FunctionsComparison (to be consistent with expression evaluation in query). */ class FieldVisitorAccurateEquals : public StaticVisitor { public: template bool operator() (const T & l, const U & r) const { if constexpr (std::is_same_v || std::is_same_v) return std::is_same_v; else { if constexpr (std::is_same_v) return l == r; if constexpr (std::is_arithmetic_v && std::is_arithmetic_v) return accurate::equalsOp(l, r); if constexpr (isDecimalField() && isDecimalField()) return l == r; if constexpr (isDecimalField() && std::is_arithmetic_v) return l == DecimalField(r, 0); if constexpr (std::is_arithmetic_v && isDecimalField()) return DecimalField(l, 0) == r; if constexpr (std::is_same_v) { if constexpr (std::is_same_v) return stringToUUID(l) == r; if constexpr (std::is_arithmetic_v) { ReadBufferFromString in(l); U parsed; readText(parsed, in); return operator()(parsed, r); } } if constexpr (std::is_same_v) { if constexpr (std::is_same_v) return l == stringToUUID(r); if constexpr (std::is_arithmetic_v) { ReadBufferFromString in(r); T parsed; readText(parsed, in); return operator()(l, parsed); } } } throw Exception("Cannot compare " + demangle(typeid(T).name()) + " with " + demangle(typeid(U).name()), ErrorCodes::BAD_TYPE_OF_FIELD); } }; class FieldVisitorAccurateLess : public StaticVisitor { public: template bool operator() (const T & l, const U & r) const { if constexpr (std::is_same_v || std::is_same_v) return false; else { if constexpr (std::is_same_v) return l < r; if constexpr (std::is_arithmetic_v && std::is_arithmetic_v) return accurate::lessOp(l, r); if constexpr (isDecimalField() && isDecimalField()) return l < r; if constexpr (isDecimalField() && std::is_arithmetic_v) return l < DecimalField(r, 0); if constexpr (std::is_arithmetic_v && isDecimalField()) return DecimalField(l, 0) < r; if constexpr (std::is_same_v) { if constexpr (std::is_same_v) return stringToUUID(l) < r; if constexpr (std::is_arithmetic_v) { ReadBufferFromString in(l); U parsed; readText(parsed, in); return operator()(parsed, r); } } if constexpr (std::is_same_v) { if constexpr (std::is_same_v) return l < stringToUUID(r); if constexpr (std::is_arithmetic_v) { ReadBufferFromString in(r); T parsed; readText(parsed, in); return operator()(l, parsed); } } } throw Exception("Cannot compare " + demangle(typeid(T).name()) + " with " + demangle(typeid(U).name()), ErrorCodes::BAD_TYPE_OF_FIELD); } }; }