mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-18 13:42:02 +00:00
d89ee33ce2
commitc567d4e1fe
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 20:35:01 2017 +0300 Style [#METR-2944]. commit26bf3e1228
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 20:33:11 2017 +0300 Miscellaneous [#METR-2944]. commiteb946f4c6f
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 20:30:19 2017 +0300 Miscellaneous [#METR-2944]. commit78c867a147
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 20:11:41 2017 +0300 Miscellaneous [#METR-2944]. commit6604c5c83c
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 19:56:15 2017 +0300 Miscellaneous [#METR-2944]. commit23fbf05c1d
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 19:47:52 2017 +0300 Miscellaneous [#METR-2944]. commit98772faf11
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 19:46:05 2017 +0300 Miscellaneous [#METR-2944]. commit3dc636ab9f
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 19:39:46 2017 +0300 Miscellaneous [#METR-2944]. commit3e16aee954
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 19:38:03 2017 +0300 Miscellaneous [#METR-2944]. commitae7e7e90eb
Author: Alexey Milovidov <milovidov@yandex-team.ru> Date: Fri Jan 6 19:34:15 2017 +0300 Miscellaneous [#METR-2944].
235 lines
5.8 KiB
C++
235 lines
5.8 KiB
C++
#include <DB/IO/ReadBuffer.h>
|
|
#include <DB/IO/WriteBuffer.h>
|
|
#include <DB/IO/ReadHelpers.h>
|
|
#include <DB/IO/WriteHelpers.h>
|
|
#include <DB/IO/ReadBufferFromString.h>
|
|
#include <DB/IO/WriteBufferFromString.h>
|
|
#include <DB/Core/FieldVisitors.h>
|
|
#include <DB/Common/SipHash.h>
|
|
|
|
|
|
namespace DB
|
|
{
|
|
|
|
|
|
template <typename T>
|
|
static inline String formatQuoted(T x)
|
|
{
|
|
String res;
|
|
WriteBufferFromString wb(res);
|
|
writeQuoted(x, wb);
|
|
return res;
|
|
}
|
|
|
|
template <typename T>
|
|
static inline String formatQuotedWithPrefix(T x, const char * prefix)
|
|
{
|
|
String res;
|
|
WriteBufferFromString wb(res);
|
|
wb.write(prefix, strlen(prefix));
|
|
writeQuoted(x, wb);
|
|
return res;
|
|
}
|
|
|
|
|
|
String FieldVisitorDump::operator() (const Null & x) const { return "NULL"; }
|
|
String FieldVisitorDump::operator() (const UInt64 & x) const { return formatQuotedWithPrefix(x, "UInt64_"); }
|
|
String FieldVisitorDump::operator() (const Int64 & x) const { return formatQuotedWithPrefix(x, "Int64_"); }
|
|
String FieldVisitorDump::operator() (const Float64 & x) const { return formatQuotedWithPrefix(x, "Float64_"); }
|
|
|
|
|
|
String FieldVisitorDump::operator() (const String & x) const
|
|
{
|
|
String res;
|
|
WriteBufferFromString wb(res);
|
|
writeQuoted(x, wb);
|
|
return res;
|
|
}
|
|
|
|
String FieldVisitorDump::operator() (const Array & x) const
|
|
{
|
|
String res;
|
|
WriteBufferFromString wb(res);
|
|
|
|
wb.write("Array_[", 7);
|
|
for (auto it = x.begin(); it != x.end(); ++it)
|
|
{
|
|
if (it != x.begin())
|
|
wb.write(", ", 2);
|
|
writeString(applyVisitor(*this, *it), wb);
|
|
}
|
|
writeChar(']', wb);
|
|
|
|
return res;
|
|
}
|
|
|
|
String FieldVisitorDump::operator() (const Tuple & x_def) const
|
|
{
|
|
auto & x = x_def.t;
|
|
String res;
|
|
WriteBufferFromString wb(res);
|
|
|
|
wb.write("Tuple_(", 7);
|
|
for (auto it = x.begin(); it != x.end(); ++it)
|
|
{
|
|
if (it != x.begin())
|
|
wb.write(", ", 2);
|
|
writeString(applyVisitor(*this, *it), wb);
|
|
}
|
|
writeChar(')', wb);
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
/** In contrast to writeFloatText (and writeQuoted),
|
|
* even if number looks like integer after formatting, prints decimal point nevertheless (for example, Float64(1) is printed as 1.).
|
|
* - because resulting text must be able to be parsed back as Float64 by query parser (otherwise it will be parsed as integer).
|
|
*
|
|
* Trailing zeros after decimal point are omitted.
|
|
*
|
|
* NOTE: Roundtrip may lead to loss of precision.
|
|
*/
|
|
static String formatFloat(const Float64 x)
|
|
{
|
|
DoubleConverter<true>::BufferType buffer;
|
|
double_conversion::StringBuilder builder{buffer, sizeof(buffer)};
|
|
|
|
const auto result = DoubleConverter<true>::instance().ToShortest(x, &builder);
|
|
|
|
if (!result)
|
|
throw Exception("Cannot print float or double number", ErrorCodes::CANNOT_PRINT_FLOAT_OR_DOUBLE_NUMBER);
|
|
|
|
return { buffer, buffer + builder.position() };
|
|
}
|
|
|
|
|
|
String FieldVisitorToString::operator() (const Null & x) const { return "NULL"; }
|
|
String FieldVisitorToString::operator() (const UInt64 & x) const { return formatQuoted(x); }
|
|
String FieldVisitorToString::operator() (const Int64 & x) const { return formatQuoted(x); }
|
|
String FieldVisitorToString::operator() (const Float64 & x) const { return formatFloat(x); }
|
|
String FieldVisitorToString::operator() (const String & x) const { return formatQuoted(x); }
|
|
|
|
|
|
String FieldVisitorToString::operator() (const Array & x) const
|
|
{
|
|
String res;
|
|
WriteBufferFromString wb(res);
|
|
|
|
writeChar('[', wb);
|
|
for (Array::const_iterator it = x.begin(); it != x.end(); ++it)
|
|
{
|
|
if (it != x.begin())
|
|
wb.write(", ", 2);
|
|
writeString(applyVisitor(*this, *it), wb);
|
|
}
|
|
writeChar(']', wb);
|
|
|
|
return res;
|
|
}
|
|
|
|
String FieldVisitorToString::operator() (const Tuple & x_def) const
|
|
{
|
|
auto & x = x_def.t;
|
|
String res;
|
|
WriteBufferFromString wb(res);
|
|
|
|
writeChar('(', wb);
|
|
for (auto it = x.begin(); it != x.end(); ++it)
|
|
{
|
|
if (it != x.begin())
|
|
wb.write(", ", 2);
|
|
writeString(applyVisitor(*this, *it), wb);
|
|
}
|
|
writeChar(')', wb);
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
FieldVisitorHash::FieldVisitorHash(SipHash & hash) : hash(hash) {}
|
|
|
|
void FieldVisitorHash::operator() (const Null & x) const
|
|
{
|
|
UInt8 type = Field::Types::Null;
|
|
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
|
}
|
|
|
|
void FieldVisitorHash::operator() (const UInt64 & x) const
|
|
{
|
|
UInt8 type = Field::Types::UInt64;
|
|
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
|
hash.update(reinterpret_cast<const char *>(&x), sizeof(x));
|
|
}
|
|
|
|
void FieldVisitorHash::operator() (const Int64 & x) const
|
|
{
|
|
UInt8 type = Field::Types::Int64;
|
|
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
|
hash.update(reinterpret_cast<const char *>(&x), sizeof(x));
|
|
}
|
|
|
|
void FieldVisitorHash::operator() (const Float64 & x) const
|
|
{
|
|
UInt8 type = Field::Types::Float64;
|
|
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
|
hash.update(reinterpret_cast<const char *>(&x), sizeof(x));
|
|
}
|
|
|
|
void FieldVisitorHash::operator() (const String & x) const
|
|
{
|
|
UInt8 type = Field::Types::String;
|
|
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
|
size_t size = x.size();
|
|
hash.update(reinterpret_cast<const char *>(&size), sizeof(size));
|
|
hash.update(x.data(), x.size());
|
|
}
|
|
|
|
void FieldVisitorHash::operator() (const Array & x) const
|
|
{
|
|
UInt8 type = Field::Types::Array;
|
|
hash.update(reinterpret_cast<const char *>(&type), sizeof(type));
|
|
size_t size = x.size();
|
|
hash.update(reinterpret_cast<const char *>(&size), sizeof(size));
|
|
|
|
for (const auto & elem : x)
|
|
applyVisitor(*this, elem);
|
|
}
|
|
|
|
|
|
UInt64 stringToDateOrDateTime(const String & s)
|
|
{
|
|
if (s.size() == strlen("YYYY-MM-DD"))
|
|
return stringToDate(s);
|
|
else
|
|
return stringToDateTime(s);
|
|
}
|
|
|
|
|
|
DayNum_t stringToDate(const String & s)
|
|
{
|
|
ReadBufferFromString in(s);
|
|
DayNum_t date{};
|
|
|
|
readDateText(date, in);
|
|
if (!in.eof())
|
|
throw Exception("String is too long for Date: " + s);
|
|
|
|
return date;
|
|
}
|
|
|
|
UInt64 stringToDateTime(const String & s)
|
|
{
|
|
ReadBufferFromString in(s);
|
|
time_t date_time{};
|
|
|
|
readDateTimeText(date_time, in);
|
|
if (!in.eof())
|
|
throw Exception("String is too long for DateTime: " + s);
|
|
|
|
return UInt64(date_time);
|
|
}
|
|
|
|
|
|
}
|