mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 23:21:59 +00:00
DBMS: development.
This commit is contained in:
parent
aafe93c440
commit
ea150ca671
293
dbms/include/DB/ColumnType.h
Normal file
293
dbms/include/DB/ColumnType.h
Normal file
@ -0,0 +1,293 @@
|
||||
#ifndef DBMS_COLUMN_TYPE_H
|
||||
#define DBMS_COLUMN_TYPE_H
|
||||
|
||||
#include <ostream>
|
||||
|
||||
#include <Poco/SharedPtr.h>
|
||||
#include <Poco/BinaryWriter.h>
|
||||
#include <Poco/BinaryReader.h>
|
||||
#include <Poco/NumberParser.h>
|
||||
#include <Poco/NumberFormatter.h>
|
||||
|
||||
#include <DB/Field.h>
|
||||
#include <DB/Exception.h>
|
||||
#include <DB/ErrorCodes.h>
|
||||
#include <DB/VarInt.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
||||
/** Метаданные типа для хранения (столбца).
|
||||
* Содержит методы для сериализации/десериализации.
|
||||
*/
|
||||
class IColumnType
|
||||
{
|
||||
public:
|
||||
/// Основное имя типа (например, BIGINT UNSIGNED).
|
||||
virtual std::string getName() const = 0;
|
||||
|
||||
/// Бинарная сериализация - для сохранения на диск / в сеть и т. п.
|
||||
virtual void serializeBinary(const DB::Field & field, std::ostream & ostr) const = 0;
|
||||
virtual void deserializeBinary(DB::Field & field, std::istream & ostr) const = 0;
|
||||
|
||||
/// Текстовая сериализация - для вывода на экран / сохранения в текстовый файл и т. п.
|
||||
virtual void serializeText(const DB::Field & field, std::ostream & ostr) const = 0;
|
||||
virtual void deserializeText(DB::Field & field, std::istream & ostr) const = 0;
|
||||
|
||||
/// Шаблонные методы для параметризуемого типа сериализации.
|
||||
template <typename SerializationTag> void serialize(const DB::Field & field, std::ostream & ostr) const;
|
||||
template <typename SerializationTag> void deserialize(DB::Field & field, std::istream & ostr) const;
|
||||
};
|
||||
|
||||
|
||||
struct BinarySerializationTag;
|
||||
struct TextSerializationTag;
|
||||
|
||||
template <typename SerializationTag> struct SerializeImpl;
|
||||
|
||||
template <typename SerializationTag>
|
||||
void IColumnType::serialize(const DB::Field & field, std::ostream & ostr) const
|
||||
{
|
||||
SerializeImpl<SerializationTag>::serialize(this, field, ostr);
|
||||
}
|
||||
|
||||
template <typename SerializationTag>
|
||||
void IColumnType::deserialize(DB::Field & field, std::istream & ostr) const
|
||||
{
|
||||
SerializeImpl<SerializationTag>::deserialize(this, field, ostr);
|
||||
}
|
||||
|
||||
|
||||
template <> struct SerializeImpl<BinarySerializationTag>
|
||||
{
|
||||
static inline void serialize(const IColumnType * column, const DB::Field & field, std::ostream & ostr)
|
||||
{
|
||||
column->serializeBinary(field, ostr);
|
||||
}
|
||||
|
||||
static inline void deserialize(const IColumnType * column, DB::Field & field, std::istream & ostr)
|
||||
{
|
||||
column->deserializeBinary(field, ostr);
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct SerializeImpl<TextSerializationTag>
|
||||
{
|
||||
static inline void serialize(const IColumnType * column, const DB::Field & field, std::ostream & ostr)
|
||||
{
|
||||
column->serializeText(field, ostr);
|
||||
}
|
||||
|
||||
static inline void deserialize(const IColumnType * column, DB::Field & field, std::istream & ostr)
|
||||
{
|
||||
column->deserializeText(field, ostr);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ColumnTypeUInt64 : public IColumnType
|
||||
{
|
||||
public:
|
||||
std::string getName() const { return "UInt64"; }
|
||||
|
||||
void serializeBinary(const DB::Field & field, std::ostream & ostr) const
|
||||
{
|
||||
Poco::BinaryWriter w(ostr);
|
||||
w << boost::get<UInt>(field);
|
||||
}
|
||||
|
||||
void deserializeBinary(DB::Field & field, std::istream & istr) const
|
||||
{
|
||||
Poco::BinaryReader r(istr);
|
||||
r >> boost::get<UInt>(field);
|
||||
}
|
||||
|
||||
void serializeText(const DB::Field & field, std::ostream & ostr) const
|
||||
{
|
||||
ostr << boost::get<UInt>(field);
|
||||
}
|
||||
|
||||
void deserializeText(DB::Field & field, std::istream & istr) const
|
||||
{
|
||||
istr >> boost::get<UInt>(field);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ColumnTypeUInt32 : public IColumnType
|
||||
{
|
||||
public:
|
||||
std::string getName() const { return "UInt32"; }
|
||||
|
||||
void serializeBinary(const DB::Field & field, std::ostream & ostr) const
|
||||
{
|
||||
Poco::BinaryWriter w(ostr);
|
||||
w << static_cast<Poco::UInt32>(boost::get<UInt>(field));
|
||||
}
|
||||
|
||||
void deserializeBinary(DB::Field & field, std::istream & istr) const
|
||||
{
|
||||
Poco::BinaryReader r(istr);
|
||||
Poco::UInt32 x;
|
||||
r >> x;
|
||||
boost::get<UInt>(field) = x;
|
||||
}
|
||||
|
||||
void serializeText(const DB::Field & field, std::ostream & ostr) const
|
||||
{
|
||||
ostr << static_cast<Poco::UInt32>(boost::get<UInt>(field));
|
||||
}
|
||||
|
||||
void deserializeText(DB::Field & field, std::istream & istr) const
|
||||
{
|
||||
Poco::UInt32 x;
|
||||
istr >> x;
|
||||
boost::get<UInt>(field) = x;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ColumnTypeInt64 : public IColumnType
|
||||
{
|
||||
public:
|
||||
std::string getName() const { return "Int64"; }
|
||||
|
||||
void serializeBinary(const DB::Field & field, std::ostream & ostr) const
|
||||
{
|
||||
Poco::BinaryWriter w(ostr);
|
||||
w << boost::get<Int>(field);
|
||||
}
|
||||
|
||||
void deserializeBinary(DB::Field & field, std::istream & istr) const
|
||||
{
|
||||
Poco::BinaryReader r(istr);
|
||||
r >> boost::get<Int>(field);
|
||||
}
|
||||
|
||||
void serializeText(const DB::Field & field, std::ostream & ostr) const
|
||||
{
|
||||
ostr << boost::get<Int>(field);
|
||||
}
|
||||
|
||||
void deserializeText(DB::Field & field, std::istream & istr) const
|
||||
{
|
||||
istr >> boost::get<Int>(field);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ColumnTypeInt32 : public IColumnType
|
||||
{
|
||||
public:
|
||||
std::string getName() const { return "Int32"; }
|
||||
|
||||
void serializeBinary(const DB::Field & field, std::ostream & ostr) const
|
||||
{
|
||||
Poco::BinaryWriter w(ostr);
|
||||
w << static_cast<Poco::Int32>(boost::get<Int>(field));
|
||||
}
|
||||
|
||||
void deserializeBinary(DB::Field & field, std::istream & istr) const
|
||||
{
|
||||
Poco::BinaryReader r(istr);
|
||||
Poco::Int32 x;
|
||||
r >> x;
|
||||
boost::get<Int>(field) = x;
|
||||
}
|
||||
|
||||
void serializeText(const DB::Field & field, std::ostream & ostr) const
|
||||
{
|
||||
ostr << static_cast<Poco::Int32>(boost::get<Int>(field));
|
||||
}
|
||||
|
||||
void deserializeText(DB::Field & field, std::istream & istr) const
|
||||
{
|
||||
Poco::Int32 x;
|
||||
istr >> x;
|
||||
boost::get<Int>(field) = x;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ColumnTypeVarUInt : public IColumnType
|
||||
{
|
||||
public:
|
||||
std::string getName() const { return "VarUInt"; }
|
||||
|
||||
void serializeBinary(const DB::Field & field, std::ostream & ostr) const
|
||||
{
|
||||
writeVarUInt(boost::get<UInt>(field), ostr);
|
||||
}
|
||||
|
||||
void deserializeBinary(DB::Field & field, std::istream & istr) const
|
||||
{
|
||||
readVarUInt(boost::get<UInt>(field), istr);
|
||||
}
|
||||
|
||||
void serializeText(const DB::Field & field, std::ostream & ostr) const
|
||||
{
|
||||
ostr << boost::get<UInt>(field);
|
||||
}
|
||||
|
||||
void deserializeText(DB::Field & field, std::istream & istr) const
|
||||
{
|
||||
istr >> boost::get<UInt>(field);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ColumnTypeVarInt : public IColumnType
|
||||
{
|
||||
public:
|
||||
std::string getName() const { return "VarInt"; }
|
||||
|
||||
void serializeBinary(const DB::Field & field, std::ostream & ostr) const
|
||||
{
|
||||
writeVarInt(boost::get<Int>(field), ostr);
|
||||
}
|
||||
|
||||
void deserializeBinary(DB::Field & field, std::istream & istr) const
|
||||
{
|
||||
readVarInt(boost::get<Int>(field), istr);
|
||||
}
|
||||
|
||||
void serializeText(const DB::Field & field, std::ostream & ostr) const
|
||||
{
|
||||
ostr << boost::get<Int>(field);
|
||||
}
|
||||
|
||||
void deserializeText(DB::Field & field, std::istream & istr) const
|
||||
{
|
||||
istr >> boost::get<Int>(field);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ColumnTypeFactory
|
||||
{
|
||||
public:
|
||||
static Poco::SharedPtr<IColumnType> get(const std::string & name)
|
||||
{
|
||||
if (name == "VarUInt")
|
||||
return new ColumnTypeVarUInt;
|
||||
if (name == "VarInt")
|
||||
return new ColumnTypeVarInt;
|
||||
if (name == "UInt32")
|
||||
return new ColumnTypeUInt32;
|
||||
if (name == "UInt64")
|
||||
return new ColumnTypeUInt64;
|
||||
if (name == "Int32")
|
||||
return new ColumnTypeUInt32;
|
||||
if (name == "Int64")
|
||||
return new ColumnTypeUInt64;
|
||||
|
||||
throw Exception("Unknown column type " + name, ErrorCodes::UNKNOWN_COLUMN_TYPE);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
19
dbms/include/DB/ErrorCodes.h
Normal file
19
dbms/include/DB/ErrorCodes.h
Normal file
@ -0,0 +1,19 @@
|
||||
#ifndef DBMS_ERROR_CODES_H
|
||||
#define DBMS_ERROR_CODES_H
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
enum ErrorCodes
|
||||
{
|
||||
UNIMPLEMENTED_VISITOR_FOR_VARIANT = 1,
|
||||
UNKNOWN_COLUMN_TYPE,
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
16
dbms/include/DB/Exception.h
Normal file
16
dbms/include/DB/Exception.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef DBMS_EXCEPTION_H
|
||||
#define DBMS_EXCEPTION_H
|
||||
|
||||
#include <Poco/Exception.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Тип исключения, чтобы отличать его от других.
|
||||
*/
|
||||
POCO_DECLARE_EXCEPTION(Foundation_API, Exception, Poco::Exception);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
101
dbms/include/DB/Field.h
Normal file
101
dbms/include/DB/Field.h
Normal file
@ -0,0 +1,101 @@
|
||||
#ifndef DBMS_FIELD_H
|
||||
#define DBMS_FIELD_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <Poco/Types.h>
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/variant/recursive_variant.hpp>
|
||||
|
||||
#include <DB/Exception.h>
|
||||
#include <DB/ErrorCodes.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
||||
typedef Poco::Int64 Int;
|
||||
typedef Poco::UInt64 UInt;
|
||||
typedef std::string String;
|
||||
|
||||
struct Null {};
|
||||
|
||||
|
||||
/** Используется для хранения значений в памяти
|
||||
* - перед сериализацией и после десериализации из БД или результата.
|
||||
* - при обработке запроса, для временных таблиц, для результата.
|
||||
* Типов данных для хранения больше, чем перечисленных здесь внутренних представлений в памяти.
|
||||
* Метаданные этих типов, а также правила их сериализации/десериализации находятся в файле ColumnType.h
|
||||
*/
|
||||
typedef boost::make_recursive_variant<
|
||||
Int,
|
||||
UInt,
|
||||
String,
|
||||
Null,
|
||||
std::vector<boost::recursive_variant_> /// FieldVector
|
||||
>::type Field;
|
||||
|
||||
typedef std::vector<Field> FieldVector; /// Значение типа "массив"
|
||||
|
||||
|
||||
/** Визитор по умолчанию, который ничего не делает
|
||||
* - нужно для того, чтобы наследоваться от него и писать меньше кода
|
||||
* для визиторов, которые делают что-то содержательное только для нескольких вариантов.
|
||||
*/
|
||||
class FieldVisitorDefaultNothing : public boost::static_visitor<>
|
||||
{
|
||||
public:
|
||||
template <typename T> void operator() (const T & x) const {}
|
||||
};
|
||||
|
||||
|
||||
/** Визитор по умолчанию, который для всех вариантов кидает исключение
|
||||
* - нужно для того, чтобы наследоваться от него и писать меньше кода
|
||||
* для визиторов, которые делают что-то содержательное только для нескольких вариантов,
|
||||
* но передача в него других вариантов должна вызывать runtime ошибку.
|
||||
*/
|
||||
class FieldVisitorDefaultThrow : public boost::static_visitor<>
|
||||
{
|
||||
public:
|
||||
void operator() (const DB::Int & x) const
|
||||
{
|
||||
throw Exception("Unimplemented visitor for variant Int", ErrorCodes::UNIMPLEMENTED_VISITOR_FOR_VARIANT);
|
||||
}
|
||||
|
||||
void operator() (const DB::UInt & x) const
|
||||
{
|
||||
throw Exception("Unimplemented visitor for variant UInt", ErrorCodes::UNIMPLEMENTED_VISITOR_FOR_VARIANT);
|
||||
}
|
||||
|
||||
void operator() (const DB::String & x) const
|
||||
{
|
||||
throw Exception("Unimplemented visitor for variant String", ErrorCodes::UNIMPLEMENTED_VISITOR_FOR_VARIANT);
|
||||
}
|
||||
|
||||
void operator() (const DB::Null & x) const
|
||||
{
|
||||
throw Exception("Unimplemented visitor for variant Null", ErrorCodes::UNIMPLEMENTED_VISITOR_FOR_VARIANT);
|
||||
}
|
||||
|
||||
void operator() (const DB::FieldVector & x) const
|
||||
{
|
||||
throw Exception("Unimplemented visitor for variant FieldVector", ErrorCodes::UNIMPLEMENTED_VISITOR_FOR_VARIANT);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Возвращает true, если вариант - Null */
|
||||
class FieldVisitorIsNull : public boost::static_visitor<bool>
|
||||
{
|
||||
public:
|
||||
template <typename T> bool operator() (const T & x) const { return false; }
|
||||
bool operator() (const DB::Null & x) const { return true; }
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
17
dbms/include/DB/Row.h
Normal file
17
dbms/include/DB/Row.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef DBMS_ROW_H
|
||||
#define DBMS_ROW_H
|
||||
|
||||
#include <DB/Field.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/** Используется для хранения строк в памяти
|
||||
* - при обработке запроса, для временных таблиц, для результата.
|
||||
*/
|
||||
typedef std::vector<Field> Row;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
36
dbms/include/DB/VarInt.h
Normal file
36
dbms/include/DB/VarInt.h
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef DB_VARINT_H
|
||||
#define DB_VARINT_H
|
||||
|
||||
#include <DB/Field.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
||||
/** Записать UInt64 в формате переменной длины (base128) */
|
||||
void writeVarUInt(UInt x, std::ostream & ostr);
|
||||
|
||||
|
||||
/** Прочитать UInt64, записанный в формате переменной длины (base128) */
|
||||
void readVarUInt(UInt & x, std::istream & istr);
|
||||
|
||||
|
||||
/** Записать Int64 в формате переменной длины (base128) */
|
||||
inline void writeVarInt(Int x, std::ostream & ostr)
|
||||
{
|
||||
writeVarUInt(static_cast<UInt>((x << 1) ^ (x >> 63)), ostr);
|
||||
}
|
||||
|
||||
|
||||
/** Прочитать Int64, записанный в формате переменной длины (base128) */
|
||||
inline void readVarInt(Int & x, std::istream & istr)
|
||||
{
|
||||
readVarUInt(reinterpret_cast<UInt&>(x), istr);
|
||||
x = ((x >> 1) ^ (x << 63));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
10
dbms/src/Exception.cpp
Normal file
10
dbms/src/Exception.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include <typeinfo>
|
||||
#include <DB/Exception.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
POCO_IMPLEMENT_EXCEPTION(Exception, Poco::Exception, "DB::Exception");
|
||||
|
||||
}
|
140
dbms/src/VarInt.cpp
Normal file
140
dbms/src/VarInt.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
#include <DB/VarInt.h>
|
||||
|
||||
#include <Poco/Types.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
||||
void writeVarUInt(UInt x, std::ostream & ostr)
|
||||
{
|
||||
static char buf[9];
|
||||
|
||||
buf[0] = static_cast<Poco::UInt8>(x | 0x80);
|
||||
if (x >= (1ULL << 7))
|
||||
{
|
||||
buf[1] = static_cast<Poco::UInt8>((x >> 7) | 0x80);
|
||||
if (x >= (1ULL << 14))
|
||||
{
|
||||
buf[2] = static_cast<Poco::UInt8>((x >> 14) | 0x80);
|
||||
if (x >= (1ULL << 21))
|
||||
{
|
||||
buf[3] = static_cast<Poco::UInt8>((x >> 21) | 0x80);
|
||||
if (x >= (1ULL << 28))
|
||||
{
|
||||
buf[4] = static_cast<Poco::UInt8>((x >> 28) | 0x80);
|
||||
if (x >= (1ULL << 35))
|
||||
{
|
||||
buf[5] = static_cast<Poco::UInt8>((x >> 35) | 0x80);
|
||||
if (x >= (1ULL << 42))
|
||||
{
|
||||
buf[6] = static_cast<Poco::UInt8>((x >> 42) | 0x80);
|
||||
if (x >= (1ULL << 49))
|
||||
{
|
||||
buf[7] = static_cast<Poco::UInt8>((x >> 49) | 0x80);
|
||||
if (x >= (1ULL << 56))
|
||||
{
|
||||
buf[8] = static_cast<Poco::UInt8>((x >> 56) | 0x80);
|
||||
ostr.write(buf, 9);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[7] &= 0x7F;
|
||||
ostr.write(buf, 8);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[6] &= 0x7F;
|
||||
ostr.write(buf, 7);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[5] &= 0x7F;
|
||||
ostr.write(buf, 6);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[4] &= 0x7F;
|
||||
ostr.write(buf, 5);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[3] &= 0x7F;
|
||||
ostr.write(buf, 4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[2] &= 0x7F;
|
||||
ostr.write(buf, 3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[1] &= 0x7F;
|
||||
ostr.write(buf, 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[0] &= 0x7F;
|
||||
ostr.write(buf, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void readVarUInt(UInt & x, std::istream & istr)
|
||||
{
|
||||
int byte;
|
||||
|
||||
byte = istr.get();
|
||||
x = static_cast<Poco::UInt64>(byte) & 0x7F;
|
||||
if (byte & 0x80)
|
||||
{
|
||||
byte = istr.get();
|
||||
x |= (static_cast<Poco::UInt64>(byte) & 0x7F) << 7;
|
||||
if (byte & 0x80)
|
||||
{
|
||||
byte = istr.get();
|
||||
x |= (static_cast<Poco::UInt64>(byte) & 0x7F) << 14;
|
||||
if (byte & 0x80)
|
||||
{
|
||||
byte = istr.get();
|
||||
x |= (static_cast<Poco::UInt64>(byte) & 0x7F) << 21;
|
||||
if (byte & 0x80)
|
||||
{
|
||||
byte = istr.get();
|
||||
x |= (static_cast<Poco::UInt64>(byte) & 0x7F) << 28;
|
||||
if (byte & 0x80)
|
||||
{
|
||||
byte = istr.get();
|
||||
x |= (static_cast<Poco::UInt64>(byte) & 0x7F) << 35;
|
||||
if (byte & 0x80)
|
||||
{
|
||||
byte = istr.get();
|
||||
x |= (static_cast<Poco::UInt64>(byte) & 0x7F) << 42;
|
||||
if (byte & 0x80)
|
||||
{
|
||||
byte = istr.get();
|
||||
x |= (static_cast<Poco::UInt64>(byte) & 0x7F) << 49;
|
||||
if (byte & 0x80)
|
||||
{
|
||||
byte = istr.get();
|
||||
x |= (static_cast<Poco::UInt64>(byte) & 0x7F) << 56;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
322
dbms/src/tests/base128.cpp
Normal file
322
dbms/src/tests/base128.cpp
Normal file
@ -0,0 +1,322 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
#include <Poco/Types.h>
|
||||
#include <Poco/BinaryWriter.h>
|
||||
#include <Poco/BinaryReader.h>
|
||||
#include <Poco/Stopwatch.h>
|
||||
#include <Poco/Exception.h>
|
||||
#include <Poco/NumberFormatter.h>
|
||||
|
||||
|
||||
void writeVarUInt(Poco::UInt64 x, std::ostream & ostr)
|
||||
{
|
||||
static char buf[9];
|
||||
|
||||
buf[0] = static_cast<Poco::UInt8>(x | 0x80);
|
||||
if (x >= (1ULL << 7))
|
||||
{
|
||||
buf[1] = static_cast<Poco::UInt8>((x >> 7) | 0x80);
|
||||
if (x >= (1ULL << 14))
|
||||
{
|
||||
buf[2] = static_cast<Poco::UInt8>((x >> 14) | 0x80);
|
||||
if (x >= (1ULL << 21))
|
||||
{
|
||||
buf[3] = static_cast<Poco::UInt8>((x >> 21) | 0x80);
|
||||
if (x >= (1ULL << 28))
|
||||
{
|
||||
buf[4] = static_cast<Poco::UInt8>((x >> 28) | 0x80);
|
||||
if (x >= (1ULL << 35))
|
||||
{
|
||||
buf[5] = static_cast<Poco::UInt8>((x >> 35) | 0x80);
|
||||
if (x >= (1ULL << 42))
|
||||
{
|
||||
buf[6] = static_cast<Poco::UInt8>((x >> 42) | 0x80);
|
||||
if (x >= (1ULL << 49))
|
||||
{
|
||||
buf[7] = static_cast<Poco::UInt8>((x >> 49) | 0x80);
|
||||
if (x >= (1ULL << 56))
|
||||
{
|
||||
buf[8] = static_cast<Poco::UInt8>((x >> 56) | 0x80);
|
||||
ostr.write(buf, 9);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[7] &= 0x7F;
|
||||
ostr.write(buf, 8);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[6] &= 0x7F;
|
||||
ostr.write(buf, 7);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[5] &= 0x7F;
|
||||
ostr.write(buf, 6);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[4] &= 0x7F;
|
||||
ostr.write(buf, 5);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[3] &= 0x7F;
|
||||
ostr.write(buf, 4);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[2] &= 0x7F;
|
||||
ostr.write(buf, 3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[1] &= 0x7F;
|
||||
ostr.write(buf, 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buf[0] &= 0x7F;
|
||||
ostr.write(buf, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void readVarUInt(Poco::UInt64 & x, std::istream & istr)
|
||||
{
|
||||
int byte;
|
||||
|
||||
byte = istr.get();
|
||||
x = static_cast<Poco::UInt64>(byte) & 0x7F;
|
||||
if (byte & 0x80)
|
||||
{
|
||||
byte = istr.get();
|
||||
x |= (static_cast<Poco::UInt64>(byte) & 0x7F) << 7;
|
||||
if (byte & 0x80)
|
||||
{
|
||||
byte = istr.get();
|
||||
x |= (static_cast<Poco::UInt64>(byte) & 0x7F) << 14;
|
||||
if (byte & 0x80)
|
||||
{
|
||||
byte = istr.get();
|
||||
x |= (static_cast<Poco::UInt64>(byte) & 0x7F) << 21;
|
||||
if (byte & 0x80)
|
||||
{
|
||||
byte = istr.get();
|
||||
x |= (static_cast<Poco::UInt64>(byte) & 0x7F) << 28;
|
||||
if (byte & 0x80)
|
||||
{
|
||||
byte = istr.get();
|
||||
x |= (static_cast<Poco::UInt64>(byte) & 0x7F) << 35;
|
||||
if (byte & 0x80)
|
||||
{
|
||||
byte = istr.get();
|
||||
x |= (static_cast<Poco::UInt64>(byte) & 0x7F) << 42;
|
||||
if (byte & 0x80)
|
||||
{
|
||||
byte = istr.get();
|
||||
x |= (static_cast<Poco::UInt64>(byte) & 0x7F) << 49;
|
||||
if (byte & 0x80)
|
||||
{
|
||||
byte = istr.get();
|
||||
x |= (static_cast<Poco::UInt64>(byte) & 0x7F) << 56;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void readVarUInt_2(Poco::UInt64 & x, std::istream & istr)
|
||||
{
|
||||
static char buf[9];
|
||||
istr.read(buf, 9);
|
||||
|
||||
x = static_cast<Poco::UInt64>(buf[0]) & 0x7F;
|
||||
if (buf[0] & 0x80)
|
||||
{
|
||||
x |= (static_cast<Poco::UInt64>(buf[1]) & 0x7F) << 7;
|
||||
if (buf[1] & 0x80)
|
||||
{
|
||||
x |= (static_cast<Poco::UInt64>(buf[2]) & 0x7F) << 14;
|
||||
if (buf[2] & 0x80)
|
||||
{
|
||||
x |= (static_cast<Poco::UInt64>(buf[3]) & 0x7F) << 21;
|
||||
if (buf[3] & 0x80)
|
||||
{
|
||||
x |= (static_cast<Poco::UInt64>(buf[4]) & 0x7F) << 28;
|
||||
if (buf[4] & 0x80)
|
||||
{
|
||||
x |= (static_cast<Poco::UInt64>(buf[5]) & 0x7F) << 35;
|
||||
if (buf[5] & 0x80)
|
||||
{
|
||||
x |= (static_cast<Poco::UInt64>(buf[6]) & 0x7F) << 42;
|
||||
if (buf[6] & 0x80)
|
||||
{
|
||||
x |= (static_cast<Poco::UInt64>(buf[7]) & 0x7F) << 49;
|
||||
if (buf[7] & 0x80)
|
||||
{
|
||||
x |= (static_cast<Poco::UInt64>(buf[8]) & 0x7F) << 56;
|
||||
}
|
||||
else
|
||||
{
|
||||
istr.unget();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
istr.unget();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void writeVarInt(Poco::Int64 x, std::ostream & ostr)
|
||||
{
|
||||
writeVarUInt(static_cast<Poco::UInt64>((x << 1) ^ (x >> 63)), ostr);
|
||||
}
|
||||
|
||||
|
||||
void readVarInt(Poco::Int64 & x, std::istream & istr)
|
||||
{
|
||||
readVarUInt_2(reinterpret_cast<Poco::UInt64&>(x), istr);
|
||||
x = ((x >> 1) ^ (x << 63));
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
Poco::Stopwatch stopwatch;
|
||||
Poco::Timestamp::TimeDiff elapsed;
|
||||
Poco::Int64 start = 0;//1234567890123456789LL;
|
||||
|
||||
{
|
||||
std::ofstream ostr("tmp1");
|
||||
|
||||
stopwatch.restart();
|
||||
for (Poco::Int64 i = start; i < start + 10000000; i++)
|
||||
writeVarInt(i, ostr);
|
||||
stopwatch.stop();
|
||||
elapsed = stopwatch.elapsed();
|
||||
std::cout << "writeVarInt: " << static_cast<double>(elapsed) / 1000000 << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
std::ifstream ostr("tmp1");
|
||||
Poco::Int64 x;
|
||||
|
||||
stopwatch.restart();
|
||||
for (Poco::Int64 i = start; i < start + 10000000; i++)
|
||||
{
|
||||
readVarInt(x, ostr);
|
||||
if (x != i)
|
||||
throw Poco::Exception(Poco::NumberFormatter::format(i));
|
||||
}
|
||||
stopwatch.stop();
|
||||
elapsed = stopwatch.elapsed();
|
||||
std::cout << "readVarInt: " << static_cast<double>(elapsed) / 1000000 << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
std::ofstream ostr("tmp3");
|
||||
Poco::BinaryWriter writer(ostr);
|
||||
|
||||
stopwatch.restart();
|
||||
for (Poco::Int64 i = start; i < start + 10000000; i++)
|
||||
writer << i;
|
||||
stopwatch.stop();
|
||||
elapsed = stopwatch.elapsed();
|
||||
std::cout << "BinaryWriter: " << static_cast<double>(elapsed) / 1000000 << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
std::ofstream ostr("tmp4");
|
||||
|
||||
stopwatch.restart();
|
||||
for (Poco::Int64 i = start; i < start + 10000000; i++)
|
||||
ostr.write(reinterpret_cast<char*>(&i), 8);
|
||||
stopwatch.stop();
|
||||
elapsed = stopwatch.elapsed();
|
||||
std::cout << "ostream::write: " << static_cast<double>(elapsed) / 1000000 << std::endl;
|
||||
}
|
||||
}
|
||||
catch (const Poco::Exception & e)
|
||||
{
|
||||
std::cout << e.message() << std::endl;
|
||||
throw;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
74
dbms/src/tests/serialization.cpp
Normal file
74
dbms/src/tests/serialization.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <Poco/Stopwatch.h>
|
||||
#include <Poco/Timespan.h>
|
||||
#include <Poco/Exception.h>
|
||||
|
||||
#include <DB/ColumnType.h>
|
||||
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
DB::FieldVector vec;
|
||||
vec.reserve(10000000);
|
||||
Poco::Stopwatch stopwatch;
|
||||
Poco::SharedPtr<DB::IColumnType> column_type = DB::ColumnTypeFactory::get("VarUInt");
|
||||
|
||||
{
|
||||
stopwatch.restart();
|
||||
for (int i = 0; i < 10000000; ++i)
|
||||
{
|
||||
vec.push_back(DB::UInt(i));
|
||||
}
|
||||
stopwatch.stop();
|
||||
std::cout << "Filling array: " << static_cast<double>(stopwatch.elapsed()) / 1000000 << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
std::ofstream ostr("test");
|
||||
stopwatch.restart();
|
||||
for (int i = 0; i < 10000000; ++i)
|
||||
{
|
||||
column_type->serializeBinary(vec[i], ostr);
|
||||
}
|
||||
stopwatch.stop();
|
||||
std::cout << "Serialization: " << static_cast<double>(stopwatch.elapsed()) / 1000000 << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
std::ifstream istr("test");
|
||||
stopwatch.restart();
|
||||
for (int i = 0; i < 10000000; ++i)
|
||||
{
|
||||
column_type->deserializeBinary(vec[i], istr);
|
||||
}
|
||||
stopwatch.stop();
|
||||
std::cout << "Deserialization: " << static_cast<double>(stopwatch.elapsed()) / 1000000 << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
std::ofstream ostr("test2");
|
||||
stopwatch.restart();
|
||||
for (int i = 0; i < 10000000; ++i)
|
||||
{
|
||||
column_type->serializeText(vec[i], ostr);
|
||||
ostr.put('\t');
|
||||
}
|
||||
stopwatch.stop();
|
||||
std::cout << "Serialization (text): " << static_cast<double>(stopwatch.elapsed()) / 1000000 << std::endl;
|
||||
}
|
||||
|
||||
{
|
||||
std::ifstream istr("test2");
|
||||
stopwatch.restart();
|
||||
for (int i = 0; i < 10000000; ++i)
|
||||
{
|
||||
column_type->deserializeText(vec[i], istr);
|
||||
}
|
||||
stopwatch.stop();
|
||||
std::cout << "Deserialization (text): " << static_cast<double>(stopwatch.elapsed()) / 1000000 << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
164
dbms/src/tests/variant_vs_any.cpp
Normal file
164
dbms/src/tests/variant_vs_any.cpp
Normal file
@ -0,0 +1,164 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <cmath>
|
||||
|
||||
#include <boost/variant/static_visitor.hpp>
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
#include <boost/variant/get.hpp>
|
||||
#include <boost/any.hpp>
|
||||
|
||||
#include <Poco/Stopwatch.h>
|
||||
#include <Poco/Timespan.h>
|
||||
#include <Poco/Exception.h>
|
||||
|
||||
#include <DB/Field.h>
|
||||
#include <DB/ColumnType.h>
|
||||
|
||||
|
||||
class FieldOutVisitor : public boost::static_visitor<>
|
||||
{
|
||||
public:
|
||||
FieldOutVisitor(std::ostream & ostr_, unsigned indent_ = 0)
|
||||
: ostr(ostr_), indent(indent_) {}
|
||||
|
||||
|
||||
void operator() (const DB::Int & x) const
|
||||
{
|
||||
for (unsigned i = 0; i < indent; ++i)
|
||||
ostr.put('\t');
|
||||
ostr << x << "," << std::endl;
|
||||
}
|
||||
|
||||
void operator() (const DB::UInt & x) const
|
||||
{
|
||||
for (unsigned i = 0; i < indent; ++i)
|
||||
ostr.put('\t');
|
||||
ostr << x << "," << std::endl;
|
||||
}
|
||||
|
||||
void operator() (const DB::String & x) const
|
||||
{
|
||||
for (unsigned i = 0; i < indent; ++i)
|
||||
ostr.put('\t');
|
||||
ostr << x << "," << std::endl;
|
||||
}
|
||||
|
||||
void operator() (const DB::Null & x) const
|
||||
{
|
||||
for (unsigned i = 0; i < indent; ++i)
|
||||
ostr.put('\t');
|
||||
ostr << "NULL," << std::endl;
|
||||
}
|
||||
|
||||
void operator() (const DB::FieldVector & x) const
|
||||
{
|
||||
for (unsigned i = 0; i < indent; ++i)
|
||||
ostr.put('\t');
|
||||
ostr << '{' << std::endl;
|
||||
|
||||
FieldOutVisitor visitor(ostr, indent + 1);
|
||||
std::for_each(x.begin(), x.end(), boost::apply_visitor(visitor));
|
||||
|
||||
for (unsigned i = 0; i < indent; ++i)
|
||||
ostr.put('\t');
|
||||
ostr << '}' << "," << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
std::ostream & ostr;
|
||||
unsigned indent;
|
||||
};
|
||||
|
||||
|
||||
class TimesTwoVisitor : public boost::static_visitor<>
|
||||
{
|
||||
public:
|
||||
template <typename T> void operator() (T & x) const { x *= 2; }
|
||||
|
||||
void operator() (DB::Null & x) const {}
|
||||
void operator() (DB::String & x) const { x = ""; }
|
||||
void operator() (DB::FieldVector & x) const
|
||||
{
|
||||
TimesTwoVisitor visitor;
|
||||
std::for_each(x.begin(), x.end(), boost::apply_visitor(visitor));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class DynamicTimesTwoVisitor
|
||||
{
|
||||
public:
|
||||
void operator() (boost::any & x) const
|
||||
{
|
||||
if (x.type() == typeid(DB::UInt))
|
||||
boost::any_cast<DB::UInt&>(x) *= 2;
|
||||
else if (x.type() == typeid(DB::String))
|
||||
boost::any_cast<DB::String&>(x) = "";
|
||||
else
|
||||
throw Poco::Exception("Unknown type");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
Poco::Stopwatch stopwatch;
|
||||
|
||||
{
|
||||
DB::FieldVector arr;
|
||||
DB::Field field(arr);
|
||||
|
||||
DB::FieldVector & vec = boost::get<DB::FieldVector>(field);
|
||||
vec.reserve(10000000);
|
||||
|
||||
stopwatch.restart();
|
||||
for (int i = 0; i < 10000000; ++i)
|
||||
{
|
||||
if (i % 100 != 0)
|
||||
vec.push_back(DB::UInt(10));
|
||||
else
|
||||
vec.push_back("http://www.boost.org/doc/libs/1_39_0/doc/html/variant/tutorial.html#variant.tutorial.recursive.recursive-variant");
|
||||
}
|
||||
stopwatch.stop();
|
||||
std::cout << static_cast<double>(stopwatch.elapsed()) / 1000000 << std::endl;
|
||||
|
||||
stopwatch.restart();
|
||||
boost::apply_visitor(TimesTwoVisitor(), field);
|
||||
stopwatch.stop();
|
||||
std::cout << static_cast<double>(stopwatch.elapsed()) / 1000000 << std::endl;
|
||||
|
||||
//std::ofstream ostr("/dev/null");
|
||||
//boost::apply_visitor(FieldOutVisitor(ostr), field);
|
||||
sleep(10);
|
||||
}
|
||||
|
||||
{
|
||||
std::vector<boost::any> vec;
|
||||
vec.reserve(10000000);
|
||||
|
||||
stopwatch.restart();
|
||||
for (int i = 0; i < 10000000; ++i)
|
||||
{
|
||||
if (i % 100 != 0)
|
||||
vec.push_back(DB::UInt(10));
|
||||
else
|
||||
vec.push_back(DB::String("http://www.boost.org/doc/libs/1_39_0/doc/html/variant/tutorial.html#variant.tutorial.recursive.recursive-variant"));
|
||||
}
|
||||
stopwatch.stop();
|
||||
std::cout << static_cast<double>(stopwatch.elapsed()) / 1000000 << std::endl;
|
||||
|
||||
stopwatch.restart();
|
||||
DynamicTimesTwoVisitor visitor;
|
||||
std::for_each(vec.begin(), vec.end(), visitor);
|
||||
stopwatch.stop();
|
||||
Poco::Timestamp::TimeDiff elapsed(stopwatch.elapsed());
|
||||
|
||||
std::cout << static_cast<double>(elapsed) / 1000000 << std::endl;
|
||||
|
||||
sleep(10);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user