2018-08-29 11:58:40 +00:00
|
|
|
#include <Core/UUID.h>
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <IO/ReadBuffer.h>
|
|
|
|
#include <IO/WriteBuffer.h>
|
|
|
|
#include <IO/WriteHelpers.h>
|
|
|
|
#include <IO/WriteBufferFromString.h>
|
2018-08-03 20:25:47 +00:00
|
|
|
#include <IO/Operators.h>
|
2017-11-24 13:55:31 +00:00
|
|
|
#include <Common/FieldVisitors.h>
|
2017-04-01 09:19:00 +00:00
|
|
|
#include <Common/SipHash.h>
|
2015-10-12 07:05:54 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
2020-02-25 18:10:48 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int CANNOT_PRINT_FLOAT_OR_DOUBLE_NUMBER;
|
|
|
|
}
|
2015-10-12 07:05:54 +00:00
|
|
|
|
2017-01-06 17:41:19 +00:00
|
|
|
template <typename T>
|
|
|
|
static inline String formatQuoted(T x)
|
2015-10-12 07:05:54 +00:00
|
|
|
{
|
2017-07-31 21:39:24 +00:00
|
|
|
WriteBufferFromOwnString wb;
|
2017-04-01 07:20:54 +00:00
|
|
|
writeQuoted(x, wb);
|
2017-07-31 21:39:24 +00:00
|
|
|
return wb.str();
|
2015-10-12 07:05:54 +00:00
|
|
|
}
|
|
|
|
|
2017-01-06 17:41:19 +00:00
|
|
|
template <typename T>
|
|
|
|
static inline String formatQuotedWithPrefix(T x, const char * prefix)
|
|
|
|
{
|
2017-07-31 21:39:24 +00:00
|
|
|
WriteBufferFromOwnString wb;
|
2017-04-01 07:20:54 +00:00
|
|
|
wb.write(prefix, strlen(prefix));
|
|
|
|
writeQuoted(x, wb);
|
2017-07-31 21:39:24 +00:00
|
|
|
return wb.str();
|
2017-01-06 17:41:19 +00:00
|
|
|
}
|
|
|
|
|
2018-08-23 19:11:31 +00:00
|
|
|
template <typename T>
|
|
|
|
static inline void writeQuoted(const DecimalField<T> & x, WriteBuffer & buf)
|
|
|
|
{
|
|
|
|
writeChar('\'', buf);
|
|
|
|
writeText(x.getValue(), x.getScale(), buf);
|
|
|
|
writeChar('\'', buf);
|
|
|
|
}
|
|
|
|
|
2017-12-01 17:49:12 +00:00
|
|
|
String FieldVisitorDump::operator() (const Null &) const { return "NULL"; }
|
2017-07-31 21:39:24 +00:00
|
|
|
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_"); }
|
2018-08-23 19:11:31 +00:00
|
|
|
String FieldVisitorDump::operator() (const DecimalField<Decimal32> & x) const { return formatQuotedWithPrefix(x, "Decimal32_"); }
|
|
|
|
String FieldVisitorDump::operator() (const DecimalField<Decimal64> & x) const { return formatQuotedWithPrefix(x, "Decimal64_"); }
|
|
|
|
String FieldVisitorDump::operator() (const DecimalField<Decimal128> & x) const { return formatQuotedWithPrefix(x, "Decimal128_"); }
|
2020-08-19 11:52:17 +00:00
|
|
|
String FieldVisitorDump::operator() (const DecimalField<Decimal256> & x) const { return formatQuotedWithPrefix(x, "Decimal256_"); }
|
|
|
|
String FieldVisitorDump::operator() (const bUInt256 & x) const { return formatQuotedWithPrefix(x, "UInt256_"); }
|
|
|
|
String FieldVisitorDump::operator() (const bInt256 & x) const { return formatQuotedWithPrefix(x, "Int256_"); }
|
|
|
|
String FieldVisitorDump::operator() (const Int128 & x) const { return formatQuotedWithPrefix(x, "Int128_"); }
|
2018-08-29 11:58:40 +00:00
|
|
|
String FieldVisitorDump::operator() (const UInt128 & x) const { return formatQuotedWithPrefix(UUID(x), "UUID_"); }
|
2017-01-06 17:41:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
String FieldVisitorDump::operator() (const String & x) const
|
|
|
|
{
|
2017-07-31 21:39:24 +00:00
|
|
|
WriteBufferFromOwnString wb;
|
2017-04-01 07:20:54 +00:00
|
|
|
writeQuoted(x, wb);
|
2017-07-31 21:39:24 +00:00
|
|
|
return wb.str();
|
2017-01-06 17:41:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
String FieldVisitorDump::operator() (const Array & x) const
|
2015-10-12 07:05:54 +00:00
|
|
|
{
|
2017-07-31 21:39:24 +00:00
|
|
|
WriteBufferFromOwnString wb;
|
2015-10-12 07:05:54 +00:00
|
|
|
|
2018-08-03 20:25:47 +00:00
|
|
|
wb << "Array_[";
|
2017-04-01 07:20:54 +00:00
|
|
|
for (auto it = x.begin(); it != x.end(); ++it)
|
|
|
|
{
|
|
|
|
if (it != x.begin())
|
2018-08-03 20:25:47 +00:00
|
|
|
wb << ", ";
|
|
|
|
wb << applyVisitor(*this, *it);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2018-08-03 20:25:47 +00:00
|
|
|
wb << ']';
|
2015-10-12 07:05:54 +00:00
|
|
|
|
2017-07-31 21:39:24 +00:00
|
|
|
return wb.str();
|
2015-10-12 07:05:54 +00:00
|
|
|
}
|
|
|
|
|
2019-10-18 15:57:05 +00:00
|
|
|
String FieldVisitorDump::operator() (const Tuple & x) const
|
2015-12-24 14:31:41 +00:00
|
|
|
{
|
2017-07-31 21:39:24 +00:00
|
|
|
WriteBufferFromOwnString wb;
|
2015-12-24 14:31:41 +00:00
|
|
|
|
2018-08-03 20:25:47 +00:00
|
|
|
wb << "Tuple_(";
|
2017-04-01 07:20:54 +00:00
|
|
|
for (auto it = x.begin(); it != x.end(); ++it)
|
|
|
|
{
|
|
|
|
if (it != x.begin())
|
2018-08-03 20:25:47 +00:00
|
|
|
wb << ", ";
|
|
|
|
wb << applyVisitor(*this, *it);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2018-08-03 20:25:47 +00:00
|
|
|
wb << ')';
|
2015-12-24 14:31:41 +00:00
|
|
|
|
2017-07-31 21:39:24 +00:00
|
|
|
return wb.str();
|
2015-12-24 14:31:41 +00:00
|
|
|
}
|
|
|
|
|
2019-02-11 11:19:56 +00:00
|
|
|
String FieldVisitorDump::operator() (const AggregateFunctionStateData & x) const
|
|
|
|
{
|
|
|
|
WriteBufferFromOwnString wb;
|
2020-07-28 12:37:44 +00:00
|
|
|
wb << "AggregateFunctionState_(";
|
2019-02-11 13:11:52 +00:00
|
|
|
writeQuoted(x.name, wb);
|
2020-07-28 12:37:44 +00:00
|
|
|
wb << ", ";
|
2019-02-11 13:11:52 +00:00
|
|
|
writeQuoted(x.data, wb);
|
2020-07-28 12:37:44 +00:00
|
|
|
wb << ')';
|
2019-02-11 11:19:56 +00:00
|
|
|
return wb.str();
|
|
|
|
}
|
2015-10-12 07:05:54 +00:00
|
|
|
|
2017-01-06 17:41:19 +00:00
|
|
|
/** 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)
|
2015-10-12 07:05:54 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
DoubleConverter<true>::BufferType buffer;
|
|
|
|
double_conversion::StringBuilder builder{buffer, sizeof(buffer)};
|
2015-10-12 07:05:54 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
const auto result = DoubleConverter<true>::instance().ToShortest(x, &builder);
|
2015-10-12 07:05:54 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
if (!result)
|
|
|
|
throw Exception("Cannot print float or double number", ErrorCodes::CANNOT_PRINT_FLOAT_OR_DOUBLE_NUMBER);
|
2015-10-12 07:05:54 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
return { buffer, buffer + builder.position() };
|
2015-10-12 07:05:54 +00:00
|
|
|
}
|
|
|
|
|
2017-01-06 17:41:19 +00:00
|
|
|
|
2017-12-01 17:49:12 +00:00
|
|
|
String FieldVisitorToString::operator() (const Null &) const { return "NULL"; }
|
2017-07-31 21:39:24 +00:00
|
|
|
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); }
|
2018-08-23 19:11:31 +00:00
|
|
|
String FieldVisitorToString::operator() (const DecimalField<Decimal32> & x) const { return formatQuoted(x); }
|
|
|
|
String FieldVisitorToString::operator() (const DecimalField<Decimal64> & x) const { return formatQuoted(x); }
|
|
|
|
String FieldVisitorToString::operator() (const DecimalField<Decimal128> & x) const { return formatQuoted(x); }
|
2020-08-19 11:52:17 +00:00
|
|
|
String FieldVisitorToString::operator() (const DecimalField<Decimal256> & x) const { return formatQuoted(x); }
|
|
|
|
String FieldVisitorToString::operator() (const Int128 & x) const { return formatQuoted(x); }
|
2018-08-29 11:58:40 +00:00
|
|
|
String FieldVisitorToString::operator() (const UInt128 & x) const { return formatQuoted(UUID(x)); }
|
2019-02-11 13:11:52 +00:00
|
|
|
String FieldVisitorToString::operator() (const AggregateFunctionStateData & x) const
|
|
|
|
{
|
2019-09-02 09:16:49 +00:00
|
|
|
return formatQuoted(x.data);
|
2019-02-11 13:11:52 +00:00
|
|
|
}
|
2020-08-19 11:52:17 +00:00
|
|
|
String FieldVisitorToString::operator() (const bUInt256 & x) const { return formatQuoted(x); }
|
|
|
|
String FieldVisitorToString::operator() (const bInt256 & x) const { return formatQuoted(x); }
|
2017-01-06 17:41:19 +00:00
|
|
|
|
|
|
|
String FieldVisitorToString::operator() (const Array & x) const
|
2015-10-12 07:05:54 +00:00
|
|
|
{
|
2017-07-31 21:39:24 +00:00
|
|
|
WriteBufferFromOwnString wb;
|
2015-10-12 07:05:54 +00:00
|
|
|
|
2018-08-03 20:25:47 +00:00
|
|
|
wb << '[';
|
2017-04-01 07:20:54 +00:00
|
|
|
for (Array::const_iterator it = x.begin(); it != x.end(); ++it)
|
|
|
|
{
|
|
|
|
if (it != x.begin())
|
|
|
|
wb.write(", ", 2);
|
2018-08-03 20:25:47 +00:00
|
|
|
wb << applyVisitor(*this, *it);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2018-08-03 20:25:47 +00:00
|
|
|
wb << ']';
|
2015-10-12 07:05:54 +00:00
|
|
|
|
2017-07-31 21:39:24 +00:00
|
|
|
return wb.str();
|
2015-10-12 07:05:54 +00:00
|
|
|
}
|
|
|
|
|
2019-10-18 15:57:05 +00:00
|
|
|
String FieldVisitorToString::operator() (const Tuple & x) const
|
2015-12-24 14:31:41 +00:00
|
|
|
{
|
2017-07-31 21:39:24 +00:00
|
|
|
WriteBufferFromOwnString wb;
|
2015-12-24 14:31:41 +00:00
|
|
|
|
2018-08-03 20:25:47 +00:00
|
|
|
wb << '(';
|
2017-04-01 07:20:54 +00:00
|
|
|
for (auto it = x.begin(); it != x.end(); ++it)
|
|
|
|
{
|
|
|
|
if (it != x.begin())
|
2018-08-03 20:25:47 +00:00
|
|
|
wb << ", ";
|
|
|
|
wb << applyVisitor(*this, *it);
|
2017-04-01 07:20:54 +00:00
|
|
|
}
|
2018-08-03 20:25:47 +00:00
|
|
|
wb << ')';
|
2015-12-24 14:31:41 +00:00
|
|
|
|
2017-07-31 21:39:24 +00:00
|
|
|
return wb.str();
|
2015-12-24 14:31:41 +00:00
|
|
|
}
|
|
|
|
|
2015-10-12 07:05:54 +00:00
|
|
|
|
2019-08-03 11:02:40 +00:00
|
|
|
FieldVisitorHash::FieldVisitorHash(SipHash & hash_) : hash(hash_) {}
|
2017-01-06 17:41:19 +00:00
|
|
|
|
2017-12-01 17:49:12 +00:00
|
|
|
void FieldVisitorHash::operator() (const Null &) const
|
2017-01-06 17:41:19 +00:00
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
UInt8 type = Field::Types::Null;
|
2018-03-03 15:36:20 +00:00
|
|
|
hash.update(type);
|
2017-01-06 17:41:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void FieldVisitorHash::operator() (const UInt64 & x) const
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
UInt8 type = Field::Types::UInt64;
|
2018-03-03 15:36:20 +00:00
|
|
|
hash.update(type);
|
|
|
|
hash.update(x);
|
2017-01-06 17:41:19 +00:00
|
|
|
}
|
|
|
|
|
2018-07-09 21:25:56 +00:00
|
|
|
void FieldVisitorHash::operator() (const UInt128 & x) const
|
|
|
|
{
|
|
|
|
UInt8 type = Field::Types::UInt128;
|
|
|
|
hash.update(type);
|
|
|
|
hash.update(x);
|
|
|
|
}
|
|
|
|
|
2017-01-06 17:41:19 +00:00
|
|
|
void FieldVisitorHash::operator() (const Int64 & x) const
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
UInt8 type = Field::Types::Int64;
|
2018-03-03 15:36:20 +00:00
|
|
|
hash.update(type);
|
|
|
|
hash.update(x);
|
2017-01-06 17:41:19 +00:00
|
|
|
}
|
|
|
|
|
2020-08-19 11:52:17 +00:00
|
|
|
void FieldVisitorHash::operator() (const Int128 & x) const
|
|
|
|
{
|
|
|
|
UInt8 type = Field::Types::Int128;
|
|
|
|
hash.update(type);
|
|
|
|
hash.update(x);
|
|
|
|
}
|
|
|
|
|
2017-01-06 17:41:19 +00:00
|
|
|
void FieldVisitorHash::operator() (const Float64 & x) const
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
UInt8 type = Field::Types::Float64;
|
2018-03-03 15:36:20 +00:00
|
|
|
hash.update(type);
|
|
|
|
hash.update(x);
|
2017-01-06 17:41:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void FieldVisitorHash::operator() (const String & x) const
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
UInt8 type = Field::Types::String;
|
2018-03-03 15:36:20 +00:00
|
|
|
hash.update(type);
|
|
|
|
hash.update(x.size());
|
2017-04-01 07:20:54 +00:00
|
|
|
hash.update(x.data(), x.size());
|
2017-01-06 17:41:19 +00:00
|
|
|
}
|
|
|
|
|
2019-10-18 15:57:05 +00:00
|
|
|
void FieldVisitorHash::operator() (const Tuple & x) const
|
|
|
|
{
|
|
|
|
UInt8 type = Field::Types::Tuple;
|
|
|
|
hash.update(type);
|
|
|
|
hash.update(x.size());
|
|
|
|
|
|
|
|
for (const auto & elem : x)
|
|
|
|
applyVisitor(*this, elem);
|
|
|
|
}
|
|
|
|
|
2017-01-06 17:41:19 +00:00
|
|
|
void FieldVisitorHash::operator() (const Array & x) const
|
|
|
|
{
|
2017-04-01 07:20:54 +00:00
|
|
|
UInt8 type = Field::Types::Array;
|
2018-03-03 15:36:20 +00:00
|
|
|
hash.update(type);
|
|
|
|
hash.update(x.size());
|
2017-01-06 17:41:19 +00:00
|
|
|
|
2017-04-01 07:20:54 +00:00
|
|
|
for (const auto & elem : x)
|
|
|
|
applyVisitor(*this, elem);
|
2017-01-06 17:41:19 +00:00
|
|
|
}
|
|
|
|
|
2018-08-23 19:11:31 +00:00
|
|
|
void FieldVisitorHash::operator() (const DecimalField<Decimal32> & x) const
|
|
|
|
{
|
|
|
|
UInt8 type = Field::Types::Decimal32;
|
|
|
|
hash.update(type);
|
2020-08-19 11:52:17 +00:00
|
|
|
hash.update(x.getValue().value);
|
2018-08-23 19:11:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void FieldVisitorHash::operator() (const DecimalField<Decimal64> & x) const
|
|
|
|
{
|
|
|
|
UInt8 type = Field::Types::Decimal64;
|
|
|
|
hash.update(type);
|
2020-08-19 11:52:17 +00:00
|
|
|
hash.update(x.getValue().value);
|
2018-08-23 19:11:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void FieldVisitorHash::operator() (const DecimalField<Decimal128> & x) const
|
|
|
|
{
|
|
|
|
UInt8 type = Field::Types::Decimal128;
|
|
|
|
hash.update(type);
|
2020-08-19 11:52:17 +00:00
|
|
|
hash.update(x.getValue().value);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FieldVisitorHash::operator() (const DecimalField<Decimal256> & x) const
|
|
|
|
{
|
|
|
|
UInt8 type = Field::Types::Decimal256;
|
|
|
|
hash.update(type);
|
|
|
|
hash.update(x.getValue().value);
|
2018-08-23 19:11:31 +00:00
|
|
|
}
|
|
|
|
|
2019-02-11 11:19:56 +00:00
|
|
|
void FieldVisitorHash::operator() (const AggregateFunctionStateData & x) const
|
|
|
|
{
|
|
|
|
UInt8 type = Field::Types::AggregateFunctionState;
|
|
|
|
hash.update(type);
|
2019-02-11 13:11:52 +00:00
|
|
|
hash.update(x.name.size());
|
|
|
|
hash.update(x.name.data(), x.name.size());
|
|
|
|
hash.update(x.data.size());
|
|
|
|
hash.update(x.data.data(), x.data.size());
|
2019-02-11 11:19:56 +00:00
|
|
|
}
|
|
|
|
|
2020-08-19 11:52:17 +00:00
|
|
|
void FieldVisitorHash::operator() (const bUInt256 & x) const
|
|
|
|
{
|
|
|
|
UInt8 type = Field::Types::bUInt256;
|
|
|
|
hash.update(type);
|
|
|
|
hash.update(x);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FieldVisitorHash::operator() (const bInt256 & x) const
|
|
|
|
{
|
|
|
|
UInt8 type = Field::Types::bInt256;
|
|
|
|
hash.update(type);
|
|
|
|
hash.update(x);
|
|
|
|
}
|
2018-08-23 19:11:31 +00:00
|
|
|
|
2015-10-12 07:05:54 +00:00
|
|
|
}
|