mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-21 01:00:48 +00:00
dbms: added support for different numeric types in function has [#METR-18382].
This commit is contained in:
parent
d12532e7b1
commit
bb283e6602
@ -2,6 +2,8 @@
|
||||
|
||||
#include <stats/ReservoirSampler.h>
|
||||
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
#include <DB/IO/ReadHelpers.h>
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
#include <DB/AggregateFunctions/ReservoirSamplerDeterministic.h>
|
||||
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
#include <DB/IO/ReadHelpers.h>
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include <DB/Common/MemoryTracker.h>
|
||||
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
#include <DB/IO/ReadHelpers.h>
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
#include <DB/AggregateFunctions/IUnaryAggregateFunction.h>
|
||||
#include <DB/DataTypes/DataTypesNumberFixed.h>
|
||||
|
||||
|
@ -9,6 +9,9 @@
|
||||
#include <DB/Core/Field.h>
|
||||
|
||||
#include <DB/IO/ReadBufferFromString.h>
|
||||
#include <DB/IO/WriteBuffer.h>
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
@ -6,6 +6,9 @@
|
||||
#include <DB/Core/ErrorCodes.h>
|
||||
#include <DB/Common/Arena.h>
|
||||
|
||||
#include <DB/IO/WriteBuffer.h>
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
|
||||
#include <DB/Columns/IColumn.h>
|
||||
|
||||
|
||||
|
@ -11,8 +11,6 @@
|
||||
#include <Poco/Mutex.h>
|
||||
#include <Poco/ScopedLock.h>
|
||||
|
||||
#include <boost/function.hpp>
|
||||
|
||||
#include <DB/Common/Exception.h>
|
||||
#include <DB/IO/ReadBufferFromFileDescriptor.h>
|
||||
#include <DB/IO/WriteBufferFromFileDescriptor.h>
|
||||
|
@ -6,18 +6,9 @@
|
||||
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include <mysqlxx/Date.h>
|
||||
#include <mysqlxx/DateTime.h>
|
||||
#include <mysqlxx/Manip.h>
|
||||
|
||||
#include <DB/Core/Types.h>
|
||||
#include <DB/Common/Exception.h>
|
||||
#include <DB/Core/ErrorCodes.h>
|
||||
#include <DB/IO/ReadHelpers.h>
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
#include <DB/IO/WriteBufferFromString.h>
|
||||
|
||||
#include <DB/IO/DoubleConverter.h>
|
||||
#include <DB/Core/Types.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -342,6 +333,8 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
#undef DBMS_TOTAL_FIELD_SIZE
|
||||
|
||||
|
||||
template <> struct Field::TypeToEnum<Null> { static const Types::Which value = Types::Null; };
|
||||
template <> struct Field::TypeToEnum<UInt64> { static const Types::Which value = Types::UInt64; };
|
||||
@ -383,280 +376,9 @@ T safeGet(Field & field)
|
||||
}
|
||||
|
||||
|
||||
/** StaticVisitor (его наследники) - класс с перегруженными для разных типов операторами ().
|
||||
* Вызвать visitor для field можно с помощью функции apply_visitor.
|
||||
* Также поддерживается visitor, в котором оператор () принимает два аргумента.
|
||||
*/
|
||||
template <typename R = void>
|
||||
struct StaticVisitor
|
||||
{
|
||||
typedef R ResultType;
|
||||
};
|
||||
|
||||
|
||||
template <typename Visitor, typename F>
|
||||
typename Visitor::ResultType apply_visitor_impl(Visitor & visitor, F & field)
|
||||
{
|
||||
switch (field.getType())
|
||||
{
|
||||
case Field::Types::Null: return visitor(field.template get<Null>());
|
||||
case Field::Types::UInt64: return visitor(field.template get<UInt64>());
|
||||
case Field::Types::Int64: return visitor(field.template get<Int64>());
|
||||
case Field::Types::Float64: return visitor(field.template get<Float64>());
|
||||
case Field::Types::String: return visitor(field.template get<String>());
|
||||
case Field::Types::Array: return visitor(field.template get<Array>());
|
||||
|
||||
default:
|
||||
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
||||
}
|
||||
}
|
||||
|
||||
/** Эти штуки нужны, чтобы принимать временный объект по константной ссылке.
|
||||
* В шаблон выше, типы форвардятся уже с const-ом.
|
||||
*/
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, Field & field)
|
||||
{
|
||||
return apply_visitor_impl(visitor, field);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, const Field & field)
|
||||
{
|
||||
return apply_visitor_impl(visitor, field);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, Field & field)
|
||||
{
|
||||
return apply_visitor_impl(visitor, field);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, const Field & field)
|
||||
{
|
||||
return apply_visitor_impl(visitor, field);
|
||||
}
|
||||
|
||||
|
||||
template <typename Visitor, typename F1, typename F2>
|
||||
typename Visitor::ResultType apply_binary_visitor_impl2(Visitor & visitor, F1 & field1, F2 & field2)
|
||||
{
|
||||
switch (field2.getType())
|
||||
{
|
||||
case Field::Types::Null: return visitor(field1, field2.template get<Null>());
|
||||
case Field::Types::UInt64: return visitor(field1, field2.template get<UInt64>());
|
||||
case Field::Types::Int64: return visitor(field1, field2.template get<Int64>());
|
||||
case Field::Types::Float64: return visitor(field1, field2.template get<Float64>());
|
||||
case Field::Types::String: return visitor(field1, field2.template get<String>());
|
||||
case Field::Types::Array: return visitor(field1, field2.template get<Array>());
|
||||
|
||||
default:
|
||||
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Visitor, typename F1, typename F2>
|
||||
typename Visitor::ResultType apply_binary_visitor_impl1(Visitor & visitor, F1 & field1, F2 & field2)
|
||||
{
|
||||
switch (field1.getType())
|
||||
{
|
||||
case Field::Types::Null: return apply_binary_visitor_impl2(visitor, field1.template get<Null>(), field2);
|
||||
case Field::Types::UInt64: return apply_binary_visitor_impl2(visitor, field1.template get<UInt64>(), field2);
|
||||
case Field::Types::Int64: return apply_binary_visitor_impl2(visitor, field1.template get<Int64>(), field2);
|
||||
case Field::Types::Float64: return apply_binary_visitor_impl2(visitor, field1.template get<Float64>(), field2);
|
||||
case Field::Types::String: return apply_binary_visitor_impl2(visitor, field1.template get<String>(), field2);
|
||||
case Field::Types::Array: return apply_binary_visitor_impl2(visitor, field1.template get<Array>(), field2);
|
||||
|
||||
default:
|
||||
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, Field & field1, Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, Field & field1, const Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, const Field & field1, Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, const Field & field1, const Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, Field & field1, Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, Field & field1, const Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, const Field & field1, Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, const Field & field1, const Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
|
||||
template <> struct TypeName<Array> { static std::string get() { return "Array"; } };
|
||||
|
||||
|
||||
/** Возвращает строковый дамп типа */
|
||||
class FieldVisitorDump : public StaticVisitor<String>
|
||||
{
|
||||
private:
|
||||
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;
|
||||
}
|
||||
public:
|
||||
String operator() (const Null & x) const { return "NULL"; }
|
||||
String operator() (const UInt64 & x) const { return formatQuotedWithPrefix(x, "UInt64_"); }
|
||||
String operator() (const Int64 & x) const { return formatQuotedWithPrefix(x, "Int64_"); }
|
||||
String operator() (const Float64 & x) const { return formatQuotedWithPrefix(x, "Float64_"); }
|
||||
|
||||
String operator() (const String & x) const
|
||||
{
|
||||
String res;
|
||||
WriteBufferFromString wb(res);
|
||||
writeQuoted(x, wb);
|
||||
return res;
|
||||
}
|
||||
|
||||
String operator() (const Array & x) const
|
||||
{
|
||||
String res;
|
||||
WriteBufferFromString wb(res);
|
||||
FieldVisitorDump visitor;
|
||||
|
||||
wb.write("Array_[", 7);
|
||||
for (Array::const_iterator it = x.begin(); it != x.end(); ++it)
|
||||
{
|
||||
if (it != x.begin())
|
||||
wb.write(", ", 2);
|
||||
writeString(apply_visitor(visitor, *it), wb);
|
||||
}
|
||||
writeChar(']', wb);
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
/** Выводит текстовое представление типа, как литерала в SQL запросе */
|
||||
class FieldVisitorToString : public StaticVisitor<String>
|
||||
{
|
||||
private:
|
||||
template <typename T>
|
||||
static inline String formatQuoted(T x)
|
||||
{
|
||||
String res;
|
||||
WriteBufferFromString wb(res);
|
||||
writeQuoted(x, wb);
|
||||
return res;
|
||||
}
|
||||
|
||||
/** В отличие от writeFloatText (и writeQuoted), если число после форматирования выглядит целым, всё равно добавляет десятичную точку.
|
||||
* - для того, чтобы это число могло обратно распарситься как Float64 парсером запроса (иначе распарсится как целое).
|
||||
*
|
||||
* При этом, не оставляет завершающие нули справа.
|
||||
*
|
||||
* NOTE: При таком roundtrip-е, точность может теряться.
|
||||
*/
|
||||
static String formatFloat(const Float64 x)
|
||||
{
|
||||
char tmp[25];
|
||||
double_conversion::StringBuilder builder{tmp, sizeof(tmp)};
|
||||
|
||||
const auto result = getDoubleToStringConverter().ToShortest(x, &builder);
|
||||
|
||||
if (!result)
|
||||
throw Exception("Cannot print float or double number", ErrorCodes::CANNOT_PRINT_FLOAT_OR_DOUBLE_NUMBER);
|
||||
|
||||
return { tmp, tmp + builder.position() };
|
||||
}
|
||||
|
||||
public:
|
||||
String operator() (const Null & x) const { return "NULL"; }
|
||||
String operator() (const UInt64 & x) const { return formatQuoted(x); }
|
||||
String operator() (const Int64 & x) const { return formatQuoted(x); }
|
||||
String operator() (const Float64 & x) const { return formatFloat(x); }
|
||||
String operator() (const String & x) const { return formatQuoted(x); }
|
||||
|
||||
String operator() (const Array & x) const
|
||||
{
|
||||
String res;
|
||||
WriteBufferFromString wb(res);
|
||||
FieldVisitorToString visitor;
|
||||
|
||||
writeChar('[', wb);
|
||||
for (Array::const_iterator it = x.begin(); it != x.end(); ++it)
|
||||
{
|
||||
if (it != x.begin())
|
||||
wb.write(", ", 2);
|
||||
writeString(apply_visitor(visitor, *it), wb);
|
||||
}
|
||||
writeChar(']', wb);
|
||||
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
/** Числовой тип преобразует в указанный. */
|
||||
template <typename T>
|
||||
class FieldVisitorConvertToNumber : public StaticVisitor<T>
|
||||
{
|
||||
public:
|
||||
T operator() (const Null & x) const
|
||||
{
|
||||
throw Exception("Cannot convert NULL to " + TypeName<T>::get(), ErrorCodes::CANNOT_CONVERT_TYPE);
|
||||
}
|
||||
|
||||
T operator() (const String & x) const
|
||||
{
|
||||
throw Exception("Cannot convert String to " + TypeName<T>::get(), ErrorCodes::CANNOT_CONVERT_TYPE);
|
||||
}
|
||||
|
||||
T operator() (const Array & x) const
|
||||
{
|
||||
throw Exception("Cannot convert Array to " + TypeName<T>::get(), ErrorCodes::CANNOT_CONVERT_TYPE);
|
||||
}
|
||||
|
||||
T operator() (const UInt64 & x) const { return x; }
|
||||
T operator() (const Int64 & x) const { return x; }
|
||||
T operator() (const Float64 & x) const { return x; }
|
||||
};
|
||||
|
||||
|
||||
template <typename T> struct NearestFieldType;
|
||||
|
||||
template <> struct NearestFieldType<UInt8> { typedef UInt64 Type; };
|
||||
@ -684,27 +406,14 @@ typename NearestFieldType<T>::Type nearestFieldType(const T & x)
|
||||
|
||||
|
||||
/// Заглушки, чтобы DBObject-ы с полем типа Array компилировались.
|
||||
#include <mysqlxx/Manip.h>
|
||||
|
||||
namespace mysqlxx
|
||||
{
|
||||
inline std::ostream & operator<< (mysqlxx::EscapeManipResult res, const DB::Array & value)
|
||||
{
|
||||
return res.ostr << apply_visitor(DB::FieldVisitorToString(), value);
|
||||
}
|
||||
|
||||
inline std::ostream & operator<< (mysqlxx::QuoteManipResult res, const DB::Array & value)
|
||||
{
|
||||
throw Poco::Exception("Cannot quote Array with mysqlxx::quote.");
|
||||
}
|
||||
|
||||
inline std::istream & operator>> (mysqlxx::UnEscapeManipResult res, DB::Array & value)
|
||||
{
|
||||
throw Poco::Exception("Cannot unescape Array with mysqlxx::unescape.");
|
||||
}
|
||||
|
||||
inline std::istream & operator>> (mysqlxx::UnQuoteManipResult res, DB::Array & value)
|
||||
{
|
||||
throw Poco::Exception("Cannot unquote Array with mysqlxx::unquote.");
|
||||
}
|
||||
std::ostream & operator<< (mysqlxx::EscapeManipResult res, const DB::Array & value);
|
||||
std::ostream & operator<< (mysqlxx::QuoteManipResult res, const DB::Array & value);
|
||||
std::istream & operator>> (mysqlxx::UnEscapeManipResult res, DB::Array & value);
|
||||
std::istream & operator>> (mysqlxx::UnQuoteManipResult res, DB::Array & value);
|
||||
}
|
||||
|
||||
|
||||
@ -714,116 +423,15 @@ namespace DB
|
||||
class WriteBuffer;
|
||||
|
||||
/// Предполагается что у всех элементов массива одинаковый тип.
|
||||
inline void readBinary(Array & x, ReadBuffer & buf)
|
||||
{
|
||||
size_t size;
|
||||
UInt8 type;
|
||||
DB::readBinary(type, buf);
|
||||
DB::readBinary(size, buf);
|
||||
|
||||
for (size_t index = 0; index < size; ++index)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Field::Types::Null:
|
||||
{
|
||||
x.push_back(DB::Field());
|
||||
break;
|
||||
}
|
||||
case Field::Types::UInt64:
|
||||
{
|
||||
UInt64 value;
|
||||
DB::readVarUInt(value, buf);
|
||||
x.push_back(value);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Int64:
|
||||
{
|
||||
Int64 value;
|
||||
DB::readVarInt(value, buf);
|
||||
x.push_back(value);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Float64:
|
||||
{
|
||||
Float64 value;
|
||||
DB::readFloatBinary(value, buf);
|
||||
x.push_back(value);
|
||||
break;
|
||||
}
|
||||
case Field::Types::String:
|
||||
{
|
||||
std::string value;
|
||||
DB::readStringBinary(value, buf);
|
||||
x.push_back(value);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Array:
|
||||
{
|
||||
Array value;
|
||||
DB::readBinary(value, buf);
|
||||
x.push_back(value);
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
void readBinary(Array & x, ReadBuffer & buf);
|
||||
|
||||
inline void readText(Array & x, ReadBuffer & buf) { throw Exception("Cannot read Array.", ErrorCodes::NOT_IMPLEMENTED); }
|
||||
inline void readQuoted(Array & x, ReadBuffer & buf) { throw Exception("Cannot read Array.", ErrorCodes::NOT_IMPLEMENTED); }
|
||||
|
||||
/// Предполагается что у всех элементов массива одинаковый тип.
|
||||
inline void writeBinary(const Array & x, WriteBuffer & buf)
|
||||
{
|
||||
UInt8 type = Field::Types::Null;
|
||||
size_t size = x.size();
|
||||
if (size)
|
||||
type = x.front().getType();
|
||||
DB::writeBinary(type, buf);
|
||||
DB::writeBinary(size, buf);
|
||||
void writeBinary(const Array & x, WriteBuffer & buf);
|
||||
|
||||
for (Array::const_iterator it = x.begin(); it != x.end(); ++it)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Field::Types::Null: break;
|
||||
case Field::Types::UInt64:
|
||||
{
|
||||
DB::writeVarUInt(get<UInt64>(*it), buf);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Int64:
|
||||
{
|
||||
DB::writeVarInt(get<Int64>(*it), buf);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Float64:
|
||||
{
|
||||
DB::writeFloatBinary(get<Float64>(*it), buf);
|
||||
break;
|
||||
}
|
||||
case Field::Types::String:
|
||||
{
|
||||
DB::writeStringBinary(get<std::string>(*it), buf);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Array:
|
||||
{
|
||||
DB::writeBinary(get<Array>(*it), buf);
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
inline void writeText(const Array & x, WriteBuffer & buf)
|
||||
{
|
||||
DB::String res = apply_visitor(DB::FieldVisitorToString(), DB::Field(x));
|
||||
buf.write(res.data(), res.size());
|
||||
}
|
||||
void writeText(const Array & x, WriteBuffer & buf);
|
||||
|
||||
inline void writeQuoted(const Array & x, WriteBuffer & buf) { throw Exception("Cannot write Array quoted.", ErrorCodes::NOT_IMPLEMENTED); }
|
||||
}
|
||||
|
||||
|
||||
#undef DBMS_TOTAL_FIELD_SIZE
|
||||
|
344
dbms/include/DB/Core/FieldVisitors.h
Normal file
344
dbms/include/DB/Core/FieldVisitors.h
Normal file
@ -0,0 +1,344 @@
|
||||
#pragma once
|
||||
|
||||
#include <DB/Core/Field.h>
|
||||
|
||||
#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>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
||||
/** StaticVisitor (его наследники) - класс с перегруженными для разных типов операторами ().
|
||||
* Вызвать visitor для field можно с помощью функции apply_visitor.
|
||||
* Также поддерживается visitor, в котором оператор () принимает два аргумента.
|
||||
*/
|
||||
template <typename R = void>
|
||||
struct StaticVisitor
|
||||
{
|
||||
typedef R ResultType;
|
||||
};
|
||||
|
||||
|
||||
template <typename Visitor, typename F>
|
||||
typename Visitor::ResultType apply_visitor_impl(Visitor & visitor, F & field)
|
||||
{
|
||||
switch (field.getType())
|
||||
{
|
||||
case Field::Types::Null: return visitor(field.template get<Null>());
|
||||
case Field::Types::UInt64: return visitor(field.template get<UInt64>());
|
||||
case Field::Types::Int64: return visitor(field.template get<Int64>());
|
||||
case Field::Types::Float64: return visitor(field.template get<Float64>());
|
||||
case Field::Types::String: return visitor(field.template get<String>());
|
||||
case Field::Types::Array: return visitor(field.template get<Array>());
|
||||
|
||||
default:
|
||||
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
||||
}
|
||||
}
|
||||
|
||||
/** Эти штуки нужны, чтобы принимать временный объект по константной ссылке.
|
||||
* В шаблон выше, типы форвардятся уже с const-ом.
|
||||
*/
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, Field & field)
|
||||
{
|
||||
return apply_visitor_impl(visitor, field);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, const Field & field)
|
||||
{
|
||||
return apply_visitor_impl(visitor, field);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, Field & field)
|
||||
{
|
||||
return apply_visitor_impl(visitor, field);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, const Field & field)
|
||||
{
|
||||
return apply_visitor_impl(visitor, field);
|
||||
}
|
||||
|
||||
|
||||
template <typename Visitor, typename F1, typename F2>
|
||||
typename Visitor::ResultType apply_binary_visitor_impl2(Visitor & visitor, F1 & field1, F2 & field2)
|
||||
{
|
||||
switch (field2.getType())
|
||||
{
|
||||
case Field::Types::Null: return visitor(field1, field2.template get<Null>());
|
||||
case Field::Types::UInt64: return visitor(field1, field2.template get<UInt64>());
|
||||
case Field::Types::Int64: return visitor(field1, field2.template get<Int64>());
|
||||
case Field::Types::Float64: return visitor(field1, field2.template get<Float64>());
|
||||
case Field::Types::String: return visitor(field1, field2.template get<String>());
|
||||
case Field::Types::Array: return visitor(field1, field2.template get<Array>());
|
||||
|
||||
default:
|
||||
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Visitor, typename F1, typename F2>
|
||||
typename Visitor::ResultType apply_binary_visitor_impl1(Visitor & visitor, F1 & field1, F2 & field2)
|
||||
{
|
||||
switch (field1.getType())
|
||||
{
|
||||
case Field::Types::Null: return apply_binary_visitor_impl2(visitor, field1.template get<Null>(), field2);
|
||||
case Field::Types::UInt64: return apply_binary_visitor_impl2(visitor, field1.template get<UInt64>(), field2);
|
||||
case Field::Types::Int64: return apply_binary_visitor_impl2(visitor, field1.template get<Int64>(), field2);
|
||||
case Field::Types::Float64: return apply_binary_visitor_impl2(visitor, field1.template get<Float64>(), field2);
|
||||
case Field::Types::String: return apply_binary_visitor_impl2(visitor, field1.template get<String>(), field2);
|
||||
case Field::Types::Array: return apply_binary_visitor_impl2(visitor, field1.template get<Array>(), field2);
|
||||
|
||||
default:
|
||||
throw Exception("Bad type of Field", ErrorCodes::BAD_TYPE_OF_FIELD);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, Field & field1, Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, Field & field1, const Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, const Field & field1, Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(Visitor & visitor, const Field & field1, const Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, Field & field1, Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, Field & field1, const Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, const Field & field1, Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
template <typename Visitor>
|
||||
typename Visitor::ResultType apply_visitor(const Visitor & visitor, const Field & field1, const Field & field2)
|
||||
{
|
||||
return apply_binary_visitor_impl1(visitor, field1, field2);
|
||||
}
|
||||
|
||||
|
||||
/** Возвращает строковый дамп типа */
|
||||
class FieldVisitorDump : public StaticVisitor<String>
|
||||
{
|
||||
private:
|
||||
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;
|
||||
}
|
||||
public:
|
||||
String operator() (const Null & x) const { return "NULL"; }
|
||||
String operator() (const UInt64 & x) const { return formatQuotedWithPrefix(x, "UInt64_"); }
|
||||
String operator() (const Int64 & x) const { return formatQuotedWithPrefix(x, "Int64_"); }
|
||||
String operator() (const Float64 & x) const { return formatQuotedWithPrefix(x, "Float64_"); }
|
||||
String operator() (const String & x) const;
|
||||
String operator() (const Array & x) const;
|
||||
};
|
||||
|
||||
|
||||
/** Выводит текстовое представление типа, как литерала в SQL запросе */
|
||||
class FieldVisitorToString : public StaticVisitor<String>
|
||||
{
|
||||
private:
|
||||
template <typename T>
|
||||
static inline String formatQuoted(T x)
|
||||
{
|
||||
String res;
|
||||
WriteBufferFromString wb(res);
|
||||
writeQuoted(x, wb);
|
||||
return res;
|
||||
}
|
||||
|
||||
/** В отличие от writeFloatText (и writeQuoted), если число после форматирования выглядит целым, всё равно добавляет десятичную точку.
|
||||
* - для того, чтобы это число могло обратно распарситься как Float64 парсером запроса (иначе распарсится как целое).
|
||||
*
|
||||
* При этом, не оставляет завершающие нули справа.
|
||||
*
|
||||
* NOTE: При таком roundtrip-е, точность может теряться.
|
||||
*/
|
||||
static String formatFloat(const Float64 x);
|
||||
|
||||
public:
|
||||
String operator() (const Null & x) const { return "NULL"; }
|
||||
String operator() (const UInt64 & x) const { return formatQuoted(x); }
|
||||
String operator() (const Int64 & x) const { return formatQuoted(x); }
|
||||
String operator() (const Float64 & x) const { return formatFloat(x); }
|
||||
String operator() (const String & x) const { return formatQuoted(x); }
|
||||
String operator() (const Array & x) const;
|
||||
};
|
||||
|
||||
|
||||
/** Числовой тип преобразует в указанный. */
|
||||
template <typename T>
|
||||
class FieldVisitorConvertToNumber : public StaticVisitor<T>
|
||||
{
|
||||
public:
|
||||
T operator() (const Null & x) const
|
||||
{
|
||||
throw Exception("Cannot convert NULL to " + TypeName<T>::get(), ErrorCodes::CANNOT_CONVERT_TYPE);
|
||||
}
|
||||
|
||||
T operator() (const String & x) const
|
||||
{
|
||||
throw Exception("Cannot convert String to " + TypeName<T>::get(), ErrorCodes::CANNOT_CONVERT_TYPE);
|
||||
}
|
||||
|
||||
T operator() (const Array & x) const
|
||||
{
|
||||
throw Exception("Cannot convert Array to " + TypeName<T>::get(), ErrorCodes::CANNOT_CONVERT_TYPE);
|
||||
}
|
||||
|
||||
T operator() (const UInt64 & x) const { return x; }
|
||||
T operator() (const Int64 & x) const { return x; }
|
||||
T operator() (const Float64 & x) const { return x; }
|
||||
};
|
||||
|
||||
|
||||
/// Преобразование строки с датой или датой-с-временем в UInt64, содержащим числовое значение даты или даты-с-временем.
|
||||
UInt64 stringToDateOrDateTime(const String & s);
|
||||
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
|
||||
/** Более точное сравнение.
|
||||
* Отличается от Field::operator< и Field::operator== тем, что сравнивает значения разных числовых типов между собой.
|
||||
* Правила сравнения - такие же, что и в FunctionsComparison.
|
||||
* В том числе, сравнение знаковых и беззнаковых оставляем UB.
|
||||
*/
|
||||
class FieldVisitorAccurateEquals : public StaticVisitor<bool>
|
||||
{
|
||||
public:
|
||||
bool operator() (const Null & l, const Null & r) const { return true; }
|
||||
bool operator() (const Null & l, const UInt64 & r) const { return false; }
|
||||
bool operator() (const Null & l, const Int64 & r) const { return false; }
|
||||
bool operator() (const Null & l, const Float64 & r) const { return false; }
|
||||
bool operator() (const Null & l, const String & r) const { return false; }
|
||||
bool operator() (const Null & l, const Array & r) const { return false; }
|
||||
|
||||
bool operator() (const UInt64 & l, const Null & r) const { return false; }
|
||||
bool operator() (const UInt64 & l, const UInt64 & r) const { return l == r; }
|
||||
bool operator() (const UInt64 & l, const Int64 & r) const { return l == r; }
|
||||
bool operator() (const UInt64 & l, const Float64 & r) const { return l == r; }
|
||||
bool operator() (const UInt64 & l, const String & r) const { return l == stringToDateOrDateTime(r); }
|
||||
bool operator() (const UInt64 & l, const Array & r) const { return false; }
|
||||
|
||||
bool operator() (const Int64 & l, const Null & r) const { return false; }
|
||||
bool operator() (const Int64 & l, const UInt64 & r) const { return l == r; }
|
||||
bool operator() (const Int64 & l, const Int64 & r) const { return l == r; }
|
||||
bool operator() (const Int64 & l, const Float64 & r) const { return l == r; }
|
||||
bool operator() (const Int64 & l, const String & r) const { return false; }
|
||||
bool operator() (const Int64 & l, const Array & r) const { return false; }
|
||||
|
||||
bool operator() (const Float64 & l, const Null & r) const { return false; }
|
||||
bool operator() (const Float64 & l, const UInt64 & r) const { return l == r; }
|
||||
bool operator() (const Float64 & l, const Int64 & r) const { return l == r; }
|
||||
bool operator() (const Float64 & l, const Float64 & r) const { return l == r; }
|
||||
bool operator() (const Float64 & l, const String & r) const { return false; }
|
||||
bool operator() (const Float64 & l, const Array & r) const { return false; }
|
||||
|
||||
bool operator() (const String & l, const Null & r) const { return false; }
|
||||
bool operator() (const String & l, const UInt64 & r) const { return stringToDateOrDateTime(l) == r; }
|
||||
bool operator() (const String & l, const Int64 & r) const { return false; }
|
||||
bool operator() (const String & l, const Float64 & r) const { return false; }
|
||||
bool operator() (const String & l, const String & r) const { return l == r; }
|
||||
bool operator() (const String & l, const Array & r) const { return false; }
|
||||
|
||||
bool operator() (const Array & l, const Null & r) const { return false; }
|
||||
bool operator() (const Array & l, const UInt64 & r) const { return false; }
|
||||
bool operator() (const Array & l, const Int64 & r) const { return false; }
|
||||
bool operator() (const Array & l, const Float64 & r) const { return false; }
|
||||
bool operator() (const Array & l, const String & r) const { return false; }
|
||||
bool operator() (const Array & l, const Array & r) const { return l == r; }
|
||||
};
|
||||
|
||||
class FieldVisitorAccurateLess : public StaticVisitor<bool>
|
||||
{
|
||||
public:
|
||||
bool operator() (const Null & l, const Null & r) const { return false; }
|
||||
bool operator() (const Null & l, const UInt64 & r) const { return true; }
|
||||
bool operator() (const Null & l, const Int64 & r) const { return true; }
|
||||
bool operator() (const Null & l, const Float64 & r) const { return true; }
|
||||
bool operator() (const Null & l, const String & r) const { return true; }
|
||||
bool operator() (const Null & l, const Array & r) const { return true; }
|
||||
|
||||
bool operator() (const UInt64 & l, const Null & r) const { return false; }
|
||||
bool operator() (const UInt64 & l, const UInt64 & r) const { return l < r; }
|
||||
bool operator() (const UInt64 & l, const Int64 & r) const { return l < r; }
|
||||
bool operator() (const UInt64 & l, const Float64 & r) const { return l < r; }
|
||||
bool operator() (const UInt64 & l, const String & r) const { return l < stringToDateOrDateTime(r); }
|
||||
bool operator() (const UInt64 & l, const Array & r) const { return true; }
|
||||
|
||||
bool operator() (const Int64 & l, const Null & r) const { return false; }
|
||||
bool operator() (const Int64 & l, const UInt64 & r) const { return l < r; }
|
||||
bool operator() (const Int64 & l, const Int64 & r) const { return l < r; }
|
||||
bool operator() (const Int64 & l, const Float64 & r) const { return l < r; }
|
||||
bool operator() (const Int64 & l, const String & r) const { return true; }
|
||||
bool operator() (const Int64 & l, const Array & r) const { return true; }
|
||||
|
||||
bool operator() (const Float64 & l, const Null & r) const { return false; }
|
||||
bool operator() (const Float64 & l, const UInt64 & r) const { return l < r; }
|
||||
bool operator() (const Float64 & l, const Int64 & r) const { return l < r; }
|
||||
bool operator() (const Float64 & l, const Float64 & r) const { return l < r; }
|
||||
bool operator() (const Float64 & l, const String & r) const { return true; }
|
||||
bool operator() (const Float64 & l, const Array & r) const { return true; }
|
||||
|
||||
bool operator() (const String & l, const Null & r) const { return false; }
|
||||
bool operator() (const String & l, const UInt64 & r) const { return stringToDateOrDateTime(l) < r; }
|
||||
bool operator() (const String & l, const Int64 & r) const { return false; }
|
||||
bool operator() (const String & l, const Float64 & r) const { return false; }
|
||||
bool operator() (const String & l, const String & r) const { return l < r; }
|
||||
bool operator() (const String & l, const Array & r) const { return true; }
|
||||
|
||||
bool operator() (const Array & l, const Null & r) const { return false; }
|
||||
bool operator() (const Array & l, const UInt64 & r) const { return false; }
|
||||
bool operator() (const Array & l, const Int64 & r) const { return false; }
|
||||
bool operator() (const Array & l, const Float64 & r) const { return false; }
|
||||
bool operator() (const Array & l, const String & r) const { return false; }
|
||||
bool operator() (const Array & l, const Array & r) const { return l < r; }
|
||||
};
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <common/logger_useful.h>
|
||||
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
#include <DB/Core/Row.h>
|
||||
#include <DB/Core/ColumnNumbers.h>
|
||||
#include <DB/DataStreams/MergingSortedBlockInputStream.h>
|
||||
|
@ -28,29 +28,7 @@ public:
|
||||
|
||||
std::string getFunctionName() const { return function->getName(); }
|
||||
|
||||
std::string getName() const override
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "AggregateFunction(" << function->getName();
|
||||
|
||||
if (!parameters.empty())
|
||||
{
|
||||
stream << "(";
|
||||
for (size_t i = 0; i < parameters.size(); ++i)
|
||||
{
|
||||
if (i)
|
||||
stream << ", ";
|
||||
stream << apply_visitor(DB::FieldVisitorToString(), parameters[i]);
|
||||
}
|
||||
stream << ")";
|
||||
}
|
||||
|
||||
for (DataTypes::const_iterator it = argument_types.begin(); it != argument_types.end(); ++it)
|
||||
stream << ", " << (*it)->getName();
|
||||
|
||||
stream << ")";
|
||||
return stream.str();
|
||||
}
|
||||
std::string getName() const override;
|
||||
|
||||
DataTypePtr getReturnType() const { return function->getReturnType(); };
|
||||
DataTypes getArgumentsDataTypes() const { return argument_types; }
|
||||
|
@ -25,10 +25,7 @@ public:
|
||||
throw Exception("FixedString size must be positive", ErrorCodes::ARGUMENT_OUT_OF_BOUND);
|
||||
}
|
||||
|
||||
std::string getName() const override
|
||||
{
|
||||
return "FixedString(" + toString(n) + ")";
|
||||
}
|
||||
std::string getName() const override;
|
||||
|
||||
DataTypePtr clone() const override
|
||||
{
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
|
||||
#include <DB/DataTypes/DataTypesNumberFixed.h>
|
||||
#include <DB/DataTypes/DataTypeString.h>
|
||||
#include <DB/DataTypes/DataTypeArray.h>
|
||||
|
@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/function.hpp>
|
||||
|
||||
#include <Poco/SharedPtr.h>
|
||||
|
||||
#include <DB/Core/Field.h>
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include <DB/Core/ErrorCodes.h>
|
||||
#include <DB/DataTypes/DataTypeFactory.h>
|
||||
#include <DB/IO/ReadBufferFromString.h>
|
||||
#include <DB/IO/WriteBuffer.h>
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
#include <Poco/Util/AbstractConfiguration.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
|
||||
#include <DB/DataTypes/DataTypeArray.h>
|
||||
#include <DB/DataTypes/DataTypesNumberFixed.h>
|
||||
#include <DB/DataTypes/DataTypeDate.h>
|
||||
@ -795,13 +797,18 @@ struct IndexCount
|
||||
};
|
||||
|
||||
|
||||
template <typename T, typename IndexConv>
|
||||
template <typename T, typename U, typename IndexConv>
|
||||
struct ArrayIndexNumImpl
|
||||
{
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
|
||||
/// compares `lhs` against `i`-th element of `rhs`
|
||||
static bool compare(const T & lhs, const PODArray<T> & rhs, const std::size_t i ) { return lhs == rhs[i]; }
|
||||
static bool compare(const T & lhs, const PODArray<U> & rhs, const std::size_t i ) { return lhs == rhs[i]; }
|
||||
/// compares `lhs against `rhs`, third argument unused
|
||||
static bool compare(const T & lhs, const T & rhs, std::size_t) { return lhs == rhs; }
|
||||
static bool compare(const T & lhs, const U & rhs, std::size_t) { return lhs == rhs; }
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
template <typename ScalarOrVector>
|
||||
static void vector(
|
||||
@ -921,6 +928,21 @@ private:
|
||||
|
||||
template <typename T>
|
||||
bool executeNumber(Block & block, const ColumnNumbers & arguments, size_t result)
|
||||
{
|
||||
return executeNumberNumber<T, UInt8>(block, arguments, result)
|
||||
|| executeNumberNumber<T, UInt16>(block, arguments, result)
|
||||
|| executeNumberNumber<T, UInt32>(block, arguments, result)
|
||||
|| executeNumberNumber<T, UInt64>(block, arguments, result)
|
||||
|| executeNumberNumber<T, Int8>(block, arguments, result)
|
||||
|| executeNumberNumber<T, Int16>(block, arguments, result)
|
||||
|| executeNumberNumber<T, Int32>(block, arguments, result)
|
||||
|| executeNumberNumber<T, Int64>(block, arguments, result)
|
||||
|| executeNumberNumber<T, Float32>(block, arguments, result)
|
||||
|| executeNumberNumber<T, Float64>(block, arguments, result);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool executeNumberNumber(Block & block, const ColumnNumbers & arguments, size_t result)
|
||||
{
|
||||
const ColumnArray * col_array = typeid_cast<const ColumnArray *>(&*block.getByPosition(arguments[0]).column);
|
||||
|
||||
@ -934,24 +956,26 @@ private:
|
||||
|
||||
const auto item_arg = block.getByPosition(arguments[1]).column.get();
|
||||
|
||||
if (const auto item_arg_const = typeid_cast<const ColumnConst<T> *>(item_arg))
|
||||
if (const auto item_arg_const = typeid_cast<const ColumnConst<U> *>(item_arg))
|
||||
{
|
||||
const auto col_res = new ResultColumnType;
|
||||
ColumnPtr col_ptr{col_res};
|
||||
block.getByPosition(result).column = col_ptr;
|
||||
|
||||
ArrayIndexNumImpl<T, IndexConv>::vector(col_nested->getData(), col_array->getOffsets(),
|
||||
ArrayIndexNumImpl<T, U, IndexConv>::vector(col_nested->getData(), col_array->getOffsets(),
|
||||
item_arg_const->getData(), col_res->getData());
|
||||
}
|
||||
else if (const auto item_arg_vector = typeid_cast<const ColumnVector<T> *>(item_arg))
|
||||
else if (const auto item_arg_vector = typeid_cast<const ColumnVector<U> *>(item_arg))
|
||||
{
|
||||
const auto col_res = new ResultColumnType;
|
||||
ColumnPtr col_ptr{col_res};
|
||||
block.getByPosition(result).column = col_ptr;
|
||||
|
||||
ArrayIndexNumImpl<T, IndexConv>::vector(col_nested->getData(), col_array->getOffsets(),
|
||||
ArrayIndexNumImpl<T, U, IndexConv>::vector(col_nested->getData(), col_array->getOffsets(),
|
||||
item_arg_vector->getData(), col_res->getData());
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1010,7 +1034,7 @@ private:
|
||||
|
||||
for (size_t i = 0, size = arr.size(); i < size; ++i)
|
||||
{
|
||||
if (arr[i] == value)
|
||||
if (apply_visitor(FieldVisitorAccurateEquals(), arr[i], value))
|
||||
{
|
||||
if (!IndexConv::apply(i, current))
|
||||
break;
|
||||
@ -1035,7 +1059,7 @@ private:
|
||||
const auto & value = (*item_arg)[row];
|
||||
for (size_t i = 0, size = arr.size(); i < size; ++i)
|
||||
{
|
||||
if (arr[i] == value)
|
||||
if (apply_visitor(FieldVisitorAccurateEquals(), arr[i], value))
|
||||
{
|
||||
if (!IndexConv::apply(i, data[row]))
|
||||
break;
|
||||
@ -1067,7 +1091,8 @@ public:
|
||||
if (!array_type)
|
||||
throw Exception("First argument for function " + getName() + " must be array.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
if (array_type->getNestedType()->getName() != arguments[1]->getName())
|
||||
if (!(array_type->getNestedType()->behavesAsNumber() && arguments[1]->behavesAsNumber())
|
||||
&& array_type->getNestedType()->getName() != arguments[1]->getName())
|
||||
throw Exception("Type of array elements and second argument for function " + getName() + " must be same."
|
||||
" Passed: " + arguments[0]->getName() + " and " + arguments[1]->getName() + ".", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <common/Revision.h>
|
||||
|
||||
#include <DB/Core/Defines.h>
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
#include <DB/IO/WriteBufferFromString.h>
|
||||
#include <DB/DataTypes/DataTypesNumberFixed.h>
|
||||
#include <DB/DataTypes/DataTypeString.h>
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include <Poco/UTF8Encoding.h>
|
||||
#include <Poco/Unicode.h>
|
||||
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
|
||||
#include <DB/DataTypes/DataTypesNumberFixed.h>
|
||||
#include <DB/DataTypes/DataTypeString.h>
|
||||
#include <DB/DataTypes/DataTypeFixedString.h>
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
#include <DB/DataTypes/DataTypesNumberFixed.h>
|
||||
#include <DB/DataTypes/DataTypeString.h>
|
||||
#include <DB/DataTypes/DataTypeArray.h>
|
||||
|
@ -293,23 +293,7 @@ public:
|
||||
*/
|
||||
ColumnPtr execute(const Block & block, bool negative) const;
|
||||
|
||||
std::string describe() const
|
||||
{
|
||||
if (!ordered_set_elements)
|
||||
return "{}";
|
||||
|
||||
bool first = true;
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "{";
|
||||
for (const Field & f : *ordered_set_elements)
|
||||
{
|
||||
ss << (first ? "" : ", ") << apply_visitor(FieldVisitorToString(), f);
|
||||
first = false;
|
||||
}
|
||||
ss << "}";
|
||||
return ss.str();
|
||||
}
|
||||
std::string describe() const;
|
||||
|
||||
/// проверяет есть ли в Set элементы для заданного диапазона индекса
|
||||
BoolMask mayBeTrueInRange(const Range & range) const;
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <Poco/Timespan.h>
|
||||
#include <cpuid/libcpuid.h>
|
||||
#include <DB/IO/CompressedStream.h>
|
||||
#include <DB/IO/ReadHelpers.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <DB/Core/Field.h>
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
#include <DB/DataTypes/IDataType.h>
|
||||
#include <DB/Parsers/ASTWithAlias.h>
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <DB/Core/Field.h>
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
#include <DB/Parsers/IAST.h>
|
||||
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
#include <DB/Interpreters/Context.h>
|
||||
#include <DB/Core/SortDescription.h>
|
||||
#include <DB/Parsers/ASTExpressionList.h>
|
||||
|
@ -1,4 +1,6 @@
|
||||
#include <DB/AggregateFunctions/AggregateFunctionFactory.h>
|
||||
#include <DB/IO/WriteBuffer.h>
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
#include <DB/DataTypes/DataTypeAggregateFunction.h>
|
||||
#include <DB/DataTypes/DataTypeArray.h>
|
||||
|
||||
|
141
dbms/src/Core/Field.cpp
Normal file
141
dbms/src/Core/Field.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
#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/Field.h>
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
|
||||
|
||||
namespace mysqlxx
|
||||
{
|
||||
std::ostream & operator<< (mysqlxx::EscapeManipResult res, const DB::Array & value)
|
||||
{
|
||||
return res.ostr << apply_visitor(DB::FieldVisitorToString(), value);
|
||||
}
|
||||
|
||||
std::ostream & operator<< (mysqlxx::QuoteManipResult res, const DB::Array & value)
|
||||
{
|
||||
throw Poco::Exception("Cannot quote Array with mysqlxx::quote.");
|
||||
}
|
||||
|
||||
std::istream & operator>> (mysqlxx::UnEscapeManipResult res, DB::Array & value)
|
||||
{
|
||||
throw Poco::Exception("Cannot unescape Array with mysqlxx::unescape.");
|
||||
}
|
||||
|
||||
std::istream & operator>> (mysqlxx::UnQuoteManipResult res, DB::Array & value)
|
||||
{
|
||||
throw Poco::Exception("Cannot unquote Array with mysqlxx::unquote.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
inline void readBinary(Array & x, ReadBuffer & buf)
|
||||
{
|
||||
size_t size;
|
||||
UInt8 type;
|
||||
DB::readBinary(type, buf);
|
||||
DB::readBinary(size, buf);
|
||||
|
||||
for (size_t index = 0; index < size; ++index)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Field::Types::Null:
|
||||
{
|
||||
x.push_back(DB::Field());
|
||||
break;
|
||||
}
|
||||
case Field::Types::UInt64:
|
||||
{
|
||||
UInt64 value;
|
||||
DB::readVarUInt(value, buf);
|
||||
x.push_back(value);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Int64:
|
||||
{
|
||||
Int64 value;
|
||||
DB::readVarInt(value, buf);
|
||||
x.push_back(value);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Float64:
|
||||
{
|
||||
Float64 value;
|
||||
DB::readFloatBinary(value, buf);
|
||||
x.push_back(value);
|
||||
break;
|
||||
}
|
||||
case Field::Types::String:
|
||||
{
|
||||
std::string value;
|
||||
DB::readStringBinary(value, buf);
|
||||
x.push_back(value);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Array:
|
||||
{
|
||||
Array value;
|
||||
DB::readBinary(value, buf);
|
||||
x.push_back(value);
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void writeBinary(const Array & x, WriteBuffer & buf)
|
||||
{
|
||||
UInt8 type = Field::Types::Null;
|
||||
size_t size = x.size();
|
||||
if (size)
|
||||
type = x.front().getType();
|
||||
DB::writeBinary(type, buf);
|
||||
DB::writeBinary(size, buf);
|
||||
|
||||
for (Array::const_iterator it = x.begin(); it != x.end(); ++it)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Field::Types::Null: break;
|
||||
case Field::Types::UInt64:
|
||||
{
|
||||
DB::writeVarUInt(get<UInt64>(*it), buf);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Int64:
|
||||
{
|
||||
DB::writeVarInt(get<Int64>(*it), buf);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Float64:
|
||||
{
|
||||
DB::writeFloatBinary(get<Float64>(*it), buf);
|
||||
break;
|
||||
}
|
||||
case Field::Types::String:
|
||||
{
|
||||
DB::writeStringBinary(get<std::string>(*it), buf);
|
||||
break;
|
||||
}
|
||||
case Field::Types::Array:
|
||||
{
|
||||
DB::writeBinary(get<Array>(*it), buf);
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void writeText(const Array & x, WriteBuffer & buf)
|
||||
{
|
||||
DB::String res = apply_visitor(DB::FieldVisitorToString(), DB::Field(x));
|
||||
buf.write(res.data(), res.size());
|
||||
}
|
||||
}
|
88
dbms/src/Core/FieldVisitors.cpp
Normal file
88
dbms/src/Core/FieldVisitors.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
||||
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);
|
||||
FieldVisitorDump visitor;
|
||||
|
||||
wb.write("Array_[", 7);
|
||||
for (Array::const_iterator it = x.begin(); it != x.end(); ++it)
|
||||
{
|
||||
if (it != x.begin())
|
||||
wb.write(", ", 2);
|
||||
writeString(apply_visitor(visitor, *it), wb);
|
||||
}
|
||||
writeChar(']', wb);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
String FieldVisitorToString::formatFloat(const Float64 x)
|
||||
{
|
||||
char tmp[25];
|
||||
double_conversion::StringBuilder builder{tmp, sizeof(tmp)};
|
||||
|
||||
const auto result = getDoubleToStringConverter().ToShortest(x, &builder);
|
||||
|
||||
if (!result)
|
||||
throw Exception("Cannot print float or double number", ErrorCodes::CANNOT_PRINT_FLOAT_OR_DOUBLE_NUMBER);
|
||||
|
||||
return { tmp, tmp + builder.position() };
|
||||
}
|
||||
|
||||
String FieldVisitorToString::operator() (const Array & x) const
|
||||
{
|
||||
String res;
|
||||
WriteBufferFromString wb(res);
|
||||
FieldVisitorToString visitor;
|
||||
|
||||
writeChar('[', wb);
|
||||
for (Array::const_iterator it = x.begin(); it != x.end(); ++it)
|
||||
{
|
||||
if (it != x.begin())
|
||||
wb.write(", ", 2);
|
||||
writeString(apply_visitor(visitor, *it), wb);
|
||||
}
|
||||
writeChar(']', wb);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
UInt64 stringToDateOrDateTime(const String & s)
|
||||
{
|
||||
ReadBufferFromString in(s);
|
||||
|
||||
if (s.size() == strlen("YYYY-MM-DD"))
|
||||
{
|
||||
DayNum_t date{};
|
||||
readDateText(date, in);
|
||||
return UInt64(date);
|
||||
}
|
||||
else
|
||||
{
|
||||
time_t date_time{};
|
||||
readDateTimeText(date_time, in);
|
||||
if (!in.eof())
|
||||
throw Exception("String is too long for DateTime: " + s);
|
||||
return UInt64(date_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,5 +1,9 @@
|
||||
#include <DB/Core/NamesAndTypes.h>
|
||||
#include <DB/DataTypes/DataTypeFactory.h>
|
||||
#include <DB/IO/ReadBuffer.h>
|
||||
#include <DB/IO/WriteBuffer.h>
|
||||
#include <DB/IO/ReadHelpers.h>
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <sstream>
|
||||
|
||||
#include <DB/Core/Field.h>
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
|
||||
#include <DB/Common/Stopwatch.h>
|
||||
#include <DB/DataStreams/TabSeparatedRowOutputStream.h>
|
||||
@ -13,7 +14,7 @@
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
DB::FieldVisitorToString to_string;
|
||||
|
||||
|
||||
DB::Field field = DB::UInt64(0);
|
||||
std::cerr << DB::apply_visitor(to_string, field) << std::endl;
|
||||
|
||||
@ -94,8 +95,8 @@ int main(int argc, char ** argv)
|
||||
std::cerr << e.what() << ", " << e.displayText() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
std::cerr << "sizeof(Field) = " << sizeof(DB::Field) << std::endl;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
#include <DB/DataStreams/CollapsingSortedBlockInputStream.h>
|
||||
|
||||
/// Максимальное количество сообщений о некорректных данных в логе.
|
||||
|
@ -1,3 +1,5 @@
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
#include <DB/IO/ReadHelpers.h>
|
||||
|
||||
@ -13,6 +15,30 @@ namespace DB
|
||||
using Poco::SharedPtr;
|
||||
|
||||
|
||||
std::string DataTypeAggregateFunction::getName() const
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << "AggregateFunction(" << function->getName();
|
||||
|
||||
if (!parameters.empty())
|
||||
{
|
||||
stream << "(";
|
||||
for (size_t i = 0; i < parameters.size(); ++i)
|
||||
{
|
||||
if (i)
|
||||
stream << ", ";
|
||||
stream << apply_visitor(DB::FieldVisitorToString(), parameters[i]);
|
||||
}
|
||||
stream << ")";
|
||||
}
|
||||
|
||||
for (DataTypes::const_iterator it = argument_types.begin(); it != argument_types.end(); ++it)
|
||||
stream << ", " << (*it)->getName();
|
||||
|
||||
stream << ")";
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
void DataTypeAggregateFunction::serializeBinary(const Field & field, WriteBuffer & ostr) const
|
||||
{
|
||||
const String & s = get<const String &>(field);
|
||||
|
@ -1,5 +1,8 @@
|
||||
#include <Poco/SharedPtr.h>
|
||||
|
||||
#include <DB/IO/WriteBuffer.h>
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
|
||||
#include <DB/Columns/ColumnFixedString.h>
|
||||
#include <DB/Columns/ColumnsNumber.h>
|
||||
#include <DB/Columns/ColumnConst.h>
|
||||
@ -17,6 +20,12 @@ namespace DB
|
||||
using Poco::SharedPtr;
|
||||
|
||||
|
||||
std::string DataTypeFixedString::getName() const
|
||||
{
|
||||
return "FixedString(" + toString(n) + ")";
|
||||
}
|
||||
|
||||
|
||||
void DataTypeFixedString::serializeBinary(const Field & field, WriteBuffer & ostr) const
|
||||
{
|
||||
const String & s = get<const String &>(field);
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
#include <DB/DataTypes/FieldToDataType.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <DB/Core/Field.h>
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
|
||||
#include <DB/Columns/ColumnString.h>
|
||||
#include <DB/Columns/ColumnFixedString.h>
|
||||
@ -678,4 +679,23 @@ BoolMask Set::mayBeTrueInRange(const Range & range) const
|
||||
return BoolMask(can_be_true, can_be_false);
|
||||
}
|
||||
|
||||
|
||||
std::string Set::describe() const
|
||||
{
|
||||
if (!ordered_set_elements)
|
||||
return "{}";
|
||||
|
||||
bool first = true;
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "{";
|
||||
for (const Field & f : *ordered_set_elements)
|
||||
{
|
||||
ss << (first ? "" : ", ") << apply_visitor(FieldVisitorToString(), f);
|
||||
first = false;
|
||||
}
|
||||
ss << "}";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <DB/Common/SipHash.h>
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
#include <DB/Parsers/ASTLiteral.h>
|
||||
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
#include <DB/Parsers/ASTSetQuery.h>
|
||||
#include <DB/Parsers/ASTSelectQuery.h>
|
||||
|
||||
|
@ -1,4 +1,8 @@
|
||||
#include <DB/Parsers/ExpressionListParsers.h>
|
||||
#include <DB/IO/WriteBuffer.h>
|
||||
#include <DB/IO/WriteHelpers.h>
|
||||
#include <DB/IO/ReadBuffer.h>
|
||||
#include <DB/IO/ReadHelpers.h>
|
||||
#include <DB/IO/WriteBufferFromString.h>
|
||||
#include <DB/Storages/ColumnsDescription.h>
|
||||
#include <DB/DataTypes/DataTypeFactory.h>
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
#include <DB/Storages/MergeTree/MergeTreeDataSelectExecutor.h>
|
||||
#include <DB/Storages/MergeTree/MergeTreeBlockInputStream.h>
|
||||
#include <DB/Storages/MergeTree/MergeTreeReadPool.h>
|
||||
|
@ -63,130 +63,6 @@ const PKCondition::AtomMap PKCondition::atom_map{
|
||||
}
|
||||
};
|
||||
|
||||
/// Преобразование строки с датой или датой-с-временем в UInt64, содержащим числовое значение даты или даты-с-временем.
|
||||
UInt64 stringToDateOrDateTime(const String & s)
|
||||
{
|
||||
ReadBufferFromString in(s);
|
||||
|
||||
if (s.size() == strlen("YYYY-MM-DD"))
|
||||
{
|
||||
DayNum_t date{};
|
||||
readDateText(date, in);
|
||||
return UInt64(date);
|
||||
}
|
||||
else
|
||||
{
|
||||
time_t date_time{};
|
||||
readDateTimeText(date_time, in);
|
||||
if (!in.eof())
|
||||
throw Exception("String is too long for DateTime: " + s);
|
||||
return UInt64(date_time);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
|
||||
/** Более точное сравнение.
|
||||
* Отличается от Field::operator< и Field::operator== тем, что сравнивает значения разных числовых типов между собой.
|
||||
* Правила сравнения - такие же, что и в FunctionsComparison.
|
||||
* В том числе, сравнение знаковых и беззнаковых оставляем UB.
|
||||
*/
|
||||
class FieldVisitorAccurateEquals : public StaticVisitor<bool>
|
||||
{
|
||||
public:
|
||||
bool operator() (const Null & l, const Null & r) const { return true; }
|
||||
bool operator() (const Null & l, const UInt64 & r) const { return false; }
|
||||
bool operator() (const Null & l, const Int64 & r) const { return false; }
|
||||
bool operator() (const Null & l, const Float64 & r) const { return false; }
|
||||
bool operator() (const Null & l, const String & r) const { return false; }
|
||||
bool operator() (const Null & l, const Array & r) const { return false; }
|
||||
|
||||
bool operator() (const UInt64 & l, const Null & r) const { return false; }
|
||||
bool operator() (const UInt64 & l, const UInt64 & r) const { return l == r; }
|
||||
bool operator() (const UInt64 & l, const Int64 & r) const { return l == r; }
|
||||
bool operator() (const UInt64 & l, const Float64 & r) const { return l == r; }
|
||||
bool operator() (const UInt64 & l, const String & r) const { return l == stringToDateOrDateTime(r); }
|
||||
bool operator() (const UInt64 & l, const Array & r) const { return false; }
|
||||
|
||||
bool operator() (const Int64 & l, const Null & r) const { return false; }
|
||||
bool operator() (const Int64 & l, const UInt64 & r) const { return l == r; }
|
||||
bool operator() (const Int64 & l, const Int64 & r) const { return l == r; }
|
||||
bool operator() (const Int64 & l, const Float64 & r) const { return l == r; }
|
||||
bool operator() (const Int64 & l, const String & r) const { return false; }
|
||||
bool operator() (const Int64 & l, const Array & r) const { return false; }
|
||||
|
||||
bool operator() (const Float64 & l, const Null & r) const { return false; }
|
||||
bool operator() (const Float64 & l, const UInt64 & r) const { return l == r; }
|
||||
bool operator() (const Float64 & l, const Int64 & r) const { return l == r; }
|
||||
bool operator() (const Float64 & l, const Float64 & r) const { return l == r; }
|
||||
bool operator() (const Float64 & l, const String & r) const { return false; }
|
||||
bool operator() (const Float64 & l, const Array & r) const { return false; }
|
||||
|
||||
bool operator() (const String & l, const Null & r) const { return false; }
|
||||
bool operator() (const String & l, const UInt64 & r) const { return stringToDateOrDateTime(l) == r; }
|
||||
bool operator() (const String & l, const Int64 & r) const { return false; }
|
||||
bool operator() (const String & l, const Float64 & r) const { return false; }
|
||||
bool operator() (const String & l, const String & r) const { return l == r; }
|
||||
bool operator() (const String & l, const Array & r) const { return false; }
|
||||
|
||||
bool operator() (const Array & l, const Null & r) const { return false; }
|
||||
bool operator() (const Array & l, const UInt64 & r) const { return false; }
|
||||
bool operator() (const Array & l, const Int64 & r) const { return false; }
|
||||
bool operator() (const Array & l, const Float64 & r) const { return false; }
|
||||
bool operator() (const Array & l, const String & r) const { return false; }
|
||||
bool operator() (const Array & l, const Array & r) const { return l == r; }
|
||||
};
|
||||
|
||||
class FieldVisitorAccurateLess : public StaticVisitor<bool>
|
||||
{
|
||||
public:
|
||||
bool operator() (const Null & l, const Null & r) const { return false; }
|
||||
bool operator() (const Null & l, const UInt64 & r) const { return true; }
|
||||
bool operator() (const Null & l, const Int64 & r) const { return true; }
|
||||
bool operator() (const Null & l, const Float64 & r) const { return true; }
|
||||
bool operator() (const Null & l, const String & r) const { return true; }
|
||||
bool operator() (const Null & l, const Array & r) const { return true; }
|
||||
|
||||
bool operator() (const UInt64 & l, const Null & r) const { return false; }
|
||||
bool operator() (const UInt64 & l, const UInt64 & r) const { return l < r; }
|
||||
bool operator() (const UInt64 & l, const Int64 & r) const { return l < r; }
|
||||
bool operator() (const UInt64 & l, const Float64 & r) const { return l < r; }
|
||||
bool operator() (const UInt64 & l, const String & r) const { return l < stringToDateOrDateTime(r); }
|
||||
bool operator() (const UInt64 & l, const Array & r) const { return true; }
|
||||
|
||||
bool operator() (const Int64 & l, const Null & r) const { return false; }
|
||||
bool operator() (const Int64 & l, const UInt64 & r) const { return l < r; }
|
||||
bool operator() (const Int64 & l, const Int64 & r) const { return l < r; }
|
||||
bool operator() (const Int64 & l, const Float64 & r) const { return l < r; }
|
||||
bool operator() (const Int64 & l, const String & r) const { return true; }
|
||||
bool operator() (const Int64 & l, const Array & r) const { return true; }
|
||||
|
||||
bool operator() (const Float64 & l, const Null & r) const { return false; }
|
||||
bool operator() (const Float64 & l, const UInt64 & r) const { return l < r; }
|
||||
bool operator() (const Float64 & l, const Int64 & r) const { return l < r; }
|
||||
bool operator() (const Float64 & l, const Float64 & r) const { return l < r; }
|
||||
bool operator() (const Float64 & l, const String & r) const { return true; }
|
||||
bool operator() (const Float64 & l, const Array & r) const { return true; }
|
||||
|
||||
bool operator() (const String & l, const Null & r) const { return false; }
|
||||
bool operator() (const String & l, const UInt64 & r) const { return stringToDateOrDateTime(l) < r; }
|
||||
bool operator() (const String & l, const Int64 & r) const { return false; }
|
||||
bool operator() (const String & l, const Float64 & r) const { return false; }
|
||||
bool operator() (const String & l, const String & r) const { return l < r; }
|
||||
bool operator() (const String & l, const Array & r) const { return true; }
|
||||
|
||||
bool operator() (const Array & l, const Null & r) const { return false; }
|
||||
bool operator() (const Array & l, const UInt64 & r) const { return false; }
|
||||
bool operator() (const Array & l, const Int64 & r) const { return false; }
|
||||
bool operator() (const Array & l, const Float64 & r) const { return false; }
|
||||
bool operator() (const Array & l, const String & r) const { return false; }
|
||||
bool operator() (const Array & l, const Array & r) const { return l < r; }
|
||||
};
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
|
||||
inline bool Range::equals(const Field & lhs, const Field & rhs) { return apply_visitor(FieldVisitorAccurateEquals(), lhs, rhs); }
|
||||
inline bool Range::less(const Field & lhs, const Field & rhs) { return apply_visitor(FieldVisitorAccurateLess(), lhs, rhs); }
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include <Poco/Util/Application.h>
|
||||
#include <Poco/Util/AbstractConfiguration.h>
|
||||
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
|
||||
#include <DB/Parsers/ASTCreateQuery.h>
|
||||
#include <DB/Parsers/ASTIdentifier.h>
|
||||
#include <DB/Parsers/ASTLiteral.h>
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
#include <DB/Storages/StorageMergeTree.h>
|
||||
#include <DB/Storages/MergeTree/MergeTreeBlockOutputStream.h>
|
||||
#include <DB/Storages/MergeTree/DiskSpaceMonitor.h>
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <ext/range.hpp>
|
||||
#include <DB/Core/FieldVisitors.h>
|
||||
#include <DB/Storages/ColumnsDescription.h>
|
||||
#include <DB/Storages/StorageReplicatedMergeTree.h>
|
||||
#include <DB/Storages/MergeTree/ReplicatedMergeTreeBlockOutputStream.h>
|
||||
|
Loading…
Reference in New Issue
Block a user