2011-08-28 00:31:30 +00:00
|
|
|
|
#pragma once
|
2010-03-01 16:59:51 +00:00
|
|
|
|
|
|
|
|
|
#include <vector>
|
2011-08-09 19:19:00 +00:00
|
|
|
|
#include <sstream>
|
2010-03-01 16:59:51 +00:00
|
|
|
|
|
|
|
|
|
#include <boost/variant.hpp>
|
|
|
|
|
#include <boost/variant/recursive_variant.hpp>
|
|
|
|
|
#include <boost/variant/static_visitor.hpp>
|
|
|
|
|
|
2011-08-09 19:19:00 +00:00
|
|
|
|
#include <Poco/NumberFormatter.h>
|
|
|
|
|
|
2012-09-05 19:51:09 +00:00
|
|
|
|
#include <mysqlxx/Date.h>
|
|
|
|
|
#include <mysqlxx/DateTime.h>
|
|
|
|
|
#include <mysqlxx/Manip.h>
|
2011-08-09 19:19:00 +00:00
|
|
|
|
|
2010-03-01 16:59:51 +00:00
|
|
|
|
#include <DB/Core/Types.h>
|
2011-10-10 10:05:39 +00:00
|
|
|
|
#include <DB/Core/Exception.h>
|
|
|
|
|
#include <DB/Core/ErrorCodes.h>
|
2010-03-01 16:59:51 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
|
{
|
|
|
|
|
|
2011-09-19 01:42:16 +00:00
|
|
|
|
using Poco::SharedPtr;
|
|
|
|
|
|
2011-10-10 10:05:39 +00:00
|
|
|
|
class IAggregateFunction;
|
|
|
|
|
|
2010-03-01 16:59:51 +00:00
|
|
|
|
/** Типы данных для представления единичного значения произвольного типа в оперативке.
|
|
|
|
|
* Внимание! Предпочтительно вместо единичных значений хранить кусочки столбцов. См. Column.h
|
|
|
|
|
*/
|
|
|
|
|
typedef boost::make_recursive_variant<
|
|
|
|
|
Null,
|
|
|
|
|
UInt64,
|
|
|
|
|
Int64,
|
|
|
|
|
Float64,
|
|
|
|
|
String,
|
2011-10-10 10:05:39 +00:00
|
|
|
|
SharedPtr<IAggregateFunction>, /// Состояние агрегатной функции
|
2010-03-01 16:59:51 +00:00
|
|
|
|
std::vector<boost::recursive_variant_> /// Array, Tuple
|
|
|
|
|
>::type Field;
|
|
|
|
|
|
|
|
|
|
typedef std::vector<Field> Array; /// Значение типа "массив"
|
|
|
|
|
|
2012-08-26 06:48:39 +00:00
|
|
|
|
template <> struct TypeName<Array> { static std::string get() { return "Array"; } };
|
|
|
|
|
|
2010-03-01 16:59:51 +00:00
|
|
|
|
|
|
|
|
|
/** Числовое значение конкретного типа Field */
|
|
|
|
|
namespace FieldType
|
|
|
|
|
{
|
|
|
|
|
enum Enum
|
|
|
|
|
{
|
|
|
|
|
Null = 0,
|
|
|
|
|
UInt64,
|
|
|
|
|
Int64,
|
|
|
|
|
Float64,
|
|
|
|
|
String,
|
2011-09-19 01:42:16 +00:00
|
|
|
|
AggregateFunction,
|
2010-03-01 16:59:51 +00:00
|
|
|
|
Array
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Возвращает true, если вариант - Null */
|
|
|
|
|
class FieldVisitorIsNull : public boost::static_visitor<bool>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
template <typename T> bool operator() (const T & x) const { return false; }
|
|
|
|
|
bool operator() (const Null & x) const { return true; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/** Возвращает числовое значение типа */
|
|
|
|
|
class FieldVisitorGetType : public boost::static_visitor<FieldType::Enum>
|
|
|
|
|
{
|
|
|
|
|
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; }
|
2011-09-19 01:42:16 +00:00
|
|
|
|
FieldType::Enum operator() (const SharedPtr<IAggregateFunction> & x) const { return FieldType::AggregateFunction; }
|
2010-03-01 16:59:51 +00:00
|
|
|
|
FieldType::Enum operator() (const Array & x) const { return FieldType::Array; }
|
|
|
|
|
};
|
|
|
|
|
|
2011-08-09 19:19:00 +00:00
|
|
|
|
/** Возвращает строковый дамп типа */
|
|
|
|
|
class FieldVisitorDump : public boost::static_visitor<std::string>
|
|
|
|
|
{
|
|
|
|
|
public:
|
2011-09-19 01:42:16 +00:00
|
|
|
|
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<IAggregateFunction> & x) const { return "AggregateFunction"; }
|
2011-08-09 19:19:00 +00:00
|
|
|
|
|
2011-09-19 01:42:16 +00:00
|
|
|
|
String operator() (const String & x) const
|
2011-08-09 19:19:00 +00:00
|
|
|
|
{
|
|
|
|
|
std::stringstream s;
|
|
|
|
|
s << mysqlxx::quote << x;
|
|
|
|
|
return s.str();
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-19 01:42:16 +00:00
|
|
|
|
String operator() (const Array & x) const
|
2011-08-09 19:19:00 +00:00
|
|
|
|
{
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2011-08-12 18:27:39 +00:00
|
|
|
|
/** Выводит текстовое представление типа, как литерала в SQL запросе */
|
|
|
|
|
class FieldVisitorToString : public boost::static_visitor<String>
|
|
|
|
|
{
|
|
|
|
|
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); }
|
2011-09-19 01:42:16 +00:00
|
|
|
|
String operator() (const SharedPtr<IAggregateFunction> & x) const { return "AggregateFunction"; }
|
2011-08-12 18:27:39 +00:00
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2011-10-10 10:05:39 +00:00
|
|
|
|
/** Числовой тип преобразует в указанный. */
|
|
|
|
|
template <typename T>
|
|
|
|
|
class FieldVisitorConvertToNumber : public boost::static_visitor<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 SharedPtr<IAggregateFunction> & x) const
|
|
|
|
|
{
|
|
|
|
|
throw Exception("Cannot convert AggregateFunctionPtr 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; }
|
|
|
|
|
};
|
|
|
|
|
|
2010-03-01 16:59:51 +00:00
|
|
|
|
|
2012-07-21 03:45:48 +00:00
|
|
|
|
class FieldVisitorLess : public boost::static_visitor<bool>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
template <typename T, typename U>
|
|
|
|
|
bool operator() (const T &, const U &) const { return false; }
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
bool operator() (const T & lhs, const T & rhs) const { return lhs < rhs; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class FieldVisitorGreater : public boost::static_visitor<bool>
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
template <typename T, typename U>
|
|
|
|
|
bool operator() (const T &, const U &) const { return false; }
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
bool operator() (const T & lhs, const T & rhs) const { return lhs > rhs; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
2010-03-18 19:32:14 +00:00
|
|
|
|
template <typename T> struct NearestFieldType;
|
|
|
|
|
|
2011-08-21 03:41:37 +00:00
|
|
|
|
template <> struct NearestFieldType<UInt8> { typedef UInt64 Type; };
|
|
|
|
|
template <> struct NearestFieldType<UInt16> { typedef UInt64 Type; };
|
|
|
|
|
template <> struct NearestFieldType<UInt32> { typedef UInt64 Type; };
|
|
|
|
|
template <> struct NearestFieldType<UInt64> { typedef UInt64 Type; };
|
|
|
|
|
template <> struct NearestFieldType<Int8> { typedef Int64 Type; };
|
|
|
|
|
template <> struct NearestFieldType<Int16> { typedef Int64 Type; };
|
|
|
|
|
template <> struct NearestFieldType<Int32> { typedef Int64 Type; };
|
|
|
|
|
template <> struct NearestFieldType<Int64> { typedef Int64 Type; };
|
|
|
|
|
template <> struct NearestFieldType<Float32> { typedef Float64 Type; };
|
|
|
|
|
template <> struct NearestFieldType<Float64> { typedef Float64 Type; };
|
|
|
|
|
template <> struct NearestFieldType<String> { typedef String Type; };
|
2012-08-26 06:48:39 +00:00
|
|
|
|
template <> struct NearestFieldType<Array> { typedef Array Type; };
|
2012-06-07 18:32:21 +00:00
|
|
|
|
template <> struct NearestFieldType<bool> { typedef UInt64 Type; };
|
|
|
|
|
|
2010-03-01 16:59:51 +00:00
|
|
|
|
}
|
2012-09-05 19:51:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Заглушки, чтобы 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); }
|
|
|
|
|
}
|