#pragma once #include #include #include #include #include #include #include #include #include #include #include #include namespace DB { using Poco::SharedPtr; class IAggregateFunction; /** Типы данных для представления единичного значения произвольного типа в оперативке. * Внимание! Предпочтительно вместо единичных значений хранить кусочки столбцов. См. Column.h */ typedef boost::make_recursive_variant< Null, UInt64, Int64, Float64, String, SharedPtr, /// Состояние агрегатной функции std::vector /// Array, Tuple >::type Field; typedef std::vector Array; /// Значение типа "массив" template <> struct TypeName { static std::string get() { return "Array"; } }; /** Числовое значение конкретного типа Field */ namespace FieldType { enum Enum { Null = 0, UInt64, Int64, Float64, String, AggregateFunction, Array }; } /** Возвращает true, если вариант - Null */ class FieldVisitorIsNull : public boost::static_visitor { public: template bool operator() (const T & x) const { return false; } bool operator() (const Null & x) const { return true; } }; /** Возвращает числовое значение типа */ class FieldVisitorGetType : public boost::static_visitor { public: FieldType::Enum operator() (const Null & x) const { return FieldType::Null; } FieldType::Enum operator() (const UInt64 & x) const { return FieldType::UInt64; } FieldType::Enum operator() (const Int64 & x) const { return FieldType::Int64; } FieldType::Enum operator() (const Float64 & x) const { return FieldType::Float64; } FieldType::Enum operator() (const String & x) const { return FieldType::String; } FieldType::Enum operator() (const SharedPtr & x) const { return FieldType::AggregateFunction; } FieldType::Enum operator() (const Array & x) const { return FieldType::Array; } }; /** Возвращает строковый дамп типа */ class FieldVisitorDump : public boost::static_visitor { public: String operator() (const Null & x) const { return "NULL"; } String operator() (const UInt64 & x) const { return "UInt64_" + Poco::NumberFormatter::format(x); } String operator() (const Int64 & x) const { return "Int64_" + Poco::NumberFormatter::format(x); } String operator() (const Float64 & x) const { return "Float64_" + Poco::NumberFormatter::format(x); } String operator() (const SharedPtr & x) const { return "AggregateFunction"; } String operator() (const String & x) const { std::stringstream s; s << mysqlxx::quote << x; return s.str(); } String operator() (const Array & x) const { std::stringstream s; s << "Array_["; for (Array::const_iterator it = x.begin(); it != x.end(); ++it) { if (it != x.begin()) s << ", "; s << boost::apply_visitor(FieldVisitorDump(), *it); } s << "]"; return s.str(); } }; /** Выводит текстовое представление типа, как литерала в SQL запросе */ class FieldVisitorToString : public boost::static_visitor { public: String operator() (const Null & x) const { return "NULL"; } String operator() (const UInt64 & x) const { return Poco::NumberFormatter::format(x); } String operator() (const Int64 & x) const { return Poco::NumberFormatter::format(x); } String operator() (const Float64 & x) const { return Poco::NumberFormatter::format(x); } String operator() (const SharedPtr & x) const { return "AggregateFunction"; } String operator() (const String & x) const { std::stringstream s; s << mysqlxx::quote << x; return s.str(); } String operator() (const Array & x) const { std::stringstream s; FieldVisitorToString visitor; s << "["; for (Array::const_iterator it = x.begin(); it != x.end(); ++it) { if (it != x.begin()) s << ", "; s << boost::apply_visitor(FieldVisitorToString(), *it); } s << "]"; return s.str(); } }; /** Числовой тип преобразует в указанный. */ template class FieldVisitorConvertToNumber : public boost::static_visitor { public: T operator() (const Null & x) const { throw Exception("Cannot convert NULL to " + TypeName::get(), ErrorCodes::CANNOT_CONVERT_TYPE); } T operator() (const String & x) const { throw Exception("Cannot convert String to " + TypeName::get(), ErrorCodes::CANNOT_CONVERT_TYPE); } T operator() (const Array & x) const { throw Exception("Cannot convert Array to " + TypeName::get(), ErrorCodes::CANNOT_CONVERT_TYPE); } T operator() (const SharedPtr & x) const { throw Exception("Cannot convert AggregateFunctionPtr to " + TypeName::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; } }; class FieldVisitorLess : public boost::static_visitor { public: template bool operator() (const T &, const U &) const { return false; } template bool operator() (const T & lhs, const T & rhs) const { return lhs < rhs; } }; class FieldVisitorGreater : public boost::static_visitor { public: template bool operator() (const T &, const U &) const { return false; } template bool operator() (const T & lhs, const T & rhs) const { return lhs > rhs; } }; template struct NearestFieldType; template <> struct NearestFieldType { typedef UInt64 Type; }; template <> struct NearestFieldType { typedef UInt64 Type; }; template <> struct NearestFieldType { typedef UInt64 Type; }; template <> struct NearestFieldType { typedef UInt64 Type; }; template <> struct NearestFieldType { typedef Int64 Type; }; template <> struct NearestFieldType { typedef Int64 Type; }; template <> struct NearestFieldType { typedef Int64 Type; }; template <> struct NearestFieldType { typedef Int64 Type; }; template <> struct NearestFieldType { typedef Float64 Type; }; template <> struct NearestFieldType { typedef Float64 Type; }; template <> struct NearestFieldType { typedef String Type; }; template <> struct NearestFieldType { typedef Array Type; }; template <> struct NearestFieldType { typedef UInt64 Type; }; } /// Заглушки, чтобы DBObject-ы с полем типа Array компилировались. namespace mysqlxx { inline std::ostream & operator<< (mysqlxx::EscapeManipResult res, const DB::Array & value) { throw Poco::Exception("Cannot escape Array with mysqlxx::escape."); } 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."); } } namespace DB { class ReadBuffer; class WriteBuffer; inline void readBinary(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 writeBinary(const Array & x, WriteBuffer & buf) { throw Exception("Cannot write Array.", ErrorCodes::NOT_IMPLEMENTED); } inline void writeText(const Array & x, WriteBuffer & buf) { throw Exception("Cannot write Array.", ErrorCodes::NOT_IMPLEMENTED); } inline void writeQuoted(const Array & x, WriteBuffer & buf) { throw Exception("Cannot write Array.", ErrorCodes::NOT_IMPLEMENTED); } }