mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-12-04 13:32:13 +00:00
dbms: development.
This commit is contained in:
parent
c8e544b0f6
commit
2dbd493503
35
dbms/include/DB/AggregateFunction.h
Normal file
35
dbms/include/DB/AggregateFunction.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#ifndef DBMS_AGGREGATE_FUNCTION_H
|
||||||
|
#define DBMS_AGGREGATE_FUNCTION_H
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/** Агрегатная функция
|
||||||
|
* Шаблонный параметр здесь только потому что непонятно, как сделать forward declaration Field из Field.h.
|
||||||
|
*/
|
||||||
|
template<typename Field>
|
||||||
|
class IAggregateFunction
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual void add(const Field & a) = 0;
|
||||||
|
|
||||||
|
virtual Field getValue() const = 0;
|
||||||
|
|
||||||
|
/** Бинарная сериализация и десериализация состояния для передачи по сети.
|
||||||
|
* При чём, deserializeMerge производит объединение текущего и считываемого состояний.
|
||||||
|
*/
|
||||||
|
virtual void serialize(std::ostream & ostr) const = 0;
|
||||||
|
virtual void deserializeMerge(std::istream & istr) = 0;
|
||||||
|
|
||||||
|
/** Объединение состояния агрегатной функции с состоянием другой агрегатной функции. */
|
||||||
|
virtual void merge(const IAggregateFunction & rhs) = 0;
|
||||||
|
|
||||||
|
virtual ~IAggregateFunction() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
24
dbms/include/DB/Column.h
Normal file
24
dbms/include/DB/Column.h
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#ifndef DBMS_COLUMN_H
|
||||||
|
#define DBMS_COLUMN_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <Poco/SharedPtr.h>
|
||||||
|
|
||||||
|
#include <DB/ColumnType.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
/** Столбец - часть ColumnGroup, которая, в свою очередь - часть таблицы
|
||||||
|
*/
|
||||||
|
struct Column
|
||||||
|
{
|
||||||
|
std::string name;
|
||||||
|
Poco::SharedPtr<IColumnType> type;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
32
dbms/include/DB/ColumnGroup.h
Normal file
32
dbms/include/DB/ColumnGroup.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#ifndef DBMS_COLUMN_GROUP_H
|
||||||
|
#define DBMS_COLUMN_GROUP_H
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <Poco/SharedPtr.h>
|
||||||
|
|
||||||
|
#include <DB/Column.h>
|
||||||
|
#include <DB/PrimaryKey.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
/** ColumnGroup - часть таблицы, которая хранится отдельно.
|
||||||
|
* Может состоять из одного, нескольких или всех столбцов таблицы.
|
||||||
|
* Таблица состоит из column-групп.
|
||||||
|
*/
|
||||||
|
struct ColumnGroup
|
||||||
|
{
|
||||||
|
/// Номера столбцов
|
||||||
|
typedef std::vector<size_t> ColumnNumbers;
|
||||||
|
ColumnNumbers column_numbers;
|
||||||
|
|
||||||
|
/// Первичный ключ
|
||||||
|
Poco::SharedPtr<IPrimaryKey> primary_key;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -36,17 +36,19 @@ public:
|
|||||||
|
|
||||||
/// Бинарная сериализация - для сохранения на диск / в сеть и т. п.
|
/// Бинарная сериализация - для сохранения на диск / в сеть и т. п.
|
||||||
virtual void serializeBinary(const DB::Field & field, std::ostream & ostr) 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 deserializeBinary(DB::Field & field, std::istream & istr) const = 0;
|
||||||
|
|
||||||
/** Текстовая сериализация - для вывода на экран / сохранения в текстовый файл и т. п.
|
/** Текстовая сериализация - для вывода на экран / сохранения в текстовый файл и т. п.
|
||||||
* Считается, что разделители, а также escape-инг обязан делать вызывающий.
|
* Считается, что разделители, а также escape-инг обязан делать вызывающий.
|
||||||
*/
|
*/
|
||||||
virtual void serializeText(const DB::Field & field, std::ostream & 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;
|
virtual void deserializeText(DB::Field & field, std::istream & istr) const = 0;
|
||||||
|
|
||||||
/// Шаблонные методы для параметризуемого типа сериализации.
|
/// Шаблонные методы для параметризуемого типа сериализации.
|
||||||
template <typename SerializationTag> void serialize(const DB::Field & field, std::ostream & ostr) const;
|
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;
|
template <typename SerializationTag> void deserialize(DB::Field & field, std::istream & istr) const;
|
||||||
|
|
||||||
|
virtual ~IColumnType() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -288,7 +290,7 @@ public:
|
|||||||
void serializeBinary(const DB::Field & field, std::ostream & ostr) const
|
void serializeBinary(const DB::Field & field, std::ostream & ostr) const
|
||||||
{
|
{
|
||||||
const std::string & str = boost::get<String>(field);
|
const std::string & str = boost::get<String>(field);
|
||||||
writeVarUInt(str.size(), ostr);
|
writeVarUInt(UInt(str.size()), ostr);
|
||||||
ostr << str;
|
ostr << str;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,7 +337,7 @@ public:
|
|||||||
void serializeBinary(const DB::Field & field, std::ostream & ostr) const
|
void serializeBinary(const DB::Field & field, std::ostream & ostr) const
|
||||||
{
|
{
|
||||||
const String & str = boost::get<String>(field);
|
const String & str = boost::get<String>(field);
|
||||||
if (str.size() != size)
|
if (UInt(str.size()) != size)
|
||||||
throw Exception("Incorrect size of value of type " + getName()
|
throw Exception("Incorrect size of value of type " + getName()
|
||||||
+ ": " + Poco::NumberFormatter::format(str.size()), ErrorCodes::INCORRECT_SIZE_OF_VALUE);
|
+ ": " + Poco::NumberFormatter::format(str.size()), ErrorCodes::INCORRECT_SIZE_OF_VALUE);
|
||||||
|
|
||||||
@ -383,8 +385,8 @@ public:
|
|||||||
void serializeBinary(const DB::Field & field, std::ostream & ostr) const
|
void serializeBinary(const DB::Field & field, std::ostream & ostr) const
|
||||||
{
|
{
|
||||||
const FieldVector & vec = boost::get<FieldVector>(field);
|
const FieldVector & vec = boost::get<FieldVector>(field);
|
||||||
writeVarUInt(vec.size(), ostr);
|
writeVarUInt(UInt(vec.size()), ostr);
|
||||||
for (UInt i = 0; i < vec.size(); ++i)
|
for (UInt i(0); i < vec.size(); ++i)
|
||||||
nested_type->serializeBinary(vec[i], ostr);
|
nested_type->serializeBinary(vec[i], ostr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,14 +396,14 @@ public:
|
|||||||
UInt size;
|
UInt size;
|
||||||
readVarUInt(size, istr);
|
readVarUInt(size, istr);
|
||||||
vec.resize(size);
|
vec.resize(size);
|
||||||
for (UInt i = 0; i < size; ++i)
|
for (UInt i(0); i < size; ++i)
|
||||||
nested_type->deserializeBinary(vec[i], istr);
|
nested_type->deserializeBinary(vec[i], istr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void serializeText(const DB::Field & field, std::ostream & ostr) const
|
void serializeText(const DB::Field & field, std::ostream & ostr) const
|
||||||
{
|
{
|
||||||
const FieldVector & vec = boost::get<FieldVector>(field);
|
const FieldVector & vec = boost::get<FieldVector>(field);
|
||||||
for (UInt i = 0; i < vec.size(); ++i)
|
for (UInt i(0); i < vec.size(); ++i)
|
||||||
{
|
{
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
nested_type->serializeText(vec[i], stream);
|
nested_type->serializeText(vec[i], stream);
|
||||||
@ -441,11 +443,11 @@ public:
|
|||||||
{
|
{
|
||||||
const FieldVector & vec = boost::get<FieldVector>(field);
|
const FieldVector & vec = boost::get<FieldVector>(field);
|
||||||
|
|
||||||
if (vec.size() != size)
|
if (UInt(vec.size()) != size)
|
||||||
throw Exception("Incorrect size of value of type " + getName()
|
throw Exception("Incorrect size of value of type " + getName()
|
||||||
+ ": " + Poco::NumberFormatter::format(vec.size()), ErrorCodes::INCORRECT_SIZE_OF_VALUE);
|
+ ": " + Poco::NumberFormatter::format(vec.size()), ErrorCodes::INCORRECT_SIZE_OF_VALUE);
|
||||||
|
|
||||||
for (UInt i = 0; i < size; ++i)
|
for (UInt i(0); i < size; ++i)
|
||||||
nested_type->serializeBinary(vec[i], ostr);
|
nested_type->serializeBinary(vec[i], ostr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -453,14 +455,14 @@ public:
|
|||||||
{
|
{
|
||||||
FieldVector & vec = boost::get<FieldVector>(field);
|
FieldVector & vec = boost::get<FieldVector>(field);
|
||||||
vec.resize(size);
|
vec.resize(size);
|
||||||
for (UInt i = 0; i < size; ++i)
|
for (UInt i(0); i < size; ++i)
|
||||||
nested_type->deserializeBinary(vec[i], istr);
|
nested_type->deserializeBinary(vec[i], istr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void serializeText(const DB::Field & field, std::ostream & ostr) const
|
void serializeText(const DB::Field & field, std::ostream & ostr) const
|
||||||
{
|
{
|
||||||
const FieldVector & vec = boost::get<FieldVector>(field);
|
const FieldVector & vec = boost::get<FieldVector>(field);
|
||||||
for (UInt i = 0; i < size; ++i)
|
for (UInt i(0); i < size; ++i)
|
||||||
{
|
{
|
||||||
std::stringstream stream;
|
std::stringstream stream;
|
||||||
nested_type->serializeText(vec[i], stream);
|
nested_type->serializeText(vec[i], stream);
|
||||||
|
@ -14,6 +14,11 @@ namespace ErrorCodes
|
|||||||
INCORRECT_PARAMETER_FOR_TYPE,
|
INCORRECT_PARAMETER_FOR_TYPE,
|
||||||
INCORRECT_SIZE_OF_VALUE,
|
INCORRECT_SIZE_OF_VALUE,
|
||||||
METHOD_NOT_IMPLEMENTED,
|
METHOD_NOT_IMPLEMENTED,
|
||||||
|
CANT_READ_INDEX_FILE,
|
||||||
|
TOO_FEW_COLUMNS_FOR_KEY,
|
||||||
|
PRIMARY_KEY_WAS_NOT_ATTACHED,
|
||||||
|
CANT_READ_DATA_FILE,
|
||||||
|
TOO_MANY_COLUMNS_FOR_KEY
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,13 +5,17 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <Poco/Types.h>
|
#include <Poco/Types.h>
|
||||||
|
#include <Poco/Void.h>
|
||||||
|
#include <Poco/SharedPtr.h>
|
||||||
|
|
||||||
|
#include <boost/strong_typedef.hpp>
|
||||||
#include <boost/variant.hpp>
|
#include <boost/variant.hpp>
|
||||||
#include <boost/variant/recursive_variant.hpp>
|
#include <boost/variant/recursive_variant.hpp>
|
||||||
#include <boost/variant/static_visitor.hpp>
|
#include <boost/variant/static_visitor.hpp>
|
||||||
|
|
||||||
#include <DB/Exception.h>
|
#include <DB/Exception.h>
|
||||||
#include <DB/ErrorCodes.h>
|
#include <DB/ErrorCodes.h>
|
||||||
|
#include <DB/AggregateFunction.h>
|
||||||
|
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
@ -21,8 +25,7 @@ namespace DB
|
|||||||
typedef Poco::Int64 Int;
|
typedef Poco::Int64 Int;
|
||||||
typedef Poco::UInt64 UInt;
|
typedef Poco::UInt64 UInt;
|
||||||
typedef std::string String;
|
typedef std::string String;
|
||||||
|
BOOST_STRONG_TYPEDEF(char, Null);
|
||||||
struct Null {};
|
|
||||||
|
|
||||||
|
|
||||||
/** Используется для хранения значений в памяти
|
/** Используется для хранения значений в памяти
|
||||||
@ -36,56 +39,19 @@ typedef boost::make_recursive_variant<
|
|||||||
UInt,
|
UInt,
|
||||||
String,
|
String,
|
||||||
Null,
|
Null,
|
||||||
|
Poco::SharedPtr<IAggregateFunction<boost::recursive_variant_> >,
|
||||||
std::vector<boost::recursive_variant_> /// FieldVector
|
std::vector<boost::recursive_variant_> /// FieldVector
|
||||||
>::type Field;
|
>::type Field;
|
||||||
|
|
||||||
typedef std::vector<Field> FieldVector; /// Значение типа "массив"
|
typedef std::vector<Field> FieldVector; /// Значение типа "массив"
|
||||||
|
typedef Poco::SharedPtr<IAggregateFunction<Field> > AggregateFunctionPtr;
|
||||||
|
|
||||||
|
|
||||||
/** Визитор по умолчанию, который ничего не делает
|
/// почему-то у boost::variant определены операторы < и ==, но не остальные операторы сравнения
|
||||||
* - нужно для того, чтобы наследоваться от него и писать меньше кода
|
inline bool operator!= (const Field & lhs, const Field & rhs) { return !(lhs == rhs); }
|
||||||
* для визиторов, которые делают что-то содержательное только для нескольких вариантов.
|
inline bool operator<= (const Field & lhs, const Field & rhs) { return lhs < rhs || lhs == rhs; }
|
||||||
*/
|
inline bool operator>= (const Field & lhs, const Field & rhs) { return !(lhs < rhs); }
|
||||||
class FieldVisitorDefaultNothing : public boost::static_visitor<>
|
inline bool operator> (const Field & lhs, const Field & rhs) { return !(lhs < rhs) && !(lhs == rhs); }
|
||||||
{
|
|
||||||
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 */
|
/** Возвращает true, если вариант - Null */
|
||||||
@ -97,6 +63,32 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Принимает два значения Field, обновляет первое вторым.
|
||||||
|
* Если только первое - не агрегатная функция, результат обновления - замена первого вторым.
|
||||||
|
* Иначе - добавление к агрегатной функции значения или объединение агрегатных функций.
|
||||||
|
*/
|
||||||
|
class FieldVisitorUpdate : public boost::static_visitor<>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
template <typename T, typename U>
|
||||||
|
void operator() (T & x, const U & y) const
|
||||||
|
{
|
||||||
|
x = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void operator() (AggregateFunctionPtr & x, const T & y) const
|
||||||
|
{
|
||||||
|
x->add(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (AggregateFunctionPtr & x, const AggregateFunctionPtr & y) const
|
||||||
|
{
|
||||||
|
x->merge(*y);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
82
dbms/include/DB/PrimaryKey.h
Normal file
82
dbms/include/DB/PrimaryKey.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#ifndef DBMS_PRIMARY_KEY_H
|
||||||
|
#define DBMS_PRIMARY_KEY_H
|
||||||
|
|
||||||
|
#include <Poco/SharedPtr.h>
|
||||||
|
|
||||||
|
#include <DB/RowSet.h>
|
||||||
|
#include <DB/TablePartReader.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class ColumnGroup;
|
||||||
|
class Table;
|
||||||
|
|
||||||
|
|
||||||
|
/** Первичный ключ - самая важная часть БД.
|
||||||
|
* Отвечает за:
|
||||||
|
* - определение, в каком файле (или не файле) хранятся данные;
|
||||||
|
* - поиск данных и обновление данных;
|
||||||
|
* - структура хранения данных (сжатие, etc.)
|
||||||
|
* - конкуррентный доступ к данным (блокировки, etc.)
|
||||||
|
*
|
||||||
|
* Присутствуют следующие особенности первичного ключа:
|
||||||
|
* - может состоять из нескольких частей. Например, значения первых нескольких столбцов индексируются
|
||||||
|
* с помощью файловой системы для удобства бэкапа и устаревания данных; а значения остальных столбцов
|
||||||
|
* индексируются с помощью B-дерева.
|
||||||
|
* - может не полностью индексировать столбцы, однозначно идентифицирующие строку в таблице -
|
||||||
|
* для работы с пачками строк.
|
||||||
|
*/
|
||||||
|
class IPrimaryKey
|
||||||
|
{
|
||||||
|
friend class Table;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/** Установить указатель на таблицу и кол-группу.
|
||||||
|
* - часть инициализации, которая выполняется при инициализации таблицы.
|
||||||
|
* (инициализация первичного ключа выполняется в два шага:
|
||||||
|
* 1 - конструктор,
|
||||||
|
* 2 - добавление к таблице (выполняется в конструкторе Table))
|
||||||
|
*/
|
||||||
|
virtual void addToTable(Table * table_, ColumnGroup * column_group_) = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Прочитать данные, соответствующие точному значению ключа или префиксу.
|
||||||
|
* Возвращает объект, с помощью которого можно последовательно читать данные.
|
||||||
|
*/
|
||||||
|
virtual Poco::SharedPtr<ITablePartReader> read(const Row & key) = 0;
|
||||||
|
|
||||||
|
/** Записать пачку данных в таблицу, обновляя существующие данные, если они есть.
|
||||||
|
* @param data - набор данных вида ключ (набор столбцов) -> значение (набор столбцов)
|
||||||
|
* @param mask - битовая маска - какие столбцы входят в кол-группу,
|
||||||
|
* которую индексирует этот первичный ключ
|
||||||
|
*/
|
||||||
|
virtual void merge(const AggregatedRowSet & data, const ColumnMask & mask) = 0;
|
||||||
|
|
||||||
|
virtual ~IPrimaryKey() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** Реализует метод addToTable(),
|
||||||
|
* а также содержит члены table, column_group.
|
||||||
|
*/
|
||||||
|
class PrimaryKeyBase : public IPrimaryKey
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
/// Слабые указатели на таблицу и column_group, которые владеют этим первичным ключём.
|
||||||
|
Table * table;
|
||||||
|
ColumnGroup * column_group;
|
||||||
|
|
||||||
|
PrimaryKeyBase() : table(0), column_group(0) {}
|
||||||
|
|
||||||
|
void addToTable(Table * table_, ColumnGroup * column_group_)
|
||||||
|
{
|
||||||
|
table = table_;
|
||||||
|
column_group = column_group_;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
58
dbms/include/DB/PrimaryKeyNone.h
Normal file
58
dbms/include/DB/PrimaryKeyNone.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#ifndef DBMS_PRIMARY_KEY_NONE_H
|
||||||
|
#define DBMS_PRIMARY_KEY_NONE_H
|
||||||
|
|
||||||
|
#include <Poco/SharedPtr.h>
|
||||||
|
#include <Poco/File.h>
|
||||||
|
#include <Poco/FileStream.h>
|
||||||
|
|
||||||
|
#include <DB/PrimaryKey.h>
|
||||||
|
#include <DB/TablePartReader.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
/** Самый простой первичный ключ - ничего не индексирует;
|
||||||
|
* для чтения или обновления приходится читать файл целиком.
|
||||||
|
* - удобно для логов.
|
||||||
|
*/
|
||||||
|
class PrimaryKeyNone : public PrimaryKeyBase
|
||||||
|
{
|
||||||
|
friend class PrimaryKeyNoneTablePartReader;
|
||||||
|
private:
|
||||||
|
std::string path;
|
||||||
|
std::string name;
|
||||||
|
std::string data_file_name;
|
||||||
|
|
||||||
|
Poco::File data_file;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Путь со слешем на конце. */
|
||||||
|
PrimaryKeyNone(const std::string & path_, const std::string & name_);
|
||||||
|
|
||||||
|
/** Просто дописывает данные в конец. */
|
||||||
|
void merge(const AggregatedRowSet & data, const ColumnMask & mask);
|
||||||
|
|
||||||
|
/** Прочитать данные, префикс ключа которых совпадает с key */
|
||||||
|
Poco::SharedPtr<ITablePartReader> read(const Row & key);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PrimaryKeyNoneTablePartReader : public ITablePartReader
|
||||||
|
{
|
||||||
|
friend class PrimaryKeyNone;
|
||||||
|
private:
|
||||||
|
const Row key;
|
||||||
|
/// слабый указатель на первичный ключ
|
||||||
|
PrimaryKeyNone * pk;
|
||||||
|
Poco::FileInputStream istr;
|
||||||
|
|
||||||
|
PrimaryKeyNoneTablePartReader(const Row & key_, PrimaryKeyNone * pk_);
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool fetch(Row & row);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
64
dbms/include/DB/PrimaryKeyPlain.h
Normal file
64
dbms/include/DB/PrimaryKeyPlain.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#ifndef DBMS_PRIMARY_KEY_PLAIN_H
|
||||||
|
#define DBMS_PRIMARY_KEY_PLAIN_H
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <Poco/SharedPtr.h>
|
||||||
|
#include <Poco/BinaryReader.h>
|
||||||
|
|
||||||
|
#include <DB/Table.h>
|
||||||
|
|
||||||
|
#include <DB/PrimaryKey.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
/** Простой, "плоский" первичный ключ.
|
||||||
|
* Хранит список смещений в бинарном файле, список свободных блоков - в другом бинарном файле.
|
||||||
|
* Поиск в этом файле линейный.
|
||||||
|
* При обновлении данных, индексный файл полностью перезаписывается.
|
||||||
|
* Файл с данными не сжатый.
|
||||||
|
* Индекс полностью загружается в память во время работы.
|
||||||
|
*/
|
||||||
|
class PrimaryKeyPlain : public PrimaryKeyBase
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::string path;
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
std::string data_file_name;
|
||||||
|
std::string offsets_file_name;
|
||||||
|
std::string free_blocks_file_name;
|
||||||
|
|
||||||
|
Poco::File data_file;
|
||||||
|
Poco::File offsets_file;
|
||||||
|
Poco::File free_blocks_file;
|
||||||
|
|
||||||
|
struct Offset
|
||||||
|
{
|
||||||
|
size_t offset; /// смещение от начала файла
|
||||||
|
size_t size; /// размер данных
|
||||||
|
|
||||||
|
bool operator< (const Offset & rhs) const
|
||||||
|
{
|
||||||
|
return size < rhs.size;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<Row, Offset> offsets;
|
||||||
|
std::set<Offset> free_blocks;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Путь со слешем на конце. */
|
||||||
|
PrimaryKeyPlain(const std::string & path_, const std::string & name_);
|
||||||
|
|
||||||
|
void addToTable(Table * table_, ColumnGroup * column_group_);
|
||||||
|
|
||||||
|
void merge(const AggregatedRowSet & data, const ColumnMask & mask);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,13 +1,17 @@
|
|||||||
#ifndef DBMS_ROW_H
|
#ifndef DBMS_ROW_H
|
||||||
#define DBMS_ROW_H
|
#define DBMS_ROW_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <DB/Field.h>
|
#include <DB/Field.h>
|
||||||
|
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
|
|
||||||
/** Используется для хранения строк в памяти
|
/** Строка или часть строки.
|
||||||
|
* Используется для хранения строк в памяти
|
||||||
* - при обработке запроса, для временных таблиц, для результата.
|
* - при обработке запроса, для временных таблиц, для результата.
|
||||||
*/
|
*/
|
||||||
typedef std::vector<Field> Row;
|
typedef std::vector<Field> Row;
|
||||||
|
26
dbms/include/DB/RowSet.h
Normal file
26
dbms/include/DB/RowSet.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef DBMS_ROW_SET_H
|
||||||
|
#define DBMS_ROW_SET_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <DB/Row.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
/** Набор строк. */
|
||||||
|
typedef std::vector<Row> RowSet;
|
||||||
|
|
||||||
|
/** Набор строк, использующийся в качестве результата запроса с агрегатными функциями,
|
||||||
|
* а также как массив для загрузки данных в таблицу.
|
||||||
|
*/
|
||||||
|
typedef std::map<Row, Row> AggregatedRowSet;
|
||||||
|
|
||||||
|
/** Битовая маска столбцов. */
|
||||||
|
typedef std::vector<bool> ColumnMask;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
57
dbms/include/DB/Table.h
Normal file
57
dbms/include/DB/Table.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#ifndef DBMS_TABLE_H
|
||||||
|
#define DBMS_TABLE_H
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
#include <Poco/SharedPtr.h>
|
||||||
|
|
||||||
|
#include <DB/Column.h>
|
||||||
|
#include <DB/ColumnGroup.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class Table
|
||||||
|
{
|
||||||
|
friend class PrimaryKeyNone;
|
||||||
|
friend class PrimaryKeyNoneTablePartReader;
|
||||||
|
friend class PrimaryKeyPlain;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef std::vector<Column> Columns;
|
||||||
|
typedef std::vector<size_t> ColumnNumbers;
|
||||||
|
typedef std::vector<ColumnGroup> ColumnGroups;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Имя таблицы
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
/// Столбцы
|
||||||
|
Poco::SharedPtr<Columns> columns;
|
||||||
|
|
||||||
|
/// Столбцы, которые относятся к первичному ключу
|
||||||
|
Poco::SharedPtr<ColumnNumbers> primary_key_column_numbers;
|
||||||
|
|
||||||
|
/// Группы столбцов
|
||||||
|
Poco::SharedPtr<ColumnGroups> column_groups;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Table(const std::string & name_,
|
||||||
|
const Poco::SharedPtr<Columns> columns_,
|
||||||
|
const Poco::SharedPtr<ColumnNumbers> primary_key_column_numbers_,
|
||||||
|
const Poco::SharedPtr<ColumnGroups> column_groups_)
|
||||||
|
: name(name_),
|
||||||
|
columns(columns_),
|
||||||
|
primary_key_column_numbers(primary_key_column_numbers_),
|
||||||
|
column_groups(column_groups_)
|
||||||
|
{
|
||||||
|
/// Пропишем в первичных ключах в кол-группах указатель на таблицу и кол-группу
|
||||||
|
for (ColumnGroups::iterator it = column_groups->begin(); it != column_groups->end(); ++it)
|
||||||
|
it->primary_key->addToTable(this, &*it);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
21
dbms/include/DB/TablePartReader.h
Normal file
21
dbms/include/DB/TablePartReader.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#ifndef DBMS_TABLE_PART_READER_H
|
||||||
|
#define DBMS_TABLE_PART_READER_H
|
||||||
|
|
||||||
|
#include <DB/Row.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
class ITablePartReader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// прочитать следующую строку, вернуть false, если строк больше нет
|
||||||
|
virtual bool fetch(Row & row) = 0;
|
||||||
|
|
||||||
|
virtual ~ITablePartReader() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
87
dbms/src/PrimaryKeyNone.cpp
Normal file
87
dbms/src/PrimaryKeyNone.cpp
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#include <DB/Exception.h>
|
||||||
|
#include <DB/ErrorCodes.h>
|
||||||
|
#include <DB/Table.h>
|
||||||
|
#include <DB/ColumnGroup.h>
|
||||||
|
|
||||||
|
#include <DB/PrimaryKeyNone.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
PrimaryKeyNone::PrimaryKeyNone(const std::string & path_, const std::string & name_)
|
||||||
|
: path(path_),
|
||||||
|
name(name_),
|
||||||
|
data_file_name(path + name + ".dat"),
|
||||||
|
data_file(data_file_name)
|
||||||
|
{
|
||||||
|
/// создаём файлы, если их ещё нет
|
||||||
|
data_file.createFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PrimaryKeyNone::merge(const AggregatedRowSet & data, const ColumnMask & mask)
|
||||||
|
{
|
||||||
|
if (!table || !column_group)
|
||||||
|
throw Exception("Primary key was not attached to table and column group",
|
||||||
|
ErrorCodes::PRIMARY_KEY_WAS_NOT_ATTACHED);
|
||||||
|
|
||||||
|
/// просто дописываем данные в конец файла
|
||||||
|
Poco::FileOutputStream ostr(data_file_name, std::ios::out | std::ios::binary | std::ios::app);
|
||||||
|
|
||||||
|
for (AggregatedRowSet::const_iterator it = data.begin(); it != data.end(); ++it)
|
||||||
|
{
|
||||||
|
for (size_t j = 0; j != it->first.size(); ++j)
|
||||||
|
if (mask[j])
|
||||||
|
table->columns->at(column_group->column_numbers[j]).type->serializeBinary(it->first[j], ostr);
|
||||||
|
|
||||||
|
for (size_t j = 0; j != it->second.size(); ++j)
|
||||||
|
if (mask[j + it->first.size()])
|
||||||
|
table->columns->at(
|
||||||
|
column_group->column_numbers[j + it->first.size()]
|
||||||
|
).type->serializeBinary(it->second[j], ostr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Poco::SharedPtr<ITablePartReader> PrimaryKeyNone::read(const Row & key)
|
||||||
|
{
|
||||||
|
return new PrimaryKeyNoneTablePartReader(key, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PrimaryKeyNoneTablePartReader::PrimaryKeyNoneTablePartReader(
|
||||||
|
const Row & key_, PrimaryKeyNone * pk_)
|
||||||
|
: key(key_), pk(pk_), istr(pk->data_file_name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool PrimaryKeyNoneTablePartReader::fetch(Row & row)
|
||||||
|
{
|
||||||
|
if (key.size() > pk->column_group->column_numbers.size())
|
||||||
|
throw Exception("Too many columns specified for key", ErrorCodes::TOO_MANY_COLUMNS_FOR_KEY);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < pk->column_group->column_numbers.size(); ++i)
|
||||||
|
pk->table->columns->at(pk->column_group->column_numbers[i]).type->deserializeBinary(row[i], istr);
|
||||||
|
|
||||||
|
/// проверим, что ключи совпадают (замечание: столбцы ключа всегда идут первыми)
|
||||||
|
for (size_t i = 0; i < key.size(); ++i)
|
||||||
|
if (key[i] != row[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (istr.eof())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (istr.fail())
|
||||||
|
throw Exception("Cannot read data file " + pk->data_file_name
|
||||||
|
, ErrorCodes::CANT_READ_DATA_FILE);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
99
dbms/src/PrimaryKeyPlain.cpp
Normal file
99
dbms/src/PrimaryKeyPlain.cpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#include <Poco/File.h>
|
||||||
|
#include <Poco/FileStream.h>
|
||||||
|
#include <Poco/BinaryWriter.h>
|
||||||
|
|
||||||
|
#include <DB/PrimaryKeyPlain.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace DB
|
||||||
|
{
|
||||||
|
|
||||||
|
PrimaryKeyPlain::PrimaryKeyPlain(const std::string & path_, const std::string & name_)
|
||||||
|
: path(path_),
|
||||||
|
name(name_),
|
||||||
|
data_file_name(path + name + ".dat"),
|
||||||
|
offsets_file_name(path + name + ".idx"),
|
||||||
|
free_blocks_file_name(path + name + ".blk"),
|
||||||
|
data_file(data_file_name),
|
||||||
|
offsets_file(offsets_file_name),
|
||||||
|
free_blocks_file(free_blocks_file_name)
|
||||||
|
{
|
||||||
|
/// создаём файлы, если их ещё нет
|
||||||
|
data_file.createFile();
|
||||||
|
offsets_file.createFile();
|
||||||
|
free_blocks_file.createFile();
|
||||||
|
|
||||||
|
/// прочитаем список свободных блоков
|
||||||
|
Poco::FileInputStream free_blocks_istr(free_blocks_file_name);
|
||||||
|
Poco::BinaryReader free_blocks_reader(free_blocks_istr);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
Offset offset;
|
||||||
|
free_blocks_reader >> offset.offset >> offset.size;
|
||||||
|
|
||||||
|
if (free_blocks_istr.eof())
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (free_blocks_istr.fail())
|
||||||
|
throw Exception("Cannot read index file " + free_blocks_file_name
|
||||||
|
, ErrorCodes::CANT_READ_INDEX_FILE);
|
||||||
|
|
||||||
|
free_blocks.insert(offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PrimaryKeyPlain::addToTable(Table * table_, ColumnGroup * column_group_)
|
||||||
|
{
|
||||||
|
PrimaryKeyBase::addToTable(table_, column_group_);
|
||||||
|
|
||||||
|
/// прочитаем список смещений
|
||||||
|
Poco::FileInputStream offsets_istr(offsets_file_name);
|
||||||
|
Poco::BinaryReader offsets_reader(offsets_istr);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
Row key;
|
||||||
|
for (Table::ColumnNumbers::const_iterator it = table->primary_key_column_numbers->begin();
|
||||||
|
it != table->primary_key_column_numbers->end();
|
||||||
|
++it)
|
||||||
|
{
|
||||||
|
key.push_back(Field());
|
||||||
|
table->columns->at(*it).type->deserializeBinary(key.back(), offsets_istr);
|
||||||
|
}
|
||||||
|
Offset offset;
|
||||||
|
offsets_reader >> offset.offset >> offset.size;
|
||||||
|
|
||||||
|
if (offsets_istr.eof())
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (offsets_istr.fail())
|
||||||
|
throw Exception("Cannot read index file " + offsets_file_name
|
||||||
|
, ErrorCodes::CANT_READ_INDEX_FILE);
|
||||||
|
|
||||||
|
offsets[key] = offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PrimaryKeyPlain::merge(const AggregatedRowSet & data, const ColumnMask & mask)
|
||||||
|
{
|
||||||
|
/* std::set<Row> keys;
|
||||||
|
|
||||||
|
for (Result::const_iterator it = data.begin(); it != data.end(); ++it)
|
||||||
|
{
|
||||||
|
if (data->first.size() < columns.size())
|
||||||
|
throw Exception("Too few columns for key", ErrorCodes::TOO_FEW_COLUMNS_FOR_KEY);
|
||||||
|
|
||||||
|
Row key;
|
||||||
|
for (size_t j = 0; j < columns.size(); ++j)
|
||||||
|
key.push_back(it->first[j]);
|
||||||
|
|
||||||
|
keys.insert(key);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
85
dbms/src/tests/primary_key_none.cpp
Normal file
85
dbms/src/tests/primary_key_none.cpp
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <Poco/Stopwatch.h>
|
||||||
|
|
||||||
|
#include <DB/Table.h>
|
||||||
|
#include <DB/Column.h>
|
||||||
|
#include <DB/ColumnType.h>
|
||||||
|
#include <DB/PrimaryKeyNone.h>
|
||||||
|
#include <DB/RowSet.h>
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char ** argv)
|
||||||
|
{
|
||||||
|
Poco::Stopwatch stopwatch;
|
||||||
|
|
||||||
|
/// создаём таблицу
|
||||||
|
DB::Column column0;
|
||||||
|
column0.name = "ID";
|
||||||
|
column0.type = new DB::ColumnTypeVarUInt;
|
||||||
|
|
||||||
|
DB::Column column1;
|
||||||
|
column1.name = "PageViews";
|
||||||
|
column1.type = new DB::ColumnTypeVarUInt;
|
||||||
|
|
||||||
|
DB::Column column2;
|
||||||
|
column2.name = "URL";
|
||||||
|
column2.type = new DB::ColumnTypeText;
|
||||||
|
|
||||||
|
Poco::SharedPtr<DB::Table::Columns> columns = new DB::Table::Columns;
|
||||||
|
columns->push_back(column0);
|
||||||
|
columns->push_back(column1);
|
||||||
|
columns->push_back(column2);
|
||||||
|
|
||||||
|
Poco::SharedPtr<DB::Table::ColumnNumbers> primary_key_column_numbers = new DB::Table::ColumnNumbers;
|
||||||
|
primary_key_column_numbers->push_back(0);
|
||||||
|
|
||||||
|
DB::ColumnGroup column_group0;
|
||||||
|
column_group0.column_numbers.push_back(0);
|
||||||
|
column_group0.column_numbers.push_back(1);
|
||||||
|
column_group0.column_numbers.push_back(2);
|
||||||
|
column_group0.primary_key = new DB::PrimaryKeyNone("./", "TestPrimaryKeyNone");
|
||||||
|
|
||||||
|
Poco::SharedPtr<DB::Table::ColumnGroups> column_groups = new DB::Table::ColumnGroups;
|
||||||
|
column_groups->push_back(column_group0);
|
||||||
|
|
||||||
|
DB::Table table("TestTable", columns, primary_key_column_numbers, column_groups);
|
||||||
|
|
||||||
|
/// создаём набор данных
|
||||||
|
DB::AggregatedRowSet data;
|
||||||
|
{
|
||||||
|
DB::Row key;
|
||||||
|
key.push_back(DB::Field(DB::UInt(0)));
|
||||||
|
key.push_back(DB::Field(DB::UInt(0)));
|
||||||
|
key.push_back(DB::Field(DB::String("")));
|
||||||
|
|
||||||
|
DB::Row value;
|
||||||
|
|
||||||
|
stopwatch.restart();
|
||||||
|
|
||||||
|
for (int i = 0; i < 1000000; ++i)
|
||||||
|
{
|
||||||
|
key[0] = DB::UInt(i);
|
||||||
|
key[1] = DB::UInt(i * 123456789 % 1000000);
|
||||||
|
key[2] = "http://www.google.com/custom?cof=LW%3A277%3BL%3Ahttp%3A%2F%2Fwww.boost.org%2Fboost.png%3BLH%3A86%3BAH%3Acenter%3BGL%3A0%3BS%3Ahttp%3A%2F%2Fwww.boost.org%3BAWFID%3A9b83d16ce652ed5a%3B&sa=Google+Search&domains=www.boost.org%3Blists.boost.org&hq=site%3Awww.boost.org+OR+site%3Alists.boost.org&q=boost%3A%3Ablank";
|
||||||
|
|
||||||
|
data[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
stopwatch.stop();
|
||||||
|
std::cout << "Filling data: " << static_cast<double>(stopwatch.elapsed()) / 1000000 << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// заполняем таблицу
|
||||||
|
{
|
||||||
|
DB::ColumnMask mask(3, true);
|
||||||
|
|
||||||
|
stopwatch.restart();
|
||||||
|
|
||||||
|
column_group0.primary_key->merge(data, mask);
|
||||||
|
|
||||||
|
stopwatch.stop();
|
||||||
|
std::cout << "Saving data: " << static_cast<double>(stopwatch.elapsed()) / 1000000 << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
17
dbms/src/tests/variant.cpp
Normal file
17
dbms/src/tests/variant.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <boost/variant.hpp>
|
||||||
|
#include <DB/Field.h>
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char ** argv)
|
||||||
|
{
|
||||||
|
DB::Field f1(DB::UInt(10));
|
||||||
|
DB::Field f2(DB::String("test"));
|
||||||
|
|
||||||
|
std::cout << (f1 < f1) << std::endl;
|
||||||
|
std::cout << (f1 < f2) << std::endl;
|
||||||
|
std::cout << (f1 == f1) << std::endl;
|
||||||
|
std::cout << (f1 == f2) << std::endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -66,6 +66,10 @@ public:
|
|||||||
ostr << '}' << "," << std::endl;
|
ostr << '}' << "," << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void operator() (const DB::AggregateFunctionPtr & x) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::ostream & ostr;
|
std::ostream & ostr;
|
||||||
unsigned indent;
|
unsigned indent;
|
||||||
@ -75,14 +79,23 @@ private:
|
|||||||
class TimesTwoVisitor : public boost::static_visitor<>
|
class TimesTwoVisitor : public boost::static_visitor<>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template <typename T> void operator() (T & x) const { x *= 2; }
|
void operator() (DB::Int & x) const { x *= 2; }
|
||||||
|
void operator() (DB::UInt & x) const { x *= 2; }
|
||||||
|
|
||||||
void operator() (DB::Null & x) const {}
|
void operator() (const DB::String & x) const
|
||||||
void operator() (DB::String & x) const { x = ""; }
|
{
|
||||||
void operator() (DB::FieldVector & x) const
|
}
|
||||||
|
|
||||||
|
void operator() (const DB::Null & x) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (const DB::FieldVector & x) const
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator() (const DB::AggregateFunctionPtr & x) const
|
||||||
{
|
{
|
||||||
TimesTwoVisitor visitor;
|
|
||||||
std::for_each(x.begin(), x.end(), boost::apply_visitor(visitor));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user