SSQLS: added methods to read/write in tab-separated format with ReadBuffer/WriteBuffer [#CONV-3632].

This commit is contained in:
Alexey Milovidov 2011-11-21 10:09:22 +00:00
parent eff4e7a65f
commit b595e61c03
2 changed files with 169 additions and 30 deletions

View File

@ -8,6 +8,9 @@
#include <Yandex/DateLUT.h>
#include <mysqlxx/Date.h>
#include <mysqlxx/DateTime.h>
#include <DB/Core/Types.h>
#include <DB/Core/Exception.h>
#include <DB/Core/ErrorCodes.h>
@ -96,7 +99,15 @@ inline void readChar(char & x, ReadBuffer & buf)
void assertString(const char * s, ReadBuffer & buf);
/// грубо
inline void readBoolText(bool & x, ReadBuffer & buf)
{
char tmp = '0';
readChar(tmp, buf);
x = tmp != '0';
}
template <typename T>
void readIntText(T & x, ReadBuffer & buf)
{
@ -250,20 +261,6 @@ void readFloatText(T & x, ReadBuffer & buf)
x = -x;
}
template <typename T>
void readText(T & x, ReadBuffer & 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); }
/// грубо; всё до '\n' или '\t'
void readString(String & s, ReadBuffer & buf);
@ -295,6 +292,21 @@ inline void readDateText(Yandex::DayNum_t & date, ReadBuffer & buf)
date = Yandex::DateLUTSingleton::instance().makeDayNum(year, month, day);
}
inline void readDateText(mysqlxx::Date & date, ReadBuffer & buf)
{
char s[10];
size_t size = buf.read(s, 10);
if (10 != size)
{
s[size] = 0;
throw Exception(std::string("Cannot parse date ") + s, ErrorCodes::CANNOT_PARSE_DATE);
}
date.year((s[0] - '0') * 1000 + (s[1] - '0') * 100 + (s[2] - '0') * 10 + (s[3] - '0'));
date.month((s[5] - '0') * 10 + (s[6] - '0'));
date.day((s[8] - '0') * 10 + (s[9] - '0'));
}
/// в формате YYYY-MM-DD HH:MM:SS, согласно текущему часовому поясу
inline void readDateTimeText(time_t & datetime, ReadBuffer & buf)
@ -318,6 +330,49 @@ inline void readDateTimeText(time_t & datetime, ReadBuffer & buf)
datetime = Yandex::DateLUTSingleton::instance().makeDateTime(year, month, day, hour, minute, second);
}
inline void readDateTimeText(mysqlxx::DateTime & datetime, ReadBuffer & buf)
{
char s[19];
size_t size = buf.read(s, 19);
if (19 != size)
{
s[size] = 0;
throw Exception(std::string("Cannot parse datetime ") + s, ErrorCodes::CANNOT_PARSE_DATETIME);
}
datetime.year((s[0] - '0') * 1000 + (s[1] - '0') * 100 + (s[2] - '0') * 10 + (s[3] - '0'));
datetime.month((s[5] - '0') * 10 + (s[6] - '0'));
datetime.day((s[8] - '0') * 10 + (s[9] - '0'));
datetime.hour((s[11] - '0') * 10 + (s[12] - '0'));
datetime.minute((s[14] - '0') * 10 + (s[15] - '0'));
datetime.second((s[17] - '0') * 10 + (s[18] - '0'));
}
template <typename T>
void readText(T & x, ReadBuffer & buf)
{
/// Переношу ошибку в рантайм, так как метод требуется для компиляции DBObject-ов
throw Exception("Method readText is not implemented for this type.", ErrorCodes::NOT_IMPLEMENTED);
}
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 skipWhitespaceIfAny(ReadBuffer & buf)

View File

@ -7,6 +7,8 @@
#include <Yandex/DateLUT.h>
#include <mysqlxx/Row.h>
#include <DB/Core/Types.h>
#include <DB/Core/Exception.h>
#include <DB/Core/ErrorCodes.h>
@ -59,6 +61,12 @@ inline void writeStringBinary(const std::string & s, DB::WriteBuffer & buf)
}
inline void writeBoolText(bool x, WriteBuffer & buf)
{
writeChar(x ? '1' : '0', buf);
}
template <typename T>
void writeIntText(T x, WriteBuffer & buf)
{
@ -105,19 +113,6 @@ void writeFloatText(T x, WriteBuffer & buf, unsigned precision = WRITE_HELPERS_D
buf.write(tmp, res);
}
template <typename T>
void writeText(T x, WriteBuffer & buf);
template <> inline void writeText<UInt8> (UInt8 x, WriteBuffer & buf) { writeIntText(x, buf); }
template <> inline void writeText<UInt16> (UInt16 x, WriteBuffer & buf) { writeIntText(x, buf); }
template <> inline void writeText<UInt32> (UInt32 x, WriteBuffer & buf) { writeIntText(x, buf); }
template <> inline void writeText<UInt64> (UInt64 x, WriteBuffer & buf) { writeIntText(x, buf); }
template <> inline void writeText<Int8> (Int8 x, WriteBuffer & buf) { writeIntText(x, buf); }
template <> inline void writeText<Int16> (Int16 x, WriteBuffer & buf) { writeIntText(x, buf); }
template <> inline void writeText<Int32> (Int32 x, WriteBuffer & buf) { writeIntText(x, buf); }
template <> inline void writeText<Int64> (Int64 x, WriteBuffer & buf) { writeIntText(x, buf); }
template <> inline void writeText<Float32> (Float32 x, WriteBuffer & buf) { writeFloatText(x, buf); }
template <> inline void writeText<Float64> (Float64 x, WriteBuffer & buf) { writeFloatText(x, buf); }
inline void writeString(const String & s, WriteBuffer & buf)
{
@ -126,9 +121,9 @@ inline void writeString(const String & s, WriteBuffer & buf)
template <char c>
void writeAnyEscapedString(const String & s, WriteBuffer & buf)
void writeAnyEscapedString(const char * begin, const char * end, WriteBuffer & buf)
{
for (String::const_iterator it = s.begin(); it != s.end(); ++it)
for (const char * it = begin; it != end; ++it)
{
switch (*it)
{
@ -171,6 +166,13 @@ void writeAnyEscapedString(const String & s, WriteBuffer & buf)
}
template <char c>
void writeAnyEscapedString(const String & s, WriteBuffer & buf)
{
writeAnyEscapedString<c>(s.data(), s.data() + s.size(), buf);
}
inline void writeEscapedString(const String & s, WriteBuffer & buf)
{
writeAnyEscapedString<'\''>(s, buf);
@ -248,6 +250,22 @@ inline void writeDateText(Yandex::DayNum_t date, WriteBuffer & buf)
buf.write(s, 10);
}
inline void writeDateText(mysqlxx::Date date, WriteBuffer & buf)
{
char s[10] = {'0', '0', '0', '0', '-', '0', '0', '-', '0', '0'};
s[0] += date.year() / 1000;
s[1] += (date.year() / 100) % 10;
s[2] += (date.year() / 10) % 10;
s[3] += date.year() % 10;
s[5] += date.month() / 10;
s[6] += date.month() % 10;
s[8] += date.day() / 10;
s[9] += date.day() % 10;
buf.write(s, 10);
}
/// в формате YYYY-MM-DD HH:MM:SS, согласно текущему часовому поясу
inline void writeDateTimeText(time_t datetime, WriteBuffer & buf)
@ -286,5 +304,71 @@ inline void writeDateTimeText(time_t datetime, WriteBuffer & buf)
buf.write(s, 19);
}
inline void writeDateTimeText(mysqlxx::DateTime datetime, WriteBuffer & buf)
{
char s[19] = {'0', '0', '0', '0', '-', '0', '0', '-', '0', '0', ' ', '0', '0', ':', '0', '0', ':', '0', '0'};
s[0] += datetime.year() / 1000;
s[1] += (datetime.year() / 100) % 10;
s[2] += (datetime.year() / 10) % 10;
s[3] += datetime.year() % 10;
s[5] += datetime.month() / 10;
s[6] += datetime.month() % 10;
s[8] += datetime.day() / 10;
s[9] += datetime.day() % 10;
s[11] += datetime.hour() / 10;
s[12] += datetime.hour() % 10;
s[14] += datetime.minute() / 10;
s[15] += datetime.minute() % 10;
s[17] += datetime.second() / 10;
s[18] += datetime.second() % 10;
buf.write(s, 19);
}
/// Вывести mysqlxx::Row в tab-separated виде
inline void writeEscapedRow(const mysqlxx::Row & row, WriteBuffer & buf)
{
for (size_t i = 0; i < row.size(); ++i)
{
if (i != 0)
buf.write('\t');
if (unlikely(row[i].isNull()))
{
buf.write("\\N", 2);
continue;
}
writeAnyEscapedString<'\''>(row[i].data(), row[i].data() + row[i].length(), buf);
}
}
template <typename T>
void writeText(const T & x, WriteBuffer & buf)
{
/// Переношу ошибку в рантайм, так как метод требуется для компиляции DBObject-ов
throw Exception("Method writeText is not implemented for this type.", ErrorCodes::NOT_IMPLEMENTED);
}
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); }
}