This commit is contained in:
Roman Peshkurov 2015-10-19 19:47:15 +03:00
commit 95bef85dd2
77 changed files with 2186 additions and 964 deletions

View File

@ -2,6 +2,8 @@
#include <stats/ReservoirSampler.h> #include <stats/ReservoirSampler.h>
#include <DB/Core/FieldVisitors.h>
#include <DB/IO/WriteHelpers.h> #include <DB/IO/WriteHelpers.h>
#include <DB/IO/ReadHelpers.h> #include <DB/IO/ReadHelpers.h>

View File

@ -2,6 +2,8 @@
#include <DB/AggregateFunctions/ReservoirSamplerDeterministic.h> #include <DB/AggregateFunctions/ReservoirSamplerDeterministic.h>
#include <DB/Core/FieldVisitors.h>
#include <DB/IO/WriteHelpers.h> #include <DB/IO/WriteHelpers.h>
#include <DB/IO/ReadHelpers.h> #include <DB/IO/ReadHelpers.h>

View File

@ -4,6 +4,8 @@
#include <DB/Common/MemoryTracker.h> #include <DB/Common/MemoryTracker.h>
#include <DB/Core/FieldVisitors.h>
#include <DB/IO/WriteHelpers.h> #include <DB/IO/WriteHelpers.h>
#include <DB/IO/ReadHelpers.h> #include <DB/IO/ReadHelpers.h>

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <DB/Core/FieldVisitors.h>
#include <DB/AggregateFunctions/IUnaryAggregateFunction.h> #include <DB/AggregateFunctions/IUnaryAggregateFunction.h>
#include <DB/DataTypes/DataTypesNumberFixed.h> #include <DB/DataTypes/DataTypesNumberFixed.h>

View File

@ -9,6 +9,9 @@
#include <DB/Core/Field.h> #include <DB/Core/Field.h>
#include <DB/IO/ReadBufferFromString.h> #include <DB/IO/ReadBufferFromString.h>
#include <DB/IO/WriteBuffer.h>
#include <DB/IO/WriteHelpers.h>
namespace DB namespace DB
{ {

View File

@ -6,6 +6,9 @@
#include <DB/Core/ErrorCodes.h> #include <DB/Core/ErrorCodes.h>
#include <DB/Common/Arena.h> #include <DB/Common/Arena.h>
#include <DB/IO/WriteBuffer.h>
#include <DB/IO/WriteHelpers.h>
#include <DB/Columns/IColumn.h> #include <DB/Columns/IColumn.h>

View File

@ -11,8 +11,6 @@
#include <Poco/Mutex.h> #include <Poco/Mutex.h>
#include <Poco/ScopedLock.h> #include <Poco/ScopedLock.h>
#include <boost/function.hpp>
#include <DB/Common/Exception.h> #include <DB/Common/Exception.h>
#include <DB/IO/ReadBufferFromFileDescriptor.h> #include <DB/IO/ReadBufferFromFileDescriptor.h>
#include <DB/IO/WriteBufferFromFileDescriptor.h> #include <DB/IO/WriteBufferFromFileDescriptor.h>

View File

@ -294,6 +294,7 @@ namespace ErrorCodes
LIMIT_EXCEEDED = 290, LIMIT_EXCEEDED = 290,
DATABASE_ACCESS_DENIED = 291, DATABASE_ACCESS_DENIED = 291,
LEADERSHIP_CHANGED = 292, LEADERSHIP_CHANGED = 292,
MONGODB_INIT_FAILED = 293,
KEEPER_EXCEPTION = 999, KEEPER_EXCEPTION = 999,
POCO_EXCEPTION = 1000, POCO_EXCEPTION = 1000,

View File

@ -6,18 +6,9 @@
#include <boost/static_assert.hpp> #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/Common/Exception.h>
#include <DB/Core/ErrorCodes.h> #include <DB/Core/ErrorCodes.h>
#include <DB/IO/ReadHelpers.h> #include <DB/Core/Types.h>
#include <DB/IO/WriteHelpers.h>
#include <DB/IO/WriteBufferFromString.h>
#include <DB/IO/DoubleConverter.h>
namespace DB 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<Null> { static const Types::Which value = Types::Null; };
template <> struct Field::TypeToEnum<UInt64> { static const Types::Which value = Types::UInt64; }; 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"; } }; 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 <typename T> struct NearestFieldType;
template <> struct NearestFieldType<UInt8> { typedef UInt64 Type; }; template <> struct NearestFieldType<UInt8> { typedef UInt64 Type; };
@ -684,27 +406,14 @@ typename NearestFieldType<T>::Type nearestFieldType(const T & x)
/// Заглушки, чтобы DBObject-ы с полем типа Array компилировались. /// Заглушки, чтобы DBObject-ы с полем типа Array компилировались.
#include <mysqlxx/Manip.h>
namespace mysqlxx namespace mysqlxx
{ {
inline std::ostream & operator<< (mysqlxx::EscapeManipResult res, const DB::Array & value) std::ostream & operator<< (mysqlxx::EscapeManipResult res, const DB::Array & value);
{ std::ostream & operator<< (mysqlxx::QuoteManipResult res, const DB::Array & value);
return res.ostr << apply_visitor(DB::FieldVisitorToString(), value); std::istream & operator>> (mysqlxx::UnEscapeManipResult res, DB::Array & value);
} std::istream & operator>> (mysqlxx::UnQuoteManipResult res, DB::Array & 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.");
}
} }
@ -714,116 +423,15 @@ namespace DB
class WriteBuffer; class WriteBuffer;
/// Предполагается что у всех элементов массива одинаковый тип. /// Предполагается что у всех элементов массива одинаковый тип.
inline void readBinary(Array & x, ReadBuffer & buf) 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;
}
};
}
}
inline void readText(Array & x, ReadBuffer & buf) { throw Exception("Cannot read Array.", ErrorCodes::NOT_IMPLEMENTED); } 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 readQuoted(Array & x, ReadBuffer & buf) { throw Exception("Cannot read Array.", ErrorCodes::NOT_IMPLEMENTED); }
/// Предполагается что у всех элементов массива одинаковый тип. /// Предполагается что у всех элементов массива одинаковый тип.
inline void writeBinary(const Array & x, WriteBuffer & buf) 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) void writeText(const Array & x, WriteBuffer & buf);
{
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());
}
inline void writeQuoted(const Array & x, WriteBuffer & buf) { throw Exception("Cannot write Array quoted.", ErrorCodes::NOT_IMPLEMENTED); } inline void writeQuoted(const Array & x, WriteBuffer & buf) { throw Exception("Cannot write Array quoted.", ErrorCodes::NOT_IMPLEMENTED); }
} }
#undef DBMS_TOTAL_FIELD_SIZE

View 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
}

View File

@ -2,6 +2,7 @@
#include <common/logger_useful.h> #include <common/logger_useful.h>
#include <DB/Core/FieldVisitors.h>
#include <DB/Core/Row.h> #include <DB/Core/Row.h>
#include <DB/Core/ColumnNumbers.h> #include <DB/Core/ColumnNumbers.h>
#include <DB/DataStreams/MergingSortedBlockInputStream.h> #include <DB/DataStreams/MergingSortedBlockInputStream.h>

View File

@ -28,29 +28,7 @@ public:
std::string getFunctionName() const { return function->getName(); } std::string getFunctionName() const { return function->getName(); }
std::string getName() const override 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();
}
DataTypePtr getReturnType() const { return function->getReturnType(); }; DataTypePtr getReturnType() const { return function->getReturnType(); };
DataTypes getArgumentsDataTypes() const { return argument_types; } DataTypes getArgumentsDataTypes() const { return argument_types; }

View File

@ -25,10 +25,7 @@ public:
throw Exception("FixedString size must be positive", ErrorCodes::ARGUMENT_OUT_OF_BOUND); throw Exception("FixedString size must be positive", ErrorCodes::ARGUMENT_OUT_OF_BOUND);
} }
std::string getName() const override std::string getName() const override;
{
return "FixedString(" + toString(n) + ")";
}
DataTypePtr clone() const override DataTypePtr clone() const override
{ {

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <DB/Core/FieldVisitors.h>
#include <DB/DataTypes/DataTypesNumberFixed.h> #include <DB/DataTypes/DataTypesNumberFixed.h>
#include <DB/DataTypes/DataTypeString.h> #include <DB/DataTypes/DataTypeString.h>
#include <DB/DataTypes/DataTypeArray.h> #include <DB/DataTypes/DataTypeArray.h>

View File

@ -1,7 +1,5 @@
#pragma once #pragma once
#include <boost/function.hpp>
#include <Poco/SharedPtr.h> #include <Poco/SharedPtr.h>
#include <DB/Core/Field.h> #include <DB/Core/Field.h>

View File

@ -25,7 +25,7 @@ public:
ClickHouseDictionarySource(const DictionaryStructure & dict_struct, ClickHouseDictionarySource(const DictionaryStructure & dict_struct,
const Poco::Util::AbstractConfiguration & config, const Poco::Util::AbstractConfiguration & config,
const std::string & config_prefix, const std::string & config_prefix,
Block & sample_block, Context & context) const Block & sample_block, Context & context)
: dict_struct{dict_struct}, : dict_struct{dict_struct},
host{config.getString(config_prefix + ".host")}, host{config.getString(config_prefix + ".host")},
port(config.getInt(config_prefix + ".port")), port(config.getInt(config_prefix + ".port")),

View File

@ -5,6 +5,7 @@
#include <DB/Dictionaries/FileDictionarySource.h> #include <DB/Dictionaries/FileDictionarySource.h>
#include <DB/Dictionaries/MySQLDictionarySource.h> #include <DB/Dictionaries/MySQLDictionarySource.h>
#include <DB/Dictionaries/ClickHouseDictionarySource.h> #include <DB/Dictionaries/ClickHouseDictionarySource.h>
//#include <DB/Dictionaries/MongoDBDictionarySource.h>
#include <DB/DataTypes/DataTypesNumberFixed.h> #include <DB/DataTypes/DataTypesNumberFixed.h>
#include <common/singleton.h> #include <common/singleton.h>
#include <memory> #include <memory>
@ -84,6 +85,11 @@ public:
return std::make_unique<ClickHouseDictionarySource>(dict_struct, config, config_prefix + ".clickhouse", return std::make_unique<ClickHouseDictionarySource>(dict_struct, config, config_prefix + ".clickhouse",
sample_block, context); sample_block, context);
} }
/* else if ("mongodb" == source_type)
{
return std::make_unique<MongoDBDictionarySource>(dict_struct, config, config_prefix + ".mongodb",
sample_block, context);
}*/
throw Exception{ throw Exception{
name + ": unknown dictionary source type: " + source_type, name + ": unknown dictionary source type: " + source_type,

View File

@ -3,6 +3,8 @@
#include <DB/Core/ErrorCodes.h> #include <DB/Core/ErrorCodes.h>
#include <DB/DataTypes/DataTypeFactory.h> #include <DB/DataTypes/DataTypeFactory.h>
#include <DB/IO/ReadBufferFromString.h> #include <DB/IO/ReadBufferFromString.h>
#include <DB/IO/WriteBuffer.h>
#include <DB/IO/WriteHelpers.h>
#include <Poco/Util/AbstractConfiguration.h> #include <Poco/Util/AbstractConfiguration.h>
#include <vector> #include <vector>
#include <string> #include <string>

View File

@ -0,0 +1,315 @@
#pragma once
#include <DB/Core/Block.h>
#include <DB/DataStreams/IProfilingBlockInputStream.h>
#include <DB/DataTypes/DataTypesNumberFixed.h>
#include <DB/DataTypes/DataTypeString.h>
#include <DB/DataTypes/DataTypeDate.h>
#include <DB/DataTypes/DataTypeDateTime.h>
#include <DB/Columns/ColumnString.h>
#include <ext/range.hpp>
#include <mongo/client/dbclient.h>
#include <vector>
#include <string>
namespace DB
{
/// Allows processing results of a MongoDB query as a sequence of Blocks, simplifies chaining
class MongoDBBlockInputStream final : public IProfilingBlockInputStream
{
enum struct value_type_t
{
UInt8,
UInt16,
UInt32,
UInt64,
Int8,
Int16,
Int32,
Int64,
Float32,
Float64,
String,
Date,
DateTime
};
public:
MongoDBBlockInputStream(
std::unique_ptr<mongo::DBClientCursor> cursor_, const Block & sample_block, const std::size_t max_block_size)
: cursor{std::move(cursor_)}, sample_block{sample_block}, max_block_size{max_block_size}
{
if (!cursor->more())
return;
types.reserve(sample_block.columns());
for (const auto idx : ext::range(0, sample_block.columns()))
{
const auto & column = sample_block.getByPosition(idx);
const auto type = column.type.get();
if (typeid_cast<const DataTypeUInt8 *>(type))
types.push_back(value_type_t::UInt8);
else if (typeid_cast<const DataTypeUInt16 *>(type))
types.push_back(value_type_t::UInt16);
else if (typeid_cast<const DataTypeUInt32 *>(type))
types.push_back(value_type_t::UInt32);
else if (typeid_cast<const DataTypeUInt64 *>(type))
types.push_back(value_type_t::UInt64);
else if (typeid_cast<const DataTypeInt8 *>(type))
types.push_back(value_type_t::Int8);
else if (typeid_cast<const DataTypeInt16 *>(type))
types.push_back(value_type_t::Int16);
else if (typeid_cast<const DataTypeInt32 *>(type))
types.push_back(value_type_t::Int32);
else if (typeid_cast<const DataTypeInt64 *>(type))
types.push_back(value_type_t::Int64);
else if (typeid_cast<const DataTypeFloat32 *>(type))
types.push_back(value_type_t::Float32);
else if (typeid_cast<const DataTypeInt64 *>(type))
types.push_back(value_type_t::Float64);
else if (typeid_cast<const DataTypeString *>(type))
types.push_back(value_type_t::String);
else if (typeid_cast<const DataTypeDate *>(type))
types.push_back(value_type_t::Date);
else if (typeid_cast<const DataTypeDateTime *>(type))
types.push_back(value_type_t::DateTime);
else
throw Exception{
"Unsupported type " + type->getName(),
ErrorCodes::UNKNOWN_TYPE
};
names.emplace_back(column.name);
}
}
String getName() const override { return "MongoDB"; }
String getID() const override
{
using stream = std::ostringstream;
return "MongoDB(@" + static_cast<stream &>(stream{} << cursor.get()).str() + ")";
}
private:
Block readImpl() override
{
if (!cursor->more())
return {};
auto block = sample_block.cloneEmpty();
/// cache pointers returned by the calls to getByPosition
std::vector<IColumn *> columns(block.columns());
const auto size = columns.size();
for (const auto i : ext::range(0, size))
columns[i] = block.getByPosition(i).column.get();
std::size_t num_rows = 0;
while (cursor->more())
{
const auto row = cursor->next();
for (const auto idx : ext::range(0, size))
{
const auto value = row[names[idx]];
if (value.ok())
insertValue(columns[idx], types[idx], value);
else
insertDefaultValue(columns[idx], types[idx]);
}
++num_rows;
if (num_rows == max_block_size)
break;
}
return block;
}
static void insertValue(IColumn * const column, const value_type_t type, const mongo::BSONElement & value)
{
switch (type)
{
case value_type_t::UInt8:
{
if (value.type() != mongo::Bool)
throw Exception{
"Type mismatch, expected Bool, got " + std::string{mongo::typeName(value.type())},
ErrorCodes::TYPE_MISMATCH
};
static_cast<ColumnFloat64 *>(column)->insert(value.boolean());
break;
}
case value_type_t::UInt16:
{
if (!value.isNumber())
throw Exception{
"Type mismatch, expected a number, got " + std::string{mongo::typeName(value.type())},
ErrorCodes::TYPE_MISMATCH
};
static_cast<ColumnUInt16 *>(column)->insert(value.numberInt());
break;
}
case value_type_t::UInt32:
{
if (!value.isNumber())
throw Exception{
"Type mismatch, expected a number, got " + std::string{mongo::typeName(value.type())},
ErrorCodes::TYPE_MISMATCH
};
static_cast<ColumnUInt32 *>(column)->insert(value.numberInt());
break;
}
case value_type_t::UInt64:
{
if (!value.isNumber())
throw Exception{
"Type mismatch, expected a number, got " + std::string{mongo::typeName(value.type())},
ErrorCodes::TYPE_MISMATCH
};
static_cast<ColumnUInt64 *>(column)->insert(value.numberLong());
break;
}
case value_type_t::Int8:
{
if (!value.isNumber())
throw Exception{
"Type mismatch, expected a number, got " + std::string{mongo::typeName(value.type())},
ErrorCodes::TYPE_MISMATCH
};
static_cast<ColumnInt8 *>(column)->insert(value.numberInt());
break;
}
case value_type_t::Int16:
{
if (!value.isNumber())
throw Exception{
"Type mismatch, expected a number, got " + std::string{mongo::typeName(value.type())},
ErrorCodes::TYPE_MISMATCH
};
static_cast<ColumnInt16 *>(column)->insert(value.numberInt());
break;
}
case value_type_t::Int32:
{
if (!value.isNumber())
throw Exception{
"Type mismatch, expected a number, got " + std::string{mongo::typeName(value.type())},
ErrorCodes::TYPE_MISMATCH
};
static_cast<ColumnInt32 *>(column)->insert(value.numberInt());
break;
}
case value_type_t::Int64:
{
if (!value.isNumber())
throw Exception{
"Type mismatch, expected a number, got " + std::string{mongo::typeName(value.type())},
ErrorCodes::TYPE_MISMATCH
};
static_cast<ColumnInt64 *>(column)->insert(value.numberLong());
break;
}
case value_type_t::Float32:
{
if (!value.isNumber())
throw Exception{
"Type mismatch, expected a number, got " + std::string{mongo::typeName(value.type())},
ErrorCodes::TYPE_MISMATCH
};
static_cast<ColumnFloat32 *>(column)->insert(value.number());
break;
}
case value_type_t::Float64:
{
if (!value.isNumber())
throw Exception{
"Type mismatch, expected a number, got " + std::string{mongo::typeName(value.type())},
ErrorCodes::TYPE_MISMATCH
};
static_cast<ColumnFloat64 *>(column)->insert(value.number());
break;
}
case value_type_t::String:
{
if (value.type() != mongo::String)
throw Exception{
"Type mismatch, expected String, got " + std::string{mongo::typeName(value.type())},
ErrorCodes::TYPE_MISMATCH
};
const auto string = value.String();
static_cast<ColumnString *>(column)->insertDataWithTerminatingZero(string.data(), string.size() + 1);
break;
}
case value_type_t::Date:
{
if (value.type() != mongo::Date)
throw Exception{
"Type mismatch, expected Date, got " + std::string{mongo::typeName(value.type())},
ErrorCodes::TYPE_MISMATCH
};
static_cast<ColumnUInt16 *>(column)->insert(
UInt16{DateLUT::instance().toDayNum(value.date().toTimeT())});
break;
}
case value_type_t::DateTime:
{
if (value.type() != mongo::Date)
throw Exception{
"Type mismatch, expected Date, got " + std::string{mongo::typeName(value.type())},
ErrorCodes::TYPE_MISMATCH
};
static_cast<ColumnUInt32 *>(column)->insert(value.date().toTimeT());
break;
}
}
}
/// @todo insert default value from the dictionary attribute definition
static void insertDefaultValue(IColumn * const column, const value_type_t type)
{
switch (type)
{
case value_type_t::UInt8: static_cast<ColumnUInt8 *>(column)->insertDefault(); break;
case value_type_t::UInt16: static_cast<ColumnUInt16 *>(column)->insertDefault(); break;
case value_type_t::UInt32: static_cast<ColumnUInt32 *>(column)->insertDefault(); break;
case value_type_t::UInt64: static_cast<ColumnUInt64 *>(column)->insertDefault(); break;
case value_type_t::Int8: static_cast<ColumnInt8 *>(column)->insertDefault(); break;
case value_type_t::Int16: static_cast<ColumnInt16 *>(column)->insertDefault(); break;
case value_type_t::Int32: static_cast<ColumnInt32 *>(column)->insertDefault(); break;
case value_type_t::Int64: static_cast<ColumnInt64 *>(column)->insertDefault(); break;
case value_type_t::Float32: static_cast<ColumnFloat32 *>(column)->insertDefault(); break;
case value_type_t::Float64: static_cast<ColumnFloat64 *>(column)->insertDefault(); break;
case value_type_t::String: static_cast<ColumnString *>(column)->insertDefault(); break;
case value_type_t::Date: static_cast<ColumnUInt16 *>(column)->insertDefault(); break;
case value_type_t::DateTime: static_cast<ColumnUInt32 *>(column)->insertDefault(); break;
}
}
std::unique_ptr<mongo::DBClientCursor> cursor;
Block sample_block;
const std::size_t max_block_size;
std::vector<value_type_t> types;
std::vector<mongo::StringData> names;
};
}

View File

@ -0,0 +1,128 @@
#pragma once
#include <DB/Dictionaries/IDictionarySource.h>
#include <DB/Dictionaries/MongoDBBlockInputStream.h>
#include <Poco/Util/AbstractConfiguration.h>
#include <mongo/client/dbclient.h>
namespace DB
{
/// Allows loading dictionaries from a MySQL database
class MongoDBDictionarySource final : public IDictionarySource
{
MongoDBDictionarySource(
const DictionaryStructure & dict_struct, const std::string & host, const std::string & port,
const std::string & user, const std::string & password,
const std::string & db, const std::string & collection,
const Block & sample_block, Context & context)
: dict_struct{dict_struct}, host{host}, port{port}, user{user}, password{password},
db{db}, collection{collection}, sample_block{sample_block}, context(context),
connection{true}
{
init();
connection.connect(host + ':' + port);
if (!user.empty())
{
std::string error;
if (!connection.auth(db, user, password, error))
throw DB::Exception{
"Could not authenticate to a MongoDB database " + db + " with provided credentials: " + error,
ErrorCodes::WRONG_PASSWORD
};
}
/// compose BSONObj containing all requested fields
mongo::BSONObjBuilder builder;
builder << "_id" << 0;
for (const auto & column : sample_block.getColumns())
builder << column.name << 1;
fields_to_query = builder.obj();
}
static void init()
{
static const auto mongo_init_status = mongo::client::initialize();
if (!mongo_init_status.isOK())
throw DB::Exception{
"mongo::client::initialize() failed: " + mongo_init_status.toString(),
ErrorCodes::MONGODB_INIT_FAILED
};
LOG_TRACE(&Logger::get("MongoDBDictionarySource"), "mongo::client::initialize() ok");
}
public:
MongoDBDictionarySource(
const DictionaryStructure & dict_struct, const Poco::Util::AbstractConfiguration & config,
const std::string & config_prefix, Block & sample_block, Context & context)
: MongoDBDictionarySource{
dict_struct,
config.getString(config_prefix + ".host"),
config.getString(config_prefix + ".port"),
config.getString(config_prefix + ".user", ""),
config.getString(config_prefix + ".password", ""),
config.getString(config_prefix + ".db", ""),
config.getString(config_prefix + ".collection"),
sample_block, context
}
{
}
MongoDBDictionarySource(const MongoDBDictionarySource & other)
: MongoDBDictionarySource{
other.dict_struct, other.host, other.port, other.user, other.password,
other.db, other.collection, other.sample_block, other.context
}
{
}
BlockInputStreamPtr loadAll() override
{
return new MongoDBBlockInputStream{
connection.query(db + '.' + collection, {}, 0, 0, &fields_to_query),
sample_block, 8192
};
}
bool supportsSelectiveLoad() const override { return true; }
BlockInputStreamPtr loadIds(const std::vector<std::uint64_t> & ids) override
{
return new MongoDBBlockInputStream{
connection.query(db + '.' + collection, {}, 0, 0, &fields_to_query),
sample_block, 8192
};
}
bool isModified() const override { return false; }
DictionarySourcePtr clone() const override { return std::make_unique<MongoDBDictionarySource>(*this); }
std::string toString() const override
{
return "MongoDB: " + db + '.' + collection + ',' + (user.empty() ? " " : " " + user + '@') + host + ':' + port;
}
private:
const DictionaryStructure dict_struct;
const std::string host;
const std::string port;
const std::string user;
const std::string password;
const std::string db;
const std::string collection;
Block sample_block;
Context & context;
mongo::DBClientConnection connection;
mongo::BSONObj fields_to_query;
};
}

View File

@ -19,7 +19,7 @@ class MySQLDictionarySource final : public IDictionarySource
public: public:
MySQLDictionarySource(const DictionaryStructure & dict_struct, MySQLDictionarySource(const DictionaryStructure & dict_struct,
const Poco::Util::AbstractConfiguration & config, const std::string & config_prefix, const Poco::Util::AbstractConfiguration & config, const std::string & config_prefix,
Block & sample_block) const Block & sample_block)
: dict_struct{dict_struct}, : dict_struct{dict_struct},
db{config.getString(config_prefix + ".db", "")}, db{config.getString(config_prefix + ".db", "")},
table{config.getString(config_prefix + ".table")}, table{config.getString(config_prefix + ".table")},
@ -78,7 +78,6 @@ public:
private: private:
Logger * log = &Logger::get("MySQLDictionarySource"); Logger * log = &Logger::get("MySQLDictionarySource");
static std::string quoteForLike(const std::string s) static std::string quoteForLike(const std::string s)
{ {
std::string tmp; std::string tmp;

View File

@ -658,13 +658,13 @@ private:
public: public:
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 2) if (arguments.size() != 2)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -692,7 +692,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
if (!( executeLeftType<DataTypeDate>(block, arguments, result) if (!( executeLeftType<DataTypeDate>(block, arguments, result)
|| executeLeftType<DataTypeDateTime>(block, arguments, result) || executeLeftType<DataTypeDateTime>(block, arguments, result)
@ -767,13 +767,13 @@ private:
public: public:
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -799,7 +799,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
if (!( executeType<UInt8>(block, arguments, result) if (!( executeType<UInt8>(block, arguments, result)
|| executeType<UInt16>(block, arguments, result) || executeType<UInt16>(block, arguments, result)

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <DB/Core/FieldVisitors.h>
#include <DB/DataTypes/DataTypeArray.h> #include <DB/DataTypes/DataTypeArray.h>
#include <DB/DataTypes/DataTypesNumberFixed.h> #include <DB/DataTypes/DataTypesNumberFixed.h>
#include <DB/DataTypes/DataTypeDate.h> #include <DB/DataTypes/DataTypeDate.h>
@ -56,7 +58,7 @@ public:
private: private:
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
@ -159,7 +161,7 @@ private:
public: public:
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.empty()) if (arguments.empty())
throw Exception("Function array requires at least one argument.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); throw Exception("Function array requires at least one argument.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -184,7 +186,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const auto is_const = [&] { const auto is_const = [&] {
for (const auto arg_num : arguments) for (const auto arg_num : arguments)
@ -702,13 +704,13 @@ private:
} }
public: public:
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 2) if (arguments.size() != 2)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -727,7 +729,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
if (executeTuple(block, arguments, result)) if (executeTuple(block, arguments, result))
{ {
@ -795,13 +797,18 @@ struct IndexCount
}; };
template <typename T, typename IndexConv> template <typename T, typename U, typename IndexConv>
struct ArrayIndexNumImpl struct ArrayIndexNumImpl
{ {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-compare"
/// compares `lhs` against `i`-th element of `rhs` /// 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 /// 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> template <typename ScalarOrVector>
static void vector( static void vector(
@ -921,6 +928,21 @@ private:
template <typename T> template <typename T>
bool executeNumber(Block & block, const ColumnNumbers & arguments, size_t result) 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); 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(); 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; const auto col_res = new ResultColumnType;
ColumnPtr col_ptr{col_res}; ColumnPtr col_ptr{col_res};
block.getByPosition(result).column = col_ptr; 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()); 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; const auto col_res = new ResultColumnType;
ColumnPtr col_ptr{col_res}; ColumnPtr col_ptr{col_res};
block.getByPosition(result).column = col_ptr; 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()); item_arg_vector->getData(), col_res->getData());
} }
else
return false;
return true; return true;
} }
@ -1010,7 +1034,7 @@ private:
for (size_t i = 0, size = arr.size(); i < size; ++i) 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)) if (!IndexConv::apply(i, current))
break; break;
@ -1035,7 +1059,7 @@ private:
const auto & value = (*item_arg)[row]; const auto & value = (*item_arg)[row];
for (size_t i = 0, size = arr.size(); i < size; ++i) 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])) if (!IndexConv::apply(i, data[row]))
break; break;
@ -1050,13 +1074,13 @@ private:
public: public:
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 2) if (arguments.size() != 2)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1067,7 +1091,8 @@ public:
if (!array_type) if (!array_type)
throw Exception("First argument for function " + getName() + " must be array.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); 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." 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); " Passed: " + arguments[0]->getName() + " and " + arguments[1]->getName() + ".", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
@ -1075,7 +1100,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
if (!(executeNumber<UInt8>(block, arguments, result) if (!(executeNumber<UInt8>(block, arguments, result)
|| executeNumber<UInt16>(block, arguments, result) || executeNumber<UInt16>(block, arguments, result)
@ -1104,13 +1129,13 @@ public:
static IFunction * create (const Context & context) { return new FunctionArrayEnumerate; } static IFunction * create (const Context & context) { return new FunctionArrayEnumerate; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1125,7 +1150,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
if (const ColumnArray * array = typeid_cast<const ColumnArray *>(&*block.getByPosition(arguments[0]).column)) if (const ColumnArray * array = typeid_cast<const ColumnArray *>(&*block.getByPosition(arguments[0]).column))
{ {
@ -1180,13 +1205,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionArrayUniq; } static IFunction * create(const Context & context) { return new FunctionArrayUniq; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() == 0) if (arguments.size() == 0)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1205,7 +1230,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
if (arguments.size() == 1 && executeConst(block, arguments, result)) if (arguments.size() == 1 && executeConst(block, arguments, result))
return; return;
@ -1410,13 +1435,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionArrayEnumerateUniq; } static IFunction * create(const Context & context) { return new FunctionArrayEnumerateUniq; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() == 0) if (arguments.size() == 0)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1435,7 +1460,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
if (arguments.size() == 1 && executeConst(block, arguments, result)) if (arguments.size() == 1 && executeConst(block, arguments, result))
return; return;
@ -1655,12 +1680,12 @@ struct FunctionEmptyArray : public IFunction
static IFunction * create(const Context & context) { return new FunctionEmptyArray; } static IFunction * create(const Context & context) { return new FunctionEmptyArray; }
private: private:
String getName() const String getName() const override
{ {
return name; return name;
} }
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 0) if (arguments.size() != 0)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1670,7 +1695,7 @@ private:
return new DataTypeArray{new DataType{}}; return new DataTypeArray{new DataType{}};
} }
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
using UnderlyingColumnType = typename TypeToColumnType<typename DataType::FieldType>::ColumnType; using UnderlyingColumnType = typename TypeToColumnType<typename DataType::FieldType>::ColumnType;
@ -1833,13 +1858,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionEmptyArrayToSingle; } static IFunction * create(const Context & context) { return new FunctionEmptyArrayToSingle; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1855,7 +1880,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
if (executeConst(block, arguments, result)) if (executeConst(block, arguments, result))
return; return;

View File

@ -173,9 +173,9 @@ public:
static constexpr auto name = "IPv6NumToString"; static constexpr auto name = "IPv6NumToString";
static IFunction * create(const Context & context) { return new FunctionIPv6NumToString; } static IFunction * create(const Context & context) { return new FunctionIPv6NumToString; }
String getName() const { return name; } String getName() const override { return name; }
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -259,9 +259,9 @@ public:
static constexpr auto name = "cutIPv6"; static constexpr auto name = "cutIPv6";
static IFunction * create(const Context & context) { return new FunctionCutIPv6; } static IFunction * create(const Context & context) { return new FunctionCutIPv6; }
String getName() const { return name; } String getName() const override { return name; }
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 3) if (arguments.size() != 3)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -425,9 +425,9 @@ public:
static constexpr auto name = "IPv6StringToNum"; static constexpr auto name = "IPv6StringToNum";
static IFunction * create(const Context & context) { return new FunctionIPv6StringToNum; } static IFunction * create(const Context & context) { return new FunctionIPv6StringToNum; }
String getName() const { return name; } String getName() const override { return name; }
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -594,7 +594,7 @@ public:
memcpy(dst, tmp, sizeof(tmp)); memcpy(dst, tmp, sizeof(tmp));
} }
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const ColumnPtr & column = block.getByPosition(arguments[0]).column; const ColumnPtr & column = block.getByPosition(arguments[0]).column;
@ -642,13 +642,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionIPv4NumToString; } static IFunction * create(const Context & context) { return new FunctionIPv4NumToString; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -697,7 +697,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const ColumnPtr column = block.getByPosition(arguments[0]).column; const ColumnPtr column = block.getByPosition(arguments[0]).column;
@ -747,13 +747,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionIPv4StringToNum; } static IFunction * create(const Context & context) { return new FunctionIPv4StringToNum; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -796,7 +796,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const ColumnPtr column = block.getByPosition(arguments[0]).column; const ColumnPtr column = block.getByPosition(arguments[0]).column;
@ -838,13 +838,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionIPv4NumToStringClassC; } static IFunction * create(const Context & context) { return new FunctionIPv4NumToStringClassC; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -896,7 +896,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const ColumnPtr column = block.getByPosition(arguments[0]).column; const ColumnPtr column = block.getByPosition(arguments[0]).column;
@ -945,9 +945,9 @@ public:
static constexpr auto name = "IPv4ToIPv6"; static constexpr auto name = "IPv4ToIPv6";
static IFunction * create(const Context & context) { return new FunctionIPv4ToIPv6; } static IFunction * create(const Context & context) { return new FunctionIPv4ToIPv6; }
String getName() const { return name; } String getName() const override { return name; }
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1010,13 +1010,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionHex; } static IFunction * create(const Context & context) { return new FunctionHex; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1231,7 +1231,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const IColumn * column = &*block.getByPosition(arguments[0]).column; const IColumn * column = &*block.getByPosition(arguments[0]).column;
ColumnPtr & res_column = block.getByPosition(result).column; ColumnPtr & res_column = block.getByPosition(result).column;
@ -1258,13 +1258,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionUnhex; } static IFunction * create(const Context & context) { return new FunctionUnhex; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1303,7 +1303,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const ColumnPtr column = block.getByPosition(arguments[0]).column; const ColumnPtr column = block.getByPosition(arguments[0]).column;
@ -1366,13 +1366,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionBitmaskToArray; } static IFunction * create(const Context & context) { return new FunctionBitmaskToArray; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1450,7 +1450,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const IColumn * in_column = &*block.getByPosition(arguments[0]).column; const IColumn * in_column = &*block.getByPosition(arguments[0]).column;
ColumnPtr & out_column = block.getByPosition(result).column; ColumnPtr & out_column = block.getByPosition(result).column;
@ -1478,13 +1478,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionToStringCutToZero; } static IFunction * create(const Context & context) { return new FunctionToStringCutToZero; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1600,7 +1600,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const IColumn * column = &*block.getByPosition(arguments[0]).column; const IColumn * column = &*block.getByPosition(arguments[0]).column;
ColumnPtr & res_column = block.getByPosition(result).column; ColumnPtr & res_column = block.getByPosition(result).column;

View File

@ -10,7 +10,9 @@
#include <DB/DataTypes/DataTypeDate.h> #include <DB/DataTypes/DataTypeDate.h>
#include <DB/DataTypes/DataTypeString.h> #include <DB/DataTypes/DataTypeString.h>
#include <DB/DataTypes/DataTypeFixedString.h> #include <DB/DataTypes/DataTypeFixedString.h>
#include <DB/DataTypes/DataTypeTuple.h>
#include <DB/Functions/FunctionsLogical.h>
#include <DB/Functions/IFunction.h> #include <DB/Functions/IFunction.h>
@ -384,6 +386,14 @@ template <typename A, typename B>
struct StringComparisonImpl<NotEqualsOp<A, B>> : StringEqualsImpl<false> {}; struct StringComparisonImpl<NotEqualsOp<A, B>> : StringEqualsImpl<false> {};
struct NameEquals { static constexpr auto name = "equals"; };
struct NameNotEquals { static constexpr auto name = "notEquals"; };
struct NameLess { static constexpr auto name = "less"; };
struct NameGreater { static constexpr auto name = "greater"; };
struct NameLessOrEquals { static constexpr auto name = "lessOrEquals"; };
struct NameGreaterOrEquals { static constexpr auto name = "greaterOrEquals"; };
template < template <
template <typename, typename> class Op, template <typename, typename> class Op,
typename Name> typename Name>
@ -620,15 +630,117 @@ private:
} }
} }
void executeTuple(Block & block, size_t result, const IColumn * c0, const IColumn * c1)
{
/** Сравнивать кортежи будем лексикографически. Это делается следующим образом:
* x == y : x1 == y1 && x2 == y2 ...
* x != y : x1 != y1 || x2 != y2 ...
*
* x < y: x1 < y1 || (x1 == y1 && (x2 < y2 || (x2 == y2 ... && xn < yn))
* x > y: x1 > y1 || (x1 == y1 && (x2 > y2 || (x2 == y2 ... && xn > yn))
* x <= y: x1 < y1 || (x1 == y1 && (x2 < y2 || (x2 == y2 ... && xn <= yn))
*
* Рекурсивная запись:
* x <= y: x1 < y1 || (x1 == y1 && x_tail <= y_tail)
*
* x >= y: x1 > y1 || (x1 == y1 && (x2 > y2 || (x2 == y2 ... && xn >= yn))
*/
auto x = static_cast<const ColumnTuple *>(c0);
auto y = static_cast<const ColumnTuple *>(c1);
const size_t tuple_size = x->getData().columns();
if (0 == tuple_size)
throw Exception("Comparison of zero-sized tuples is not implemented.", ErrorCodes::NOT_IMPLEMENTED);
executeTupleImpl(block, result, x, y, tuple_size);
}
void executeTupleImpl(Block & block, size_t result, const ColumnTuple * x, const ColumnTuple * y, size_t tuple_size);
template <typename ComparisonFunction, typename ConvolutionFunction>
void executeTupleEqualityImpl(Block & block, size_t result, const ColumnTuple * x, const ColumnTuple * y, size_t tuple_size)
{
ComparisonFunction func_compare;
ConvolutionFunction func_convolution;
Block tmp_block;
for (size_t i = 0; i < tuple_size; ++i)
{
tmp_block.insert(x->getData().getByPosition(i));
tmp_block.insert(y->getData().getByPosition(i));
/// Сравнение элементов.
tmp_block.insert({ nullptr, new DataTypeUInt8, "" });
func_compare.execute(tmp_block, {i * 3, i * 3 + 1}, i * 3 + 2);
}
/// Логическая свёртка.
tmp_block.insert({ nullptr, new DataTypeUInt8, "" });
ColumnNumbers convolution_args(tuple_size);
for (size_t i = 0; i < tuple_size; ++i)
convolution_args[i] = i * 3 + 2;
func_convolution.execute(tmp_block, convolution_args, tuple_size * 3);
block.getByPosition(result).column = tmp_block.getByPosition(tuple_size * 3).column;
}
template <typename HeadComparisonFunction, typename TailComparisonFunction>
void executeTupleLessGreaterImpl(Block & block, size_t result, const ColumnTuple * x, const ColumnTuple * y, size_t tuple_size)
{
HeadComparisonFunction func_compare_head;
TailComparisonFunction func_compare_tail;
FunctionAnd func_and;
FunctionOr func_or;
FunctionComparison<EqualsOp, NameEquals> func_equals;
Block tmp_block;
/// Попарное сравнение на неравенство всех элементов; на равенство всех элементов кроме последнего.
for (size_t i = 0; i < tuple_size; ++i)
{
tmp_block.insert(x->getData().getByPosition(i));
tmp_block.insert(y->getData().getByPosition(i));
tmp_block.insert({ nullptr, new DataTypeUInt8, "" });
if (i + 1 != tuple_size)
{
func_compare_head.execute(tmp_block, {i * 4, i * 4 + 1}, i * 4 + 2);
tmp_block.insert({ nullptr, new DataTypeUInt8, "" });
func_equals.execute(tmp_block, {i * 4, i * 4 + 1}, i * 4 + 3);
}
else
func_compare_tail.execute(tmp_block, {i * 4, i * 4 + 1}, i * 4 + 2);
}
/// Комбинирование. Сложный код - сделайте рисунок. Можно заменить на рекурсивное сравнение кортежей.
size_t i = tuple_size - 1;
while (i > 0)
{
tmp_block.insert({ nullptr, new DataTypeUInt8, "" });
func_and.execute(tmp_block, { tmp_block.columns() - 2, (i - 1) * 4 + 3 }, tmp_block.columns() - 1);
tmp_block.insert({ nullptr, new DataTypeUInt8, "" });
func_or.execute(tmp_block, { tmp_block.columns() - 2, (i - 1) * 4 + 2 }, tmp_block.columns() - 1);
--i;
}
block.getByPosition(result).column = tmp_block.getByPosition(tmp_block.columns() - 1).column;
}
public: public:
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 2) if (arguments.size() != 2)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -639,23 +751,27 @@ public:
bool left_is_date_time = false; bool left_is_date_time = false;
bool left_is_string = false; bool left_is_string = false;
bool left_is_fixed_string = false; bool left_is_fixed_string = false;
const DataTypeTuple * left_tuple = nullptr;
false false
|| (left_is_date = typeid_cast<const DataTypeDate *>(arguments[0].get())) || (left_is_date = typeid_cast<const DataTypeDate *>(arguments[0].get()))
|| (left_is_date_time = typeid_cast<const DataTypeDateTime *>(arguments[0].get())) || (left_is_date_time = typeid_cast<const DataTypeDateTime *>(arguments[0].get()))
|| (left_is_string = typeid_cast<const DataTypeString *>(arguments[0].get())) || (left_is_string = typeid_cast<const DataTypeString *>(arguments[0].get()))
|| (left_is_fixed_string = typeid_cast<const DataTypeFixedString *>(arguments[0].get())); || (left_is_fixed_string = typeid_cast<const DataTypeFixedString *>(arguments[0].get()))
|| (left_tuple = typeid_cast<const DataTypeTuple *>(arguments[0].get()));
bool right_is_date = false; bool right_is_date = false;
bool right_is_date_time = false; bool right_is_date_time = false;
bool right_is_string = false; bool right_is_string = false;
bool right_is_fixed_string = false; bool right_is_fixed_string = false;
const DataTypeTuple * right_tuple = nullptr;
false false
|| (right_is_date = typeid_cast<const DataTypeDate *>(arguments[1].get())) || (right_is_date = typeid_cast<const DataTypeDate *>(arguments[1].get()))
|| (right_is_date_time = typeid_cast<const DataTypeDateTime *>(arguments[1].get())) || (right_is_date_time = typeid_cast<const DataTypeDateTime *>(arguments[1].get()))
|| (right_is_string = typeid_cast<const DataTypeString *>(arguments[1].get())) || (right_is_string = typeid_cast<const DataTypeString *>(arguments[1].get()))
|| (right_is_fixed_string = typeid_cast<const DataTypeFixedString *>(arguments[1].get())); || (right_is_fixed_string = typeid_cast<const DataTypeFixedString *>(arguments[1].get()))
|| (right_tuple = typeid_cast<const DataTypeTuple *>(arguments[1].get()));
if (!( (arguments[0]->behavesAsNumber() && arguments[1]->behavesAsNumber()) if (!( (arguments[0]->behavesAsNumber() && arguments[1]->behavesAsNumber())
|| ((left_is_string || left_is_fixed_string) && (right_is_string || right_is_fixed_string)) || ((left_is_string || left_is_fixed_string) && (right_is_string || right_is_fixed_string))
@ -664,15 +780,23 @@ public:
|| (left_is_string && right_is_date) || (left_is_string && right_is_date)
|| (left_is_date_time && right_is_date_time) || (left_is_date_time && right_is_date_time)
|| (left_is_date_time && right_is_string) || (left_is_date_time && right_is_string)
|| (left_is_string && right_is_date_time))) || (left_is_string && right_is_date_time)
|| (left_tuple && right_tuple && left_tuple->getElements().size() == right_tuple->getElements().size())))
throw Exception("Illegal types of arguments (" + arguments[0]->getName() + ", " + arguments[1]->getName() + ")" throw Exception("Illegal types of arguments (" + arguments[0]->getName() + ", " + arguments[1]->getName() + ")"
" of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); " of function " + getName(), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
if (left_tuple && right_tuple)
{
size_t size = left_tuple->getElements().size();
for (size_t i = 0; i < size; ++i)
getReturnType({ left_tuple->getElements()[i], right_tuple->getElements()[i] });
}
return new DataTypeUInt8; return new DataTypeUInt8;
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const IColumn * col_left_untyped = block.getByPosition(arguments[0]).column.get(); const IColumn * col_left_untyped = block.getByPosition(arguments[0]).column.get();
const IColumn * col_right_untyped = block.getByPosition(arguments[1]).column.get(); const IColumn * col_right_untyped = block.getByPosition(arguments[1]).column.get();
@ -696,25 +820,25 @@ public:
+ " of first argument of function " + getName(), + " of first argument of function " + getName(),
ErrorCodes::ILLEGAL_COLUMN); ErrorCodes::ILLEGAL_COLUMN);
} }
else if (!left_is_num && !right_is_num)
{
executeString(block, result, col_left_untyped, col_right_untyped);
}
else else
{ {
executeDateOrDateTimeWithConstString(block, result, col_left_untyped, col_right_untyped, left_is_num, right_is_num); if (typeid_cast<const ColumnTuple *>(col_left_untyped))
{
executeTuple(block, result, col_left_untyped, col_right_untyped);
}
else if (!left_is_num && !right_is_num)
{
executeString(block, result, col_left_untyped, col_right_untyped);
}
else
{
executeDateOrDateTimeWithConstString(block, result, col_left_untyped, col_right_untyped, left_is_num, right_is_num);
}
} }
} }
}; };
struct NameEquals { static constexpr auto name = "equals"; };
struct NameNotEquals { static constexpr auto name = "notEquals"; };
struct NameLess { static constexpr auto name = "less"; };
struct NameGreater { static constexpr auto name = "greater"; };
struct NameLessOrEquals { static constexpr auto name = "lessOrEquals"; };
struct NameGreaterOrEquals { static constexpr auto name = "greaterOrEquals"; };
typedef FunctionComparison<EqualsOp, NameEquals> FunctionEquals; typedef FunctionComparison<EqualsOp, NameEquals> FunctionEquals;
typedef FunctionComparison<NotEqualsOp, NameNotEquals> FunctionNotEquals; typedef FunctionComparison<NotEqualsOp, NameNotEquals> FunctionNotEquals;
typedef FunctionComparison<LessOp, NameLess> FunctionLess; typedef FunctionComparison<LessOp, NameLess> FunctionLess;
@ -722,4 +846,56 @@ typedef FunctionComparison<GreaterOp, NameGreater> FunctionGreater;
typedef FunctionComparison<LessOrEqualsOp, NameLessOrEquals> FunctionLessOrEquals; typedef FunctionComparison<LessOrEqualsOp, NameLessOrEquals> FunctionLessOrEquals;
typedef FunctionComparison<GreaterOrEqualsOp, NameGreaterOrEquals> FunctionGreaterOrEquals; typedef FunctionComparison<GreaterOrEqualsOp, NameGreaterOrEquals> FunctionGreaterOrEquals;
template <>
void FunctionComparison<EqualsOp, NameEquals>::executeTupleImpl(
Block & block, size_t result, const ColumnTuple * x, const ColumnTuple * y, size_t tuple_size)
{
return executeTupleEqualityImpl<FunctionComparison<EqualsOp, NameEquals>, FunctionAnd>(block, result, x, y, tuple_size);
}
template <>
void FunctionComparison<NotEqualsOp, NameNotEquals>::executeTupleImpl(
Block & block, size_t result, const ColumnTuple * x, const ColumnTuple * y, size_t tuple_size)
{
return executeTupleEqualityImpl<FunctionComparison<NotEqualsOp, NameNotEquals>, FunctionOr>(block, result, x, y, tuple_size);
}
template <>
void FunctionComparison<LessOp, NameLess>::executeTupleImpl(
Block & block, size_t result, const ColumnTuple * x, const ColumnTuple * y, size_t tuple_size)
{
return executeTupleLessGreaterImpl<
FunctionComparison<LessOp, NameLess>,
FunctionComparison<LessOp, NameLess>>(block, result, x, y, tuple_size);
}
template <>
void FunctionComparison<GreaterOp, NameGreater>::executeTupleImpl(
Block & block, size_t result, const ColumnTuple * x, const ColumnTuple * y, size_t tuple_size)
{
return executeTupleLessGreaterImpl<
FunctionComparison<GreaterOp, NameGreater>,
FunctionComparison<GreaterOp, NameGreater>>(block, result, x, y, tuple_size);
}
template <>
void FunctionComparison<LessOrEqualsOp, NameLessOrEquals>::executeTupleImpl(
Block & block, size_t result, const ColumnTuple * x, const ColumnTuple * y, size_t tuple_size)
{
return executeTupleLessGreaterImpl<
FunctionComparison<LessOp, NameLess>,
FunctionComparison<LessOrEqualsOp, NameLessOrEquals>>(block, result, x, y, tuple_size);
}
template <>
void FunctionComparison<GreaterOrEqualsOp, NameGreaterOrEquals>::executeTupleImpl(
Block & block, size_t result, const ColumnTuple * x, const ColumnTuple * y, size_t tuple_size)
{
return executeTupleLessGreaterImpl<
FunctionComparison<GreaterOp, NameGreater>,
FunctionComparison<GreaterOrEqualsOp, NameGreaterOrEquals>>(block, result, x, y, tuple_size);
}
} }

View File

@ -1273,13 +1273,13 @@ private:
public: public:
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 3) if (arguments.size() != 3)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1346,7 +1346,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const ColumnVector<UInt8> * cond_col = typeid_cast<const ColumnVector<UInt8> *>(&*block.getByPosition(arguments[0]).column); const ColumnVector<UInt8> * cond_col = typeid_cast<const ColumnVector<UInt8> *>(&*block.getByPosition(arguments[0]).column);
const ColumnConst<UInt8> * cond_const_col = typeid_cast<const ColumnConst<UInt8> *>(&*block.getByPosition(arguments[0]).column); const ColumnConst<UInt8> * cond_const_col = typeid_cast<const ColumnConst<UInt8> *>(&*block.getByPosition(arguments[0]).column);

View File

@ -896,19 +896,19 @@ public:
static IFunction * create(const Context & context) { return new FunctionConvert; } static IFunction * create(const Context & context) { return new FunctionConvert; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
return getReturnTypeImpl(arguments); return getReturnTypeImpl(arguments);
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
IDataType * from_type = &*block.getByPosition(arguments[0]).type; IDataType * from_type = &*block.getByPosition(arguments[0]).type;
@ -1009,7 +1009,7 @@ public:
static IFunction * create(const Context & context) { return new FunctionToFixedString; }; static IFunction * create(const Context & context) { return new FunctionToFixedString; };
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
@ -1020,7 +1020,7 @@ public:
*/ */
void getReturnTypeAndPrerequisites(const ColumnsWithTypeAndName & arguments, void getReturnTypeAndPrerequisites(const ColumnsWithTypeAndName & arguments,
DataTypePtr & out_return_type, DataTypePtr & out_return_type,
std::vector<ExpressionAction> & out_prerequisites) std::vector<ExpressionAction> & out_prerequisites) override
{ {
if (arguments.size() != 2) if (arguments.size() != 2)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1038,7 +1038,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
ColumnPtr column = block.getByPosition(arguments[0]).column; ColumnPtr column = block.getByPosition(arguments[0]).column;
size_t n = getSize(block.getByPosition(arguments[1])); size_t n = getSize(block.getByPosition(arguments[1]));

View File

@ -397,7 +397,7 @@ public:
static IFunction * create(const Context & context) { return new FunctionDateOrDateTimeToSomething; }; static IFunction * create(const Context & context) { return new FunctionDateOrDateTimeToSomething; };
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
@ -408,7 +408,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
IDataType * from_type = &*block.getByPosition(arguments[0]).type; IDataType * from_type = &*block.getByPosition(arguments[0]).type;
@ -479,13 +479,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionNow; }; static IFunction * create(const Context & context) { return new FunctionNow; };
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 0) if (arguments.size() != 0)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -496,7 +496,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
block.getByPosition(result).column = new ColumnConstUInt32( block.getByPosition(result).column = new ColumnConstUInt32(
block.rowsInFirstColumn(), block.rowsInFirstColumn(),
@ -512,13 +512,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionToday; }; static IFunction * create(const Context & context) { return new FunctionToday; };
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 0) if (arguments.size() != 0)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -529,7 +529,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
block.getByPosition(result).column = new ColumnConstUInt16( block.getByPosition(result).column = new ColumnConstUInt16(
block.rowsInFirstColumn(), block.rowsInFirstColumn(),
@ -545,13 +545,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionYesterday; }; static IFunction * create(const Context & context) { return new FunctionYesterday; };
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 0) if (arguments.size() != 0)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -562,7 +562,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
block.getByPosition(result).column = new ColumnConstUInt16( block.getByPosition(result).column = new ColumnConstUInt16(
block.rowsInFirstColumn(), block.rowsInFirstColumn(),
@ -578,13 +578,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionTimeSlot; }; static IFunction * create(const Context & context) { return new FunctionTimeSlot; };
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -599,7 +599,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
if (const ColumnUInt32 * times = typeid_cast<const ColumnUInt32 *>(&*block.getByPosition(arguments[0]).column)) if (const ColumnUInt32 * times = typeid_cast<const ColumnUInt32 *>(&*block.getByPosition(arguments[0]).column))
{ {
@ -714,13 +714,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionTimeSlots; }; static IFunction * create(const Context & context) { return new FunctionTimeSlots; };
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 2) if (arguments.size() != 2)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -739,7 +739,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const ColumnUInt32 * starts = typeid_cast<const ColumnUInt32 *>(&*block.getByPosition(arguments[0]).column); const ColumnUInt32 * starts = typeid_cast<const ColumnUInt32 *>(&*block.getByPosition(arguments[0]).column);
const ColumnConstUInt32 * const_starts = typeid_cast<const ColumnConstUInt32 *>(&*block.getByPosition(arguments[0]).column); const ColumnConstUInt32 * const_starts = typeid_cast<const ColumnConstUInt32 *>(&*block.getByPosition(arguments[0]).column);

View File

@ -182,13 +182,13 @@ public:
} }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1 && arguments.size() != 2) if (arguments.size() != 1 && arguments.size() != 2)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -209,7 +209,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
/// Ключ словаря, определяющий "точку зрения". /// Ключ словаря, определяющий "точку зрения".
std::string dict_key; std::string dict_key;
@ -274,13 +274,13 @@ public:
} }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 2 && arguments.size() != 3) if (arguments.size() != 2 && arguments.size() != 3)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -306,7 +306,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
/// Ключ словаря, определяющий "точку зрения". /// Ключ словаря, определяющий "точку зрения".
std::string dict_key; std::string dict_key;
@ -407,13 +407,13 @@ public:
} }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1 && arguments.size() != 2) if (arguments.size() != 1 && arguments.size() != 2)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -434,7 +434,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
/// Ключ словаря, определяющий "точку зрения". /// Ключ словаря, определяющий "точку зрения".
std::string dict_key; std::string dict_key;
@ -667,13 +667,13 @@ public:
} }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1 && arguments.size() != 2) if (arguments.size() != 1 && arguments.size() != 2)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -694,7 +694,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
RegionsNames::Language language = RegionsNames::Language::RU; RegionsNames::Language language = RegionsNames::Language::RU;

View File

@ -25,13 +25,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionBitmaskToList; } static IFunction * create(const Context & context) { return new FunctionBitmaskToList; }
/// Получить основное имя функции. /// Получить основное имя функции.
virtual String getName() const virtual String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
virtual DataTypePtr getReturnType(const DataTypes & arguments) const virtual DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -54,7 +54,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
if (!( executeType<UInt8>(block, arguments, result) if (!( executeType<UInt8>(block, arguments, result)
|| executeType<UInt16>(block, arguments, result) || executeType<UInt16>(block, arguments, result)
@ -138,13 +138,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionFormatReadableSize; } static IFunction * create(const Context & context) { return new FunctionFormatReadableSize; }
/// Получить основное имя функции. /// Получить основное имя функции.
virtual String getName() const virtual String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
virtual DataTypePtr getReturnType(const DataTypes & arguments) const virtual DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -160,7 +160,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
if (!( executeType<UInt8>(block, arguments, result) if (!( executeType<UInt8>(block, arguments, result)
|| executeType<UInt16>(block, arguments, result) || executeType<UInt16>(block, arguments, result)

View File

@ -174,13 +174,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionStringHash64; }; static IFunction * create(const Context & context) { return new FunctionStringHash64; };
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -195,7 +195,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
if (const ColumnString * col_from = typeid_cast<const ColumnString *>(&*block.getByPosition(arguments[0]).column)) if (const ColumnString * col_from = typeid_cast<const ColumnString *>(&*block.getByPosition(arguments[0]).column))
{ {
@ -235,13 +235,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionStringHashFixedString; }; static IFunction * create(const Context & context) { return new FunctionStringHashFixedString; };
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -256,7 +256,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
if (const ColumnString * col_from = typeid_cast<const ColumnString *>(&*block.getByPosition(arguments[0]).column)) if (const ColumnString * col_from = typeid_cast<const ColumnString *>(&*block.getByPosition(arguments[0]).column))
{ {
@ -334,13 +334,13 @@ private:
public: public:
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -355,7 +355,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
IDataType * from_type = &*block.getByPosition(arguments[0]).type; IDataType * from_type = &*block.getByPosition(arguments[0]).type;
@ -567,19 +567,19 @@ private:
public: public:
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
return new DataTypeUInt64; return new DataTypeUInt64;
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
size_t rows = block.rowsInFirstColumn(); size_t rows = block.rowsInFirstColumn();
ColumnUInt64 * col_to = new ColumnUInt64(rows); ColumnUInt64 * col_to = new ColumnUInt64(rows);

View File

@ -8,7 +8,7 @@
#include <DB/Columns/ColumnExpression.h> #include <DB/Columns/ColumnExpression.h>
#include <DB/Functions/IFunction.h> #include <DB/Functions/IFunction.h>
#include "FunctionsMiscellaneous.h" #include <DB/Functions/FunctionsMiscellaneous.h>
namespace DB namespace DB
@ -549,7 +549,7 @@ public:
static IFunction * create(const Context & context) { return new FunctionArrayMapped; }; static IFunction * create(const Context & context) { return new FunctionArrayMapped; };
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
@ -588,7 +588,7 @@ public:
void getReturnTypeAndPrerequisites(const ColumnsWithTypeAndName & arguments, void getReturnTypeAndPrerequisites(const ColumnsWithTypeAndName & arguments,
DataTypePtr & out_return_type, DataTypePtr & out_return_type,
ExpressionActions::Actions & out_prerequisites) ExpressionActions::Actions & out_prerequisites) override
{ {
size_t min_args = Impl::needExpression() ? 2 : 1; size_t min_args = Impl::needExpression() ? 2 : 1;
if (arguments.size() < min_args) if (arguments.size() < min_args)

View File

@ -242,13 +242,13 @@ private:
public: public:
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() < 2) if (arguments.size() < 2)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -268,7 +268,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
ColumnPlainPtrs in(arguments.size()); ColumnPlainPtrs in(arguments.size());
for (size_t i = 0; i < arguments.size(); ++i) for (size_t i = 0; i < arguments.size(); ++i)
@ -396,13 +396,13 @@ private:
public: public:
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -419,7 +419,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
if (!( executeType<UInt8>(block, arguments, result) if (!( executeType<UInt8>(block, arguments, result)
|| executeType<UInt16>(block, arguments, result) || executeType<UInt16>(block, arguments, result)

View File

@ -4,6 +4,7 @@
#include <common/Revision.h> #include <common/Revision.h>
#include <DB/Core/Defines.h> #include <DB/Core/Defines.h>
#include <DB/Core/FieldVisitors.h>
#include <DB/IO/WriteBufferFromString.h> #include <DB/IO/WriteBufferFromString.h>
#include <DB/DataTypes/DataTypesNumberFixed.h> #include <DB/DataTypes/DataTypesNumberFixed.h>
#include <DB/DataTypes/DataTypeString.h> #include <DB/DataTypes/DataTypeString.h>
@ -94,11 +95,11 @@ public:
explicit FunctionCurrentDatabase(const String & db_name) : db_name{db_name} {} explicit FunctionCurrentDatabase(const String & db_name) : db_name{db_name} {}
String getName() const { String getName() const override {
return name; return name;
} }
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 0) if (arguments.size() != 0)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -125,13 +126,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionHostName; } static IFunction * create(const Context & context) { return new FunctionHostName; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 0) if (arguments.size() != 0)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -143,7 +144,7 @@ public:
/** Выполнить функцию над блоком. convertToFullColumn вызывается для того, чтобы в случае /** Выполнить функцию над блоком. convertToFullColumn вызывается для того, чтобы в случае
* распределенного выполнения запроса каждый сервер возвращал свое имя хоста. */ * распределенного выполнения запроса каждый сервер возвращал свое имя хоста. */
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
block.getByPosition(result).column = ColumnConstString( block.getByPosition(result).column = ColumnConstString(
block.rowsInFirstColumn(), block.rowsInFirstColumn(),
@ -159,13 +160,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionVisibleWidth; } static IFunction * create(const Context & context) { return new FunctionVisibleWidth; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -176,7 +177,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result); void execute(Block & block, const ColumnNumbers & arguments, size_t result) override;
}; };
@ -187,13 +188,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionToTypeName; } static IFunction * create(const Context & context) { return new FunctionToTypeName; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -204,7 +205,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
block.getByPosition(result).column = new ColumnConstString(block.rowsInFirstColumn(), block.getByPosition(arguments[0]).type->getName()); block.getByPosition(result).column = new ColumnConstString(block.rowsInFirstColumn(), block.getByPosition(arguments[0]).type->getName());
} }
@ -218,13 +219,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionBlockSize; } static IFunction * create(const Context & context) { return new FunctionBlockSize; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (!arguments.empty()) if (!arguments.empty())
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -235,7 +236,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
size_t size = block.rowsInFirstColumn(); size_t size = block.rowsInFirstColumn();
block.getByPosition(result).column = ColumnConstUInt64(size, size).convertToFullColumn(); block.getByPosition(result).column = ColumnConstUInt64(size, size).convertToFullColumn();
@ -250,13 +251,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionSleep; } static IFunction * create(const Context & context) { return new FunctionSleep; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -276,7 +277,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
IColumn * col = &*block.getByPosition(arguments[0]).column; IColumn * col = &*block.getByPosition(arguments[0]).column;
double seconds; double seconds;
@ -319,13 +320,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionMaterialize; } static IFunction * create(const Context & context) { return new FunctionMaterialize; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -336,7 +337,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const IColumn & argument = *block.getByPosition(arguments[0]).column; const IColumn & argument = *block.getByPosition(arguments[0]).column;
if (!argument.isConst()) if (!argument.isConst())
@ -360,13 +361,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionIn; } static IFunction * create(const Context & context) { return new FunctionIn; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 2) if (arguments.size() != 2)
throw Exception("Number of arguments for function '" + getName() + "' doesn't match: passed " throw Exception("Number of arguments for function '" + getName() + "' doesn't match: passed "
@ -377,7 +378,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
/// Второй аргумент - обязательно ColumnSet. /// Второй аргумент - обязательно ColumnSet.
ColumnPtr column_set_ptr = block.getByPosition(arguments[1]).column; ColumnPtr column_set_ptr = block.getByPosition(arguments[1]).column;
@ -407,13 +408,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionTuple; } static IFunction * create(const Context & context) { return new FunctionTuple; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() < 1) if (arguments.size() < 1)
throw Exception("Function " + getName() + " requires at least one argument.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); throw Exception("Function " + getName() + " requires at least one argument.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -422,7 +423,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
Block tuple_block; Block tuple_block;
@ -441,14 +442,14 @@ public:
static IFunction * create(const Context & context) { return new FunctionTupleElement; } static IFunction * create(const Context & context) { return new FunctionTupleElement; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
void getReturnTypeAndPrerequisites(const ColumnsWithTypeAndName & arguments, void getReturnTypeAndPrerequisites(const ColumnsWithTypeAndName & arguments,
DataTypePtr & out_return_type, DataTypePtr & out_return_type,
ExpressionActions::Actions & out_prerequisites) ExpressionActions::Actions & out_prerequisites) override
{ {
if (arguments.size() != 2) if (arguments.size() != 2)
throw Exception("Function " + getName() + " requires exactly two arguments: tuple and element index.", throw Exception("Function " + getName() + " requires exactly two arguments: tuple and element index.",
@ -476,7 +477,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const ColumnTuple * tuple_col = typeid_cast<const ColumnTuple *>(&*block.getByPosition(arguments[0]).column); const ColumnTuple * tuple_col = typeid_cast<const ColumnTuple *>(&*block.getByPosition(arguments[0]).column);
const ColumnConstUInt8 * index_col = typeid_cast<const ColumnConstUInt8 *>(&*block.getByPosition(arguments[1]).column); const ColumnConstUInt8 * index_col = typeid_cast<const ColumnConstUInt8 *>(&*block.getByPosition(arguments[1]).column);
@ -508,19 +509,19 @@ public:
static IFunction * create(const Context & context) { return new FunctionIgnore; } static IFunction * create(const Context & context) { return new FunctionIgnore; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
return new DataTypeUInt8; return new DataTypeUInt8;
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
block.getByPosition(result).column = new ColumnConstUInt8(block.rowsInFirstColumn(), 0); block.getByPosition(result).column = new ColumnConstUInt8(block.rowsInFirstColumn(), 0);
} }
@ -534,13 +535,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionIdentity; } static IFunction * create(const Context & context) { return new FunctionIdentity; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Function " + getName() + " requires exactly one argument.", throw Exception("Function " + getName() + " requires exactly one argument.",
@ -550,7 +551,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
block.getByPosition(result).column = block.getByPosition(arguments.front()).column; block.getByPosition(result).column = block.getByPosition(arguments.front()).column;
} }
@ -565,13 +566,13 @@ public:
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Function " + getName() + " requires exactly one argument.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); throw Exception("Function " + getName() + " requires exactly one argument.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
@ -584,7 +585,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
throw Exception("Function " + getName() + " must not be executed directly.", ErrorCodes::FUNCTION_IS_SPECIAL); throw Exception("Function " + getName() + " must not be executed directly.", ErrorCodes::FUNCTION_IS_SPECIAL);
} }
@ -601,13 +602,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionReplicate; } static IFunction * create(const Context & context) { return new FunctionReplicate; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 2) if (arguments.size() != 2)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -622,7 +623,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
ColumnPtr first_column = block.getByPosition(arguments[0]).column; ColumnPtr first_column = block.getByPosition(arguments[0]).column;
@ -652,13 +653,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionBar; } static IFunction * create(const Context & context) { return new FunctionBar; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 3 && arguments.size() != 4) if (arguments.size() != 3 && arguments.size() != 4)
throw Exception("Function " + getName() + " requires from 3 or 4 parameters: value, min_value, max_value, [max_width_of_bar = 80]. Passed " throw Exception("Function " + getName() + " requires from 3 or 4 parameters: value, min_value, max_value, [max_width_of_bar = 80]. Passed "
@ -673,7 +674,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
Int64 min = extractConstant<Int64>(block, arguments, 1, "Second"); /// Уровень значения, при котором полоска имеет нулевую длину. Int64 min = extractConstant<Int64>(block, arguments, 1, "Second"); /// Уровень значения, при котором полоска имеет нулевую длину.
Int64 max = extractConstant<Int64>(block, arguments, 2, "Third"); /// Уровень значения, при котором полоска имеет максимальную длину. Int64 max = extractConstant<Int64>(block, arguments, 2, "Third"); /// Уровень значения, при котором полоска имеет максимальную длину.

View File

@ -153,13 +153,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionRandom; } static IFunction * create(const Context & context) { return new FunctionRandom; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() > 1) if (arguments.size() > 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -170,7 +170,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
ColumnVector<ToType> * col_to = new ColumnVector<ToType>; ColumnVector<ToType> * col_to = new ColumnVector<ToType>;
block.getByPosition(result).column = col_to; block.getByPosition(result).column = col_to;
@ -199,13 +199,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionRandomConstant; } static IFunction * create(const Context & context) { return new FunctionRandomConstant; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() > 1) if (arguments.size() > 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -216,7 +216,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
if (!is_initialized) if (!is_initialized)
{ {

View File

@ -27,13 +27,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionReinterpretAsStringImpl; }; static IFunction * create(const Context & context) { return new FunctionReinterpretAsStringImpl; };
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -97,7 +97,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
if (!( executeType<UInt8>(block, arguments, result) if (!( executeType<UInt8>(block, arguments, result)
|| executeType<UInt16>(block, arguments, result) || executeType<UInt16>(block, arguments, result)
@ -125,13 +125,13 @@ public:
typedef typename ToDataType::FieldType ToFieldType; typedef typename ToDataType::FieldType ToFieldType;
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -147,7 +147,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
if (ColumnString * col_from = typeid_cast<ColumnString *>(&*block.getByPosition(arguments[0]).column)) if (ColumnString * col_from = typeid_cast<ColumnString *>(&*block.getByPosition(arguments[0]).column))
{ {

View File

@ -3,6 +3,8 @@
#include <Poco/UTF8Encoding.h> #include <Poco/UTF8Encoding.h>
#include <Poco/Unicode.h> #include <Poco/Unicode.h>
#include <DB/Core/FieldVisitors.h>
#include <DB/DataTypes/DataTypesNumberFixed.h> #include <DB/DataTypes/DataTypesNumberFixed.h>
#include <DB/DataTypes/DataTypeString.h> #include <DB/DataTypes/DataTypeString.h>
#include <DB/DataTypes/DataTypeFixedString.h> #include <DB/DataTypes/DataTypeFixedString.h>
@ -770,13 +772,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionStringOrArrayToT; } static IFunction * create(const Context & context) { return new FunctionStringOrArrayToT; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -792,7 +794,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const ColumnPtr column = block.getByPosition(arguments[0]).column; const ColumnPtr column = block.getByPosition(arguments[0]).column;
if (const ColumnString * col = typeid_cast<const ColumnString *>(&*column)) if (const ColumnString * col = typeid_cast<const ColumnString *>(&*column))
@ -866,13 +868,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionStringToString; } static IFunction * create(const Context & context) { return new FunctionStringToString; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 1) if (arguments.size() != 1)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -887,7 +889,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const ColumnPtr column = block.getByPosition(arguments[0]).column; const ColumnPtr column = block.getByPosition(arguments[0]).column;
if (const ColumnString * col = typeid_cast<const ColumnString *>(&*column)) if (const ColumnString * col = typeid_cast<const ColumnString *>(&*column))
@ -926,13 +928,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionConcat; } static IFunction * create(const Context & context) { return new FunctionConcat; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() < 2) if (arguments.size() < 2)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1397,13 +1399,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionStringNumNumToString; } static IFunction * create(const Context & context) { return new FunctionStringNumNumToString; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 3) if (arguments.size() != 3)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1422,7 +1424,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const ColumnPtr column_string = block.getByPosition(arguments[0]).column; const ColumnPtr column_string = block.getByPosition(arguments[0]).column;
const ColumnPtr column_start = block.getByPosition(arguments[1]).column; const ColumnPtr column_start = block.getByPosition(arguments[1]).column;
@ -1477,13 +1479,13 @@ public:
static constexpr auto name = "appendTrailingCharIfAbsent"; static constexpr auto name = "appendTrailingCharIfAbsent";
static IFunction * create(const Context & context) { return new FunctionAppendTrailingCharIfAbsent; } static IFunction * create(const Context & context) { return new FunctionAppendTrailingCharIfAbsent; }
String getName() const String getName() const override
{ {
return name; return name;
} }
private: private:
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 2) if (arguments.size() != 2)
throw Exception{ throw Exception{

View File

@ -316,13 +316,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionTokens; } static IFunction * create(const Context & context) { return new FunctionTokens; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
Generator::checkArguments(arguments); Generator::checkArguments(arguments);
@ -330,7 +330,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
Generator generator; Generator generator;
generator.init(block, arguments); generator.init(block, arguments);

View File

@ -75,7 +75,7 @@ struct PositionImpl
while (pos < end && end != (pos = searcher.search(pos, end - pos))) while (pos < end && end != (pos = searcher.search(pos, end - pos)))
{ {
/// Определим, к какому индексу оно относится. /// Определим, к какому индексу оно относится.
while (begin + offsets[i] < pos) while (begin + offsets[i] <= pos)
{ {
res[i] = 0; res[i] = 0;
++i; ++i;
@ -163,7 +163,7 @@ struct PositionUTF8Impl
while (pos < end && end != (pos = searcher.search(pos, end - pos))) while (pos < end && end != (pos = searcher.search(pos, end - pos)))
{ {
/// Определим, к какому индексу оно относится. /// Определим, к какому индексу оно относится.
while (begin + offsets[i] < pos) while (begin + offsets[i] <= pos)
{ {
res[i] = 0; res[i] = 0;
++i; ++i;
@ -364,7 +364,7 @@ public:
while (pos < end && end != (pos = searcher.find(pos, end))) while (pos < end && end != (pos = searcher.find(pos, end)))
{ {
/// Определим, к какому индексу оно относится. /// Определим, к какому индексу оно относится.
while (begin + offsets[i] < pos) while (begin + offsets[i] <= pos)
{ {
res[i] = 0; res[i] = 0;
++i; ++i;
@ -627,7 +627,7 @@ public:
while (pos < end && end != (pos = searcher.find(pos, end))) while (pos < end && end != (pos = searcher.find(pos, end)))
{ {
/// Определим, к какому индексу оно относится. /// Определим, к какому индексу оно относится.
while (begin + offsets[i] < pos) while (begin + offsets[i] <= pos)
{ {
res[i] = 0; res[i] = 0;
++i; ++i;
@ -898,7 +898,7 @@ struct MatchImpl
while (pos < end && end != (pos = searcher.search(pos, end - pos))) while (pos < end && end != (pos = searcher.search(pos, end - pos)))
{ {
/// Определим, к какому индексу оно относится. /// Определим, к какому индексу оно относится.
while (begin + offsets[i] < pos) while (begin + offsets[i] <= pos)
{ {
res[i] = revert; res[i] = revert;
++i; ++i;
@ -965,7 +965,7 @@ struct MatchImpl
while (pos < end && end != (pos = searcher.search(pos, end - pos))) while (pos < end && end != (pos = searcher.search(pos, end - pos)))
{ {
/// Определим, к какому индексу оно относится. /// Определим, к какому индексу оно относится.
while (begin + offsets[i] < pos) while (begin + offsets[i] <= pos)
{ {
res[i] = revert; res[i] = revert;
++i; ++i;
@ -1361,7 +1361,7 @@ struct ReplaceStringImpl
memcpy(&res_data[res_offset], pos, match - pos); memcpy(&res_data[res_offset], pos, match - pos);
/// Определим, к какому индексу оно относится. /// Определим, к какому индексу оно относится.
while (i < offsets.size() && begin + offsets[i] < match) while (i < offsets.size() && begin + offsets[i] <= match)
{ {
res_offsets[i] = res_offset + ((begin + offsets[i]) - pos); res_offsets[i] = res_offset + ((begin + offsets[i]) - pos);
++i; ++i;
@ -1398,6 +1398,7 @@ struct ReplaceStringImpl
res_offset += (begin + offsets[i] - pos); res_offset += (begin + offsets[i] - pos);
res_offsets[i] = res_offset; res_offsets[i] = res_offset;
pos = begin + offsets[i]; pos = begin + offsets[i];
++i;
} }
} }
} }
@ -1430,7 +1431,7 @@ struct ReplaceStringImpl
memcpy(&res_data[res_offset], pos, match - pos); memcpy(&res_data[res_offset], pos, match - pos);
/// Определим, к какому индексу оно относится. /// Определим, к какому индексу оно относится.
while (i < size && begin + n * (i + 1) < match) while (i < size && begin + n * (i + 1) <= match)
{ {
res_offsets[i] = res_offset + ((begin + n * (i + 1)) - pos); res_offsets[i] = res_offset + ((begin + n * (i + 1)) - pos);
++i; ++i;
@ -1504,13 +1505,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionStringReplace; } static IFunction * create(const Context & context) { return new FunctionStringReplace; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 3) if (arguments.size() != 3)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1533,7 +1534,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const ColumnPtr column_src = block.getByPosition(arguments[0]).column; const ColumnPtr column_src = block.getByPosition(arguments[0]).column;
const ColumnPtr column_needle = block.getByPosition(arguments[1]).column; const ColumnPtr column_needle = block.getByPosition(arguments[1]).column;
@ -1591,13 +1592,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionsStringSearch; } static IFunction * create(const Context & context) { return new FunctionsStringSearch; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 2) if (arguments.size() != 2)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1616,7 +1617,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
typedef typename Impl::ResultType ResultType; typedef typename Impl::ResultType ResultType;
@ -1660,13 +1661,13 @@ public:
static IFunction * create(const Context & context) { return new FunctionsStringSearchToString; } static IFunction * create(const Context & context) { return new FunctionsStringSearchToString; }
/// Получить имя функции. /// Получить имя функции.
String getName() const String getName() const override
{ {
return name; return name;
} }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение. /// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnType(const DataTypes & arguments) const DataTypePtr getReturnType(const DataTypes & arguments) const override
{ {
if (arguments.size() != 2) if (arguments.size() != 2)
throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " throw Exception("Number of arguments for function " + getName() + " doesn't match: passed "
@ -1685,7 +1686,7 @@ public:
} }
/// Выполнить функцию над блоком. /// Выполнить функцию над блоком.
void execute(Block & block, const ColumnNumbers & arguments, size_t result) void execute(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
const ColumnPtr column = block.getByPosition(arguments[0]).column; const ColumnPtr column = block.getByPosition(arguments[0]).column;
const ColumnPtr column_needle = block.getByPosition(arguments[1]).column; const ColumnPtr column_needle = block.getByPosition(arguments[1]).column;

View File

@ -2,6 +2,7 @@
#include <mutex> #include <mutex>
#include <DB/Core/FieldVisitors.h>
#include <DB/DataTypes/DataTypesNumberFixed.h> #include <DB/DataTypes/DataTypesNumberFixed.h>
#include <DB/DataTypes/DataTypeString.h> #include <DB/DataTypes/DataTypeString.h>
#include <DB/DataTypes/DataTypeArray.h> #include <DB/DataTypes/DataTypeArray.h>

View File

@ -306,7 +306,7 @@ struct ExtractParamImpl
while (pos < end && end != (pos = searcher.search(pos, end - pos))) while (pos < end && end != (pos = searcher.search(pos, end - pos)))
{ {
/// Определим, к какому индексу оно относится. /// Определим, к какому индексу оно относится.
while (begin + offsets[i] < pos) while (begin + offsets[i] <= pos)
{ {
res[i] = 0; res[i] = 0;
++i; ++i;
@ -369,7 +369,7 @@ struct ExtractParamToStringImpl
while (pos < end && end != (pos = searcher.search(pos, end - pos))) while (pos < end && end != (pos = searcher.search(pos, end - pos)))
{ {
/// Определим, к какому индексу оно относится. /// Определим, к какому индексу оно относится.
while (begin + offsets[i] < pos) while (begin + offsets[i] <= pos)
{ {
res_data.push_back(0); res_data.push_back(0);
res_offsets[i] = res_data.size(); res_offsets[i] = res_data.size();

View File

@ -293,23 +293,7 @@ public:
*/ */
ColumnPtr execute(const Block & block, bool negative) const; ColumnPtr execute(const Block & block, bool negative) const;
std::string describe() 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();
}
/// проверяет есть ли в Set элементы для заданного диапазона индекса /// проверяет есть ли в Set элементы для заданного диапазона индекса
BoolMask mayBeTrueInRange(const Range & range) const; BoolMask mayBeTrueInRange(const Range & range) const;

View File

@ -5,6 +5,8 @@
#include <Poco/Timespan.h> #include <Poco/Timespan.h>
#include <cpuid/libcpuid.h> #include <cpuid/libcpuid.h>
#include <DB/IO/CompressedStream.h> #include <DB/IO/CompressedStream.h>
#include <DB/IO/ReadHelpers.h>
namespace DB namespace DB
{ {

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <DB/Core/Field.h> #include <DB/Core/Field.h>
#include <DB/Core/FieldVisitors.h>
#include <DB/DataTypes/IDataType.h> #include <DB/DataTypes/IDataType.h>
#include <DB/Parsers/ASTWithAlias.h> #include <DB/Parsers/ASTWithAlias.h>

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <DB/Core/Field.h> #include <DB/Core/Field.h>
#include <DB/Core/FieldVisitors.h>
#include <DB/Parsers/IAST.h> #include <DB/Parsers/IAST.h>

View File

@ -225,6 +225,11 @@ private:
std::size_t getIdentifiersColumnSize(const IdentifierNameSet & identifiers) const std::size_t getIdentifiersColumnSize(const IdentifierNameSet & identifiers) const
{ {
/** for expressions containing no columns (or where columns could not be determined otherwise) assume maximum
* possible size so they do not have priority in eligibility over other expressions. */
if (identifiers.empty())
return std::numeric_limits<std::size_t>::max();
std::size_t size{}; std::size_t size{};
for (const auto & identifier : identifiers) for (const auto & identifier : identifiers)

View File

@ -2,6 +2,7 @@
#include <sstream> #include <sstream>
#include <DB/Core/FieldVisitors.h>
#include <DB/Interpreters/Context.h> #include <DB/Interpreters/Context.h>
#include <DB/Core/SortDescription.h> #include <DB/Core/SortDescription.h>
#include <DB/Parsers/ASTExpressionList.h> #include <DB/Parsers/ASTExpressionList.h>

View File

@ -1,4 +1,6 @@
#include <DB/AggregateFunctions/AggregateFunctionFactory.h> #include <DB/AggregateFunctions/AggregateFunctionFactory.h>
#include <DB/IO/WriteBuffer.h>
#include <DB/IO/WriteHelpers.h>
#include <DB/DataTypes/DataTypeAggregateFunction.h> #include <DB/DataTypes/DataTypeAggregateFunction.h>
#include <DB/DataTypes/DataTypeArray.h> #include <DB/DataTypes/DataTypeArray.h>

141
dbms/src/Core/Field.cpp Normal file
View 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());
}
}

View 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);
}
}
}

View File

@ -1,5 +1,9 @@
#include <DB/Core/NamesAndTypes.h> #include <DB/Core/NamesAndTypes.h>
#include <DB/DataTypes/DataTypeFactory.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 namespace DB

View File

@ -3,6 +3,7 @@
#include <sstream> #include <sstream>
#include <DB/Core/Field.h> #include <DB/Core/Field.h>
#include <DB/Core/FieldVisitors.h>
#include <DB/Common/Stopwatch.h> #include <DB/Common/Stopwatch.h>
#include <DB/DataStreams/TabSeparatedRowOutputStream.h> #include <DB/DataStreams/TabSeparatedRowOutputStream.h>
@ -13,7 +14,7 @@
int main(int argc, char ** argv) int main(int argc, char ** argv)
{ {
DB::FieldVisitorToString to_string; DB::FieldVisitorToString to_string;
DB::Field field = DB::UInt64(0); DB::Field field = DB::UInt64(0);
std::cerr << DB::apply_visitor(to_string, field) << std::endl; 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; std::cerr << e.what() << ", " << e.displayText() << std::endl;
return 1; return 1;
} }
std::cerr << "sizeof(Field) = " << sizeof(DB::Field) << std::endl; std::cerr << "sizeof(Field) = " << sizeof(DB::Field) << std::endl;
return 0; return 0;
} }

View File

@ -1,3 +1,4 @@
#include <DB/Core/FieldVisitors.h>
#include <DB/DataStreams/CollapsingSortedBlockInputStream.h> #include <DB/DataStreams/CollapsingSortedBlockInputStream.h>
/// Максимальное количество сообщений о некорректных данных в логе. /// Максимальное количество сообщений о некорректных данных в логе.

View File

@ -1,3 +1,5 @@
#include <DB/Core/FieldVisitors.h>
#include <DB/IO/WriteHelpers.h> #include <DB/IO/WriteHelpers.h>
#include <DB/IO/ReadHelpers.h> #include <DB/IO/ReadHelpers.h>
@ -13,6 +15,30 @@ namespace DB
using Poco::SharedPtr; 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 void DataTypeAggregateFunction::serializeBinary(const Field & field, WriteBuffer & ostr) const
{ {
const String & s = get<const String &>(field); const String & s = get<const String &>(field);

View File

@ -1,5 +1,8 @@
#include <Poco/SharedPtr.h> #include <Poco/SharedPtr.h>
#include <DB/IO/WriteBuffer.h>
#include <DB/IO/WriteHelpers.h>
#include <DB/Columns/ColumnFixedString.h> #include <DB/Columns/ColumnFixedString.h>
#include <DB/Columns/ColumnsNumber.h> #include <DB/Columns/ColumnsNumber.h>
#include <DB/Columns/ColumnConst.h> #include <DB/Columns/ColumnConst.h>
@ -17,6 +20,12 @@ namespace DB
using Poco::SharedPtr; using Poco::SharedPtr;
std::string DataTypeFixedString::getName() const
{
return "FixedString(" + toString(n) + ")";
}
void DataTypeFixedString::serializeBinary(const Field & field, WriteBuffer & ostr) const void DataTypeFixedString::serializeBinary(const Field & field, WriteBuffer & ostr) const
{ {
const String & s = get<const String &>(field); const String & s = get<const String &>(field);

View File

@ -1,5 +1,7 @@
#include <DB/Core/FieldVisitors.h>
#include <DB/DataTypes/FieldToDataType.h> #include <DB/DataTypes/FieldToDataType.h>
namespace DB namespace DB
{ {

View File

@ -1,4 +1,5 @@
#include <DB/Core/Field.h> #include <DB/Core/Field.h>
#include <DB/Core/FieldVisitors.h>
#include <DB/Columns/ColumnString.h> #include <DB/Columns/ColumnString.h>
#include <DB/Columns/ColumnFixedString.h> #include <DB/Columns/ColumnFixedString.h>
@ -230,144 +231,97 @@ bool Set::insertFromBlock(const Block & block, bool create_ordered_set)
} }
/** Чтобы корректно работали выражения вида 1.0 IN (1). /** Проверка попадания Field from, имеющим тип From в диапазон значений типа To.
* From и To - числовые типы. Могут быть типами с плавающей запятой.
* From - это одно из UInt64, Int64, Float64,
* тогда как To может быть также 8, 16, 32 битным.
*
* Если попадает в диапазон, то from конвертируется в Field ближайшего к To типа.
* Если не попадает - возвращается Field(Null).
*/
template <typename From, typename To>
static Field convertNumericTypeImpl(const Field & from)
{
From value = from.get<From>();
if (static_cast<long double>(value) != static_cast<long double>(To(value)))
return {};
return Field(typename NearestFieldType<To>::Type(value));
}
template <typename To>
static Field convertNumericType(const Field & from, const IDataType & type)
{
if (from.getType() == Field::Types::UInt64)
return convertNumericTypeImpl<UInt64, To>(from);
if (from.getType() == Field::Types::Int64)
return convertNumericTypeImpl<Int64, To>(from);
if (from.getType() == Field::Types::Float64)
return convertNumericTypeImpl<Float64, To>(from);
throw Exception("Type mismatch in IN section: " + type.getName() + " at left, "
+ Field::Types::toString(from.getType()) + " at right", ErrorCodes::TYPE_MISMATCH);
}
/** Чтобы корректно работали выражения вида 1.0 IN (1) или чтобы 1 IN (1, 2.0, 2.5, -1) работало так же, как 1 IN (1, 2).
* Проверяет совместимость типов, проверяет попадание значений в диапазон допустимых значений типа, делает преобразование типа. * Проверяет совместимость типов, проверяет попадание значений в диапазон допустимых значений типа, делает преобразование типа.
* Код слегка дурацкий. * Если значение не попадает в диапазон - возвращает Null.
*/ */
static Field convertToType(const Field & src, const IDataType & type) static Field convertToType(const Field & src, const IDataType & type)
{ {
if (type.isNumeric()) if (type.isNumeric())
{ {
bool is_uint8 = false; if (typeid_cast<const DataTypeUInt8 *>(&type)) return convertNumericType<UInt8>(src, type);
bool is_uint16 = false; if (typeid_cast<const DataTypeUInt16 *>(&type)) return convertNumericType<UInt16>(src, type);
bool is_uint32 = false; if (typeid_cast<const DataTypeUInt32 *>(&type)) return convertNumericType<UInt32>(src, type);
bool is_uint64 = false; if (typeid_cast<const DataTypeUInt64 *>(&type)) return convertNumericType<UInt64>(src, type);
bool is_int8 = false; if (typeid_cast<const DataTypeInt8 *>(&type)) return convertNumericType<Int8>(src, type);
bool is_int16 = false; if (typeid_cast<const DataTypeInt16 *>(&type)) return convertNumericType<Int16>(src, type);
bool is_int32 = false; if (typeid_cast<const DataTypeInt32 *>(&type)) return convertNumericType<Int32>(src, type);
bool is_int64 = false; if (typeid_cast<const DataTypeInt64 *>(&type)) return convertNumericType<Int64>(src, type);
bool is_float32 = false; if (typeid_cast<const DataTypeFloat32 *>(&type)) return convertNumericType<Float32>(src, type);
bool is_float64 = false; if (typeid_cast<const DataTypeFloat64 *>(&type)) return convertNumericType<Float64>(src, type);
bool is_date = false;
bool is_datetime = false;
false bool is_date = typeid_cast<const DataTypeDate *>(&type);
|| (is_uint8 = typeid_cast<const DataTypeUInt8 * >(&type)) bool is_datetime = typeid_cast<const DataTypeDateTime *>(&type);
|| (is_uint16 = typeid_cast<const DataTypeUInt16 * >(&type))
|| (is_uint32 = typeid_cast<const DataTypeUInt32 * >(&type))
|| (is_uint64 = typeid_cast<const DataTypeUInt64 * >(&type))
|| (is_int8 = typeid_cast<const DataTypeInt8 * >(&type))
|| (is_int16 = typeid_cast<const DataTypeInt16 * >(&type))
|| (is_int32 = typeid_cast<const DataTypeInt32 * >(&type))
|| (is_int64 = typeid_cast<const DataTypeInt64 * >(&type))
|| (is_float32 = typeid_cast<const DataTypeFloat32 * >(&type))
|| (is_float64 = typeid_cast<const DataTypeFloat64 * >(&type))
|| (is_date = typeid_cast<const DataTypeDate * >(&type))
|| (is_datetime = typeid_cast<const DataTypeDateTime * >(&type))
;
if (is_uint8 || is_uint16 || is_uint32 || is_uint64) if (!is_date && !is_datetime)
throw Exception("Logical error: unknown numeric type " + type.getName(), ErrorCodes::LOGICAL_ERROR);
if (src.getType() == Field::Types::UInt64)
return src;
if (src.getType() == Field::Types::String)
{ {
if (src.getType() == Field::Types::Int64) /// Возможность сравнивать даты и даты-с-временем со строкой.
throw Exception("Type mismatch in IN section: " + type.getName() + " at left, signed at right"); const String & str = src.get<const String &>();
ReadBufferFromString in(str);
if (src.getType() == Field::Types::Float64) if (is_date)
throw Exception("Type mismatch in IN section: " + type.getName() + " at left, floating point at right");
if (src.getType() == Field::Types::UInt64)
{ {
UInt64 value = src.get<const UInt64 &>(); DayNum_t date{};
if ((is_uint8 && value > std::numeric_limits<uint8_t>::max()) readDateText(date, in);
|| (is_uint16 && value > std::numeric_limits<uint16_t>::max()) if (!in.eof())
|| (is_uint32 && value > std::numeric_limits<uint32_t>::max())) throw Exception("String is too long for Date: " + str);
throw Exception("Value (" + toString(value) + ") in IN section is out of range of type " + type.getName() + " at left");
return src; return Field(UInt64(date));
} }
else
throw Exception("Type mismatch in IN section: " + type.getName() + " at left, "
+ Field::Types::toString(src.getType()) + " at right");
}
else if (is_int8 || is_int16 || is_int32 || is_int64)
{
if (src.getType() == Field::Types::Float64)
throw Exception("Type mismatch in IN section: " + type.getName() + " at left, floating point at right");
if (src.getType() == Field::Types::UInt64)
{ {
UInt64 value = src.get<const UInt64 &>(); time_t date_time{};
readDateTimeText(date_time, in);
if (!in.eof())
throw Exception("String is too long for DateTime: " + str);
if ((is_int8 && value > uint8_t(std::numeric_limits<int8_t>::max())) return Field(UInt64(date_time));
|| (is_int16 && value > uint16_t(std::numeric_limits<int16_t>::max()))
|| (is_int32 && value > uint32_t(std::numeric_limits<int32_t>::max()))
|| (is_int64 && value > uint64_t(std::numeric_limits<int64_t>::max())))
throw Exception("Value (" + toString(value) + ") in IN section is out of range of type " + type.getName() + " at left");
return Field(Int64(value));
} }
if (src.getType() == Field::Types::Int64)
{
Int64 value = src.get<const Int64 &>();
if ((is_int8 && (value < std::numeric_limits<int8_t>::min() || value > std::numeric_limits<int8_t>::max()))
|| (is_int16 && (value < std::numeric_limits<int16_t>::min() || value > std::numeric_limits<int16_t>::max()))
|| (is_int32 && (value < std::numeric_limits<int32_t>::min() || value > std::numeric_limits<int32_t>::max())))
throw Exception("Value (" + toString(value) + ") in IN section is out of range of type " + type.getName() + " at left");
return src;
}
throw Exception("Type mismatch in IN section: " + type.getName() + " at left, "
+ Field::Types::toString(src.getType()) + " at right");
} }
else if (is_float32 || is_float64)
{
if (src.getType() == Field::Types::UInt64)
return Field(Float64(src.get<UInt64>()));
if (src.getType() == Field::Types::Int64) throw Exception("Type mismatch in IN section: " + type.getName() + " at left, "
return Field(Float64(src.get<Int64>())); + Field::Types::toString(src.getType()) + " at right", ErrorCodes::TYPE_MISMATCH);
if (src.getType() == Field::Types::Float64)
return src;
throw Exception("Type mismatch in IN section: " + type.getName() + " at left, "
+ Field::Types::toString(src.getType()) + " at right");
}
else if (is_date || is_datetime)
{
if (src.getType() == Field::Types::UInt64)
return src;
if (src.getType() == Field::Types::String)
{
/// Возможность сравнивать даты и даты-с-временем со строкой.
const String & str = src.get<const String &>();
ReadBufferFromString in(str);
if (is_date)
{
DayNum_t date{};
readDateText(date, in);
if (!in.eof())
throw Exception("String is too long for Date: " + str);
return Field(UInt64(date));
}
else
{
time_t date_time{};
readDateTimeText(date_time, in);
if (!in.eof())
throw Exception("String is too long for DateTime: " + str);
return Field(UInt64(date_time));
}
}
throw Exception("Type mismatch in IN section: " + type.getName() + " at left, "
+ Field::Types::toString(src.getType()) + " at right");
}
} }
else else
{ {
@ -381,7 +335,7 @@ static Field convertToType(const Field & src, const IDataType & type)
|| (src.getType() == Field::Types::Array || (src.getType() == Field::Types::Array
&& !typeid_cast<const DataTypeArray *>(&type))) && !typeid_cast<const DataTypeArray *>(&type)))
throw Exception("Type mismatch in IN section: " + type.getName() + " at left, " throw Exception("Type mismatch in IN section: " + type.getName() + " at left, "
+ Field::Types::toString(src.getType()) + " at right"); + Field::Types::toString(src.getType()) + " at right", ErrorCodes::TYPE_MISMATCH);
} }
return src; return src;
@ -448,7 +402,10 @@ void Set::createFromAST(DataTypes & types, ASTPtr node, const Context & context,
{ {
if (data_types.size() == 1) if (data_types.size() == 1)
{ {
block.getByPosition(0).column->insert(extractValueFromNode(*it, *data_types[0], context)); Field value = extractValueFromNode(*it, *data_types[0], context);
if (!value.isNull())
block.getByPosition(0).column->insert(value);
} }
else if (ASTFunction * func = typeid_cast<ASTFunction *>(&**it)) else if (ASTFunction * func = typeid_cast<ASTFunction *>(&**it))
{ {
@ -461,7 +418,10 @@ void Set::createFromAST(DataTypes & types, ASTPtr node, const Context & context,
for (size_t j = 0; j < tuple_size; ++j) for (size_t j = 0; j < tuple_size; ++j)
{ {
block.getByPosition(j).column->insert(extractValueFromNode(func->arguments->children[j], *data_types[j], context)); Field value = extractValueFromNode(func->arguments->children[j], *data_types[j], context);
if (!value.isNull())
block.getByPosition(j).column->insert(value);
} }
} }
else else
@ -719,4 +679,23 @@ BoolMask Set::mayBeTrueInRange(const Range & range) const
return BoolMask(can_be_true, can_be_false); 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();
}
} }

View File

@ -1,4 +1,5 @@
#include <DB/Common/SipHash.h> #include <DB/Common/SipHash.h>
#include <DB/Core/FieldVisitors.h>
#include <DB/Parsers/ASTLiteral.h> #include <DB/Parsers/ASTLiteral.h>

View File

@ -1,3 +1,4 @@
#include <DB/Core/FieldVisitors.h>
#include <DB/Parsers/ASTSetQuery.h> #include <DB/Parsers/ASTSetQuery.h>
#include <DB/Parsers/ASTSelectQuery.h> #include <DB/Parsers/ASTSelectQuery.h>

View File

@ -50,8 +50,8 @@ void OLAPHTTPHandler::processQuery(Poco::Net::HTTPServerRequest & request, Poco:
Context context = *server.global_context; Context context = *server.global_context;
context.setGlobalContext(*server.global_context); context.setGlobalContext(*server.global_context);
context.setUser(user, password, request.clientAddress().host(), quota_key);
context.setSetting("profile", profile); context.setSetting("profile", profile);
context.setUser(user, password, request.clientAddress().host(), quota_key);
context.setInterface(Context::Interface::OLAP_HTTP); context.setInterface(Context::Interface::OLAP_HTTP);
context.setHTTPMethod(Context::HTTPMethod::POST); context.setHTTPMethod(Context::HTTPMethod::POST);

View File

@ -48,7 +48,7 @@ void QueryConverter::OLAPServerQueryToClickHouse(const QueryParseResult & query,
if (query.format != FORMAT_TAB) if (query.format != FORMAT_TAB)
throw Exception("Only tab-separated output format is supported", ErrorCodes::UNSUPPORTED_PARAMETER); throw Exception("Only tab-separated output format is supported", ErrorCodes::UNSUPPORTED_PARAMETER);
/// Учтем некоторые настройки (пока далеко не все). /// Учтем некоторые настройки (далеко не все).
Settings new_settings = inout_context.getSettings(); Settings new_settings = inout_context.getSettings();
@ -61,17 +61,20 @@ void QueryConverter::OLAPServerQueryToClickHouse(const QueryParseResult & query,
if (query.max_result_size != 0) if (query.max_result_size != 0)
new_settings.limits.max_rows_to_group_by = query.max_result_size; new_settings.limits.max_rows_to_group_by = query.max_result_size;
switch (query.overflow_mode) if (query.has_overflow_mode)
{ {
case OLAP::OVERFLOW_MODE_THROW: switch (query.overflow_mode)
new_settings.limits.group_by_overflow_mode = DB::OverflowMode::THROW; {
break; case OLAP::OVERFLOW_MODE_THROW:
case OLAP::OVERFLOW_MODE_BREAK: new_settings.limits.group_by_overflow_mode = DB::OverflowMode::THROW;
new_settings.limits.group_by_overflow_mode = DB::OverflowMode::BREAK; break;
break; case OLAP::OVERFLOW_MODE_BREAK:
case OLAP::OVERFLOW_MODE_ANY: new_settings.limits.group_by_overflow_mode = DB::OverflowMode::BREAK;
new_settings.limits.group_by_overflow_mode = DB::OverflowMode::ANY; break;
break; case OLAP::OVERFLOW_MODE_ANY:
new_settings.limits.group_by_overflow_mode = DB::OverflowMode::ANY;
break;
}
} }
inout_context.setSettings(new_settings); inout_context.setSettings(new_settings);

View File

@ -100,7 +100,6 @@ QueryParseResult QueryParser::parse(std::istream & s)
result.cut_date_last = false; result.cut_date_last = false;
result.cut_dates_for_goals = false; result.cut_dates_for_goals = false;
result.overflow_mode = OVERFLOW_MODE_THROW;
result.concurrency = 0; result.concurrency = 0;
result.max_threads_per_counter = 0; result.max_threads_per_counter = 0;
result.limit = 0; result.limit = 0;
@ -152,9 +151,10 @@ QueryParseResult QueryParser::parse(std::istream & s)
throw Exception(std::string("Unknown overflow mode: ") + overflow_mode_str, throw Exception(std::string("Unknown overflow mode: ") + overflow_mode_str,
ErrorCodes::UNKNOWN_OVERFLOW_MODE); ErrorCodes::UNKNOWN_OVERFLOW_MODE);
result.has_overflow_mode = true;
result.overflow_mode = overflow_mode_str == "throw" ? OVERFLOW_MODE_THROW result.overflow_mode = overflow_mode_str == "throw" ? OVERFLOW_MODE_THROW
: (overflow_mode_str == "break" ? OVERFLOW_MODE_BREAK : (overflow_mode_str == "break" ? OVERFLOW_MODE_BREAK
: OVERFLOW_MODE_ANY); : OVERFLOW_MODE_ANY);
} }
else if (settings_child_nodes->item(i)->nodeName() == "concurrency") else if (settings_child_nodes->item(i)->nodeName() == "concurrency")
{ {

View File

@ -87,6 +87,8 @@ struct QueryParseResult
float sample; float sample;
Format format; Format format;
bool has_overflow_mode = false;
OverflowMode overflow_mode; OverflowMode overflow_mode;
Poco::AutoPtr<Poco::XML::Document> query; Poco::AutoPtr<Poco::XML::Document> query;

View File

@ -1,4 +1,8 @@
#include <DB/Parsers/ExpressionListParsers.h> #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/IO/WriteBufferFromString.h>
#include <DB/Storages/ColumnsDescription.h> #include <DB/Storages/ColumnsDescription.h>
#include <DB/DataTypes/DataTypeFactory.h> #include <DB/DataTypes/DataTypeFactory.h>

View File

@ -1,3 +1,4 @@
#include <DB/Core/FieldVisitors.h>
#include <DB/Storages/MergeTree/MergeTreeDataSelectExecutor.h> #include <DB/Storages/MergeTree/MergeTreeDataSelectExecutor.h>
#include <DB/Storages/MergeTree/MergeTreeBlockInputStream.h> #include <DB/Storages/MergeTree/MergeTreeBlockInputStream.h>
#include <DB/Storages/MergeTree/MergeTreeReadPool.h> #include <DB/Storages/MergeTree/MergeTreeReadPool.h>
@ -389,6 +390,10 @@ BlockInputStreams MergeTreeDataSelectExecutor::spreadMarkRangesAmongThreads(
if (sum_marks > 0 && settings.merge_tree_uniform_read_distribution == 1) if (sum_marks > 0 && settings.merge_tree_uniform_read_distribution == 1)
{ {
/// Уменьшим количество потоков, если данных мало.
if (sum_marks < threads * min_marks_for_concurrent_read && parts.size() < threads)
threads = std::max((sum_marks + min_marks_for_concurrent_read - 1) / min_marks_for_concurrent_read, parts.size());
MergeTreeReadPoolPtr pool = std::make_shared<MergeTreeReadPool>( MergeTreeReadPoolPtr pool = std::make_shared<MergeTreeReadPool>(
threads, sum_marks, min_marks_for_concurrent_read, parts, data, prewhere_actions, prewhere_column, true, threads, sum_marks, min_marks_for_concurrent_read, parts, data, prewhere_actions, prewhere_column, true,
column_names); column_names);

View File

@ -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::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); } inline bool Range::less(const Field & lhs, const Field & rhs) { return apply_visitor(FieldVisitorAccurateLess(), lhs, rhs); }

View File

@ -1,6 +1,8 @@
#include <Poco/Util/Application.h> #include <Poco/Util/Application.h>
#include <Poco/Util/AbstractConfiguration.h> #include <Poco/Util/AbstractConfiguration.h>
#include <DB/Core/FieldVisitors.h>
#include <DB/Parsers/ASTCreateQuery.h> #include <DB/Parsers/ASTCreateQuery.h>
#include <DB/Parsers/ASTIdentifier.h> #include <DB/Parsers/ASTIdentifier.h>
#include <DB/Parsers/ASTLiteral.h> #include <DB/Parsers/ASTLiteral.h>

View File

@ -1,3 +1,4 @@
#include <DB/Core/FieldVisitors.h>
#include <DB/Storages/StorageMergeTree.h> #include <DB/Storages/StorageMergeTree.h>
#include <DB/Storages/MergeTree/MergeTreeBlockOutputStream.h> #include <DB/Storages/MergeTree/MergeTreeBlockOutputStream.h>
#include <DB/Storages/MergeTree/DiskSpaceMonitor.h> #include <DB/Storages/MergeTree/DiskSpaceMonitor.h>

View File

@ -1,4 +1,5 @@
#include <ext/range.hpp> #include <ext/range.hpp>
#include <DB/Core/FieldVisitors.h>
#include <DB/Storages/ColumnsDescription.h> #include <DB/Storages/ColumnsDescription.h>
#include <DB/Storages/StorageReplicatedMergeTree.h> #include <DB/Storages/StorageReplicatedMergeTree.h>
#include <DB/Storages/MergeTree/ReplicatedMergeTreeBlockOutputStream.h> #include <DB/Storages/MergeTree/ReplicatedMergeTreeBlockOutputStream.h>

View File

@ -0,0 +1,14 @@
1 1
1 1
1 0
1 1 1 1 0 1
0
0
1
0
0
1
0
0
0
0

View File

@ -0,0 +1,13 @@
select 1 as x, x = 1 or x = 2 or x = 3 or x = -1;
select 1 as x, x = 1.0 or x = 2 or x = 3 or x = -1;
select 1 as x, x = 1.5 or x = 2 or x = 3 or x = -1;
SELECT
1 IN (1, -1, 2.0, 2.5),
1.0 IN (1, -1, 2.0, 2.5),
1 IN (1.0, -1, 2.0, 2.5),
1.0 IN (1.0, -1, 2.0, 2.5),
1 IN (1.1, -1, 2.0, 2.5),
-1 IN (1, -1, 2.0, 2.5);
SELECT -number IN (1, 2, 3, -5.0, -2.0) FROM system.numbers LIMIT 10;

View File

@ -0,0 +1,192 @@
. . . 1
. . . 1
. . . 1
._ .o .o 1
. . . 1
_. o. o. 1
. . . 1
_._ o.o o.o 1
._ .o .o 1
. . . 1
._ .o .o 1
._ .o .o 1
._ .o .o 1
_. o. o. 1
._ .o .o 1
_._ o.o o.o 1
_. o. o. 1
. . . 1
_. o. o. 1
._ .o .o 1
_. o. o. 1
_. o. o. 1
_. o. o. 1
_._ o.o o.o 1
_._ o.o o.o 1
. . . 1
_._ o.o o.o 1
._ .o .o 1
_._ o.o o.o 1
_. o. o. 1
_._ o.o o.o 1
_._ o.o o.o 1
. . . 1
. . . 1
. . . 1
._ .oo .oo 1
. . . 1
_. oo. oo. 1
. . . 1
_._ oo.oo oo.oo 1
._ .oo .oo 1
. . . 1
._ .oo .oo 1
._ .oo .oo 1
._ .oo .oo 1
_. oo. oo. 1
._ .oo .oo 1
_._ oo.oo oo.oo 1
_. oo. oo. 1
. . . 1
_. oo. oo. 1
._ .oo .oo 1
_. oo. oo. 1
_. oo. oo. 1
_. oo. oo. 1
_._ oo.oo oo.oo 1
_._ oo.oo oo.oo 1
. . . 1
_._ oo.oo oo.oo 1
._ .oo .oo 1
_._ oo.oo oo.oo 1
_. oo. oo. 1
_._ oo.oo oo.oo 1
_._ oo.oo oo.oo 1
. . . 1
. . . 1
. . . 1
.__ .oo .oo 1
. . . 1
__. oo. oo. 1
. . . 1
__.__ oo.oo oo.oo 1
.__ .oo .oo 1
. . . 1
.__ .oo .oo 1
.__ .oo .oo 1
.__ .oo .oo 1
__. oo. oo. 1
.__ .oo .oo 1
__.__ oo.oo oo.oo 1
__. oo. oo. 1
. . . 1
__. oo. oo. 1
.__ .oo .oo 1
__. oo. oo. 1
__. oo. oo. 1
__. oo. oo. 1
__.__ oo.oo oo.oo 1
__.__ oo.oo oo.oo 1
. . . 1
__.__ oo.oo oo.oo 1
.__ .oo .oo 1
__.__ oo.oo oo.oo 1
__. oo. oo. 1
__.__ oo.oo oo.oo 1
__.__ oo.oo oo.oo 1
. . . 1
. . . 1
. . . 1
._ .o .o 1
. . . 1
_. o. o. 1
. . . 1
_._ o._ o._ 1
._ .o .o 1
. . . 1
._ .o .o 1
._ .o .o 1
._ .o .o 1
_. o. o. 1
._ .o .o 1
_._ o._ o._ 1
_. o. o. 1
. . . 1
_. o. o. 1
._ .o .o 1
_. o. o. 1
_. o. o. 1
_. o. o. 1
_._ o._ o._ 1
_._ o._ o._ 1
. . . 1
_._ o._ o._ 1
._ .o .o 1
_._ o._ o._ 1
_. o. o. 1
_._ o._ o._ 1
_._ o._ o._ 1
. . . 1
. . . 1
. . . 1
._ .oo .oo 1
. . . 1
_. oo. oo. 1
. . . 1
_._ oo._ oo._ 1
._ .oo .oo 1
. . . 1
._ .oo .oo 1
._ .oo .oo 1
._ .oo .oo 1
_. oo. oo. 1
._ .oo .oo 1
_._ oo._ oo._ 1
_. oo. oo. 1
. . . 1
_. oo. oo. 1
._ .oo .oo 1
_. oo. oo. 1
_. oo. oo. 1
_. oo. oo. 1
_._ oo._ oo._ 1
_._ oo._ oo._ 1
. . . 1
_._ oo._ oo._ 1
._ .oo .oo 1
_._ oo._ oo._ 1
_. oo. oo. 1
_._ oo._ oo._ 1
_._ oo._ oo._ 1
. . . 1
. . . 1
. . . 1
.__ .o_ .o_ 1
. . . 1
__. o_. o_. 1
. . . 1
__.__ o_.__ o_.__ 1
.__ .o_ .o_ 1
. . . 1
.__ .o_ .o_ 1
.__ .o_ .o_ 1
.__ .o_ .o_ 1
__. o_. o_. 1
.__ .o_ .o_ 1
__.__ o_.__ o_.__ 1
__. o_. o_. 1
. . . 1
__. o_. o_. 1
.__ .o_ .o_ 1
__. o_. o_. 1
__. o_. o_. 1
__. o_. o_. 1
__.__ o_.__ o_.__ 1
__.__ o_.__ o_.__ 1
. . . 1
__.__ o_.__ o_.__ 1
.__ .o_ .o_ 1
__.__ o_.__ o_.__ 1
__. o_. o_. 1
__.__ o_.__ o_.__ 1
__.__ o_.__ o_.__ 1

View File

@ -0,0 +1,101 @@
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.', '.']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.', '._']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.', '_.']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.', '_._']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['._', '.']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['._', '._']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['._', '_.']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['._', '_._']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['_.', '.']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['_.', '._']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['_.', '_.']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['_.', '_._']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['_._', '.']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['_._', '._']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['_._', '_.']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['_._', '_._']) AS s);
SELECT s, replaceAll(s, '_', 'oo') AS a, replaceRegexpAll(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['.', '.']) AS s);
SELECT s, replaceAll(s, '_', 'oo') AS a, replaceRegexpAll(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['.', '._']) AS s);
SELECT s, replaceAll(s, '_', 'oo') AS a, replaceRegexpAll(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['.', '_.']) AS s);
SELECT s, replaceAll(s, '_', 'oo') AS a, replaceRegexpAll(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['.', '_._']) AS s);
SELECT s, replaceAll(s, '_', 'oo') AS a, replaceRegexpAll(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['._', '.']) AS s);
SELECT s, replaceAll(s, '_', 'oo') AS a, replaceRegexpAll(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['._', '._']) AS s);
SELECT s, replaceAll(s, '_', 'oo') AS a, replaceRegexpAll(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['._', '_.']) AS s);
SELECT s, replaceAll(s, '_', 'oo') AS a, replaceRegexpAll(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['._', '_._']) AS s);
SELECT s, replaceAll(s, '_', 'oo') AS a, replaceRegexpAll(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['_.', '.']) AS s);
SELECT s, replaceAll(s, '_', 'oo') AS a, replaceRegexpAll(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['_.', '._']) AS s);
SELECT s, replaceAll(s, '_', 'oo') AS a, replaceRegexpAll(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['_.', '_.']) AS s);
SELECT s, replaceAll(s, '_', 'oo') AS a, replaceRegexpAll(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['_.', '_._']) AS s);
SELECT s, replaceAll(s, '_', 'oo') AS a, replaceRegexpAll(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['_._', '.']) AS s);
SELECT s, replaceAll(s, '_', 'oo') AS a, replaceRegexpAll(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['_._', '._']) AS s);
SELECT s, replaceAll(s, '_', 'oo') AS a, replaceRegexpAll(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['_._', '_.']) AS s);
SELECT s, replaceAll(s, '_', 'oo') AS a, replaceRegexpAll(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['_._', '_._']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.', '.']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.', '.__']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.', '__.']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.', '__.__']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.__', '.']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.__', '.__']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.__', '__.']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.__', '__.__']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['__.', '.']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['__.', '.__']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['__.', '__.']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['__.', '__.__']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['__.__', '.']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['__.__', '.__']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['__.__', '__.']) AS s);
SELECT s, replaceAll(s, '_', 'o') AS a, replaceRegexpAll(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['__.__', '__.__']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.', '.']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.', '._']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.', '_.']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.', '_._']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['._', '.']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['._', '._']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['._', '_.']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['._', '_._']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['_.', '.']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['_.', '._']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['_.', '_.']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['_.', '_._']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['_._', '.']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['_._', '._']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['_._', '_.']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['_._', '_._']) AS s);
SELECT s, replaceOne(s, '_', 'oo') AS a, replaceRegexpOne(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['.', '.']) AS s);
SELECT s, replaceOne(s, '_', 'oo') AS a, replaceRegexpOne(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['.', '._']) AS s);
SELECT s, replaceOne(s, '_', 'oo') AS a, replaceRegexpOne(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['.', '_.']) AS s);
SELECT s, replaceOne(s, '_', 'oo') AS a, replaceRegexpOne(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['.', '_._']) AS s);
SELECT s, replaceOne(s, '_', 'oo') AS a, replaceRegexpOne(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['._', '.']) AS s);
SELECT s, replaceOne(s, '_', 'oo') AS a, replaceRegexpOne(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['._', '._']) AS s);
SELECT s, replaceOne(s, '_', 'oo') AS a, replaceRegexpOne(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['._', '_.']) AS s);
SELECT s, replaceOne(s, '_', 'oo') AS a, replaceRegexpOne(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['._', '_._']) AS s);
SELECT s, replaceOne(s, '_', 'oo') AS a, replaceRegexpOne(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['_.', '.']) AS s);
SELECT s, replaceOne(s, '_', 'oo') AS a, replaceRegexpOne(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['_.', '._']) AS s);
SELECT s, replaceOne(s, '_', 'oo') AS a, replaceRegexpOne(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['_.', '_.']) AS s);
SELECT s, replaceOne(s, '_', 'oo') AS a, replaceRegexpOne(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['_.', '_._']) AS s);
SELECT s, replaceOne(s, '_', 'oo') AS a, replaceRegexpOne(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['_._', '.']) AS s);
SELECT s, replaceOne(s, '_', 'oo') AS a, replaceRegexpOne(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['_._', '._']) AS s);
SELECT s, replaceOne(s, '_', 'oo') AS a, replaceRegexpOne(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['_._', '_.']) AS s);
SELECT s, replaceOne(s, '_', 'oo') AS a, replaceRegexpOne(s, '_', 'oo') AS b, a = b FROM (SELECT arrayJoin(['_._', '_._']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.', '.']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.', '.__']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.', '__.']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.', '__.__']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.__', '.']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.__', '.__']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.__', '__.']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['.__', '__.__']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['__.', '.']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['__.', '.__']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['__.', '__.']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['__.', '__.__']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['__.__', '.']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['__.__', '.__']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['__.__', '__.']) AS s);
SELECT s, replaceOne(s, '_', 'o') AS a, replaceRegexpOne(s, '_', 'o') AS b, a = b FROM (SELECT arrayJoin(['__.__', '__.__']) AS s);

View File

@ -0,0 +1,15 @@
1 0 0 0 1 1
0 1 1 0 1 0
0 1 1 0 1 0
0 1 1 0 1 0
0 1 0 1 0 1
0 1 0 1 0 1
0 1 0 1 0 1
1 0 0 0 1 1
0 1 1 0 1 0
0 1 1 0 1 0
0 1 0 1 0 1
0 1 0 1 0 1
1 0 0 0 1 1
0 1 1 0 1 0
0 1 0 1 0 1

View File

@ -0,0 +1,105 @@
SELECT
(1, 'Hello', 23) = (1, 'Hello', 23),
(1, 'Hello', 23) != (1, 'Hello', 23),
(1, 'Hello', 23) < (1, 'Hello', 23),
(1, 'Hello', 23) > (1, 'Hello', 23),
(1, 'Hello', 23) <= (1, 'Hello', 23),
(1, 'Hello', 23) >= (1, 'Hello', 23);
SELECT
(1, 'Hello', 23) = (2, 'Hello', 23),
(1, 'Hello', 23) != (2, 'Hello', 23),
(1, 'Hello', 23) < (2, 'Hello', 23),
(1, 'Hello', 23) > (2, 'Hello', 23),
(1, 'Hello', 23) <= (2, 'Hello', 23),
(1, 'Hello', 23) >= (2, 'Hello', 23);
SELECT
(1, 'Hello', 23) = (1, 'World', 23),
(1, 'Hello', 23) != (1, 'World', 23),
(1, 'Hello', 23) < (1, 'World', 23),
(1, 'Hello', 23) > (1, 'World', 23),
(1, 'Hello', 23) <= (1, 'World', 23),
(1, 'Hello', 23) >= (1, 'World', 23);
SELECT
(1, 'Hello', 23) = (1, 'Hello', 24),
(1, 'Hello', 23) != (1, 'Hello', 24),
(1, 'Hello', 23) < (1, 'Hello', 24),
(1, 'Hello', 23) > (1, 'Hello', 24),
(1, 'Hello', 23) <= (1, 'Hello', 24),
(1, 'Hello', 23) >= (1, 'Hello', 24);
SELECT
(2, 'Hello', 23) = (1, 'Hello', 23),
(2, 'Hello', 23) != (1, 'Hello', 23),
(2, 'Hello', 23) < (1, 'Hello', 23),
(2, 'Hello', 23) > (1, 'Hello', 23),
(2, 'Hello', 23) <= (1, 'Hello', 23),
(2, 'Hello', 23) >= (1, 'Hello', 23);
SELECT
(1, 'World', 23) = (1, 'Hello', 23),
(1, 'World', 23) != (1, 'Hello', 23),
(1, 'World', 23) < (1, 'Hello', 23),
(1, 'World', 23) > (1, 'Hello', 23),
(1, 'World', 23) <= (1, 'Hello', 23),
(1, 'World', 23) >= (1, 'Hello', 23);
SELECT
(1, 'Hello', 24) = (1, 'Hello', 23),
(1, 'Hello', 24) != (1, 'Hello', 23),
(1, 'Hello', 24) < (1, 'Hello', 23),
(1, 'Hello', 24) > (1, 'Hello', 23),
(1, 'Hello', 24) <= (1, 'Hello', 23),
(1, 'Hello', 24) >= (1, 'Hello', 23);
SELECT
(1, 'Hello') = (1, 'Hello'),
(1, 'Hello') != (1, 'Hello'),
(1, 'Hello') < (1, 'Hello'),
(1, 'Hello') > (1, 'Hello'),
(1, 'Hello') <= (1, 'Hello'),
(1, 'Hello') >= (1, 'Hello');
SELECT
(1, 'Hello') = (2, 'Hello'),
(1, 'Hello') != (2, 'Hello'),
(1, 'Hello') < (2, 'Hello'),
(1, 'Hello') > (2, 'Hello'),
(1, 'Hello') <= (2, 'Hello'),
(1, 'Hello') >= (2, 'Hello');
SELECT
(1, 'Hello') = (1, 'World'),
(1, 'Hello') != (1, 'World'),
(1, 'Hello') < (1, 'World'),
(1, 'Hello') > (1, 'World'),
(1, 'Hello') <= (1, 'World'),
(1, 'Hello') >= (1, 'World');
SELECT
(2, 'Hello') = (1, 'Hello'),
(2, 'Hello') != (1, 'Hello'),
(2, 'Hello') < (1, 'Hello'),
(2, 'Hello') > (1, 'Hello'),
(2, 'Hello') <= (1, 'Hello'),
(2, 'Hello') >= (1, 'Hello');
SELECT
(1, 'World') = (1, 'Hello'),
(1, 'World') != (1, 'Hello'),
(1, 'World') < (1, 'Hello'),
(1, 'World') > (1, 'Hello'),
(1, 'World') <= (1, 'Hello'),
(1, 'World') >= (1, 'Hello');
SELECT
tuple(1) = tuple(1),
tuple(1) != tuple(1),
tuple(1) < tuple(1),
tuple(1) > tuple(1),
tuple(1) <= tuple(1),
tuple(1) >= tuple(1);
SELECT
tuple(1) = tuple(2),
tuple(1) != tuple(2),
tuple(1) < tuple(2),
tuple(1) > tuple(2),
tuple(1) <= tuple(2),
tuple(1) >= tuple(2);
SELECT
tuple(2) = tuple(1),
tuple(2) != tuple(1),
tuple(2) < tuple(1),
tuple(2) > tuple(1),
tuple(2) <= tuple(1),
tuple(2) >= tuple(1);

View File

@ -0,0 +1,20 @@
1
1
0
1
0
1
1
0
1
0
1
1
0
1
0
1
1
0
1
0

View File

@ -0,0 +1,23 @@
SELECT has([1, 2, 3], 3.0);
SELECT has([1, 2.0, 3], 2);
SELECT has([1, 2.1, 3], 2);
SELECT has([1, -1], 1);
SELECT has([1, -1], 1000);
SELECT has(materialize([1, 2, 3]), 3.0);
SELECT has(materialize([1, 2.0, 3]), 2);
SELECT has(materialize([1, 2.1, 3]), 2);
SELECT has(materialize([1, -1]), 1);
SELECT has(materialize([1, -1]), 1000);
SELECT has([1, 2, 3], materialize(3.0));
SELECT has([1, 2.0, 3], materialize(2));
SELECT has([1, 2.1, 3], materialize(2));
SELECT has([1, -1], materialize(1));
SELECT has([1, -1], materialize(1000));
SELECT has(materialize([1, 2, 3]), materialize(3.0));
SELECT has(materialize([1, 2.0, 3]), materialize(2));
SELECT has(materialize([1, 2.1, 3]), materialize(2));
SELECT has(materialize([1, -1]), materialize(1));
SELECT has(materialize([1, -1]), materialize(1000));