#include #include namespace DB { class FieldVisitorHash : public boost::static_visitor<> { public: MD5_CTX state; FieldVisitorHash() { MD5_Init(&state); } void finalize(unsigned char * place) { MD5_Final(place, &state); } void operator() (const Null & x) { char type = FieldType::Null; MD5_Update(&state, reinterpret_cast(&type), sizeof(type)); } void operator() (const UInt64 & x) { char type = FieldType::UInt64; MD5_Update(&state, reinterpret_cast(&type), sizeof(type)); MD5_Update(&state, reinterpret_cast(&x), sizeof(x)); } void operator() (const Int64 & x) { char type = FieldType::Int64; MD5_Update(&state, reinterpret_cast(&type), sizeof(type)); MD5_Update(&state, reinterpret_cast(&x), sizeof(x)); } void operator() (const Float64 & x) { char type = FieldType::Float64; MD5_Update(&state, reinterpret_cast(&type), sizeof(type)); MD5_Update(&state, reinterpret_cast(&x), sizeof(x)); } void operator() (const String & x) { char type = FieldType::String; MD5_Update(&state, reinterpret_cast(&type), sizeof(type)); /// Используем ноль на конце. MD5_Update(&state, x.c_str(), x.size() + 1); } void operator() (const Array & x) { throw Exception("Cannot aggregate by array", ErrorCodes::ILLEGAL_KEY_OF_AGGREGATION); } void operator() (const SharedPtr & x) { throw Exception("Cannot aggregate by state of aggregate function", ErrorCodes::ILLEGAL_KEY_OF_AGGREGATION); } }; /** Преобразование значения в 64 бита. Для чисел - однозначное, для строк - некриптографический хэш. */ class FieldVisitorToUInt64 : public boost::static_visitor { public: FieldVisitorToUInt64() {} UInt64 operator() (const Null & x) const { return 0; } UInt64 operator() (const UInt64 & x) const { return x; } UInt64 operator() (const Int64 & x) const { return x; } UInt64 operator() (const Float64 & x) const { UInt64 res = 0; memcpy(reinterpret_cast(&res), reinterpret_cast(&x), sizeof(x)); return res; } UInt64 operator() (const String & x) const { return std::tr1::hash()(x); } UInt64 operator() (const Array & x) const { throw Exception("Cannot aggregate by array", ErrorCodes::ILLEGAL_KEY_OF_AGGREGATION); } UInt64 operator() (const SharedPtr & x) const { throw Exception("Cannot aggregate by state of aggregate function", ErrorCodes::ILLEGAL_KEY_OF_AGGREGATION); } }; }