mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 23:52:03 +00:00
Fixed with BLOBs serialization [#CONV-4191].
This commit is contained in:
parent
51f4954d88
commit
313950c6c8
@ -6,6 +6,7 @@
|
||||
|
||||
#include <tr1/type_traits>
|
||||
|
||||
#include <Yandex/Common.h>
|
||||
#include <Yandex/DateLUT.h>
|
||||
|
||||
#include <mysqlxx/Date.h>
|
||||
@ -53,9 +54,9 @@ static inline void throwReadAfterEOF()
|
||||
}
|
||||
|
||||
|
||||
/// Чтение числа в native формате
|
||||
/// Чтение POD-типа в native формате
|
||||
template <typename T>
|
||||
inline void readBinary(T & x, ReadBuffer & buf)
|
||||
inline void readPODBinary(T & x, ReadBuffer & buf)
|
||||
{
|
||||
buf.readStrict(reinterpret_cast<char *>(&x), sizeof(x));
|
||||
}
|
||||
@ -63,13 +64,13 @@ inline void readBinary(T & x, ReadBuffer & buf)
|
||||
template <typename T>
|
||||
inline void readIntBinary(T & x, ReadBuffer & buf)
|
||||
{
|
||||
readBinary(x, buf);
|
||||
readPODBinary(x, buf);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void readFloatBinary(T & x, ReadBuffer & buf)
|
||||
{
|
||||
readBinary(x, buf);
|
||||
readPODBinary(x, buf);
|
||||
}
|
||||
|
||||
|
||||
@ -85,8 +86,6 @@ inline void readStringBinary(std::string & s, DB::ReadBuffer & buf, size_t MAX_S
|
||||
buf.readStrict(const_cast<char *>(s.data()), size);
|
||||
}
|
||||
|
||||
template <> inline void readBinary(std::string & s, DB::ReadBuffer & buf) { readStringBinary(s, buf); }
|
||||
|
||||
|
||||
inline void readChar(char & x, ReadBuffer & buf)
|
||||
{
|
||||
@ -352,60 +351,68 @@ inline void readDateTimeText(mysqlxx::DateTime & datetime, ReadBuffer & buf)
|
||||
}
|
||||
|
||||
|
||||
/// Общие методы для чтения значения в бинарном формате.
|
||||
inline void readBinary(UInt8 & x, ReadBuffer & buf) { readPODBinary(x, buf); }
|
||||
inline void readBinary(UInt16 & x, ReadBuffer & buf) { readPODBinary(x, buf); }
|
||||
inline void readBinary(UInt32 & x, ReadBuffer & buf) { readPODBinary(x, buf); }
|
||||
inline void readBinary(UInt64 & x, ReadBuffer & buf) { readPODBinary(x, buf); }
|
||||
inline void readBinary(Int8 & x, ReadBuffer & buf) { readPODBinary(x, buf); }
|
||||
inline void readBinary(Int16 & x, ReadBuffer & buf) { readPODBinary(x, buf); }
|
||||
inline void readBinary(Int32 & x, ReadBuffer & buf) { readPODBinary(x, buf); }
|
||||
inline void readBinary(Int64 & x, ReadBuffer & buf) { readPODBinary(x, buf); }
|
||||
inline void readBinary(Float32 & x, ReadBuffer & buf) { readPODBinary(x, buf); }
|
||||
inline void readBinary(Float64 & x, ReadBuffer & buf) { readPODBinary(x, buf); }
|
||||
inline void readBinary(String & x, ReadBuffer & buf) { readStringBinary(x, buf); }
|
||||
inline void readBinary(bool & x, ReadBuffer & buf) { readPODBinary(x, buf); }
|
||||
|
||||
inline void readBinary(Yandex::VisitID_t & x, ReadBuffer & buf) { readPODBinary(x, buf); }
|
||||
inline void readBinary(mysqlxx::Date & x, ReadBuffer & buf) { readPODBinary(x, buf); }
|
||||
inline void readBinary(mysqlxx::DateTime & x, ReadBuffer & buf) { readPODBinary(x, buf); }
|
||||
|
||||
|
||||
/// Общие методы для чтения значения в текстовом виде из tab-separated формата.
|
||||
template <typename T>
|
||||
void readText(T & x, ReadBuffer & buf)
|
||||
{
|
||||
/// Переношу ошибку в рантайм, так как метод требуется для компиляции DBObject-ов
|
||||
throw Exception("Method readText is not implemented for this type.", ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
inline void readText(UInt8 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
inline void readText(UInt16 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
inline void readText(UInt32 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
inline void readText(UInt64 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
inline void readText(Int8 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
inline void readText(Int16 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
inline void readText(Int32 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
inline void readText(Int64 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
inline void readText(Float32 & x, ReadBuffer & buf) { readFloatText(x, buf); }
|
||||
inline void readText(Float64 & x, ReadBuffer & buf) { readFloatText(x, buf); }
|
||||
inline void readText(String & x, ReadBuffer & buf) { readEscapedString(x, buf); }
|
||||
inline void readText(bool & x, ReadBuffer & buf) { readBoolText(x, buf); }
|
||||
|
||||
template <> inline void readText<UInt8> (UInt8 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
template <> inline void readText<UInt16> (UInt16 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
template <> inline void readText<UInt32> (UInt32 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
template <> inline void readText<UInt64> (UInt64 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
template <> inline void readText<Int8> (Int8 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
template <> inline void readText<Int16> (Int16 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
template <> inline void readText<Int32> (Int32 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
template <> inline void readText<Int64> (Int64 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
template <> inline void readText<Float32> (Float32 & x, ReadBuffer & buf) { readFloatText(x, buf); }
|
||||
template <> inline void readText<Float64> (Float64 & x, ReadBuffer & buf) { readFloatText(x, buf); }
|
||||
template <> inline void readText<String> (String & x, ReadBuffer & buf) { readEscapedString(x, buf); }
|
||||
template <> inline void readText<bool> (bool & x, ReadBuffer & buf) { readBoolText(x, buf); }
|
||||
|
||||
template <> inline void readText<mysqlxx::Date> (mysqlxx::Date & x, ReadBuffer & buf) { readDateText(x, buf); }
|
||||
template <> inline void readText<mysqlxx::DateTime> (mysqlxx::DateTime & x, ReadBuffer & buf) { readDateTimeText(x, buf); }
|
||||
inline void readText(Yandex::VisitID_t & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
inline void readText(mysqlxx::Date & x, ReadBuffer & buf) { readDateText(x, buf); }
|
||||
inline void readText(mysqlxx::DateTime & x, ReadBuffer & buf) { readDateTimeText(x, buf); }
|
||||
|
||||
|
||||
/// Общие методы для чтения значения в текстовом виде, при необходимости, в кавычках.
|
||||
template <typename T>
|
||||
void readQuoted(T & x, ReadBuffer & buf)
|
||||
{
|
||||
/// Переношу ошибку в рантайм, так как метод требуется для компиляции DBObject-ов
|
||||
throw Exception("Method readQuoted is not implemented for this type.", ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
inline void readQuoted(UInt8 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
inline void readQuoted(UInt16 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
inline void readQuoted(UInt32 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
inline void readQuoted(UInt64 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
inline void readQuoted(Int8 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
inline void readQuoted(Int16 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
inline void readQuoted(Int32 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
inline void readQuoted(Int64 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
inline void readQuoted(Float32 & x, ReadBuffer & buf) { readFloatText(x, buf); }
|
||||
inline void readQuoted(Float64 & x, ReadBuffer & buf) { readFloatText(x, buf); }
|
||||
inline void readQuoted(String & x, ReadBuffer & buf) { readQuotedString(x, buf); }
|
||||
inline void readQuoted(bool & x, ReadBuffer & buf) { readBoolText(x, buf); }
|
||||
|
||||
template <> inline void readQuoted<UInt8> (UInt8 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
template <> inline void readQuoted<UInt16> (UInt16 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
template <> inline void readQuoted<UInt32> (UInt32 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
template <> inline void readQuoted<UInt64> (UInt64 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
template <> inline void readQuoted<Int8> (Int8 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
template <> inline void readQuoted<Int16> (Int16 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
template <> inline void readQuoted<Int32> (Int32 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
template <> inline void readQuoted<Int64> (Int64 & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
template <> inline void readQuoted<Float32> (Float32 & x, ReadBuffer & buf) { readFloatText(x, buf); }
|
||||
template <> inline void readQuoted<Float64> (Float64 & x, ReadBuffer & buf) { readFloatText(x, buf); }
|
||||
template <> inline void readQuoted<String> (String & x, ReadBuffer & buf) { readQuotedString(x, buf); }
|
||||
template <> inline void readQuoted<bool> (bool & x, ReadBuffer & buf) { readBoolText(x, buf); }
|
||||
inline void readQuoted(Yandex::VisitID_t & x, ReadBuffer & buf) { readIntText(x, buf); }
|
||||
|
||||
template <> inline void readQuoted<mysqlxx::Date> (mysqlxx::Date & x, ReadBuffer & buf)
|
||||
inline void readQuoted(mysqlxx::Date & x, ReadBuffer & buf)
|
||||
{
|
||||
assertString("'", buf);
|
||||
readDateText(x, buf);
|
||||
assertString("'", buf);
|
||||
}
|
||||
|
||||
template <> inline void readQuoted<mysqlxx::DateTime> (mysqlxx::DateTime & x, ReadBuffer & buf)
|
||||
inline void readQuoted(mysqlxx::DateTime & x, ReadBuffer & buf)
|
||||
{
|
||||
assertString("'", buf);
|
||||
readDateTimeText(x, buf);
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <limits>
|
||||
#include <algorithm>
|
||||
|
||||
#include <Yandex/Common.h>
|
||||
#include <Yandex/DateLUT.h>
|
||||
|
||||
#include <mysqlxx/Row.h>
|
||||
@ -34,9 +35,9 @@ inline void writeChar(char x, WriteBuffer & buf)
|
||||
}
|
||||
|
||||
|
||||
/// Запись числа в native формате
|
||||
/// Запись POD-типа в native формате
|
||||
template <typename T>
|
||||
inline void writeBinary(const T & x, WriteBuffer & buf)
|
||||
inline void writePODBinary(const T & x, WriteBuffer & buf)
|
||||
{
|
||||
buf.write(reinterpret_cast<const char *>(&x), sizeof(x));
|
||||
}
|
||||
@ -44,13 +45,13 @@ inline void writeBinary(const T & x, WriteBuffer & buf)
|
||||
template <typename T>
|
||||
inline void writeIntBinary(const T & x, WriteBuffer & buf)
|
||||
{
|
||||
writeBinary(x, buf);
|
||||
writePODBinary(x, buf);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void writeFloatBinary(const T & x, WriteBuffer & buf)
|
||||
{
|
||||
writeBinary(x, buf);
|
||||
writePODBinary(x, buf);
|
||||
}
|
||||
|
||||
|
||||
@ -60,8 +61,6 @@ inline void writeStringBinary(const std::string & s, DB::WriteBuffer & buf)
|
||||
buf.write(s.data(), s.size());
|
||||
}
|
||||
|
||||
template <> inline void writeBinary(const std::string & s, DB::WriteBuffer & buf) { writeStringBinary(s, buf); }
|
||||
|
||||
|
||||
inline void writeBoolText(bool x, WriteBuffer & buf)
|
||||
{
|
||||
@ -353,60 +352,71 @@ inline void writeEscapedRow(const mysqlxx::Row & row, WriteBuffer & buf)
|
||||
}
|
||||
|
||||
|
||||
/// Общие методы для вывода значения в текстовом виде для tab-separated формата.
|
||||
template <typename T>
|
||||
void writeText(const T & x, WriteBuffer & buf)
|
||||
/// Методы вывода в бинарном виде
|
||||
inline void writeBinary(const UInt8 & x, WriteBuffer & buf) { writePODBinary(x, buf); }
|
||||
inline void writeBinary(const UInt16 & x, WriteBuffer & buf) { writePODBinary(x, buf); }
|
||||
inline void writeBinary(const UInt32 & x, WriteBuffer & buf) { writePODBinary(x, buf); }
|
||||
inline void writeBinary(const UInt64 & x, WriteBuffer & buf) { writePODBinary(x, buf); }
|
||||
inline void writeBinary(const Int8 & x, WriteBuffer & buf) { writePODBinary(x, buf); }
|
||||
inline void writeBinary(const Int16 & x, WriteBuffer & buf) { writePODBinary(x, buf); }
|
||||
inline void writeBinary(const Int32 & x, WriteBuffer & buf) { writePODBinary(x, buf); }
|
||||
inline void writeBinary(const Int64 & x, WriteBuffer & buf) { writePODBinary(x, buf); }
|
||||
inline void writeBinary(const Float32 & x, WriteBuffer & buf) { writePODBinary(x, buf); }
|
||||
inline void writeBinary(const Float64 & x, WriteBuffer & buf) { writePODBinary(x, buf); }
|
||||
inline void writeBinary(const String & x, WriteBuffer & buf) { writeStringBinary(x, buf); }
|
||||
inline void writeBinary(const bool & x, WriteBuffer & buf) { writePODBinary(x, buf); }
|
||||
|
||||
inline void writeBinary(const Yandex::VisitID_t & x, WriteBuffer & buf) { writePODBinary(static_cast<const UInt64 &>(x), buf); }
|
||||
inline void writeBinary(const mysqlxx::Date & x, WriteBuffer & buf) { writePODBinary(x, buf); }
|
||||
inline void writeBinary(const mysqlxx::DateTime & x, WriteBuffer & buf) { writePODBinary(x, buf); }
|
||||
|
||||
|
||||
/// Методы для вывода значения в текстовом виде для tab-separated формата.
|
||||
inline void writeText(const UInt8 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
inline void writeText(const UInt16 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
inline void writeText(const UInt32 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
inline void writeText(const UInt64 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
inline void writeText(const Int8 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
inline void writeText(const Int16 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
inline void writeText(const Int32 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
inline void writeText(const Int64 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
inline void writeText(const Float32 & x, WriteBuffer & buf) { writeFloatText(x, buf); }
|
||||
inline void writeText(const Float64 & x, WriteBuffer & buf) { writeFloatText(x, buf); }
|
||||
inline void writeText(const String & x, WriteBuffer & buf) { writeEscapedString(x, buf); }
|
||||
inline void writeText(const bool & x, WriteBuffer & buf) { writeBoolText(x, buf); }
|
||||
|
||||
inline void writeText(const Yandex::VisitID_t & x, WriteBuffer & buf) { writeIntText(static_cast<const UInt64 &>(x), buf); }
|
||||
inline void writeText(const mysqlxx::Date & x, WriteBuffer & buf) { writeDateText(x, buf); }
|
||||
inline void writeText(const mysqlxx::DateTime & x, WriteBuffer & buf) { writeDateTimeText(x, buf); }
|
||||
|
||||
|
||||
/// Методы для вывода в текстовом виде в кавычках
|
||||
inline void writeQuoted(const UInt8 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
inline void writeQuoted(const UInt16 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
inline void writeQuoted(const UInt32 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
inline void writeQuoted(const UInt64 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
inline void writeQuoted(const Int8 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
inline void writeQuoted(const Int16 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
inline void writeQuoted(const Int32 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
inline void writeQuoted(const Int64 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
inline void writeQuoted(const Float32 & x, WriteBuffer & buf) { writeFloatText(x, buf); }
|
||||
inline void writeQuoted(const Float64 & x, WriteBuffer & buf) { writeFloatText(x, buf); }
|
||||
inline void writeQuoted(const String & x, WriteBuffer & buf) { writeQuotedString(x, buf); }
|
||||
inline void writeQuoted(const bool & x, WriteBuffer & buf) { writeBoolText(x, buf); }
|
||||
|
||||
inline void writeQuoted(const Yandex::VisitID_t & x, WriteBuffer & buf)
|
||||
{
|
||||
/// Переношу ошибку в рантайм, так как метод требуется для компиляции DBObject-ов
|
||||
throw Exception("Method writeText is not implemented for this type.", ErrorCodes::NOT_IMPLEMENTED);
|
||||
writeIntText(static_cast<const UInt64 &>(x), buf);
|
||||
}
|
||||
|
||||
template <> inline void writeText<UInt8> (const UInt8 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
template <> inline void writeText<UInt16> (const UInt16 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
template <> inline void writeText<UInt32> (const UInt32 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
template <> inline void writeText<UInt64> (const UInt64 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
template <> inline void writeText<Int8> (const Int8 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
template <> inline void writeText<Int16> (const Int16 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
template <> inline void writeText<Int32> (const Int32 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
template <> inline void writeText<Int64> (const Int64 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
template <> inline void writeText<Float32> (const Float32 & x, WriteBuffer & buf) { writeFloatText(x, buf); }
|
||||
template <> inline void writeText<Float64> (const Float64 & x, WriteBuffer & buf) { writeFloatText(x, buf); }
|
||||
template <> inline void writeText<String> (const String & x, WriteBuffer & buf) { writeEscapedString(x, buf); }
|
||||
template <> inline void writeText<bool> (const bool & x, WriteBuffer & buf) { writeBoolText(x, buf); }
|
||||
|
||||
template <> inline void writeText<mysqlxx::Date> (const mysqlxx::Date & x, WriteBuffer & buf) { writeDateText(x, buf); }
|
||||
template <> inline void writeText<mysqlxx::DateTime> (const mysqlxx::DateTime & x, WriteBuffer & buf) { writeDateTimeText(x, buf); }
|
||||
|
||||
|
||||
/// Общие методы для вывода значения в текстовом виде, при необходимости, в кавычках.
|
||||
template <typename T>
|
||||
void writeQuoted(const T & x, WriteBuffer & buf)
|
||||
{
|
||||
/// Переношу ошибку в рантайм, так как метод требуется для компиляции DBObject-ов
|
||||
throw Exception("Method writeQuoted is not implemented for this type.", ErrorCodes::NOT_IMPLEMENTED);
|
||||
}
|
||||
|
||||
template <> inline void writeQuoted<UInt8> (const UInt8 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
template <> inline void writeQuoted<UInt16> (const UInt16 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
template <> inline void writeQuoted<UInt32> (const UInt32 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
template <> inline void writeQuoted<UInt64> (const UInt64 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
template <> inline void writeQuoted<Int8> (const Int8 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
template <> inline void writeQuoted<Int16> (const Int16 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
template <> inline void writeQuoted<Int32> (const Int32 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
template <> inline void writeQuoted<Int64> (const Int64 & x, WriteBuffer & buf) { writeIntText(x, buf); }
|
||||
template <> inline void writeQuoted<Float32> (const Float32 & x, WriteBuffer & buf) { writeFloatText(x, buf); }
|
||||
template <> inline void writeQuoted<Float64> (const Float64 & x, WriteBuffer & buf) { writeFloatText(x, buf); }
|
||||
template <> inline void writeQuoted<String> (const String & x, WriteBuffer & buf) { writeQuotedString(x, buf); }
|
||||
template <> inline void writeQuoted<bool> (const bool & x, WriteBuffer & buf) { writeBoolText(x, buf); }
|
||||
|
||||
template <> inline void writeQuoted<mysqlxx::Date> (const mysqlxx::Date & x, WriteBuffer & buf)
|
||||
inline void writeQuoted(const mysqlxx::Date & x, WriteBuffer & buf)
|
||||
{
|
||||
writeChar('\'', buf);
|
||||
writeDateText(x, buf);
|
||||
writeChar('\'', buf);
|
||||
}
|
||||
|
||||
template <> inline void writeQuoted<mysqlxx::DateTime> (const mysqlxx::DateTime & x, WriteBuffer & buf)
|
||||
inline void writeQuoted(const mysqlxx::DateTime & x, WriteBuffer & buf)
|
||||
{
|
||||
writeChar('\'', buf);
|
||||
writeDateTimeText(x, buf);
|
||||
|
Loading…
Reference in New Issue
Block a user