#include #include #include #include #include #include #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int CANNOT_RESTORE_FROM_FIELD_DUMP; extern const int DECIMAL_OVERFLOW; } inline Field getBinaryValue(UInt8 type, ReadBuffer & buf) { switch (type) { case Field::Types::Null: { return Field(); } case Field::Types::UInt64: { UInt64 value; readVarUInt(value, buf); return value; } case Field::Types::UInt128: { UInt128 value; readBinary(value, buf); return value; } case Field::Types::UInt256: { UInt256 value; readBinary(value, buf); return value; } case Field::Types::UUID: { UUID value; readBinary(value, buf); return value; } case Field::Types::Int64: { Int64 value; readVarInt(value, buf); return value; } case Field::Types::Int128: { Int128 value; readBinary(value, buf); return value; } case Field::Types::Int256: { Int256 value; readBinary(value, buf); return value; } case Field::Types::Float64: { Float64 value; readFloatBinary(value, buf); return value; } case Field::Types::String: { std::string value; readStringBinary(value, buf); return value; } case Field::Types::Array: { Array value; readBinary(value, buf); return value; } case Field::Types::Tuple: { Tuple value; readBinary(value, buf); return value; } case Field::Types::Map: { Map value; readBinary(value, buf); return value; } case Field::Types::AggregateFunctionState: { AggregateFunctionStateData value; readStringBinary(value.name, buf); readStringBinary(value.data, buf); return value; } case Field::Types::Bool: { UInt8 value; readBinary(value, buf); return bool(value); } } return Field(); } void readBinary(Array & x, ReadBuffer & buf) { size_t size; UInt8 type; readBinary(type, buf); readBinary(size, buf); for (size_t index = 0; index < size; ++index) x.push_back(getBinaryValue(type, buf)); } void writeBinary(const Array & x, WriteBuffer & buf) { UInt8 type = Field::Types::Null; size_t size = x.size(); if (size) type = x.front().getType(); writeBinary(type, buf); writeBinary(size, buf); for (const auto & elem : x) Field::dispatch([&buf] (const auto & value) { FieldVisitorWriteBinary()(value, buf); }, elem); } void writeText(const Array & x, WriteBuffer & buf) { String res = applyVisitor(FieldVisitorToString(), Field(x)); buf.write(res.data(), res.size()); } void readBinary(Tuple & x, ReadBuffer & buf) { size_t size; readBinary(size, buf); for (size_t index = 0; index < size; ++index) { UInt8 type; readBinary(type, buf); x.push_back(getBinaryValue(type, buf)); } } void writeBinary(const Tuple & x, WriteBuffer & buf) { const size_t size = x.size(); writeBinary(size, buf); for (const auto & elem : x) { const UInt8 type = elem.getType(); writeBinary(type, buf); Field::dispatch([&buf] (const auto & value) { FieldVisitorWriteBinary()(value, buf); }, elem); } } void writeText(const Tuple & x, WriteBuffer & buf) { writeFieldText(Field(x), buf); } void readBinary(Map & x, ReadBuffer & buf) { size_t size; readBinary(size, buf); for (size_t index = 0; index < size; ++index) { UInt8 type; readBinary(type, buf); x.push_back(getBinaryValue(type, buf)); } } void writeBinary(const Map & x, WriteBuffer & buf) { const size_t size = x.size(); writeBinary(size, buf); for (const auto & elem : x) { const UInt8 type = elem.getType(); writeBinary(type, buf); Field::dispatch([&buf] (const auto & value) { FieldVisitorWriteBinary()(value, buf); }, elem); } } void writeText(const Map & x, WriteBuffer & buf) { writeFieldText(Field(x), buf); } template void readQuoted(DecimalField & x, ReadBuffer & buf) { assertChar('\'', buf); T value; UInt32 scale; int32_t exponent; uint32_t max_digits = static_cast(-1); readDigits(buf, value, max_digits, exponent, true); if (exponent > 0) { scale = 0; if (common::mulOverflow(value.value, DecimalUtils::scaleMultiplier(exponent), value.value)) throw Exception("Decimal math overflow", ErrorCodes::DECIMAL_OVERFLOW); } else scale = -exponent; assertChar('\'', buf); x = DecimalField{value, scale}; } template void readQuoted(DecimalField & x, ReadBuffer & buf); template void readQuoted(DecimalField & x, ReadBuffer & buf); template void readQuoted(DecimalField & x, ReadBuffer & buf); template void readQuoted(DecimalField & x, ReadBuffer & buf); void writeFieldText(const Field & x, WriteBuffer & buf) { String res = Field::dispatch(FieldVisitorToString(), x); buf.write(res.data(), res.size()); } String Field::dump() const { return applyVisitor(FieldVisitorDump(), *this); } Field Field::restoreFromDump(const std::string_view & dump_) { auto show_error = [&dump_] { throw Exception("Couldn't restore Field from dump: " + String{dump_}, ErrorCodes::CANNOT_RESTORE_FROM_FIELD_DUMP); }; std::string_view dump = dump_; trim(dump); if (dump == "NULL") return {}; std::string_view prefix = std::string_view{"Int64_"}; if (dump.starts_with(prefix)) { Int64 value = parseFromString(dump.substr(prefix.length())); return value; } prefix = std::string_view{"UInt64_"}; if (dump.starts_with(prefix)) { UInt64 value = parseFromString(dump.substr(prefix.length())); return value; } prefix = std::string_view{"Int128_"}; if (dump.starts_with(prefix)) { Int128 value = parseFromString(dump.substr(prefix.length())); return value; } prefix = std::string_view{"UInt128_"}; if (dump.starts_with(prefix)) { UInt128 value = parseFromString(dump.substr(prefix.length())); return value; } prefix = std::string_view{"Int256_"}; if (dump.starts_with(prefix)) { Int256 value = parseFromString(dump.substr(prefix.length())); return value; } prefix = std::string_view{"UInt256_"}; if (dump.starts_with(prefix)) { UInt256 value = parseFromString(dump.substr(prefix.length())); return value; } prefix = std::string_view{"Float64_"}; if (dump.starts_with(prefix)) { Float64 value = parseFromString(dump.substr(prefix.length())); return value; } prefix = std::string_view{"Decimal32_"}; if (dump_.starts_with(prefix)) { DecimalField decimal; ReadBufferFromString buf{dump.substr(prefix.length())}; readQuoted(decimal, buf); return decimal; } prefix = std::string_view{"Decimal64_"}; if (dump_.starts_with(prefix)) { DecimalField decimal; ReadBufferFromString buf{dump.substr(prefix.length())}; readQuoted(decimal, buf); return decimal; } prefix = std::string_view{"Decimal128_"}; if (dump_.starts_with(prefix)) { DecimalField decimal; ReadBufferFromString buf{dump.substr(prefix.length())}; readQuoted(decimal, buf); return decimal; } prefix = std::string_view{"Decimal256_"}; if (dump_.starts_with(prefix)) { DecimalField decimal; ReadBufferFromString buf{dump.substr(prefix.length())}; readQuoted(decimal, buf); return decimal; } if (dump.starts_with("\'")) { String str; ReadBufferFromString buf{dump}; readQuoted(str, buf); return str; } prefix = std::string_view{"Bool_"}; if (dump.starts_with(prefix)) { bool value = parseFromString(dump.substr(prefix.length())); return value; } prefix = std::string_view{"Array_["}; if (dump.starts_with(prefix)) { std::string_view tail = dump.substr(prefix.length()); trimLeft(tail); Array array; while (tail != "]") { size_t separator = tail.find_first_of(",]"); if (separator == std::string_view::npos) show_error(); bool comma = (tail[separator] == ','); std::string_view element = tail.substr(0, separator); tail.remove_prefix(separator); if (comma) tail.remove_prefix(1); trimLeft(tail); if (!comma && tail != "]") show_error(); array.push_back(Field::restoreFromDump(element)); } return array; } prefix = std::string_view{"Tuple_("}; if (dump.starts_with(prefix)) { std::string_view tail = dump.substr(prefix.length()); trimLeft(tail); Tuple tuple; while (tail != ")") { size_t separator = tail.find_first_of(",)"); if (separator == std::string_view::npos) show_error(); bool comma = (tail[separator] == ','); std::string_view element = tail.substr(0, separator); tail.remove_prefix(separator); if (comma) tail.remove_prefix(1); trimLeft(tail); if (!comma && tail != ")") show_error(); tuple.push_back(Field::restoreFromDump(element)); } return tuple; } prefix = std::string_view{"Map_("}; if (dump.starts_with(prefix)) { std::string_view tail = dump.substr(prefix.length()); trimLeft(tail); Map map; while (tail != ")") { size_t separator = tail.find_first_of(",)"); if (separator == std::string_view::npos) show_error(); bool comma = (tail[separator] == ','); std::string_view element = tail.substr(0, separator); tail.remove_prefix(separator); if (comma) tail.remove_prefix(1); trimLeft(tail); if (!comma && tail != ")") show_error(); map.push_back(Field::restoreFromDump(element)); } return map; } prefix = std::string_view{"AggregateFunctionState_("}; if (dump.starts_with(prefix)) { std::string_view after_prefix = dump.substr(prefix.length()); size_t comma = after_prefix.find(','); size_t end = after_prefix.find(')', comma + 1); if ((comma == std::string_view::npos) || (end != after_prefix.length() - 1)) show_error(); std::string_view name_view = after_prefix.substr(0, comma); std::string_view data_view = after_prefix.substr(comma + 1, end - comma - 1); trim(name_view); trim(data_view); ReadBufferFromString name_buf{name_view}; ReadBufferFromString data_buf{data_view}; AggregateFunctionStateData res; readQuotedString(res.name, name_buf); readQuotedString(res.data, data_buf); return res; } show_error(); __builtin_unreachable(); } template bool decimalEqual(T x, T y, UInt32 x_scale, UInt32 y_scale) { using Comparator = DecimalComparison; return Comparator::compare(x, y, x_scale, y_scale); } template bool decimalLess(T x, T y, UInt32 x_scale, UInt32 y_scale) { using Comparator = DecimalComparison; return Comparator::compare(x, y, x_scale, y_scale); } template bool decimalLessOrEqual(T x, T y, UInt32 x_scale, UInt32 y_scale) { using Comparator = DecimalComparison; return Comparator::compare(x, y, x_scale, y_scale); } template bool decimalEqual(Decimal32 x, Decimal32 y, UInt32 x_scale, UInt32 y_scale); template bool decimalEqual(Decimal64 x, Decimal64 y, UInt32 x_scale, UInt32 y_scale); template bool decimalEqual(Decimal128 x, Decimal128 y, UInt32 x_scale, UInt32 y_scale); template bool decimalEqual(Decimal256 x, Decimal256 y, UInt32 x_scale, UInt32 y_scale); template bool decimalEqual(DateTime64 x, DateTime64 y, UInt32 x_scale, UInt32 y_scale); template bool decimalLess(Decimal32 x, Decimal32 y, UInt32 x_scale, UInt32 y_scale); template bool decimalLess(Decimal64 x, Decimal64 y, UInt32 x_scale, UInt32 y_scale); template bool decimalLess(Decimal128 x, Decimal128 y, UInt32 x_scale, UInt32 y_scale); template bool decimalLess(Decimal256 x, Decimal256 y, UInt32 x_scale, UInt32 y_scale); template bool decimalLess(DateTime64 x, DateTime64 y, UInt32 x_scale, UInt32 y_scale); template bool decimalLessOrEqual(Decimal32 x, Decimal32 y, UInt32 x_scale, UInt32 y_scale); template bool decimalLessOrEqual(Decimal64 x, Decimal64 y, UInt32 x_scale, UInt32 y_scale); template bool decimalLessOrEqual(Decimal128 x, Decimal128 y, UInt32 x_scale, UInt32 y_scale); template bool decimalLessOrEqual(Decimal256 x, Decimal256 y, UInt32 x_scale, UInt32 y_scale); template bool decimalLessOrEqual(DateTime64 x, DateTime64 y, UInt32 x_scale, UInt32 y_scale); inline void writeText(const Null & x, WriteBuffer & buf) { if (x.isNegativeInfinity()) writeText("-Inf", buf); if (x.isPositiveInfinity()) writeText("+Inf", buf); else writeText("NULL", buf); } String toString(const Field & x) { return Field::dispatch( [] (const auto & value) { // Use explicit type to prevent implicit construction of Field and // infinite recursion into toString. return toString(value); }, x); } }