This commit is contained in:
Evgeniy Gatov 2014-11-13 18:17:51 +03:00
commit 52fc1d3560
135 changed files with 3602 additions and 1448 deletions

View File

@ -20,6 +20,8 @@ namespace DB
* Позволяет вставлять, удалять столбцы в любом порядке, менять порядок столбцов.
*/
class Context;
class Block
{
public:
@ -54,6 +56,7 @@ public:
void insert(size_t position, const ColumnWithNameAndType & elem);
/// вставить столбец в конец
void insert(const ColumnWithNameAndType & elem);
void insertDefault(const String & name, const DataTypePtr & type);
/// вставить столбец в конец, если столбца с таким именем ещё нет
void insertUnique(const ColumnWithNameAndType & elem);
/// удалить столбец в заданной позиции
@ -61,7 +64,7 @@ public:
/// удалить столбец с заданным именем
void erase(const String & name);
/// Добавляет в блок недостающие столбцы со значениями по-умолчанию
void addDefaults(NamesAndTypesListPtr required_columns);
void addDefaults(const NamesAndTypesList & required_columns);
ColumnWithNameAndType & getByPosition(size_t position);
const ColumnWithNameAndType & getByPosition(size_t position) const;

View File

@ -3,8 +3,10 @@
#include <Poco/SharedPtr.h>
#include <DB/DataStreams/IProfilingBlockInputStream.h>
#include <DB/Interpreters/evaluateMissingDefaults.h>
#include <DB/Columns/ColumnConst.h>
#include <DB/Storages/ColumnDefault.h>
namespace DB
@ -19,12 +21,20 @@ class AddingDefaultBlockInputStream : public IProfilingBlockInputStream
public:
AddingDefaultBlockInputStream(
BlockInputStreamPtr input_,
NamesAndTypesListPtr required_columns_)
: required_columns(required_columns_)
NamesAndTypesListPtr required_columns_,
const ColumnDefaults & column_defaults_,
const Context & context_)
: required_columns(required_columns_),
column_defaults(column_defaults_), context(context_)
{
children.push_back(input_);
}
AddingDefaultBlockInputStream(BlockInputStreamPtr input_, NamesAndTypesListPtr required_columns_, const Context & context_)
: AddingDefaultBlockInputStream{input_, required_columns, {}, context}
{
}
String getName() const override { return "AddingDefaultBlockInputStream"; }
String getID() const override
@ -45,12 +55,15 @@ protected:
Block res = children.back()->read();
if (!res)
return res;
res.addDefaults(required_columns);
evaluateMissingDefaults(res, *required_columns, column_defaults, context);
res.addDefaults(*required_columns);
return res;
}
private:
NamesAndTypesListPtr required_columns;
const ColumnDefaults & column_defaults;
Context context;
};
}

View File

@ -5,6 +5,9 @@
#include <DB/DataStreams/IBlockOutputStream.h>
#include <DB/Columns/ColumnConst.h>
#include <DB/Storages/ColumnDefault.h>
#include <DB/Interpreters/Context.h>
#include <DB/Interpreters/evaluateMissingDefaults.h>
namespace DB
@ -19,15 +22,25 @@ class AddingDefaultBlockOutputStream : public IBlockOutputStream
public:
AddingDefaultBlockOutputStream(
BlockOutputStreamPtr output_,
NamesAndTypesListPtr required_columns_)
: output(output_), required_columns(required_columns_)
NamesAndTypesListPtr required_columns_,
const ColumnDefaults & column_defaults_,
const Context & context_)
: output(output_), required_columns(required_columns_),
column_defaults(column_defaults_), context(context_)
{
}
AddingDefaultBlockOutputStream(BlockOutputStreamPtr output_, NamesAndTypesListPtr required_columns_, const Context & context_)
: AddingDefaultBlockOutputStream{output_, required_columns_, {}, context_}
{
}
void write(const Block & block) override
{
Block res = block;
res.addDefaults(required_columns);
evaluateMissingDefaults(res, *required_columns, column_defaults, context);
res.addDefaults(*required_columns);
output->write(res);
}
@ -39,6 +52,8 @@ public:
private:
BlockOutputStreamPtr output;
NamesAndTypesListPtr required_columns;
const ColumnDefaults & column_defaults;
Context context;
};

View File

@ -0,0 +1,37 @@
#pragma once
#include <DB/Columns/ColumnConst.h>
#include <DB/DataStreams/IBlockOutputStream.h>
#include <statdaemons/ext/range.hpp>
namespace DB
{
/** Преобразует столбцы-константы в полноценные столбцы ("материализует" их).
*/
class MaterializingBlockOutputStream : public IBlockOutputStream
{
public:
MaterializingBlockOutputStream(const BlockOutputStreamPtr & output) : output{output}
{}
void write(const Block & original_block) override
{
/// copy block to get rid of const
auto block = original_block;
for (const auto i : ext::range(0, block.columns()))
{
ColumnPtr & col = block.getByPosition(i).column;
if (col->isConst())
col = dynamic_cast<IColumnConst &>(*col).convertToFullColumn();
}
output->write(block);
}
BlockOutputStreamPtr output;
};
}

View File

@ -0,0 +1,39 @@
#pragma once
#include <DB/DataStreams/IBlockOutputStream.h>
namespace DB
{
/// Throws exception on encountering prohibited column in block
class ProhibitColumnsBlockOutputStream : public IBlockOutputStream
{
public:
ProhibitColumnsBlockOutputStream(const BlockOutputStreamPtr & output, const NamesAndTypesList & columns)
: output{output}, columns{columns}
{
}
private:
void write(const Block & block) override
{
for (const auto & column : columns)
if (block.has(column.name))
throw Exception{"Cannot insert column " + column.name, ErrorCodes::ILLEGAL_COLUMN};
output->write(block);
}
void flush() override { output->flush(); }
void writePrefix() override { output->writePrefix(); }
void writeSuffix() override { output->writeSuffix(); }
BlockOutputStreamPtr output;
NamesAndTypesList columns;
};
}

View File

@ -25,9 +25,10 @@ public:
FunctionPtr get(const String & name, const Context & context) const;
void registerFunction(const String & name, Creator creator)
template <typename F> void registerFunction()
{
functions[name] = creator;
static_assert(std::is_same<decltype(&F::create), Creator>::value, "F::create has incorrect type");
functions[F::name] = &F::create;
}
};

View File

@ -367,6 +367,10 @@ struct BinaryOperationTraits
template <template <typename, typename> class Op, typename Name>
class FunctionBinaryArithmetic : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionBinaryArithmetic; }
private:
/// Overload for InvalidType
template <typename ResultDataType,
@ -585,7 +589,7 @@ public:
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -641,6 +645,10 @@ public:
template <template <typename> class Op, typename Name>
class FunctionUnaryArithmetic : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionUnaryArithmetic; }
private:
template <typename T0>
bool checkType(const DataTypes & arguments, DataTypePtr & result) const
@ -690,7 +698,7 @@ public:
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -739,19 +747,19 @@ public:
};
struct NamePlus { static const char * get() { return "plus"; } };
struct NameMinus { static const char * get() { return "minus"; } };
struct NameMultiply { static const char * get() { return "multiply"; } };
struct NameDivideFloating { static const char * get() { return "divide"; } };
struct NameDivideIntegral { static const char * get() { return "intDiv"; } };
struct NameModulo { static const char * get() { return "modulo"; } };
struct NameNegate { static const char * get() { return "negate"; } };
struct NameBitAnd { static const char * get() { return "bitAnd"; } };
struct NameBitOr { static const char * get() { return "bitOr"; } };
struct NameBitXor { static const char * get() { return "bitXor"; } };
struct NameBitNot { static const char * get() { return "bitNot"; } };
struct NameBitShiftLeft { static const char * get() { return "bitShiftLeft"; } };
struct NameBitShiftRight { static const char * get() { return "bitShiftRight"; } };
struct NamePlus { static constexpr auto name = "plus"; };
struct NameMinus { static constexpr auto name = "minus"; };
struct NameMultiply { static constexpr auto name = "multiply"; };
struct NameDivideFloating { static constexpr auto name = "divide"; };
struct NameDivideIntegral { static constexpr auto name = "intDiv"; };
struct NameModulo { static constexpr auto name = "modulo"; };
struct NameNegate { static constexpr auto name = "negate"; };
struct NameBitAnd { static constexpr auto name = "bitAnd"; };
struct NameBitOr { static constexpr auto name = "bitOr"; };
struct NameBitXor { static constexpr auto name = "bitXor"; };
struct NameBitNot { static constexpr auto name = "bitNot"; };
struct NameBitShiftLeft { static constexpr auto name = "bitShiftLeft"; };
struct NameBitShiftRight { static constexpr auto name = "bitShiftRight"; };
typedef FunctionBinaryArithmetic<PlusImpl, NamePlus> FunctionPlus;
typedef FunctionBinaryArithmetic<MinusImpl, NameMinus> FunctionMinus;

View File

@ -41,11 +41,15 @@ namespace DB
class FunctionArray : public IFunction
{
public:
static constexpr auto name = "array";
static IFunction * create(const Context & context) { return new FunctionArray; }
private:
/// Получить имя функции.
String getName() const
{
return "array";
return name;
}
template <typename T0, typename T1>
@ -384,6 +388,10 @@ struct ArrayElementStringImpl
class FunctionArrayElement : public IFunction
{
public:
static constexpr auto name = "arrayElement";
static IFunction * create(const Context & context) { return new FunctionArrayElement; }
private:
template <typename T>
bool executeNumberConst(Block & block, const ColumnNumbers & arguments, size_t result, const Field & index)
@ -592,7 +600,7 @@ public:
/// Получить имя функции.
String getName() const
{
return "arrayElement";
return name;
}
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -755,6 +763,10 @@ struct ArrayIndexStringImpl
template <typename IndexConv, typename Name>
class FunctionArrayIndex : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionArrayIndex; }
private:
typedef ColumnVector<typename IndexConv::ResultType> ResultColumnType;
@ -842,7 +854,7 @@ public:
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -893,10 +905,13 @@ public:
class FunctionArrayEnumerate : public IFunction
{
public:
static constexpr auto name = "arrayEnumerate";
static IFunction * create (const Context & context) { return new FunctionArrayEnumerate; }
/// Получить имя функции.
String getName() const
{
return "arrayEnumerate";
return name;
}
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -963,10 +978,13 @@ public:
class FunctionArrayEnumerateUniq : public IFunction
{
public:
static constexpr auto name = "arrayEnumerateUniq";
static IFunction * create(const Context & context) { return new FunctionArrayEnumerateUniq; }
/// Получить имя функции.
String getName() const
{
return "arrayEnumerateUniq";
return name;
}
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -1202,11 +1220,15 @@ template <> struct DataTypeToName<DataTypeDate> { static std::string get() { ret
template <> struct DataTypeToName<DataTypeDateTime> { static std::string get() { return "DateTime"; } };
template <typename DataType>
struct EmptyArray : public IFunction
struct FunctionEmptyArray : public IFunction
{
static constexpr auto base_name = "emptyArray";
static const String name;
static IFunction * create(const Context & context) { return new FunctionEmptyArray; }
String getName() const
{
return "emptyArray" + DataTypeToName<DataType>::get();
return name;
}
DataTypePtr getReturnType(const DataTypes & arguments) const
@ -1230,28 +1252,31 @@ struct EmptyArray : public IFunction
}
};
template <typename DataType>
const String FunctionEmptyArray<DataType>::name = FunctionEmptyArray::base_name + DataTypeToName<DataType>::get();
struct NameHas { static const char * get() { return "has"; } };
struct NameIndexOf { static const char * get() { return "indexOf"; } };
struct NameCountEqual { static const char * get() { return "countEqual"; } };
struct NameHas { static constexpr auto name = "has"; };
struct NameIndexOf { static constexpr auto name = "indexOf"; };
struct NameCountEqual { static constexpr auto name = "countEqual"; };
typedef FunctionArrayIndex<IndexToOne, NameHas> FunctionHas;
typedef FunctionArrayIndex<IndexIdentity, NameIndexOf> FunctionIndexOf;
typedef FunctionArrayIndex<IndexCount, NameCountEqual> FunctionCountEqual;
using FunctionEmptyArrayUInt8 = EmptyArray<DataTypeUInt8>;
using FunctionEmptyArrayUInt16 = EmptyArray<DataTypeUInt16>;
using FunctionEmptyArrayUInt32 = EmptyArray<DataTypeUInt32>;
using FunctionEmptyArrayUInt64 = EmptyArray<DataTypeUInt64>;
using FunctionEmptyArrayInt8 = EmptyArray<DataTypeInt8>;
using FunctionEmptyArrayInt16 = EmptyArray<DataTypeInt16>;
using FunctionEmptyArrayInt32 = EmptyArray<DataTypeInt32>;
using FunctionEmptyArrayInt64 = EmptyArray<DataTypeInt64>;
using FunctionEmptyArrayFloat32 = EmptyArray<DataTypeFloat32>;
using FunctionEmptyArrayFloat64 = EmptyArray<DataTypeFloat64>;
using FunctionEmptyArrayDate = EmptyArray<DataTypeDate>;
using FunctionEmptyArrayDateTime = EmptyArray<DataTypeDateTime>;
using FunctionEmptyArrayString = EmptyArray<DataTypeString>;
using FunctionEmptyArrayUInt8 = FunctionEmptyArray<DataTypeUInt8>;
using FunctionEmptyArrayUInt16 = FunctionEmptyArray<DataTypeUInt16>;
using FunctionEmptyArrayUInt32 = FunctionEmptyArray<DataTypeUInt32>;
using FunctionEmptyArrayUInt64 = FunctionEmptyArray<DataTypeUInt64>;
using FunctionEmptyArrayInt8 = FunctionEmptyArray<DataTypeInt8>;
using FunctionEmptyArrayInt16 = FunctionEmptyArray<DataTypeInt16>;
using FunctionEmptyArrayInt32 = FunctionEmptyArray<DataTypeInt32>;
using FunctionEmptyArrayInt64 = FunctionEmptyArray<DataTypeInt64>;
using FunctionEmptyArrayFloat32 = FunctionEmptyArray<DataTypeFloat32>;
using FunctionEmptyArrayFloat64 = FunctionEmptyArray<DataTypeFloat64>;
using FunctionEmptyArrayDate = FunctionEmptyArray<DataTypeDate>;
using FunctionEmptyArrayDateTime = FunctionEmptyArray<DataTypeDateTime>;
using FunctionEmptyArrayString = FunctionEmptyArray<DataTypeString>;
}

View File

@ -45,7 +45,10 @@ const auto ipv6_bytes_length = 16;
class FunctionIPv6NumToString : public IFunction
{
public:
String getName() const { return "IPv6NumToString"; }
static constexpr auto name = "IPv6NumToString";
static IFunction * create(const Context & context) { return new FunctionIPv6NumToString; }
String getName() const { return name; }
DataTypePtr getReturnType(const DataTypes & arguments) const
{
@ -247,7 +250,10 @@ public:
class FunctionIPv6StringToNum : public IFunction
{
public:
String getName() const { return "IPv6StringToNum"; }
static constexpr auto name = "IPv6StringToNum";
static IFunction * create(const Context & context) { return new FunctionIPv6StringToNum; }
String getName() const { return name; }
DataTypePtr getReturnType(const DataTypes & arguments) const
{
@ -462,10 +468,13 @@ public:
class FunctionIPv4NumToString : public IFunction
{
public:
static constexpr auto name = "IPv4NumToString";
static IFunction * create(const Context & context) { return new FunctionIPv4NumToString; }
/// Получить имя функции.
String getName() const
{
return "IPv4NumToString";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -564,10 +573,13 @@ public:
class FunctionIPv4StringToNum : public IFunction
{
public:
static constexpr auto name = "IPv4StringToNum";
static IFunction * create(const Context & context) { return new FunctionIPv4StringToNum; }
/// Получить имя функции.
String getName() const
{
return "IPv4StringToNum";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -652,10 +664,13 @@ public:
class FunctionHex : public IFunction
{
public:
static constexpr auto name = "hex";
static IFunction * create(const Context & context) { return new FunctionHex; }
/// Получить имя функции.
String getName() const
{
return "hex";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -897,10 +912,13 @@ public:
class FunctionUnhex : public IFunction
{
public:
static constexpr auto name = "unhex";
static IFunction * create(const Context & context) { return new FunctionUnhex; }
/// Получить имя функции.
String getName() const
{
return "unhex";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -1002,10 +1020,13 @@ public:
class FunctionBitmaskToArray : public IFunction
{
public:
static constexpr auto name = "bitmaskToArray";
static IFunction * create(const Context & context) { return new FunctionBitmaskToArray; }
/// Получить имя функции.
String getName() const
{
return "bitmaskToArray";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -1111,10 +1132,13 @@ public:
class FunctionToStringCutToZero : public IFunction
{
public:
static constexpr auto name = "toStringCutToZero";
static IFunction * create(const Context & context) { return new FunctionToStringCutToZero; }
/// Получить имя функции.
String getName() const
{
return "toStringCutToZero";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.

View File

@ -385,8 +385,11 @@ template <
typename Name>
class FunctionComparison : public IFunction
{
private:
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionComparison; };
private:
template <typename T0, typename T1>
bool executeNumRightType(Block & block, const ColumnNumbers & arguments, size_t result, const ColumnVector<T0> * col_left)
{
@ -567,7 +570,7 @@ public:
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -615,12 +618,12 @@ public:
};
struct NameEquals { static const char * get() { return "equals"; } };
struct NameNotEquals { static const char * get() { return "notEquals"; } };
struct NameLess { static const char * get() { return "less"; } };
struct NameGreater { static const char * get() { return "greater"; } };
struct NameLessOrEquals { static const char * get() { return "lessOrEquals"; } };
struct NameGreaterOrEquals { static const char * get() { return "greaterOrEquals"; } };
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<NotEqualsOp, NameNotEquals> FunctionNotEquals;

View File

@ -296,6 +296,10 @@ struct DataTypeFromFieldTypeOrError<NumberTraits::Error>
class FunctionIf : public IFunction
{
public:
static constexpr auto name = "if";
static IFunction * create(const Context & context) { return new FunctionIf; }
private:
template <typename T0, typename T1>
bool checkRightType(const DataTypes & arguments, DataTypePtr & type_res) const
@ -473,7 +477,7 @@ public:
/// Получить имя функции.
String getName() const
{
return "if";
return name;
}
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.

View File

@ -51,7 +51,7 @@ struct ConvertImpl
}
else
throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName()
+ " of first argument of function " + Name::get(),
+ " of first argument of function " + Name::name,
ErrorCodes::ILLEGAL_COLUMN);
}
};
@ -91,7 +91,7 @@ struct ConvertImpl<DataTypeDate, DataTypeDateTime, Name>
}
else
throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName()
+ " of first argument of function " + Name::get(),
+ " of first argument of function " + Name::name,
ErrorCodes::ILLEGAL_COLUMN);
}
};
@ -128,7 +128,7 @@ struct ConvertImpl<DataTypeDateTime, DataTypeDate, Name>
}
else
throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName()
+ " of first argument of function " + Name::get(),
+ " of first argument of function " + Name::name,
ErrorCodes::ILLEGAL_COLUMN);
}
};
@ -178,7 +178,7 @@ struct ConvertImpl<FromDataType, DataTypeString, Name>
}
else
throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName()
+ " of first argument of function " + Name::get(),
+ " of first argument of function " + Name::name,
ErrorCodes::ILLEGAL_COLUMN);
}
};
@ -240,7 +240,7 @@ struct ConvertImpl<DataTypeString, ToDataType, Name>
}
else
throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName()
+ " of first argument of function " + Name::get(),
+ " of first argument of function " + Name::name,
ErrorCodes::ILLEGAL_COLUMN);
}
};
@ -300,7 +300,7 @@ struct ConvertImpl<DataTypeFixedString, ToDataType, Name>
}
else
throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName()
+ " of first argument of function " + Name::get(),
+ " of first argument of function " + Name::name,
ErrorCodes::ILLEGAL_COLUMN);
}
};
@ -356,7 +356,7 @@ struct ConvertImpl<DataTypeFixedString, DataTypeString, Name>
}
else
throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName()
+ " of first argument of function " + Name::get(),
+ " of first argument of function " + Name::name,
ErrorCodes::ILLEGAL_COLUMN);
}
};
@ -366,10 +366,13 @@ template <typename ToDataType, typename Name>
class FunctionConvert : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionConvert; }
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -414,10 +417,13 @@ public:
class FunctionToFixedString : public IFunction
{
public:
static constexpr auto name = "toFixedString";
static IFunction * create(const Context & context) { return new FunctionToFixedString; };
/// Получить имя функции.
String getName() const
{
return "toFixedString";
return name;
}
/** Получить тип результата по типам аргументов и значениям константных аргументов.
@ -515,19 +521,19 @@ private:
};
struct NameToUInt8 { static const char * get() { return "toUInt8"; } };
struct NameToUInt16 { static const char * get() { return "toUInt16"; } };
struct NameToUInt32 { static const char * get() { return "toUInt32"; } };
struct NameToUInt64 { static const char * get() { return "toUInt64"; } };
struct NameToInt8 { static const char * get() { return "toInt8"; } };
struct NameToInt16 { static const char * get() { return "toInt16"; } };
struct NameToInt32 { static const char * get() { return "toInt32"; } };
struct NameToInt64 { static const char * get() { return "toInt64"; } };
struct NameToFloat32 { static const char * get() { return "toFloat32"; } };
struct NameToFloat64 { static const char * get() { return "toFloat64"; } };
struct NameToDate { static const char * get() { return "toDate"; } };
struct NameToDateTime { static const char * get() { return "toDateTime"; } };
struct NameToString { static const char * get() { return "toString"; } };
struct NameToUInt8 { static constexpr auto name = "toUInt8"; };
struct NameToUInt16 { static constexpr auto name = "toUInt16"; };
struct NameToUInt32 { static constexpr auto name = "toUInt32"; };
struct NameToUInt64 { static constexpr auto name = "toUInt64"; };
struct NameToInt8 { static constexpr auto name = "toInt8"; };
struct NameToInt16 { static constexpr auto name = "toInt16"; };
struct NameToInt32 { static constexpr auto name = "toInt32"; };
struct NameToInt64 { static constexpr auto name = "toInt64"; };
struct NameToFloat32 { static constexpr auto name = "toFloat32"; };
struct NameToFloat64 { static constexpr auto name = "toFloat64"; };
struct NameToDate { static constexpr auto name = "toDate"; };
struct NameToDateTime { static constexpr auto name = "toDateTime"; };
struct NameToString { static constexpr auto name = "toString"; };
typedef FunctionConvert<DataTypeUInt8, NameToUInt8> FunctionToUInt8;
typedef FunctionConvert<DataTypeUInt16, NameToUInt16> FunctionToUInt16;

View File

@ -229,7 +229,7 @@ struct DateTimeTransformImpl
}
else
throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName()
+ " of first argument of function " + Name::get(),
+ " of first argument of function " + Name::name,
ErrorCodes::ILLEGAL_COLUMN);
}
};
@ -239,10 +239,13 @@ template <typename ToDataType, typename Transform, typename Name>
class FunctionDateOrDateTimeToSomething : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionDateOrDateTimeToSomething; };
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -276,10 +279,13 @@ public:
class FunctionNow : public IFunction
{
public:
static constexpr auto name = "now";
static IFunction * create(const Context & context) { return new FunctionNow; };
/// Получить имя функции.
String getName() const
{
return "now";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -306,10 +312,13 @@ public:
class FunctionToday : public IFunction
{
public:
static constexpr auto name = "today";
static IFunction * create(const Context & context) { return new FunctionToday; };
/// Получить имя функции.
String getName() const
{
return "today";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -336,10 +345,13 @@ public:
class FunctionYesterday : public IFunction
{
public:
static constexpr auto name = "yesterday";
static IFunction * create(const Context & context) { return new FunctionYesterday; };
/// Получить имя функции.
String getName() const
{
return "yesterday";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -366,10 +378,13 @@ public:
class FunctionTimeSlot : public IFunction
{
public:
static constexpr auto name = "timeSlot";
static IFunction * create(const Context & context) { return new FunctionTimeSlot; };
/// Получить имя функции.
String getName() const
{
return "timeSlot";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -498,10 +513,13 @@ struct TimeSlotsImpl
class FunctionTimeSlots : public IFunction
{
public:
static constexpr auto name = "timeSlots";
static IFunction * create(const Context & context) { return new FunctionTimeSlots; };
/// Получить имя функции.
String getName() const
{
return "timeSlots";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -565,27 +583,27 @@ public:
};
struct NameToYear { static const char * get() { return "toYear"; } };
struct NameToMonth { static const char * get() { return "toMonth"; } };
struct NameToDayOfMonth { static const char * get() { return "toDayOfMonth"; } };
struct NameToDayOfWeek { static const char * get() { return "toDayOfWeek"; } };
struct NameToHour { static const char * get() { return "toHour"; } };
struct NameToMinute { static const char * get() { return "toMinute"; } };
struct NameToSecond { static const char * get() { return "toSecond"; } };
struct NameToMonday { static const char * get() { return "toMonday"; } };
struct NameToStartOfMonth { static const char * get() { return "toStartOfMonth"; } };
struct NameToStartOfQuarter { static const char * get() { return "toStartOfQuarter"; } };
struct NameToStartOfYear { static const char * get() { return "toStartOfYear"; } };
struct NameToStartOfMinute { static const char * get() { return "toStartOfMinute"; } };
struct NameToStartOfHour { static const char * get() { return "toStartOfHour"; } };
struct NameToTime { static const char * get() { return "toTime"; } };
struct NameToRelativeYearNum { static const char * get() { return "toRelativeYearNum"; } };
struct NameToRelativeMonthNum { static const char * get() { return "toRelativeMonthNum"; } };
struct NameToRelativeWeekNum { static const char * get() { return "toRelativeWeekNum"; } };
struct NameToRelativeDayNum { static const char * get() { return "toRelativeDayNum"; } };
struct NameToRelativeHourNum { static const char * get() { return "toRelativeHourNum"; } };
struct NameToRelativeMinuteNum { static const char * get() { return "toRelativeMinuteNum"; } };
struct NameToRelativeSecondNum { static const char * get() { return "toRelativeSecondNum"; } };
struct NameToYear { static constexpr auto name = "toYear"; };
struct NameToMonth { static constexpr auto name = "toMonth"; };
struct NameToDayOfMonth { static constexpr auto name = "toDayOfMonth"; };
struct NameToDayOfWeek { static constexpr auto name = "toDayOfWeek"; };
struct NameToHour { static constexpr auto name = "toHour"; };
struct NameToMinute { static constexpr auto name = "toMinute"; };
struct NameToSecond { static constexpr auto name = "toSecond"; };
struct NameToMonday { static constexpr auto name = "toMonday"; };
struct NameToStartOfMonth { static constexpr auto name = "toStartOfMonth"; };
struct NameToStartOfQuarter { static constexpr auto name = "toStartOfQuarter"; };
struct NameToStartOfYear { static constexpr auto name = "toStartOfYear"; };
struct NameToStartOfMinute { static constexpr auto name = "toStartOfMinute"; };
struct NameToStartOfHour { static constexpr auto name = "toStartOfHour"; };
struct NameToTime { static constexpr auto name = "toTime"; };
struct NameToRelativeYearNum { static constexpr auto name = "toRelativeYearNum"; };
struct NameToRelativeMonthNum { static constexpr auto name = "toRelativeMonthNum"; };
struct NameToRelativeWeekNum { static constexpr auto name = "toRelativeWeekNum"; };
struct NameToRelativeDayNum { static constexpr auto name = "toRelativeDayNum"; };
struct NameToRelativeHourNum { static constexpr auto name = "toRelativeHourNum"; };
struct NameToRelativeMinuteNum { static constexpr auto name = "toRelativeMinuteNum"; };
struct NameToRelativeSecondNum { static constexpr auto name = "toRelativeSecondNum"; };
typedef FunctionDateOrDateTimeToSomething<DataTypeUInt16, ToYearImpl, NameToYear> FunctionToYear;

View File

@ -161,6 +161,10 @@ struct IdentityDictionaryGetter
template <typename T, typename Transform, typename DictGetter, typename Name>
class FunctionTransformWithDictionary : public IFunction
{
public:
static constexpr auto name = Name::name;
using base_type = FunctionTransformWithDictionary;
private:
const SharedPtr<typename DictGetter::Src> owned_dict;
@ -175,7 +179,7 @@ public:
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -211,7 +215,7 @@ public:
if (!key_col)
throw Exception("Illegal column " + block.getByPosition(arguments[1]).column->getName()
+ " of second ('point of view') argument of function " + Name::get()
+ " of second ('point of view') argument of function " + name
+ ". Must be constant string.",
ErrorCodes::ILLEGAL_COLUMN);
@ -239,7 +243,7 @@ public:
}
else
throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName()
+ " of first argument of function " + Name::get(),
+ " of first argument of function " + name,
ErrorCodes::ILLEGAL_COLUMN);
}
};
@ -249,6 +253,10 @@ public:
template <typename T, typename Transform, typename DictGetter, typename Name>
class FunctionIsInWithDictionary : public IFunction
{
public:
static constexpr auto name = Name::name;
using base_type = FunctionIsInWithDictionary;
private:
const SharedPtr<typename DictGetter::Src> owned_dict;
@ -263,7 +271,7 @@ public:
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -304,7 +312,7 @@ public:
if (!key_col)
throw Exception("Illegal column " + block.getByPosition(arguments[2]).column->getName()
+ " of third ('point of view') argument of function " + Name::get()
+ " of third ('point of view') argument of function " + name
+ ". Must be constant string.",
ErrorCodes::ILLEGAL_COLUMN);
@ -368,7 +376,7 @@ public:
else
throw Exception("Illegal columns " + block.getByPosition(arguments[0]).column->getName()
+ " and " + block.getByPosition(arguments[1]).column->getName()
+ " of arguments of function " + Name::get(),
+ " of arguments of function " + name,
ErrorCodes::ILLEGAL_COLUMN);
}
};
@ -378,6 +386,10 @@ public:
template <typename T, typename Transform, typename DictGetter, typename Name>
class FunctionHierarchyWithDictionary : public IFunction
{
public:
static constexpr auto name = Name::name;
using base_type = FunctionHierarchyWithDictionary;
private:
const SharedPtr<typename DictGetter::Src> owned_dict;
@ -392,7 +404,7 @@ public:
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -428,7 +440,7 @@ public:
if (!key_col)
throw Exception("Illegal column " + block.getByPosition(arguments[1]).column->getName()
+ " of second ('point of view') argument of function " + Name::get()
+ " of second ('point of view') argument of function " + name
+ ". Must be constant string.",
ErrorCodes::ILLEGAL_COLUMN);
@ -477,88 +489,197 @@ public:
}
else
throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName()
+ " of first argument of function " + Name::get(),
+ " of first argument of function " + name,
ErrorCodes::ILLEGAL_COLUMN);
}
};
struct NameRegionToCity { static const char * get() { return "regionToCity"; } };
struct NameRegionToArea { static const char * get() { return "regionToArea"; } };
struct NameRegionToDistrict { static const char * get() { return "regionToDistrict"; } };
struct NameRegionToCountry { static const char * get() { return "regionToCountry"; } };
struct NameRegionToContinent{ static const char * get() { return "regionToContient"; } };
struct NameOSToRoot { static const char * get() { return "OSToRoot"; } };
struct NameSEToRoot { static const char * get() { return "SEToRoot"; } };
struct NameCategoryToRoot { static const char * get() { return "categoryToRoot"; } };
struct NameCategoryToSecondLevel { static const char * get() { return "categoryToSecondLevel"; } };
struct NameRegionToCity { static constexpr auto name = "regionToCity"; };
struct NameRegionToArea { static constexpr auto name = "regionToArea"; };
struct NameRegionToDistrict { static constexpr auto name = "regionToDistrict"; };
struct NameRegionToCountry { static constexpr auto name = "regionToCountry"; };
struct NameRegionToContinent { static constexpr auto name = "regionToContient"; };
struct NameOSToRoot { static constexpr auto name = "OSToRoot"; };
struct NameSEToRoot { static constexpr auto name = "SEToRoot"; };
struct NameCategoryToRoot { static constexpr auto name = "categoryToRoot"; };
struct NameCategoryToSecondLevel { static constexpr auto name = "categoryToSecondLevel"; };
struct NameRegionIn { static const char * get() { return "regionIn"; } };
struct NameOSIn { static const char * get() { return "OSIn"; } };
struct NameSEIn { static const char * get() { return "SEIn"; } };
struct NameCategoryIn { static const char * get() { return "categoryIn"; } };
struct NameRegionIn { static constexpr auto name = "regionIn"; };
struct NameOSIn { static constexpr auto name = "OSIn"; };
struct NameSEIn { static constexpr auto name = "SEIn"; };
struct NameCategoryIn { static constexpr auto name = "categoryIn"; };
struct NameRegionHierarchy { static const char * get() { return "regionHierarchy"; } };
struct NameOSHierarchy { static const char * get() { return "OSHierarchy"; } };
struct NameSEHierarchy { static const char * get() { return "SEHierarchy"; } };
struct NameCategoryHierarchy{ static const char * get() { return "categoryHierarchy"; } };
struct NameRegionHierarchy { static constexpr auto name = "regionHierarchy"; };
struct NameOSHierarchy { static constexpr auto name = "OSHierarchy"; };
struct NameSEHierarchy { static constexpr auto name = "SEHierarchy"; };
struct NameCategoryHierarchy { static constexpr auto name = "categoryHierarchy"; };
typedef FunctionTransformWithDictionary
<UInt32, RegionToCityImpl, RegionsHierarchyGetter, NameRegionToCity> FunctionRegionToCity;
struct FunctionRegionToCity :
public FunctionTransformWithDictionary<UInt32, RegionToCityImpl, RegionsHierarchyGetter, NameRegionToCity>
{
static IFunction * create(const Context & context)
{
return new base_type{context.getDictionaries().getRegionsHierarchies()};
}
};
typedef FunctionTransformWithDictionary
<UInt32, RegionToAreaImpl, RegionsHierarchyGetter, NameRegionToArea> FunctionRegionToArea;
struct FunctionRegionToArea :
public FunctionTransformWithDictionary<UInt32, RegionToAreaImpl, RegionsHierarchyGetter, NameRegionToArea>
{
static IFunction * create(const Context & context)
{
return new base_type{context.getDictionaries().getRegionsHierarchies()};
}
};
typedef FunctionTransformWithDictionary
<UInt32, RegionToDistrictImpl, RegionsHierarchyGetter, NameRegionToDistrict> FunctionRegionToDistrict;
struct FunctionRegionToDistrict :
public FunctionTransformWithDictionary<UInt32, RegionToDistrictImpl, RegionsHierarchyGetter, NameRegionToDistrict>
{
static IFunction * create(const Context & context)
{
return new base_type{context.getDictionaries().getRegionsHierarchies()};
}
};
typedef FunctionTransformWithDictionary
<UInt32, RegionToCountryImpl, RegionsHierarchyGetter, NameRegionToCountry> FunctionRegionToCountry;
struct FunctionRegionToCountry :
public FunctionTransformWithDictionary<UInt32, RegionToCountryImpl, RegionsHierarchyGetter, NameRegionToCountry>
{
static IFunction * create(const Context & context)
{
return new base_type{context.getDictionaries().getRegionsHierarchies()};
}
};
typedef FunctionTransformWithDictionary
<UInt32, RegionToContinentImpl, RegionsHierarchyGetter, NameRegionToContinent> FunctionRegionToContinent;
struct FunctionRegionToContinent :
public FunctionTransformWithDictionary<UInt32, RegionToContinentImpl, RegionsHierarchyGetter, NameRegionToContinent>
{
static IFunction * create(const Context & context)
{
return new base_type{context.getDictionaries().getRegionsHierarchies()};
}
};
typedef FunctionTransformWithDictionary
<UInt8, OSToRootImpl, IdentityDictionaryGetter<TechDataHierarchy>, NameOSToRoot> FunctionOSToRoot;
struct FunctionOSToRoot :
public FunctionTransformWithDictionary<UInt8, OSToRootImpl, IdentityDictionaryGetter<TechDataHierarchy>, NameOSToRoot>
{
static IFunction * create(const Context & context)
{
return new base_type{context.getDictionaries().getTechDataHierarchy()};
}
};
typedef FunctionTransformWithDictionary
<UInt8, SEToRootImpl, IdentityDictionaryGetter<TechDataHierarchy>, NameSEToRoot> FunctionSEToRoot;
struct FunctionSEToRoot :
public FunctionTransformWithDictionary<UInt8, SEToRootImpl, IdentityDictionaryGetter<TechDataHierarchy>, NameSEToRoot>
{
static IFunction * create(const Context & context)
{
return new base_type{context.getDictionaries().getTechDataHierarchy()};
}
};
typedef FunctionTransformWithDictionary
<UInt16, CategoryToRootImpl, IdentityDictionaryGetter<CategoriesHierarchy>, NameCategoryToRoot> FunctionCategoryToRoot;
struct FunctionCategoryToRoot :
public FunctionTransformWithDictionary<UInt16, CategoryToRootImpl, IdentityDictionaryGetter<CategoriesHierarchy>, NameCategoryToRoot>
{
static IFunction * create(const Context & context)
{
return new base_type{context.getDictionaries().getCategoriesHierarchy()};
}
};
typedef FunctionTransformWithDictionary
<UInt16, CategoryToSecondLevelImpl, IdentityDictionaryGetter<CategoriesHierarchy>, NameCategoryToSecondLevel> FunctionCategoryToSecondLevel;
struct FunctionCategoryToSecondLevel :
public FunctionTransformWithDictionary<UInt16, CategoryToSecondLevelImpl, IdentityDictionaryGetter<CategoriesHierarchy>, NameCategoryToSecondLevel>
{
static IFunction * create(const Context & context)
{
return new base_type{context.getDictionaries().getCategoriesHierarchy()};
}
};
typedef FunctionIsInWithDictionary
<UInt32, RegionInImpl, RegionsHierarchyGetter, NameRegionIn> FunctionRegionIn;
struct FunctionRegionIn :
public FunctionIsInWithDictionary<UInt32, RegionInImpl, RegionsHierarchyGetter, NameRegionIn>
{
static IFunction * create(const Context & context)
{
return new base_type{context.getDictionaries().getRegionsHierarchies()};
}
};
typedef FunctionIsInWithDictionary
<UInt8, OSInImpl, IdentityDictionaryGetter<TechDataHierarchy>, NameOSIn> FunctionOSIn;
struct FunctionOSIn :
public FunctionIsInWithDictionary<UInt8, OSInImpl, IdentityDictionaryGetter<TechDataHierarchy>, NameOSIn>
{
static IFunction * create(const Context & context)
{
return new base_type{context.getDictionaries().getTechDataHierarchy()};
}
};
typedef FunctionIsInWithDictionary
<UInt8, SEInImpl, IdentityDictionaryGetter<TechDataHierarchy>, NameSEIn> FunctionSEIn;
struct FunctionSEIn :
public FunctionIsInWithDictionary<UInt8, SEInImpl, IdentityDictionaryGetter<TechDataHierarchy>, NameSEIn>
{
static IFunction * create(const Context & context)
{
return new base_type{context.getDictionaries().getTechDataHierarchy()};
}
};
typedef FunctionIsInWithDictionary
<UInt16, CategoryInImpl, IdentityDictionaryGetter<CategoriesHierarchy>, NameCategoryIn> FunctionCategoryIn;
struct FunctionCategoryIn :
public FunctionIsInWithDictionary<UInt16, CategoryInImpl, IdentityDictionaryGetter<CategoriesHierarchy>, NameCategoryIn>
{
static IFunction * create(const Context & context)
{
return new base_type{context.getDictionaries().getCategoriesHierarchy()};
}
};
typedef FunctionHierarchyWithDictionary
<UInt32, RegionHierarchyImpl, RegionsHierarchyGetter, NameRegionHierarchy> FunctionRegionHierarchy;
struct FunctionRegionHierarchy :
public FunctionHierarchyWithDictionary<UInt32, RegionHierarchyImpl, RegionsHierarchyGetter, NameRegionHierarchy>
{
static IFunction * create(const Context & context)
{
return new base_type{context.getDictionaries().getRegionsHierarchies()};
}
};
typedef FunctionHierarchyWithDictionary
<UInt8, OSHierarchyImpl, IdentityDictionaryGetter<TechDataHierarchy>, NameOSHierarchy> FunctionOSHierarchy;
struct FunctionOSHierarchy :
public FunctionHierarchyWithDictionary<UInt8, OSHierarchyImpl, IdentityDictionaryGetter<TechDataHierarchy>, NameOSHierarchy>
{
static IFunction * create(const Context & context)
{
return new base_type{context.getDictionaries().getTechDataHierarchy()};
}
};
typedef FunctionHierarchyWithDictionary
<UInt8, SEHierarchyImpl, IdentityDictionaryGetter<TechDataHierarchy>, NameSEHierarchy> FunctionSEHierarchy;
struct FunctionSEHierarchy :
public FunctionHierarchyWithDictionary<UInt8, SEHierarchyImpl, IdentityDictionaryGetter<TechDataHierarchy>, NameSEHierarchy>
{
static IFunction * create(const Context & context)
{
return new base_type{context.getDictionaries().getTechDataHierarchy()};
}
};
typedef FunctionHierarchyWithDictionary
<UInt16, CategoryHierarchyImpl, IdentityDictionaryGetter<CategoriesHierarchy>, NameCategoryHierarchy> FunctionCategoryHierarchy;
struct FunctionCategoryHierarchy :
public FunctionHierarchyWithDictionary<UInt16, CategoryHierarchyImpl, IdentityDictionaryGetter<CategoriesHierarchy>, NameCategoryHierarchy>
{
static IFunction * create(const Context & context)
{
return new base_type{context.getDictionaries().getCategoriesHierarchy()};
}
};
/// Преобразует числовой идентификатор региона в имя на заданном языке, используя словарь.
class FunctionRegionToName : public IFunction
{
public:
static constexpr auto name = "regionToName";
static IFunction * create(const Context & context)
{
return new FunctionRegionToName(context.getDictionaries().getRegionsNames());
}
private:
const SharedPtr<RegionsNames> owned_dict;
@ -573,7 +694,7 @@ public:
/// Получить имя функции.
String getName() const
{
return "regionToName";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.

View File

@ -18,10 +18,13 @@ namespace DB
class FunctionBitmaskToList : public IFunction
{
public:
static constexpr auto name = "bitmaskToList";
static IFunction * create(const Context & context) { return new FunctionBitmaskToList; }
/// Получить основное имя функции.
virtual String getName() const
{
return "bitmaskToList";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.

View File

@ -166,10 +166,13 @@ template <typename Impl, typename Name>
class FunctionStringHash64 : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionStringHash64; };
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -214,7 +217,7 @@ public:
}
else
throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName()
+ " of first argument of function " + Name::get(),
+ " of first argument of function " + Name::name,
ErrorCodes::ILLEGAL_COLUMN);
}
};
@ -224,10 +227,13 @@ template <typename Impl>
class FunctionStringHashFixedString : public IFunction
{
public:
static constexpr auto name = Impl::name;
static IFunction * create(const Context & context) { return new FunctionStringHashFixedString; };
/// Получить имя функции.
String getName() const
{
return Impl::name;
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -289,6 +295,10 @@ public:
template <typename Impl, typename Name>
class FunctionIntHash : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionIntHash; };
private:
typedef typename Impl::ReturnType ToType;
@ -314,7 +324,7 @@ private:
}
else
throw Exception("Illegal column " + block.getByPosition(arguments[0]).column->getName()
+ " of first argument of function " + Name::get(),
+ " of first argument of function " + Name::name,
ErrorCodes::ILLEGAL_COLUMN);
}
@ -322,7 +332,7 @@ public:
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -387,6 +397,10 @@ UInt64 toInteger<Float64>(Float64 x)
class FunctionCityHash64 : public IFunction
{
public:
static constexpr auto name = "cityHash64";
static IFunction * create(const Context & context) { return new FunctionCityHash64; };
private:
template <typename FromType, bool first>
void executeIntType(const IColumn * column, ColumnUInt64::Container_t & vec_to)
@ -550,7 +564,7 @@ public:
/// Получить имя функции.
String getName() const
{
return "cityHash64";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -589,11 +603,11 @@ public:
};
struct NameHalfMD5 { static const char * get() { return "halfMD5"; } };
struct NameSipHash64 { static const char * get() { return "sipHash64"; } };
struct NameCityHash64 { static const char * get() { return "cityHash64"; } };
struct NameIntHash32 { static const char * get() { return "intHash32"; } };
struct NameIntHash64 { static const char * get() { return "intHash64"; } };
struct NameHalfMD5 { static constexpr auto name = "halfMD5"; };
struct NameSipHash64 { static constexpr auto name = "sipHash64"; };
struct NameCityHash64 { static constexpr auto name = "cityHash64"; };
struct NameIntHash32 { static constexpr auto name = "intHash32"; };
struct NameIntHash64 { static constexpr auto name = "intHash64"; };
typedef FunctionStringHash64<HalfMD5Impl, NameHalfMD5> FunctionHalfMD5;
typedef FunctionStringHash64<SipHash64Impl, NameSipHash64> FunctionSipHash64;

View File

@ -381,10 +381,13 @@ template <typename Impl, typename Name>
class FunctionArrayMapped : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionArrayMapped; };
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Вызывается, если хоть один агрумент функции - лямбда-выражение.
@ -591,14 +594,14 @@ public:
};
struct NameArrayMap { static const char * get() { return "arrayMap"; } };
struct NameArrayFilter { static const char * get() { return "arrayFilter"; } };
struct NameArrayCount { static const char * get() { return "arrayCount"; } };
struct NameArrayExists { static const char * get() { return "arrayExists"; } };
struct NameArrayAll { static const char * get() { return "arrayAll"; } };
struct NameArraySum { static const char * get() { return "arraySum"; } };
struct NameArrayFirst { static const char * get() { return "arrayFirst"; } };
struct NameArrayFirstIndex { static const char * get() { return "arrayFirstIndex"; } };
struct NameArrayMap { static constexpr auto name = "arrayMap"; };
struct NameArrayFilter { static constexpr auto name = "arrayFilter"; };
struct NameArrayCount { static constexpr auto name = "arrayCount"; };
struct NameArrayExists { static constexpr auto name = "arrayExists"; };
struct NameArrayAll { static constexpr auto name = "arrayAll"; };
struct NameArraySum { static constexpr auto name = "arraySum"; };
struct NameArrayFirst { static constexpr auto name = "arrayFirst"; };
struct NameArrayFirstIndex { static constexpr auto name = "arrayFirstIndex"; };
typedef FunctionArrayMapped<ArrayMapImpl, NameArrayMap> FunctionArrayMap;
typedef FunctionArrayMapped<ArrayFilterImpl, NameArrayFilter> FunctionArrayFilter;

View File

@ -152,6 +152,10 @@ struct AssociativeOperationImpl<Op, 1>
template <template <typename> class Impl, typename Name>
class FunctionAnyArityLogical : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionAnyArityLogical; };
private:
bool extractConstColumns(ColumnPlainPtrs & in, UInt8 & res)
{
@ -240,7 +244,7 @@ public:
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -357,8 +361,11 @@ public:
template <template <typename> class Impl, typename Name>
class FunctionUnaryLogical : public IFunction
{
private:
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionUnaryLogical; };
private:
template <typename T>
bool executeType(Block & block, const ColumnNumbers & arguments, size_t result)
{
@ -391,7 +398,7 @@ public:
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -431,10 +438,10 @@ public:
};
struct NameAnd { static const char * get() { return "and"; } };
struct NameOr { static const char * get() { return "or"; } };
struct NameXor { static const char * get() { return "xor"; } };
struct NameNot { static const char * get() { return "not"; } };
struct NameAnd { static constexpr auto name = "and"; };
struct NameOr { static constexpr auto name = "or"; };
struct NameXor { static constexpr auto name = "xor"; };
struct NameNot { static constexpr auto name = "not"; };
typedef FunctionAnyArityLogical <AndImpl, NameAnd> FunctionAnd;
typedef FunctionAnyArityLogical <OrImpl, NameOr> FunctionOr;

View File

@ -76,13 +76,16 @@ static inline void stringWidthConstant(const String & data, UInt64 & res)
class FunctionCurrentDatabase : public IFunction
{
const String name;
const String db_name;
public:
explicit FunctionCurrentDatabase(const String & name) : name(name) {}
static constexpr auto name = "currentDatabase";
static IFunction * create(const Context & context) { return new FunctionCurrentDatabase{context.getCurrentDatabase()}; }
explicit FunctionCurrentDatabase(const String & db_name) : db_name{db_name} {}
String getName() const {
return "currentDatabase";
return name;
}
DataTypePtr getReturnType(const DataTypes & arguments) const
@ -98,7 +101,7 @@ public:
void execute(Block & block, const ColumnNumbers & arguments, const size_t result)
{
block.getByPosition(result).column = new ColumnConstString{
block.rowsInFirstColumn(), name
block.rowsInFirstColumn(), db_name
};
}
};
@ -107,10 +110,13 @@ public:
class FunctionHostName : public IFunction
{
public:
static constexpr auto name = "hostName";
static IFunction * create(const Context & context) { return new FunctionHostName; }
/// Получить имя функции.
String getName() const
{
return "hostName";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -124,7 +130,8 @@ public:
return new DataTypeString;
}
/// Выполнить функцию над блоком.
/** Выполнить функцию над блоком. convertToFullColumn вызывается для того, чтобы в случае
* распределенного выполнения запроса каждый сервер возвращал свое имя хоста. */
void execute(Block & block, const ColumnNumbers & arguments, size_t result)
{
block.getByPosition(result).column = ColumnConstString(
@ -136,10 +143,13 @@ public:
class FunctionVisibleWidth : public IFunction
{
public:
static constexpr auto name = "visibleWidth";
static IFunction * create(const Context & context) { return new FunctionVisibleWidth; }
/// Получить имя функции.
String getName() const
{
return "visibleWidth";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -161,10 +171,13 @@ public:
class FunctionToTypeName : public IFunction
{
public:
static constexpr auto name = "toTypeName";
static IFunction * create(const Context & context) { return new FunctionToTypeName; }
/// Получить имя функции.
String getName() const
{
return "toTypeName";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -189,10 +202,13 @@ public:
class FunctionBlockSize : public IFunction
{
public:
static constexpr auto name = "blockSize";
static IFunction * create(const Context & context) { return new FunctionBlockSize; }
/// Получить имя функции.
String getName() const
{
return "blockSize";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -218,10 +234,13 @@ public:
class FunctionSleep : public IFunction
{
public:
static constexpr auto name = "sleep";
static IFunction * create(const Context & context) { return new FunctionSleep; }
/// Получить имя функции.
String getName() const
{
return "sleep";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -284,10 +303,13 @@ public:
class FunctionMaterialize : public IFunction
{
public:
static constexpr auto name = "materialize";
static IFunction * create(const Context & context) { return new FunctionMaterialize; }
/// Получить имя функции.
String getName() const
{
return "materialize";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -312,23 +334,23 @@ public:
}
};
template <bool negative, bool global> struct FunctionInName;
template <> struct FunctionInName<false, false> { static constexpr auto name = "in"; };
template <> struct FunctionInName<false, true> { static constexpr auto name = "globalIn"; };
template <> struct FunctionInName<true, false> { static constexpr auto name = "notIn"; };
template <> struct FunctionInName<true, true> { static constexpr auto name = "globalNotIn"; };
template <bool negative, bool global>
class FunctionIn : public IFunction
{
private:
bool negative;
bool global;
public:
FunctionIn(bool negative_ = false, bool global_ = false) : negative(negative_), global(global_) {}
static constexpr auto name = FunctionInName<negative, global>::name;
static IFunction * create(const Context & context) { return new FunctionIn; }
/// Получить имя функции.
String getName() const
{
if (global)
return negative ? "globalNotIn" : "globalIn";
else
return negative ? "notIn" : "in";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -376,10 +398,13 @@ public:
class FunctionTuple : public IFunction
{
public:
static constexpr auto name = "tuple";
static IFunction * create(const Context & context) { return new FunctionTuple; }
/// Получить имя функции.
String getName() const
{
return "tuple";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -407,10 +432,13 @@ public:
class FunctionTupleElement : public IFunction
{
public:
static constexpr auto name = "tupleElement";
static IFunction * create(const Context & context) { return new FunctionTupleElement; }
/// Получить имя функции.
String getName() const
{
return "tupleElement";
return name;
}
void getReturnTypeAndPrerequisites(const ColumnsWithNameAndType & arguments,
@ -471,10 +499,13 @@ public:
class FunctionIgnore : public IFunction
{
public:
static constexpr auto name = "ignore";
static IFunction * create(const Context & context) { return new FunctionIgnore; }
/// Получить имя функции.
String getName() const
{
return "ignore";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -494,10 +525,14 @@ public:
class FunctionArrayJoin : public IFunction
{
public:
static constexpr auto name = "arrayJoin";
static IFunction * create(const Context & context) { return new FunctionArrayJoin; }
/// Получить имя функции.
String getName() const
{
return "arrayJoin";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -529,10 +564,14 @@ public:
*/
class FunctionReplicate : public IFunction
{
static constexpr auto name = "replicate";
static IFunction * create(const Context & context) { return new FunctionReplicate; }
/// Получить имя функции.
String getName() const
{
return "replicate";
return name;
}
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -575,10 +614,13 @@ class FunctionReplicate : public IFunction
class FunctionBar : public IFunction
{
public:
static constexpr auto name = "bar";
static IFunction * create(const Context & context) { return new FunctionBar; }
/// Получить имя функции.
String getName() const
{
return "bar";
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.

View File

@ -147,10 +147,13 @@ private:
typedef typename Impl::ReturnType ToType;
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionRandom; }
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -179,8 +182,8 @@ public:
};
struct NameRand { static const char * get() { return "rand"; } };
struct NameRand64 { static const char * get() { return "rand64"; } };
struct NameRand { static constexpr auto name = "rand"; };
struct NameRand64 { static constexpr auto name = "rand64"; };
typedef FunctionRandom<RandImpl, NameRand> FunctionRand;
typedef FunctionRandom<Rand64Impl, NameRand64> FunctionRand64;

View File

@ -23,10 +23,13 @@ template<typename Name>
class FunctionReinterpretAsStringImpl : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionReinterpretAsStringImpl; };
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -116,12 +119,15 @@ template<typename ToDataType, typename Name>
class FunctionReinterpretStringAs : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionReinterpretStringAs; };
typedef typename ToDataType::FieldType ToFieldType;
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -202,19 +208,19 @@ public:
};
struct NameReinterpretAsUInt8 { static const char * get() { return "reinterpretAsUInt8"; } };
struct NameReinterpretAsUInt16 { static const char * get() { return "reinterpretAsUInt16"; } };
struct NameReinterpretAsUInt32 { static const char * get() { return "reinterpretAsUInt32"; } };
struct NameReinterpretAsUInt64 { static const char * get() { return "reinterpretAsUInt64"; } };
struct NameReinterpretAsInt8 { static const char * get() { return "reinterpretAsInt8"; } };
struct NameReinterpretAsInt16 { static const char * get() { return "reinterpretAsInt16"; } };
struct NameReinterpretAsInt32 { static const char * get() { return "reinterpretAsInt32"; } };
struct NameReinterpretAsInt64 { static const char * get() { return "reinterpretAsInt64"; } };
struct NameReinterpretAsFloat32 { static const char * get() { return "reinterpretAsFloat32"; } };
struct NameReinterpretAsFloat64 { static const char * get() { return "reinterpretAsFloat64"; } };
struct NameReinterpretAsDate { static const char * get() { return "reinterpretAsDate"; } };
struct NameReinterpretAsDateTime { static const char * get() { return "reinterpretAsDateTime"; } };
struct NameReinterpretAsString { static const char * get() { return "reinterpretAsString"; } };
struct NameReinterpretAsUInt8 { static constexpr auto name = "reinterpretAsUInt8"; };
struct NameReinterpretAsUInt16 { static constexpr auto name = "reinterpretAsUInt16"; };
struct NameReinterpretAsUInt32 { static constexpr auto name = "reinterpretAsUInt32"; };
struct NameReinterpretAsUInt64 { static constexpr auto name = "reinterpretAsUInt64"; };
struct NameReinterpretAsInt8 { static constexpr auto name = "reinterpretAsInt8"; };
struct NameReinterpretAsInt16 { static constexpr auto name = "reinterpretAsInt16"; };
struct NameReinterpretAsInt32 { static constexpr auto name = "reinterpretAsInt32"; };
struct NameReinterpretAsInt64 { static constexpr auto name = "reinterpretAsInt64"; };
struct NameReinterpretAsFloat32 { static constexpr auto name = "reinterpretAsFloat32"; };
struct NameReinterpretAsFloat64 { static constexpr auto name = "reinterpretAsFloat64"; };
struct NameReinterpretAsDate { static constexpr auto name = "reinterpretAsDate"; };
struct NameReinterpretAsDateTime { static constexpr auto name = "reinterpretAsDateTime"; };
struct NameReinterpretAsString { static constexpr auto name = "reinterpretAsString"; };
typedef FunctionReinterpretStringAs<DataTypeUInt8, NameReinterpretAsUInt8> FunctionReinterpretAsUInt8;
typedef FunctionReinterpretStringAs<DataTypeUInt16, NameReinterpretAsUInt16> FunctionReinterpretAsUInt16;

View File

@ -6,51 +6,51 @@
namespace DB
{
/** Функции округления:
* roundToExp2 - вниз до ближайшей степени двойки;
* roundDuration - вниз до ближайшего из: 0, 1, 10, 30, 60, 120, 180, 240, 300, 600, 1200, 1800, 3600, 7200, 18000, 36000;
* roundAge - вниз до ближайшего из: 0, 18, 25, 35, 45.
*/
template<typename A>
struct RoundToExp2Impl
{
typedef A ResultType;
static inline A apply(A x)
{
return x <= 0 ? static_cast<A>(0) : (static_cast<A>(1) << static_cast<UInt64>(log2(static_cast<double>(x))));
}
};
template<>
struct RoundToExp2Impl<Float32>
{
typedef Float32 ResultType;
static inline Float32 apply(Float32 x)
{
return static_cast<Float32>(x < 1 ? 0. : pow(2., floor(log2(x))));
}
};
template<>
struct RoundToExp2Impl<Float64>
{
typedef Float64 ResultType;
static inline Float64 apply(Float64 x)
{
return x < 1 ? 0. : pow(2., floor(log2(x)));
}
};
template<typename A>
struct RoundDurationImpl
{
typedef UInt16 ResultType;
static inline ResultType apply(A x)
{
return x < 1 ? 0
@ -71,12 +71,12 @@ namespace DB
: 36000))))))))))))));
}
};
template<typename A>
struct RoundAgeImpl
{
typedef UInt8 ResultType;
static inline ResultType apply(A x)
{
return x < 18 ? 0
@ -86,14 +86,14 @@ namespace DB
: 45)));
}
};
struct NameRoundToExp2 { static const char * get() { return "roundToExp2"; } };
struct NameRoundDuration { static const char * get() { return "roundDuration"; } };
struct NameRoundAge { static const char * get() { return "roundAge"; } };
struct NameRoundToExp2 { static constexpr auto name = "roundToExp2"; };
struct NameRoundDuration { static constexpr auto name = "roundDuration"; };
struct NameRoundAge { static constexpr auto name = "roundAge"; };
typedef FunctionUnaryArithmetic<RoundToExp2Impl, NameRoundToExp2> FunctionRoundToExp2;
typedef FunctionUnaryArithmetic<RoundDurationImpl, NameRoundDuration> FunctionRoundDuration;
typedef FunctionUnaryArithmetic<RoundAgeImpl, NameRoundAge> FunctionRoundAge;
}

View File

@ -809,10 +809,13 @@ template <typename Impl, typename Name, typename ResultType>
class FunctionStringOrArrayToT : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionStringOrArrayToT; }
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -902,10 +905,13 @@ template <typename Impl, typename Name>
class FunctionStringToString : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionStringToString; }
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -960,10 +966,13 @@ template <typename Impl, typename Name>
class FunctionStringStringToString : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionStringStringToString; }
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -1212,10 +1221,13 @@ template <typename Impl, typename Name>
class FunctionStringNumNumToString : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionStringNumNumToString; }
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -1287,19 +1299,19 @@ public:
};
struct NameEmpty { static const char * get() { return "empty"; } };
struct NameNotEmpty { static const char * get() { return "notEmpty"; } };
struct NameLength { static const char * get() { return "length"; } };
struct NameLengthUTF8 { static const char * get() { return "lengthUTF8"; } };
struct NameLower { static const char * get() { return "lower"; } };
struct NameUpper { static const char * get() { return "upper"; } };
struct NameLowerUTF8 { static const char * get() { return "lowerUTF8"; } };
struct NameUpperUTF8 { static const char * get() { return "upperUTF8"; } };
struct NameReverse { static const char * get() { return "reverse"; } };
struct NameReverseUTF8 { static const char * get() { return "reverseUTF8"; } };
struct NameConcat { static const char * get() { return "concat"; } };
struct NameSubstring { static const char * get() { return "substring"; } };
struct NameSubstringUTF8 { static const char * get() { return "substringUTF8"; } };
struct NameEmpty { static constexpr auto name = "empty"; };
struct NameNotEmpty { static constexpr auto name = "notEmpty"; };
struct NameLength { static constexpr auto name = "length"; };
struct NameLengthUTF8 { static constexpr auto name = "lengthUTF8"; };
struct NameLower { static constexpr auto name = "lower"; };
struct NameUpper { static constexpr auto name = "upper"; };
struct NameLowerUTF8 { static constexpr auto name = "lowerUTF8"; };
struct NameUpperUTF8 { static constexpr auto name = "upperUTF8"; };
struct NameReverse { static constexpr auto name = "reverse"; };
struct NameReverseUTF8 { static constexpr auto name = "reverseUTF8"; };
struct NameConcat { static constexpr auto name = "concat"; };
struct NameSubstring { static constexpr auto name = "substring"; };
struct NameSubstringUTF8 { static constexpr auto name = "substringUTF8"; };
typedef FunctionStringOrArrayToT<EmptyImpl<false>, NameEmpty, UInt8> FunctionEmpty;
typedef FunctionStringOrArrayToT<EmptyImpl<true>, NameNotEmpty, UInt8> FunctionNotEmpty;

View File

@ -45,7 +45,8 @@ private:
public:
/// Получить имя фукнции.
static String getName() { return "alphaTokens"; }
static constexpr auto name = "alphaTokens";
static String getName() { return name; }
/// Проверить типы агрументов функции.
static void checkArguments(const DataTypes & arguments)
@ -107,7 +108,8 @@ private:
char sep;
public:
static String getName() { return "splitByChar"; }
static constexpr auto name = "splitByChar";
static String getName() { return name; }
static void checkArguments(const DataTypes & arguments)
{
@ -183,7 +185,8 @@ private:
String sep;
public:
static String getName() { return "splitByString"; }
static constexpr auto name = "splitByString";
static String getName() { return name; }
static void checkArguments(const DataTypes & arguments)
{
@ -246,7 +249,8 @@ private:
Pos end;
public:
/// Получить имя функции.
static String getName() { return "extractAll"; }
static constexpr auto name = "extractAll";
static String getName() { return name; }
/// Проверить типы агрументов функции.
static void checkArguments( const DataTypes & arguments )
@ -305,10 +309,13 @@ template <typename Generator>
class FunctionTokens : public IFunction
{
public:
static constexpr auto name = Generator::name;
static IFunction * create(const Context & context) { return new FunctionTokens; }
/// Получить имя функции.
String getName() const
{
return Generator::getName();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.

View File

@ -870,10 +870,13 @@ template <typename Impl, typename Name>
class FunctionStringReplace : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionStringReplace; }
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -954,10 +957,13 @@ template <typename Impl, typename Name>
class FunctionsStringSearch : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionsStringSearch; }
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -1020,10 +1026,13 @@ template <typename Impl, typename Name>
class FunctionsStringSearchToString : public IFunction
{
public:
static constexpr auto name = Name::name;
static IFunction * create(const Context & context) { return new FunctionsStringSearchToString; }
/// Получить имя функции.
String getName() const
{
return Name::get();
return name;
}
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
@ -1091,16 +1100,16 @@ public:
};
struct NamePosition { static const char * get() { return "position"; } };
struct NamePositionUTF8 { static const char * get() { return "positionUTF8"; } };
struct NameMatch { static const char * get() { return "match"; } };
struct NameLike { static const char * get() { return "like"; } };
struct NameNotLike { static const char * get() { return "notLike"; } };
struct NameExtract { static const char * get() { return "extract"; } };
struct NameReplaceOne { static const char * get() { return "replaceOne"; } };
struct NameReplaceAll { static const char * get() { return "replaceAll"; } };
struct NameReplaceRegexpOne { static const char * get() { return "replaceRegexpOne"; } };
struct NameReplaceRegexpAll { static const char * get() { return "replaceRegexpAll"; } };
struct NamePosition { static constexpr auto name = "position"; };
struct NamePositionUTF8 { static constexpr auto name = "positionUTF8"; };
struct NameMatch { static constexpr auto name = "match"; };
struct NameLike { static constexpr auto name = "like"; };
struct NameNotLike { static constexpr auto name = "notLike"; };
struct NameExtract { static constexpr auto name = "extract"; };
struct NameReplaceOne { static constexpr auto name = "replaceOne"; };
struct NameReplaceAll { static constexpr auto name = "replaceAll"; };
struct NameReplaceRegexpOne { static constexpr auto name = "replaceRegexpOne"; };
struct NameReplaceRegexpAll { static constexpr auto name = "replaceRegexpAll"; };
typedef FunctionsStringSearch<PositionImpl, NamePosition> FunctionPosition;
typedef FunctionsStringSearch<PositionUTF8Impl, NamePositionUTF8> FunctionPositionUTF8;

View File

@ -327,6 +327,11 @@ struct ExtractQueryStringAndFragment
res_data = pos + (without_leading_char ? 1 : 0);
res_size = end - res_data;
}
else if (nullptr != (pos = strchr(data, '#')))
{
res_data = pos;
res_size = end - res_data;
}
}
};
@ -503,7 +508,8 @@ private:
bool first;
public:
static String getName() { return "extractURLParameters"; }
static constexpr auto name = "extractURLParameters";
static String getName() { return name; }
static void checkArguments(const DataTypes & arguments)
{
@ -571,7 +577,8 @@ private:
bool first;
public:
static String getName() { return "extractURLParameterNames"; }
static constexpr auto name = "extractURLParameterNames";
static String getName() { return name; }
static void checkArguments(const DataTypes & arguments)
{
@ -639,7 +646,8 @@ private:
Pos end;
public:
static String getName() { return "URLHierarchy"; }
static constexpr auto name = "URLHierarchy";
static String getName() { return name; }
static void checkArguments(const DataTypes & arguments)
{
@ -737,7 +745,8 @@ private:
Pos start;
public:
static String getName() { return "URLPathHierarchy"; }
static constexpr auto name = "URLPathHierarchy";
static String getName() { return name; }
static void checkArguments(const DataTypes & arguments)
{
@ -924,25 +933,25 @@ struct CutSubstringImpl
};
struct NameProtocol { static const char * get() { return "protocol"; } };
struct NameDomain { static const char * get() { return "domain"; } };
struct NameDomainWithoutWWW { static const char * get() { return "domainWithoutWWW"; } };
struct NameFirstSignificantSubdomain { static const char * get() { return "firstSignificantSubdomain"; } };
struct NameTopLevelDomain { static const char * get() { return "topLevelDomain"; } };
struct NamePath { static const char * get() { return "path"; } };
struct NameQueryString { static const char * get() { return "queryString"; } };
struct NameFragment { static const char * get() { return "fragment"; } };
struct NameQueryStringAndFragment { static const char * get() { return "queryStringAndFragment"; } };
struct NameProtocol { static constexpr auto name = "protocol"; };
struct NameDomain { static constexpr auto name = "domain"; };
struct NameDomainWithoutWWW { static constexpr auto name = "domainWithoutWWW"; };
struct NameFirstSignificantSubdomain { static constexpr auto name = "firstSignificantSubdomain"; };
struct NameTopLevelDomain { static constexpr auto name = "topLevelDomain"; };
struct NamePath { static constexpr auto name = "path"; };
struct NameQueryString { static constexpr auto name = "queryString"; };
struct NameFragment { static constexpr auto name = "fragment"; };
struct NameQueryStringAndFragment { static constexpr auto name = "queryStringAndFragment"; };
struct NameCutToFirstSignificantSubdomain { static const char * get() { return "cutToFirstSignificantSubdomain"; } };
struct NameCutToFirstSignificantSubdomain { static constexpr auto name = "cutToFirstSignificantSubdomain"; };
struct NameCutWWW { static const char * get() { return "cutWWW"; } };
struct NameCutQueryString { static const char * get() { return "cutQueryString"; } };
struct NameCutFragment { static const char * get() { return "cutFragment"; } };
struct NameCutQueryStringAndFragment { static const char * get() { return "cutQueryStringAndFragment"; } };
struct NameCutWWW { static constexpr auto name = "cutWWW"; };
struct NameCutQueryString { static constexpr auto name = "cutQueryString"; };
struct NameCutFragment { static constexpr auto name = "cutFragment"; };
struct NameCutQueryStringAndFragment { static constexpr auto name = "cutQueryStringAndFragment"; };
struct NameExtractURLParameter { static const char * get() { return "extractURLParameter"; } };
struct NameCutURLParameter { static const char * get() { return "cutURLParameter"; } };
struct NameExtractURLParameter { static constexpr auto name = "extractURLParameter"; };
struct NameCutURLParameter { static constexpr auto name = "cutURLParameter"; };
typedef FunctionStringToString<ExtractSubstringImpl<ExtractProtocol>, NameProtocol> FunctionProtocol;
typedef FunctionStringToString<ExtractSubstringImpl<ExtractDomain<false> >, NameDomain> FunctionDomain;

View File

@ -16,16 +16,16 @@
/** Функции для извлечения параметров визитов.
* Реализованы через шаблоны из FunctionsStringSearch.h.
*
*
* Проверить есть ли параметр
* visitParamHas
*
*
* Извлечь числовое значение параметра
* visitParamExtractUInt
* visitParamExtractInt
* visitParamExtractFloat
* visitParamExtractBool
*
*
* Извлечь строкое значение параметра
* visitParamExtractString - значение разэскейпливается
* visitParamExtractRaw
@ -37,7 +37,7 @@ namespace DB
struct HasParam
{
typedef UInt8 ResultType;
static UInt8 extract(const UInt8 * begin, const UInt8 * end)
{
return true;
@ -48,15 +48,15 @@ template<typename NumericType>
struct ExtractNumericType
{
typedef NumericType ResultType;
static ResultType extract(const UInt8 * begin, const UInt8 * end)
{
ReadBuffer in(const_cast<char *>(reinterpret_cast<const char *>(begin)), end - begin, 0);
/// Учимся читать числа в двойных кавычках
if (!in.eof() && *in.position() == '"')
++in.position();
ResultType x = 0;
if (!in.eof())
readText(x, in);
@ -67,7 +67,7 @@ struct ExtractNumericType
struct ExtractBool
{
typedef UInt8 ResultType;
static UInt8 extract(const UInt8 * begin, const UInt8 * end)
{
return begin + 4 <= end && 0 == strncmp(reinterpret_cast<const char *>(begin), "true", 4);
@ -81,7 +81,7 @@ struct ExtractRaw
{
if (pos == end)
return;
UInt8 open_char = *pos;
UInt8 close_char = 0;
switch (open_char)
@ -96,19 +96,19 @@ struct ExtractRaw
close_char = '"';
break;
}
if (close_char != 0)
{
size_t balance = 1;
size_t balance = 1;
char last_char = 0;
res_data.push_back(*pos);
++pos;
for (; pos != end && balance > 0; ++pos)
{
res_data.push_back(*pos);
if (open_char == '"' && *pos == '"')
{
if (last_char != '\\')
@ -121,7 +121,7 @@ struct ExtractRaw
if (*pos == close_char)
--balance;
}
if (last_char == '\\')
last_char = 0;
else
@ -157,12 +157,12 @@ struct ExtractString
}
return false;
}
static bool tryUnhex(const UInt8 * pos, const UInt8 * end, int & res)
{
if (pos + 3 >= end)
return false;
res = 0;
{
UInt8 major, minor;
@ -183,12 +183,12 @@ struct ExtractString
}
return true;
}
static bool tryExtract(const UInt8 * pos, const UInt8 * end, ColumnString::Chars_t & res_data)
{
if (pos == end || *pos != '"')
return false;
++pos;
while (pos != end)
{
@ -228,20 +228,20 @@ struct ExtractString
case 'u':
{
++pos;
int unicode;
if (!tryUnhex(pos, end, unicode))
return false;
pos += 3;
res_data.resize(res_data.size() + 6); /// максимальный размер UTF8 многобайтовой последовательности
Poco::UTF8Encoding utf8;
int length = utf8.convert(unicode, const_cast<UInt8 *>(&res_data[0]) + res_data.size() - 6, 6);
if (!length)
return false;
res_data.resize(res_data.size() - 6 + length);
break;
}
@ -261,11 +261,11 @@ struct ExtractString
}
return false;
}
static void extract(const UInt8 * pos, const UInt8 * end, ColumnString::Chars_t & res_data)
{
size_t old_size = res_data.size();
if (!tryExtract(pos, end, res_data))
res_data.resize(old_size);
}
@ -276,7 +276,7 @@ struct ExtractString
* на каждое вхождение поля, передавая ему указатель на часть строки,
* где начинается вхождение значения поля.
* ParamExtractor должен распарсить и вернуть значение нужного типа.
*
*
* Если поле не было найдено или полю соответствует некорректное значение,
* то используется значение по умолчанию - 0.
*/
@ -292,7 +292,7 @@ struct ExtractParamImpl
{
/// Ищем параметр просто как подстроку вида "name":
needle = "\"" + needle + "\":";
const UInt8 * begin = &data[0];
const UInt8 * pos = begin;
const UInt8 * end = pos + data.size();
@ -352,10 +352,10 @@ struct ExtractParamToStringImpl
/// Константа 5 взята из функции, выполняющей похожую задачу FunctionsStringSearch.h::ExtractImpl
res_data.reserve(data.size() / 5);
res_offsets.resize(offsets.size());
/// Ищем параметр просто как подстроку вида "name":
needle = "\"" + needle + "\":";
const UInt8 * begin = &data[0];
const UInt8 * pos = begin;
const UInt8 * end = pos + data.size();
@ -381,12 +381,12 @@ struct ExtractParamToStringImpl
ParamExtractor::extract(pos + needle.size(), begin + offsets[i], res_data);
pos = begin + offsets[i];
res_data.push_back(0);
res_offsets[i] = res_data.size();
++i;
}
while (i < res_offsets.size())
{
res_data.push_back(0);
@ -397,13 +397,13 @@ struct ExtractParamToStringImpl
};
struct NameVisitParamHas { static const char * get() { return "visitParamHas"; } };
struct NameVisitParamExtractUInt { static const char * get() { return "visitParamExtractUInt"; } };
struct NameVisitParamExtractInt { static const char * get() { return "visitParamExtractInt"; } };
struct NameVisitParamExtractFloat { static const char * get() { return "visitParamExtractFloat"; } };
struct NameVisitParamExtractBool { static const char * get() { return "visitParamExtractBool"; } };
struct NameVisitParamExtractRaw { static const char * get() { return "visitParamExtractRaw"; } };
struct NameVisitParamExtractString { static const char * get() { return "visitParamExtractString"; } };
struct NameVisitParamHas { static constexpr auto name = "visitParamHas"; };
struct NameVisitParamExtractUInt { static constexpr auto name = "visitParamExtractUInt"; };
struct NameVisitParamExtractInt { static constexpr auto name = "visitParamExtractInt"; };
struct NameVisitParamExtractFloat { static constexpr auto name = "visitParamExtractFloat"; };
struct NameVisitParamExtractBool { static constexpr auto name = "visitParamExtractBool"; };
struct NameVisitParamExtractRaw { static constexpr auto name = "visitParamExtractRaw"; };
struct NameVisitParamExtractString { static constexpr auto name = "visitParamExtractString"; };
typedef FunctionsStringSearch<ExtractParamImpl<HasParam>, NameVisitParamHas> FunctionVisitParamHas;
@ -414,4 +414,4 @@ typedef FunctionsStringSearch<ExtractParamImpl<ExtractBool>, NameVisitParamExtra
typedef FunctionsStringSearchToString<ExtractParamToStringImpl<ExtractRaw>, NameVisitParamExtractRaw> FunctionVisitParamExtractRaw;
typedef FunctionsStringSearchToString<ExtractParamToStringImpl<ExtractString>, NameVisitParamExtractString> FunctionVisitParamExtractString;
}
}

View File

@ -210,9 +210,11 @@ private:
*/
void collectJoinedColumns(NameSet & joined_columns, NamesAndTypesList & joined_columns_name_type);
void addStorageAliases();
/** Создать словарь алиасов.
*/
void createAliasesDict(ASTPtr & ast, int ignore_levels = 0);
void addASTAliases(ASTPtr & ast, int ignore_levels = 0);
/** Для узлов-звёздочек - раскрыть их в список всех столбцов.
* Для узлов-литералов - подставить алиасы.

View File

@ -22,7 +22,13 @@ public:
/** Изменяет список столбцов в метаданных таблицы на диске. Нужно вызывать под TableStructureLock соответствующей таблицы.
*/
static void updateMetadata(const String & database, const String & table, const NamesAndTypesList & columns, Context & context);
static void updateMetadata(const String & database,
const String & table,
const NamesAndTypesList & columns,
const NamesAndTypesList & materialized_columns,
const NamesAndTypesList & alias_columns,
const ColumnDefaults & column_defaults,
Context & context);
private:
struct PartitionCommand
{
@ -74,4 +80,5 @@ private:
static void parseAlter(const ASTAlterQuery::ParameterContainer & params, const DataTypeFactory & data_type_factory,
AlterCommands & out_alter_commands, PartitionCommands & out_partition_commands);
};
}

View File

@ -2,6 +2,7 @@
#include <DB/Storages/IStorage.h>
#include <DB/Interpreters/Context.h>
#include <DB/Storages/ColumnDefault.h>
namespace DB
@ -14,7 +15,7 @@ class InterpreterCreateQuery
{
public:
InterpreterCreateQuery(ASTPtr query_ptr_, Context & context_);
/** В случае таблицы: добавляет созданную таблицу в контекст, а также возвращает её.
* В случае БД: добавляет созданную БД в контекст и возвращает NULL.
* assume_metadata_exists - не проверять наличие файла с метаданными и не создавать его
@ -22,12 +23,22 @@ public:
*/
StoragePtr execute(bool assume_metadata_exists = false);
/** AST в список столбцов с типами и обратно. Столбцы типа Nested развернуты в список настоящих столбцов.
*/
static NamesAndTypesList parseColumns(ASTPtr expression_list, const DataTypeFactory & data_type_factory);
/// Список столбцов с типами в AST.
static ASTPtr formatColumns(const NamesAndTypesList & columns);
static ASTPtr formatColumns(
NamesAndTypesList columns,
const NamesAndTypesList & materialized_columns,
const NamesAndTypesList & alias_columns,
const ColumnDefaults & column_defaults);
private:
/// AST в список столбцов с типами. Столбцы типа Nested развернуты в список настоящих столбцов.
using ColumnsAndDefaults = std::pair<NamesAndTypesList, ColumnDefaults>;
ColumnsAndDefaults parseColumns(ASTPtr expression_list);
/// removes columns from the columns list and return them in a separate list
static NamesAndTypesList removeAndReturnColumns(ColumnsAndDefaults & columns_and_defaults, ColumnDefaultType type);
ASTPtr query_ptr;
Context context;
};

View File

@ -10,6 +10,8 @@
#include <DB/DataTypes/DataTypesNumberFixed.h>
#include <DB/DataTypes/DataTypeString.h>
#include <DB/Columns/ColumnString.h>
#include <DB/Parsers/formatAST.h>
namespace DB
@ -59,13 +61,18 @@ private:
col.name = "name";
col.type = new DataTypeString;
col.column = col.type->createColumn();
block.insert(col);
col.name = "type";
block.insert(col);
col.name = "default_type";
block.insert(col);
col.name = "default_expression";
block.insert(col);
return block;
}
@ -74,27 +81,42 @@ private:
const ASTDescribeQuery & ast = typeid_cast<const ASTDescribeQuery &>(*query_ptr);
NamesAndTypesList columns;
ColumnDefaults column_defaults;
{
StoragePtr table = context.getTable(ast.database, ast.table);
auto table_lock = table->lockStructure(false);
columns = table->getColumnsList();
columns.insert(std::end(columns), std::begin(table->alias_columns), std::end(table->alias_columns));
column_defaults = table->column_defaults;
}
ColumnString * name_column = new ColumnString;
ColumnString * type_column = new ColumnString;
ColumnWithNameAndType name_column{new ColumnString, new DataTypeString, "name"};
ColumnWithNameAndType type_column{new ColumnString, new DataTypeString, "type" };
ColumnWithNameAndType default_type_column{new ColumnString, new DataTypeString, "default_type" };
ColumnWithNameAndType default_expression_column{new ColumnString, new DataTypeString, "default_expression" };;
Block block;
block.insert(ColumnWithNameAndType(name_column, new DataTypeString, "name"));
block.insert(ColumnWithNameAndType(type_column, new DataTypeString, "type"));
for (NamesAndTypesList::iterator it = columns.begin(); it != columns.end(); ++it)
for (const auto column : columns)
{
name_column->insert(it->name);
type_column->insert(it->type->getName());
name_column.column->insert(column.name);
type_column.column->insert(column.type->getName());
const auto it = column_defaults.find(column.name);
if (it == std::end(column_defaults))
{
default_type_column.column->insertDefault();
default_expression_column.column->insertDefault();
}
else
{
default_type_column.column->insert(toString(it->second.type));
default_expression_column.column->insert(queryToString(it->second.expression));
}
}
return new OneBlockInputStream(block);
return new OneBlockInputStream{
{name_column, type_column, default_type_column, default_expression_column}
};
}
};

View File

@ -0,0 +1,49 @@
#pragma once
#include <DB/Core/Block.h>
#include <DB/Storages/ColumnDefault.h>
#include <DB/Interpreters/ExpressionAnalyzer.h>
#include <utility>
namespace DB
{
inline void evaluateMissingDefaults(Block & block,
const NamesAndTypesList & required_columns,
const ColumnDefaults & column_defaults,
const Context & context)
{
if (column_defaults.empty())
return;
ASTPtr default_expr_list{stdext::make_unique<ASTExpressionList>().release()};
for (const auto & column : required_columns)
{
if (block.has(column.name))
continue;
const auto it = column_defaults.find(column.name);
/// expressions must be cloned to prevent modification by the ExpressionAnalyzer
if (it != column_defaults.end())
default_expr_list->children.emplace_back(
setAlias(it->second.expression->clone(), it->first));
}
/// nothing to evaluate
if (default_expr_list->children.empty())
return;
/** ExpressionAnalyzer eliminates "unused" columns, in order to ensure their safety
* we are going to operate on a copy instead of the original block */
Block copy_block{block};
/// evaluate default values for defaulted columns
ExpressionAnalyzer{default_expr_list, context, required_columns}.getActions(true)->execute(copy_block);
/// move evaluated columns to the original block
for (auto & column_name_type : copy_block.getColumns())
block.insert(std::move(column_name_type));
}
}

View File

@ -38,7 +38,7 @@ public:
* В запросе DROP это поле не используется
* В запросе MODIFY здесь хранится имя столбца и новый тип
*/
ASTPtr name_type;
ASTPtr col_decl;
/** В запросе ADD COLUMN здесь опционально хранится имя столбца, следующее после AFTER
* В запросе DROP здесь хранится имя столбца для удаления
@ -61,7 +61,7 @@ public:
void clone(Parameters & p) const
{
p = *this;
p.name_type = name_type->clone();
p.col_decl = col_decl->clone();
p.column = column->clone();
p.partition = partition->clone();
}
@ -75,8 +75,8 @@ public:
void addParameters(const Parameters & params)
{
parameters.push_back(params);
if (params.name_type)
children.push_back(params.name_type);
if (params.col_decl)
children.push_back(params.col_decl);
if (params.column)
children.push_back(params.column);
if (params.partition)

View File

@ -0,0 +1,43 @@
#pragma once
#include <DB/Parsers/IAST.h>
namespace DB
{
/** Name, type, default-specifier, default-expression.
* The type is optional if default-expression is specified.
*/
class ASTColumnDeclaration : public IAST
{
public:
String name;
ASTPtr type;
String default_specifier;
ASTPtr default_expression;
ASTColumnDeclaration() = default;
ASTColumnDeclaration(StringRange range) : IAST{range} {}
String getID() const { return "ColumnDeclaration_" + name; }
ASTPtr clone() const
{
const auto res = new ASTColumnDeclaration{*this};
res->children.clear();
if (type) {
res->type = type->clone();
res->children.push_back(res->type);
}
if (default_expression) {
res->default_expression = default_expression->clone();
res->children.push_back(res->default_expression);
}
return res;
}
};
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <DB/Parsers/ASTWithAlias.h>
#include <DB/Parsers/ASTExpressionList.h>
#include <DB/Functions/IFunction.h>
#include <DB/AggregateFunctions/IAggregateFunction.h>
#include <DB/IO/WriteBufferFromString.h>
@ -81,4 +82,37 @@ public:
}
};
template <typename... Args>
ASTPtr makeASTFunction(const String & name, Args &&... args)
{
const auto function = new ASTFunction{};
ASTPtr result{function};
function->name = name;
function->arguments = new ASTExpressionList{};
function->children.push_back(function->arguments);
function->arguments->children = { std::forward<Args>(args)... };
return result;
}
template <typename... Args>
ASTPtr makeASTFunction(const String & name, const StringRange & function_range,
const StringRange & arguments_range, Args &&... args)
{
const auto function = new ASTFunction{function_range};
ASTPtr result{function};
function->name = name;
function->arguments = new ASTExpressionList{arguments_range};
function->children.push_back(function->arguments);
function->arguments->children = { std::forward<Args>(args)... };
return result;
}
}

View File

@ -21,4 +21,12 @@ public:
void setAlias(const String & to) override { alias = to; }
};
/// helper for setting aliases and chaining result to other functions
inline ASTPtr setAlias(ASTPtr ast, const String & alias) {
dynamic_cast<ASTWithAlias &>(*ast).alias = alias;
return ast;
};
}

View File

@ -2,9 +2,12 @@
#include <DB/Parsers/IParserBase.h>
#include <DB/Parsers/ExpressionElementParsers.h>
#include <DB/Parsers/ExpressionListParsers.h>
#include <DB/Parsers/ASTNameTypePair.h>
#include <DB/Parsers/ASTColumnDeclaration.h>
#include <DB/Parsers/ASTIdentifier.h>
#include <DB/Parsers/CommonParsers.h>
#include <Poco/String.h>
namespace DB
@ -93,6 +96,101 @@ protected:
};
template <class NameParser>
class IParserColumnDeclaration : public IParserBase
{
protected:
const char * getName() const { return "column declaration"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, Expected & expected);
};
typedef IParserColumnDeclaration<ParserIdentifier> ParserColumnDeclaration;
typedef IParserColumnDeclaration<ParserCompoundIdentifier> ParserCompoundColumnDeclaration;
template <class NameParser>
bool IParserColumnDeclaration<NameParser>::parseImpl(Pos & pos, Pos end, ASTPtr & node, Expected & expected)
{
NameParser name_parser;
ParserIdentifierWithOptionalParameters type_parser;
ParserWhiteSpaceOrComments ws;
ParserString s_default{"DEFAULT", true, true};
ParserString s_materialized{"MATERIALIZED", true, true};
ParserString s_alias{"ALIAS", true, true};
ParserTernaryOperatorExpression expr_parser;
const auto begin = pos;
const auto reset_pos_and_return = [&pos, begin] {
pos = begin;
return false;
};
/// mandatory column name
ASTPtr name;
if (!name_parser.parse(pos, end, name, expected))
return false;
ws.ignore(pos, end, expected);
/** column name should be followed by type name if it
* is not immediately followed by {DEFAULT, MATERIALIZED, ALIAS} */
ASTPtr type;
const auto fallback_pos = pos;
if (!s_default.check(pos, end, expected) &&
!s_materialized.check(pos, end, expected) &&
!s_alias.check(pos, end, expected))
{
if (type_parser.parse(pos, end, type, expected))
ws.ignore(pos, end, expected);
}
else
pos = fallback_pos;
/// parse {DEFAULT, MATERIALIZED, ALIAS}
String default_specifier;
ASTPtr default_expression;
const auto pos_before_specifier = pos;
if (s_default.ignore(pos, end, expected) ||
s_materialized.ignore(pos, end, expected) ||
s_alias.ignore(pos, end, expected))
{
default_specifier = Poco::toUpper(std::string{pos_before_specifier, pos});
/// should be followed by an expression
ws.ignore(pos, end, expected);
if (!expr_parser.parse(pos, end, default_expression, expected))
return reset_pos_and_return();
}
else if (!type)
return reset_pos_and_return(); /// reject sole column name without type
const auto column_declaration = new ASTColumnDeclaration{StringRange{begin, pos}};
node = column_declaration;
column_declaration->name = typeid_cast<ASTIdentifier &>(*name).name;
if (type)
{
column_declaration->type = type;
column_declaration->children.push_back(std::move(type));
}
if (default_expression)
{
column_declaration->default_specifier = default_specifier;
column_declaration->default_expression = default_expression;
column_declaration->children.push_back(std::move(default_expression));
}
return true;
}
class ParserColumnDeclarationList : public IParserBase
{
protected:
const char * getName() const { return "column declaration list"; }
bool parseImpl(Pos & pos, Pos end, ASTPtr & node, Expected & expected);
};
/** ENGINE = name. */
class ParserEngine : public IParserBase
{

View File

@ -18,6 +18,7 @@
#include <DB/Parsers/ASTIdentifier.h>
#include <DB/Parsers/ASTLiteral.h>
#include <DB/Parsers/ASTNameTypePair.h>
#include <DB/Parsers/ASTColumnDeclaration.h>
#include <DB/Parsers/ASTAsterisk.h>
#include <DB/Parsers/ASTOrderByElement.h>
#include <DB/Parsers/ASTSubquery.h>
@ -54,6 +55,7 @@ void formatAST(const ASTFunction & ast, std::ostream & s, size_t indent = 0, b
void formatAST(const ASTIdentifier & ast, std::ostream & s, size_t indent = 0, bool hilite = true, bool one_line = false, bool need_parens = false);
void formatAST(const ASTLiteral & ast, std::ostream & s, size_t indent = 0, bool hilite = true, bool one_line = false, bool need_parens = false);
void formatAST(const ASTNameTypePair & ast, std::ostream & s, size_t indent = 0, bool hilite = true, bool one_line = false, bool need_parens = false);
void formatAST(const ASTColumnDeclaration & ast, std::ostream & s, size_t indent = 0, bool hilite = true, bool one_line = false, bool need_parens = false);
void formatAST(const ASTAsterisk & ast, std::ostream & s, size_t indent = 0, bool hilite = true, bool one_line = false, bool need_parens = false);
void formatAST(const ASTOrderByElement & ast, std::ostream & s, size_t indent = 0, bool hilite = true, bool one_line = false, bool need_parens = false);
void formatAST(const ASTSubquery & ast, std::ostream & s, size_t indent = 0, bool hilite = true, bool one_line = false, bool need_parens = false);

View File

@ -0,0 +1,8 @@
#pragma once
#include <DB/Parsers/IAST.h>
namespace DB
{
String queryToString(const ASTPtr & query);
}

View File

@ -1,7 +1,7 @@
#pragma once
#include <DB/Core/NamesAndTypes.h>
#include <DB/DataTypes/DataTypeNested.h>
#include <DB/DataTypes/DataTypeArray.h>
#include <DB/Storages/ColumnDefault.h>
namespace DB
{
@ -23,6 +23,9 @@ struct AlterCommand
/// Для ADD и MODIFY - новый тип столбца.
DataTypePtr data_type;
ColumnDefaultType default_type{};
ASTPtr default_expression{};
/// Для ADD - после какого столбца добавить новый. Если пустая строка, добавить в конец. Добавить в начало сейчас нельзя.
String after_column;
@ -34,87 +37,32 @@ struct AlterCommand
return (name_with_dot == name_type.name.substr(0, name_without_dot.length() + 1) || name_without_dot == name_type.name);
}
void apply(NamesAndTypesList & columns) const
{
if (type == ADD)
{
if (std::count_if(columns.begin(), columns.end(), std::bind(namesEqual, column_name, std::placeholders::_1)))
throw Exception("Cannot add column " + column_name + ": column with this name already exisits.",
DB::ErrorCodes::ILLEGAL_COLUMN);
void apply(NamesAndTypesList & columns,
NamesAndTypesList & materialized_columns,
NamesAndTypesList & alias_columns,
ColumnDefaults & column_defaults) const;
if (DataTypeNested::extractNestedTableName(column_name) != column_name &&
!typeid_cast<const DataTypeArray *>(&*data_type))
throw Exception("Can't add nested column " + column_name + " of non-array type " + data_type->getName(),
ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT);
NamesAndTypesList::iterator insert_it = columns.end();
if (!after_column.empty())
{
/// Пытаемся найти первую с конца колонку с именем column_name или с именем, начинающимся с column_name и ".".
/// Например "fruits.bananas"
/// одинаковыми считаются имена, если они совпадают целиком или name_without_dot совпадает с частью имени до точки
NamesAndTypesList::reverse_iterator reverse_insert_it = std::find_if(columns.rbegin(), columns.rend(),
std::bind(namesEqual, after_column, std::placeholders::_1));
if (reverse_insert_it == columns.rend())
throw Exception("Wrong column name. Cannot find column " + column_name + " to insert after",
DB::ErrorCodes::ILLEGAL_COLUMN);
else
{
/// base возвращает итератор, уже смещенный на один элемент вправо
insert_it = reverse_insert_it.base();
}
}
columns.insert(insert_it, NameAndTypePair(column_name, data_type));
/// Медленно, так как каждый раз копируется список
columns = *DataTypeNested::expandNestedColumns(columns);
}
else if (type == DROP)
{
bool is_first = true;
NamesAndTypesList::iterator column_it;
do
{
column_it = std::find_if(columns.begin(), columns.end(), std::bind(namesEqual, column_name, std::placeholders::_1));
if (column_it == columns.end())
{
if (is_first)
throw Exception("Wrong column name. Cannot find column " + column_name + " to drop",
DB::ErrorCodes::ILLEGAL_COLUMN);
}
else
columns.erase(column_it);
is_first = false;
}
while (column_it != columns.end());
}
else if (type == MODIFY)
{
NamesAndTypesList::iterator column_it = std::find_if(columns.begin(), columns.end(),
std::bind(namesEqual, column_name, std::placeholders::_1) );
if (column_it == columns.end())
throw Exception("Wrong column name. Cannot find column " + column_name + " to modify.",
DB::ErrorCodes::ILLEGAL_COLUMN);
column_it->type = data_type;
}
else
throw Exception("Wrong parameter type in ALTER query", ErrorCodes::LOGICAL_ERROR);
}
AlterCommand() = default;
AlterCommand(const Type type, const String & column_name, const DataTypePtr & data_type,
const ColumnDefaultType default_type, const ASTPtr & default_expression,
const String & after_column = String{})
: type{type}, column_name{column_name}, data_type{data_type}, default_type{default_type},
default_expression{default_expression}, after_column{after_column}
{}
};
class IStorage;
class Context;
class AlterCommands : public std::vector<AlterCommand>
{
public:
void apply(NamesAndTypesList & columns) const
{
NamesAndTypesList new_columns = columns;
for (const AlterCommand & command : *this)
command.apply(new_columns);
columns = new_columns;
}
void apply(NamesAndTypesList & columns,
NamesAndTypesList & materialized_columns,
NamesAndTypesList & alias_columns,
ColumnDefaults & column_defaults) const;
void validate(IStorage * table, const Context & context);
};
}

View File

@ -0,0 +1,178 @@
#pragma once
#include <DB/Parsers/IAST.h>
#include <DB/Parsers/queryToString.h>
#include <DB/Parsers/ExpressionListParsers.h>
#include <DB/IO/WriteBufferFromString.h>
#include <unordered_map>
namespace DB
{
enum struct ColumnDefaultType
{
Default,
Materialized,
Alias
};
}
namespace std
{
template<> struct hash<DB::ColumnDefaultType>
{
size_t operator()(const DB::ColumnDefaultType type) const
{
return hash<int>{}(static_cast<int>(type));
}
};
}
namespace DB
{
inline ColumnDefaultType columnDefaultTypeFromString(const String & str)
{
static const std::unordered_map<String, ColumnDefaultType> map{
{ "DEFAULT", ColumnDefaultType::Default },
{ "MATERIALIZED", ColumnDefaultType::Materialized },
{ "ALIAS", ColumnDefaultType::Alias }
};
const auto it = map.find(str);
return it != std::end(map) ? it->second : throw Exception{"Unknown column default specifier: " + str};
}
inline String toString(const ColumnDefaultType type)
{
static const std::unordered_map<ColumnDefaultType, String> map{
{ ColumnDefaultType::Default, "DEFAULT" },
{ ColumnDefaultType::Materialized, "MATERIALIZED" },
{ ColumnDefaultType::Alias, "ALIAS" }
};
const auto it = map.find(type);
return it != std::end(map) ? it->second : throw Exception{"Invalid ColumnDefaultType"};
}
struct ColumnDefault
{
ColumnDefaultType type;
ASTPtr expression;
};
inline bool operator==(const ColumnDefault & lhs, const ColumnDefault & rhs)
{
return lhs.type == rhs.type && queryToString(lhs.expression) == queryToString(rhs.expression);
}
using ColumnDefaults = std::unordered_map<String, ColumnDefault>;
template <bool store>
struct ColumnsDescription
{
template <typename T> using by_value_or_cref = typename std::conditional<store, T, const T &>::type;
by_value_or_cref<NamesAndTypesList> columns;
by_value_or_cref<NamesAndTypesList> materialized;
by_value_or_cref<NamesAndTypesList> alias;
by_value_or_cref<ColumnDefaults> defaults;
String toString() const
{
String s;
WriteBufferFromString buf{s};
writeString("columns format version: 1\n", buf);
writeText(columns.size() + materialized.size() + alias.size(), buf);
writeString(" columns:\n", buf);
const auto write_columns = [this, &buf] (const NamesAndTypesList & columns) {
for (const auto & column : columns)
{
const auto it = defaults.find(column.name);
writeBackQuotedString(column.name, buf);
writeChar(' ', buf);
writeString(column.type->getName(), buf);
if (it == std::end(defaults))
{
writeChar('\n', buf);
continue;
}
else
writeChar('\t', buf);
writeString(DB::toString(it->second.type), buf);
writeChar('\t', buf);
writeString(queryToString(it->second.expression), buf);
writeChar('\n', buf);
}
};
write_columns(columns);
write_columns(materialized);
write_columns(alias);
return s;
}
static ColumnsDescription parse(const String & str, const DataTypeFactory & data_type_factory)
{
ReadBufferFromString buf{str};
assertString("columns format version: 1\n", buf);
size_t count{};
readText(count, buf);
assertString(" columns:\n", buf);
ParserTernaryOperatorExpression expr_parser;
ColumnsDescription result{};
for (size_t i = 0; i < count; ++i)
{
String column_name;
readBackQuotedString(column_name, buf);
assertString(" ", buf);
String type_name;
readString(type_name, buf);
auto type = data_type_factory.get(type_name);
if (*buf.position() == '\n')
{
assertString("\n", buf);
result.columns.emplace_back(column_name, std::move(type));
continue;
}
assertString("\t", buf);
String default_type_str;
readString(default_type_str, buf);
const auto default_type = columnDefaultTypeFromString(default_type_str);
assertString("\t", buf);
String default_expr_str;
readText(default_expr_str, buf);
assertString("\n", buf);
ASTPtr default_expr;
Expected expected{};
auto begin = default_expr_str.data();
const auto end = begin + default_expr_str.size();
if (!expr_parser.parse(begin, end, default_expr, expected))
throw Exception{"Could not parse default expression", DB::ErrorCodes::CANNOT_PARSE_TEXT};
if (ColumnDefaultType::Default == default_type)
result.columns.emplace_back(column_name, std::move(type));
else if (ColumnDefaultType::Materialized == default_type)
result.materialized.emplace_back(column_name, std::move(type));
else if (ColumnDefaultType::Alias == default_type)
result.alias.emplace_back(column_name, std::move(type));
result.defaults.emplace(column_name, ColumnDefault{default_type, default_expr});
}
assertEOF(buf);
return result;
}
};
}

View File

@ -1,7 +1,8 @@
#pragma once
#include <DB/Storages/StorageDistributed.h>
#include <DB/Storages/Distributed/queryToString.h>
#include <DB/Parsers/formatAST.h>
#include <DB/IO/WriteBufferFromFile.h>
#include <DB/IO/CompressedWriteBuffer.h>

View File

@ -1,14 +0,0 @@
#pragma once
#include <DB/Parsers/formatAST.h>
namespace DB
{
inline std::string queryToString(const ASTPtr & query)
{
std::ostringstream s;
formatAST(*query, s, 0, false, true);
return s.str();
}
}

View File

@ -14,6 +14,7 @@
#include <DB/Storages/AlterCommands.h>
#include <Poco/File.h>
#include <Poco/RWLock.h>
#include <statdaemons/stdext.h>
namespace DB
@ -107,8 +108,8 @@ public:
return res;
}
typedef Poco::SharedPtr<Poco::ScopedWriteRWLock> TableStructureWriteLockPtr;
typedef Poco::SharedPtr<Poco::ScopedWriteRWLock> TableDataWriteLockPtr;
typedef std::unique_ptr<Poco::ScopedWriteRWLock> TableStructureWriteLockPtr;
typedef std::unique_ptr<Poco::ScopedWriteRWLock> TableDataWriteLockPtr;
typedef std::pair<TableDataWriteLockPtr, TableStructureWriteLockPtr> TableFullWriteLockPtr;
/** Не дает читать структуру таблицы. Берется для ALTER, RENAME и DROP.
@ -124,7 +125,7 @@ public:
*/
TableDataWriteLockPtr lockDataForAlter()
{
TableDataWriteLockPtr res = new Poco::ScopedWriteRWLock(data_lock);
auto res = stdext::make_unique<Poco::ScopedWriteRWLock>(data_lock);
if (is_dropped)
throw Exception("Table is dropped", ErrorCodes::TABLE_IS_DROPPED);
return res;
@ -132,7 +133,7 @@ public:
TableStructureWriteLockPtr lockStructureForAlter()
{
TableStructureWriteLockPtr res = new Poco::ScopedWriteRWLock(structure_lock);
auto res = stdext::make_unique<Poco::ScopedWriteRWLock>(structure_lock);
if (is_dropped)
throw Exception("Table is dropped", ErrorCodes::TABLE_IS_DROPPED);
return res;
@ -271,7 +272,7 @@ public:
return res;
}
bool is_dropped;
bool is_dropped{false};
/// Поддерживается ли индекс в секции IN
virtual bool supportsIndexForIn() const { return false; };
@ -280,7 +281,7 @@ public:
virtual bool checkData() const { throw DB::Exception("Check query is not supported for " + getName() + " storage"); }
protected:
IStorage() : is_dropped(false) {}
using ITableDeclaration::ITableDeclaration;
private:
std::weak_ptr<IStorage> this_ptr;

View File

@ -4,6 +4,7 @@
#include <DB/Core/NamesAndTypes.h>
#include <DB/Core/Exception.h>
#include <DB/Core/Block.h>
#include <DB/Storages/ColumnDefault.h>
namespace DB
{
@ -22,7 +23,8 @@ public:
/** Получить список имён и типов столбцов таблицы, только невиртуальные.
*/
virtual const NamesAndTypesList & getColumnsList() const = 0;
NamesAndTypesList getColumnsList() const;
const NamesAndTypesList & getColumnsListNonMaterialized() const { return getColumnsListImpl(); }
/** Получить список имён столбцов таблицы, только невиртуальные.
*/
@ -36,6 +38,9 @@ public:
*/
virtual bool hasRealColumn(const String & column_name) const;
NameAndTypePair getMaterializedColumn(const String & column_name) const;
bool hasMaterializedColumn(const String & column_name) const;
/** Получить описание любого столбца по его имени.
*/
virtual NameAndTypePair getColumn(const String & column_name) const;
@ -49,6 +54,7 @@ public:
/** То же самое, но в виде блока-образца.
*/
Block getSampleBlock() const;
Block getSampleBlockNonMaterialized() const;
/** Проверить, что все запрошенные имена есть в таблице и заданы корректно.
* (список имён не пустой и имена не повторяются)
@ -69,7 +75,25 @@ public:
*/
void check(const Block & block, bool need_all = false) const;
virtual ~ITableDeclaration() {}
virtual ~ITableDeclaration() = default;
ITableDeclaration() = default;
ITableDeclaration(
const NamesAndTypesList & materialized_columns,
const NamesAndTypesList & alias_columns,
const ColumnDefaults & column_defaults)
: materialized_columns{materialized_columns},
alias_columns{alias_columns},
column_defaults{column_defaults}
{}
NamesAndTypesList materialized_columns{};
NamesAndTypesList alias_columns{};
ColumnDefaults column_defaults{};
private:
virtual const NamesAndTypesList & getColumnsListImpl() const = 0;
};
}

View File

@ -107,6 +107,47 @@ protected:
/// Будем вызывать progressImpl самостоятельно.
void progress(const Progress & value) override {}
void injectRequiredColumns(NamesAndTypesList & columns) const {
std::set<NameAndTypePair> required_columns;
auto modified = false;
for (auto it = std::begin(columns); it != std::end(columns);)
{
required_columns.emplace(*it);
if (!owned_data_part->hasColumnFiles(it->name))
{
const auto default_it = storage.column_defaults.find(it->name);
if (default_it != std::end(storage.column_defaults))
{
IdentifierNameSet identifiers;
default_it->second.expression->collectIdentifierNames(identifiers);
for (const auto & identifier : identifiers)
{
if (storage.hasColumn(identifier))
{
NameAndTypePair column{identifier, storage.getDataTypeByName(identifier)};
if (required_columns.count(column) == 0)
{
it = columns.emplace(++it, std::move(column));
modified = true;
}
}
}
if (modified)
continue;
}
}
++it;
}
if (modified)
columns = NamesAndTypesList{std::begin(required_columns), std::end(required_columns)};
}
Block readImpl()
{
Block res;
@ -120,6 +161,9 @@ protected:
/// NOTE В конструкторе это делать не получилось бы, потому что тогда ещё не установлен progress_callback.
progressImpl(Progress(0, 0, total_rows));
injectRequiredColumns(columns);
injectRequiredColumns(pre_columns);
UncompressedCache * uncompressed_cache = use_uncompressed_cache ? storage.context.getUncompressedCache() : NULL;
reader.reset(new MergeTreeReader(path, owned_data_part->name, columns, uncompressed_cache, storage, all_mark_ranges));
if (prewhere_actions)

View File

@ -585,6 +585,9 @@ public:
* require_part_metadata - обязательно ли в директории с куском должны быть checksums.txt и columns.txt
*/
MergeTreeData( const String & full_path_, NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
const Context & context_,
ASTPtr & primary_expr_ast_,
const String & date_column_name_,
@ -613,7 +616,7 @@ public:
throw Exception("Logical error: calling method getTableName of not a table.", ErrorCodes::LOGICAL_ERROR);
}
const NamesAndTypesList & getColumnsList() const { return *columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return *columns; }
NameAndTypePair getColumn(const String & column_name) const
{
@ -621,14 +624,16 @@ public:
return NameAndTypePair("_part", new DataTypeString);
if (column_name == "_part_index")
return NameAndTypePair("_part_index", new DataTypeUInt64);
return getRealColumn(column_name);
return ITableDeclaration::getColumn(column_name);
}
bool hasColumn(const String & column_name) const
{
if (column_name == "_part") return true;
if (column_name == "_part_index") return true;
return hasRealColumn(column_name);
if (column_name == "_part")
return true;
if (column_name == "_part_index")
return true;
return ITableDeclaration::hasColumn(column_name);
}
String getFullPath() const { return full_path; }

View File

@ -10,6 +10,7 @@
#include <DB/IO/CompressedReadBufferFromFile.h>
#include <DB/Columns/ColumnArray.h>
#include <DB/Columns/ColumnNested.h>
#include <DB/Interpreters/evaluateMissingDefaults.h>
namespace DB
@ -124,7 +125,7 @@ public:
storage.reportBrokenPart(part_name);
/// Более хорошая диагностика.
throw Exception(e.message() + " (while reading from part " + path + " from mark " + toString(from_mark) + " to "
throw Exception(e.message() + "\n(while reading from part " + path + " from mark " + toString(from_mark) + " to "
+ toString(to_mark) + ")", e.code());
}
catch (...)
@ -161,7 +162,8 @@ public:
size_t pos = 0; /// Позиция, куда надо вставить недостающий столбец.
for (NamesAndTypesList::const_iterator it = columns.begin(); it != columns.end(); ++it, ++pos)
{
if (!res.has(it->name))
/// insert default values only for columns without default expressions
if (!res.has(it->name) && storage.column_defaults.count(it->name) == 0)
{
ColumnWithNameAndType column;
column.name = it->name;
@ -192,11 +194,15 @@ public:
res.insert(pos, column);
}
}
/// evaluate defaulted columns
evaluateMissingDefaults(res, columns, storage.column_defaults, storage.context);
}
catch (const Exception & e)
{
/// Более хорошая диагностика.
throw Exception(e.message() + " (while reading from part " + path + ")", e.code());
throw Exception(e.message() + '\n' + e.getStackTrace().toString()
+ "\n(while reading from part " + path + ")", e.code());
}
}

View File

@ -56,7 +56,7 @@ public:
std::string getName() const override { return "Buffer"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return *columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return *columns; }
BlockInputStreams read(
const Names & column_names,

View File

@ -21,6 +21,9 @@ public:
const std::string & this_database_,/// Имя БД для этой таблицы.
const std::string & name_, /// Имя таблицы.
NamesAndTypesListPtr columns_, /// Список столбцов.
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
const String & source_database_, /// В какой БД искать таблицы-источники.
const String & table_name_regexp_, /// Регексп имён таблиц-источников.
const std::string & destination_name_prefix_, /// Префикс имен создаваемых таблиц типа Chunks.
@ -30,7 +33,7 @@ public:
std::string getName() const override { return "ChunkMerger"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return *columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return *columns; }
NameAndTypePair getColumn(const String & column_name) const override;
bool hasColumn(const String & column_name) const override;
@ -70,6 +73,9 @@ private:
const std::string & this_database_,
const std::string & name_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
const String & source_database_,
const String & table_name_regexp_,
const std::string & destination_name_prefix_,

View File

@ -5,7 +5,7 @@
namespace DB
{
/** Ссылка на кусок данных в таблице типа Chunks.
* Запись не поддерживается.
*/
@ -13,11 +13,11 @@ class StorageChunkRef : public IStorage
{
public:
static StoragePtr create(const std::string & name_, const Context & context_, const std::string & source_database_name_, const std::string & source_table_name_, bool attach);
std::string getName() const override { return "ChunkRef"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return getSource().getColumnsList(); }
const NamesAndTypesList & getColumnsListImpl() const override { return getSource().getColumnsListImpl(); }
/// В таблице, на которую мы ссылаемся, могут быть виртуальные столбцы.
NameAndTypePair getColumn(const String & column_name) const override { return getSource().getColumn(column_name); };
bool hasColumn(const String & column_name) const override { return getSource().hasColumn(column_name); };
@ -31,23 +31,23 @@ public:
unsigned threads = 1) override;
ASTPtr getCustomCreateQuery(const Context & context) const;
void drop() override;
String source_database_name;
String source_table_name;
bool checkData() const override;
private:
String name;
const Context & context;
StorageChunkRef(const std::string & name_, const Context & context_, const std::string & source_database_name_, const std::string & source_table_name_, bool attach);
/// TODO: может быть, можно просто хранить указатель на родительскую таблицу?
StorageChunks & getSource();
const StorageChunks & getSource() const;
};
}

View File

@ -7,7 +7,7 @@
namespace DB
{
/** Хранит несколько кусков данных. Читает из всех кусков.
* Запись не поддерживается. Для записи используются таблицы типа ChunkMerger.
* Таблицы типа ChunkRef могут ссылаться на отдельные куски внутри таблицы типа Chunks.
@ -20,17 +20,20 @@ class StorageChunks : public StorageLog
using StorageLog::read;
public:
static StoragePtr create(const std::string & path_,
const std::string & name_,
const std::string & database_name_,
NamesAndTypesListPtr columns_,
Context & context_,
bool attach);
const std::string & name_,
const std::string & database_name_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
Context & context_,
bool attach);
void addReference();
void removeReference();
std::string getName() const override { return "Chunks"; }
BlockInputStreams read(
const Names & column_names,
ASTPtr query,
@ -53,13 +56,13 @@ public:
BlockOutputStreamPtr writeToNewChunk(
const std::string & chunk_name);
/// Если бы запись была разрешена, непонятно, как назвать новый чанк.
BlockOutputStreamPtr write(ASTPtr query) override
{
throw Exception("Table doesn't support writing", ErrorCodes::NOT_IMPLEMENTED);
}
/// Переименование испортило бы целостность количества ссылок из таблиц ChunkRef.
void rename(const String & new_path_to_db, const String & new_database_name, const String & new_table_name) override
{
@ -79,29 +82,32 @@ private:
typedef std::vector<String> ChunkNumToChunkName;
String database_name;
ChunkNumToMark chunk_num_to_marks;
ChunkIndices chunk_indices;
ChunkNumToChunkName chunk_names;
CounterInFile reference_counter;
Context & context;
Logger * log;
StorageChunks(const std::string & path_,
const std::string & name_,
const std::string & database_name_,
NamesAndTypesListPtr columns_,
Context & context_,
bool attach);
const std::string & name_,
const std::string & database_name_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
Context & context_,
bool attach);
void dropThis();
void loadIndex();
void appendChunkToIndex(const std::string & chunk_name, size_t mark);
Block getBlockWithVirtualColumns() const;
};
}

View File

@ -25,6 +25,9 @@ public:
static StoragePtr create(
const std::string & name_, /// Имя таблицы.
NamesAndTypesListPtr columns_, /// Список столбцов.
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
const String & remote_database_, /// БД на удалённых серверах.
const String & remote_table_, /// Имя таблицы на удалённых серверах.
const String & cluster_name,
@ -46,7 +49,7 @@ public:
bool supportsFinal() const override { return true; }
bool supportsPrewhere() const override { return true; }
const NamesAndTypesList & getColumnsList() const override { return *columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return *columns; }
NameAndTypePair getColumn(const String & column_name) const override;
bool hasColumn(const String & column_name) const override;
@ -88,6 +91,19 @@ private:
const ASTPtr & sharding_key_ = nullptr,
const String & data_path_ = String{});
StorageDistributed(
const std::string & name_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
const String & remote_database_,
const String & remote_table_,
Cluster & cluster_,
Context & context_,
const ASTPtr & sharding_key_ = nullptr,
const String & data_path_ = String{});
/// create directory monitor thread by subdirectory name
void createDirectoryMonitor(const std::string & name);

View File

@ -23,6 +23,9 @@ public:
Context & context,
ASTPtr & query,
NamesAndTypesListPtr columns,
const NamesAndTypesList & materialized_columns,
const NamesAndTypesList & alias_columns,
const ColumnDefaults & column_defaults,
bool attach) const;
};

View File

@ -64,11 +64,11 @@ private:
if (offset)
plain.seek(offset);
}
ReadBufferFromFile plain;
CompressedReadBuffer compressed;
};
typedef std::map<std::string, std::unique_ptr<Stream> > FileStreams;
FileStreams streams;
@ -97,7 +97,7 @@ private:
{
plain_offset = Poco::File(data_path).getSize();
}
WriteBufferFromFile plain;
CompressedWriteBuffer compressed;
@ -111,12 +111,12 @@ private:
};
typedef std::vector<std::pair<size_t, Mark> > MarksForColumns;
typedef std::map<std::string, std::unique_ptr<Stream> > FileStreams;
FileStreams streams;
typedef std::set<std::string> OffsetColumns;
WriteBufferFromFile marks_stream; /// Объявлен ниже lock, чтобы файл открывался при захваченном rwlock.
void addStream(const String & name, const IDataType & type, size_t level = 0);
@ -143,12 +143,21 @@ public:
const std::string & path_,
const std::string & name_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
size_t max_compress_block_size_ = DEFAULT_MAX_COMPRESS_BLOCK_SIZE);
static StoragePtr create(
const std::string & path_,
const std::string & name_,
NamesAndTypesListPtr columns_,
size_t max_compress_block_size_ = DEFAULT_MAX_COMPRESS_BLOCK_SIZE);
std::string getName() const override { return "Log"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return *columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return *columns; }
virtual BlockInputStreams read(
const Names & column_names,
@ -196,16 +205,23 @@ protected:
throw Exception("There is no column " + _table_column_name + " in table " + getTableName(), ErrorCodes::NO_SUCH_COLUMN_IN_TABLE);
}
StorageLog(const std::string & path_, const std::string & name_, NamesAndTypesListPtr columns_, size_t max_compress_block_size_);
StorageLog(
const std::string & path_,
const std::string & name_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
size_t max_compress_block_size_);
/// Прочитать файлы с засечками, если они ещё не прочитаны.
/// Делается лениво, чтобы при большом количестве таблиц, сервер быстро стартовал.
/// Нельзя вызывать с залоченным на запись rwlock.
void loadMarks();
/// Можно вызывать при любом состоянии rwlock.
size_t marksCount();
BlockInputStreams read(
size_t from_mark,
size_t to_mark,
@ -215,14 +231,14 @@ protected:
QueryProcessingStage::Enum & processed_stage,
size_t max_block_size = DEFAULT_BLOCK_SIZE,
unsigned threads = 1);
private:
Files_t files; /// name -> data
Names column_names; /// column_index -> name
Poco::File marks_file;
/// Порядок добавления файлов не должен меняться: он соответствует порядку столбцов в файле с засечками.
void addFile(const String & column_name, const IDataType & type, size_t level = 0);

View File

@ -9,8 +9,16 @@ namespace DB
class StorageMaterializedView : public StorageView {
public:
static StoragePtr create(const String & table_name_, const String & database_name_,
Context & context_, ASTPtr & query_, NamesAndTypesListPtr columns_, bool attach_);
static StoragePtr create(
const String & table_name_,
const String & database_name_,
Context & context_,
ASTPtr & query_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
bool attach_);
std::string getName() const override { return "MaterializedView"; }
std::string getInnerTableName() const { return ".inner." + table_name; }
@ -37,8 +45,16 @@ public:
private:
StoragePtr data;
StorageMaterializedView(const String & table_name_, const String & database_name_,
Context & context_, ASTPtr & query_, NamesAndTypesListPtr columns_, bool attach_);
StorageMaterializedView(
const String & table_name_,
const String & database_name_,
Context & context_,
ASTPtr & query_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
bool attach_);
};
}

View File

@ -62,12 +62,21 @@ friend class MemoryBlockInputStream;
friend class MemoryBlockOutputStream;
public:
static StoragePtr create(const std::string & name_, NamesAndTypesListPtr columns_);
static StoragePtr create(
const std::string & name_,
NamesAndTypesListPtr columns_);
static StoragePtr create(
const std::string & name_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_);
std::string getName() const override { return "Memory"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return *columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return *columns; }
size_t getSize() const { return data.size(); }
@ -93,7 +102,16 @@ private:
Poco::FastMutex mutex;
StorageMemory(const std::string & name_, NamesAndTypesListPtr columns_);
StorageMemory(
const std::string & name_,
NamesAndTypesListPtr columns_);
StorageMemory(
const std::string & name_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_);
};
}

View File

@ -25,6 +25,16 @@ public:
const String & table_name_regexp_, /// Регексп имён таблиц-источников.
const Context & context_); /// Известные таблицы.
static StoragePtr create(
const std::string & name_, /// Имя таблицы.
NamesAndTypesListPtr columns_, /// Список столбцов.
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
const String & source_database_, /// В какой БД искать таблицы-источники.
const String & table_name_regexp_, /// Регексп имён таблиц-источников.
const Context & context_); /// Известные таблицы.
std::string getName() const override { return "Merge"; }
std::string getTableName() const override { return name; }
bool supportsSampling() const override { return true; }
@ -32,9 +42,9 @@ public:
/// Проверка откладывается до метода read. Там проверяется поддержка PREWHERE у использующихся таблиц.
bool supportsPrewhere() const override { return true; }
const NamesAndTypesList & getColumnsList() const override { return *columns; }
NameAndTypePair getColumn(const String & column_name) const override;
bool hasColumn(const String & column_name) const override;
const NamesAndTypesList & getColumnsListImpl() const override { return *columns; }
NameAndTypePair getColumn(const String &column_name) const override;
bool hasColumn(const String &column_name) const override;
BlockInputStreams read(
const Names & column_names,
@ -65,6 +75,16 @@ private:
const String & table_name_regexp_,
const Context & context_);
StorageMerge(
const std::string & name_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
const String & source_database_,
const String & table_name_regexp_,
const Context & context_);
void getSelectedTables(StorageVector & selected_tables) const;
Block getBlockWithVirtualColumns(const StorageVector & selected_tables) const;

View File

@ -24,7 +24,27 @@ public:
* date_column_name - имя столбца с датой;
* index_granularity - на сколько строчек пишется одно значение индекса.
*/
static StoragePtr create(const String & path_, const String & database_name_, const String & table_name_,
static StoragePtr create(
const String & path_,
const String & database_name_,
const String & table_name_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
Context & context_,
ASTPtr & primary_expr_ast_,
const String & date_column_name_,
const ASTPtr & sampling_expression_, /// nullptr, если семплирование не поддерживается.
size_t index_granularity_,
MergeTreeData::Mode mode_ = MergeTreeData::Ordinary,
const String & sign_column_ = "",
const MergeTreeSettings & settings_ = MergeTreeSettings());
static StoragePtr create(
const String & path_,
const String & database_name_,
const String & table_name_,
NamesAndTypesListPtr columns_,
Context & context_,
ASTPtr & primary_expr_ast_,
@ -35,6 +55,7 @@ public:
const String & sign_column_ = "",
const MergeTreeSettings & settings_ = MergeTreeSettings());
void shutdown() override;
~StorageMergeTree() override;
@ -48,7 +69,7 @@ public:
bool supportsFinal() const override { return data.supportsFinal(); }
bool supportsPrewhere() const override { return data.supportsPrewhere(); }
const NamesAndTypesList & getColumnsList() const override { return data.getColumnsList(); }
const NamesAndTypesList & getColumnsListImpl() const override { return data.getColumnsListNonMaterialized(); }
NameAndTypePair getColumn(const String & column_name) const override
{
@ -157,16 +178,22 @@ private:
typedef Poco::SharedPtr<CurrentlyMergingPartsTagger> CurrentlyMergingPartsTaggerPtr;
StorageMergeTree(const String & path_, const String & database_name_, const String & table_name_,
NamesAndTypesListPtr columns_,
Context & context_,
ASTPtr & primary_expr_ast_,
const String & date_column_name_,
const ASTPtr & sampling_expression_, /// nullptr, если семплирование не поддерживается.
size_t index_granularity_,
MergeTreeData::Mode mode_,
const String & sign_column_,
const MergeTreeSettings & settings_);
StorageMergeTree(
const String & path_,
const String & database_name_,
const String & table_name_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
Context & context_,
ASTPtr & primary_expr_ast_,
const String & date_column_name_,
const ASTPtr & sampling_expression_, /// nullptr, если семплирование не поддерживается.
size_t index_granularity_,
MergeTreeData::Mode mode_,
const String & sign_column_,
const MergeTreeSettings & settings_);
/** Определяет, какие куски нужно объединять, и объединяет их.
* Если aggressive - выбрать куски, не обращая внимание на соотношение размеров и их новизну (для запроса OPTIMIZE).

View File

@ -15,15 +15,20 @@ namespace DB
class StorageNull : public IStorage
{
public:
static StoragePtr create(const std::string & name_, NamesAndTypesListPtr columns_)
static StoragePtr create(
const std::string & name_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_)
{
return (new StorageNull(name_, columns_))->thisPtr();
return (new StorageNull{name_, columns_, materialized_columns_, alias_columns_, column_defaults_})->thisPtr();
}
std::string getName() const override { return "Null"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return *columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return *columns; }
BlockInputStreams read(
const Names & column_names,
@ -47,8 +52,13 @@ private:
String name;
NamesAndTypesListPtr columns;
StorageNull(const std::string & name_, NamesAndTypesListPtr columns_)
: name(name_), columns(columns_) {}
StorageNull(
const std::string & name_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_)
: IStorage{materialized_columns_, alias_columns_, column_defaults_}, name(name_), columns(columns_) {}
};
}

View File

@ -31,6 +31,9 @@ public:
bool attach,
const String & path_, const String & database_name_, const String & name_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
Context & context_,
ASTPtr & primary_expr_ast_,
const String & date_column_name_,
@ -53,7 +56,7 @@ public:
bool supportsFinal() const override { return data.supportsFinal(); }
bool supportsPrewhere() const override { return data.supportsPrewhere(); }
const NamesAndTypesList & getColumnsList() const override { return data.getColumnsList(); }
const NamesAndTypesList & getColumnsListImpl() const override { return data.getColumnsListNonMaterialized(); }
NameAndTypePair getColumn(const String & column_name) const override
{
@ -248,6 +251,9 @@ private:
bool attach,
const String & path_, const String & database_name_, const String & name_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
Context & context_,
ASTPtr & primary_expr_ast_,
const String & date_column_name_,

View File

@ -22,7 +22,7 @@ public:
std::string getName() const override { return "SystemDatabases"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return columns; }
BlockInputStreams read(
const Names & column_names,

View File

@ -21,7 +21,7 @@ public:
std::string getName() const override { return "SystemEvents"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return columns; }
BlockInputStreams read(
const Names & column_names,

View File

@ -13,7 +13,7 @@ public:
std::string getName() const override { return "SystemMerges"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return columns; }
BlockInputStreams read(
const Names & column_names,
ASTPtr query,

View File

@ -19,11 +19,11 @@ class StorageSystemNumbers : public IStorage
{
public:
static StoragePtr create(const std::string & name_, bool multithreaded_ = false);
std::string getName() const override { return "SystemNumbers"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return columns; }
BlockInputStreams read(
const Names & column_names,
@ -37,7 +37,7 @@ private:
const std::string name;
NamesAndTypesList columns;
bool multithreaded;
StorageSystemNumbers(const std::string & name_, bool multithreaded_);
};

View File

@ -16,11 +16,11 @@ class StorageSystemOne : public IStorage
{
public:
static StoragePtr create(const std::string & name_);
std::string getName() const override { return "SystemOne"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return columns; }
BlockInputStreams read(
const Names & column_names,
@ -33,7 +33,7 @@ public:
private:
const std::string name;
NamesAndTypesList columns;
StorageSystemOne(const std::string & name_);
};

View File

@ -22,7 +22,7 @@ public:
std::string getName() const override{ return "SystemParts"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return columns; }
BlockInputStreams read(
const Names & column_names,

View File

@ -22,7 +22,7 @@ public:
std::string getName() const override { return "SystemProcesses"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return columns; }
BlockInputStreams read(
const Names & column_names,

View File

@ -22,7 +22,7 @@ public:
std::string getName() const override { return "SystemReplicas"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return columns; }
BlockInputStreams read(
const Names & column_names,

View File

@ -22,7 +22,7 @@ public:
std::string getName() const override { return "SystemSettings"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return columns; }
BlockInputStreams read(
const Names & column_names,

View File

@ -22,7 +22,7 @@ public:
std::string getName() const override { return "SystemTables"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return columns; }
BlockInputStreams read(
const Names & column_names,
@ -38,6 +38,8 @@ private:
NamesAndTypesList columns;
StorageSystemTables(const std::string & name_, const Context & context_);
ColumnWithNameAndType getFilteredDatabases(ASTPtr query);
};
}

View File

@ -22,7 +22,7 @@ public:
std::string getName() const override { return "SystemZooKeeper"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return columns; }
BlockInputStreams read(
const Names & column_names,

View File

@ -29,7 +29,7 @@ public:
String getName() const { return "TinyLogBlockInputStream"; }
String getID() const;
protected:
Block readImpl();
private:
@ -89,7 +89,7 @@ private:
typedef std::map<std::string, std::unique_ptr<Stream> > FileStreams;
FileStreams streams;
typedef std::set<std::string> OffsetColumns;
void addStream(const String & name, const IDataType & type, size_t level = 0);
@ -115,13 +115,16 @@ public:
const std::string & path_,
const std::string & name_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
bool attach,
size_t max_compress_block_size_ = DEFAULT_MAX_COMPRESS_BLOCK_SIZE);
std::string getName() const override { return "TinyLog"; }
std::string getTableName() const override { return name; }
const NamesAndTypesList & getColumnsList() const override { return *columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return *columns; }
BlockInputStreams read(
const Names & column_names,
@ -134,7 +137,7 @@ public:
BlockOutputStreamPtr write(ASTPtr query) override;
void drop() override;
void rename(const String & new_path_to_db, const String & new_database_name, const String & new_table_name) override;
bool checkData() const override;
@ -148,7 +151,7 @@ public:
Files_t & getFiles();
std::string full_path() { return path + escapeForFileName(name) + '/';}
std::string full_path() { return path + escapeForFileName(name) + '/';}
private:
String path;
@ -163,8 +166,16 @@ private:
Logger * log;
StorageTinyLog(const std::string & path_, const std::string & name_, NamesAndTypesListPtr columns_, bool attach, size_t max_compress_block_size_);
StorageTinyLog(
const std::string & path_,
const std::string & name_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_,
bool attach,
size_t max_compress_block_size_);
void addFile(const String & column_name, const IDataType & type, size_t level = 0);
};

View File

@ -11,12 +11,19 @@ class StorageView : public IStorage
{
public:
static StoragePtr create(const String & table_name_, const String & database_name_,
Context & context_, ASTPtr & query_, NamesAndTypesListPtr columns_);
static StoragePtr create(
const String & table_name_,
const String & database_name_,
Context & context_,
ASTPtr & query_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_);
std::string getName() const override { return "View"; }
std::string getTableName() const override { return table_name; }
const NamesAndTypesList & getColumnsList() const override { return *columns; }
const NamesAndTypesList & getColumnsListImpl() const override { return *columns; }
ASTPtr getInnerQuery() const { return inner_query.clone(); };
/// Пробрасывается внутрь запроса и решается на его уровне.
@ -42,8 +49,15 @@ protected:
Context & context;
NamesAndTypesListPtr columns;
StorageView(const String & table_name_, const String & database_name_,
Context & context_, ASTPtr & query_, NamesAndTypesListPtr columns_);
StorageView(
const String & table_name_,
const String & database_name_,
Context & context_,
ASTPtr & query_,
NamesAndTypesListPtr columns_,
const NamesAndTypesList & materialized_columns_,
const NamesAndTypesList & alias_columns_,
const ColumnDefaults & column_defaults_);
};
}

View File

@ -48,7 +48,8 @@ public:
/// Нам необходимо его пометить как имя базы данных, поскольку по умолчанию стоит значение column
typeid_cast<ASTIdentifier &>(*args[0]).kind = ASTIdentifier::Database;
return StorageMerge::create(getName(), chooseColumns(source_database, table_name_regexp, context), source_database, table_name_regexp, context);
return StorageMerge::create(getName(), chooseColumns(source_database, table_name_regexp, context),
source_database, table_name_regexp, context);
}
private:

View File

@ -5,9 +5,17 @@
#include <DB/Core/Block.h>
#include <DB/Storages/ColumnDefault.h>
#include <DB/Columns/ColumnArray.h>
#include <DB/DataTypes/DataTypeNested.h>
#include <DB/Parsers/ASTExpressionList.h>
#include <DB/Interpreters/ExpressionAnalyzer.h>
#include <statdaemons/stdext.h>
#include <DB/Parsers/formatAST.h>
namespace DB
{
@ -19,20 +27,11 @@ Block::Block(const Block & other)
}
void Block::addDefaults(NamesAndTypesListPtr required_columns)
void Block::addDefaults(const NamesAndTypesList & required_columns)
{
for (NamesAndTypesList::const_iterator it = required_columns->begin(); it != required_columns->end(); ++it)
{
if (!has(it->name))
{
ColumnWithNameAndType col;
col.name = it->name;
col.type = it->type;
col.column = dynamic_cast<IColumnConst &>(*it->type->createConstColumn(
rows(), it->type->getDefault())).convertToFullColumn();
insert(col);
}
}
for (const auto & column : required_columns)
if (!has(column.name))
insertDefault(column.name, column.type);
}
Block & Block::operator= (const Block & other)
@ -82,6 +81,16 @@ void Block::insert(const ColumnWithNameAndType & elem)
index_by_position.push_back(it);
}
void Block::insertDefault(const String & name, const DataTypePtr & type)
{
insert({
dynamic_cast<IColumnConst &>(*type->createConstColumn(rows(),
type->getDefault())).convertToFullColumn(),
type, name
});
}
void Block::insertUnique(const ColumnWithNameAndType & elem)
{

View File

@ -6,23 +6,19 @@ namespace DB
void registerFunctionsArithmetic(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction*
factory.registerFunction("plus", F { return new FunctionPlus; });
factory.registerFunction("minus", F { return new FunctionMinus; });
factory.registerFunction("multiply", F { return new FunctionMultiply; });
factory.registerFunction("divide", F { return new FunctionDivideFloating; });
factory.registerFunction("intDiv", F { return new FunctionDivideIntegral; });
factory.registerFunction("modulo", F { return new FunctionModulo; });
factory.registerFunction("negate", F { return new FunctionNegate; });
factory.registerFunction("bitAnd", F { return new FunctionBitAnd; });
factory.registerFunction("bitOr", F { return new FunctionBitOr; });
factory.registerFunction("bitXor", F { return new FunctionBitXor; });
factory.registerFunction("bitNot", F { return new FunctionBitNot; });
factory.registerFunction("bitShiftLeft", F { return new FunctionBitShiftLeft; });
factory.registerFunction("bitShiftRight", F { return new FunctionBitShiftRight; });
#undef F
factory.registerFunction<FunctionPlus>();
factory.registerFunction<FunctionMinus>();
factory.registerFunction<FunctionMultiply>();
factory.registerFunction<FunctionDivideFloating>();
factory.registerFunction<FunctionDivideIntegral>();
factory.registerFunction<FunctionModulo>();
factory.registerFunction<FunctionNegate>();
factory.registerFunction<FunctionBitAnd>();
factory.registerFunction<FunctionBitOr>();
factory.registerFunction<FunctionBitXor>();
factory.registerFunction<FunctionBitNot>();
factory.registerFunction<FunctionBitShiftLeft>();
factory.registerFunction<FunctionBitShiftRight>();
}
}

View File

@ -6,31 +6,26 @@ namespace DB
void registerFunctionsArray(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction *
factory.registerFunction("array", F { return new FunctionArray; });
factory.registerFunction("arrayElement", F { return new FunctionArrayElement; });
factory.registerFunction("has", F { return new FunctionHas; });
factory.registerFunction("indexOf", F { return new FunctionIndexOf; });
factory.registerFunction("countEqual", F { return new FunctionCountEqual; });
factory.registerFunction("arrayEnumerate", F { return new FunctionArrayEnumerate; });
factory.registerFunction("arrayEnumerateUniq", F { return new FunctionArrayEnumerateUniq; });
factory.registerFunction("emptyArrayUInt8", F { return new FunctionEmptyArrayUInt8; });
factory.registerFunction("emptyArrayUInt16", F { return new FunctionEmptyArrayUInt16; });
factory.registerFunction("emptyArrayUInt32", F { return new FunctionEmptyArrayUInt32; });
factory.registerFunction("emptyArrayUInt64", F { return new FunctionEmptyArrayUInt64; });
factory.registerFunction("emptyArrayInt8", F { return new FunctionEmptyArrayInt8; });
factory.registerFunction("emptyArrayInt16", F { return new FunctionEmptyArrayInt16; });
factory.registerFunction("emptyArrayInt32", F { return new FunctionEmptyArrayInt32; });
factory.registerFunction("emptyArrayInt64", F { return new FunctionEmptyArrayInt64; });
factory.registerFunction("emptyArrayFloat32", F { return new FunctionEmptyArrayFloat32; });
factory.registerFunction("emptyArrayFloat64", F { return new FunctionEmptyArrayFloat64; });
factory.registerFunction("emptyArrayDate", F { return new FunctionEmptyArrayDate; });
factory.registerFunction("emptyArrayDateTime", F { return new FunctionEmptyArrayDateTime; });
factory.registerFunction("emptyArrayString", F { return new FunctionEmptyArrayString; });
#undef F
factory.registerFunction<FunctionArray>();
factory.registerFunction<FunctionArrayElement>();
factory.registerFunction<FunctionHas>();
factory.registerFunction<FunctionIndexOf>();
factory.registerFunction<FunctionCountEqual>();
factory.registerFunction<FunctionArrayEnumerate>();
factory.registerFunction<FunctionArrayEnumerateUniq>();
factory.registerFunction<FunctionEmptyArrayUInt8>();
factory.registerFunction<FunctionEmptyArrayUInt16>();
factory.registerFunction<FunctionEmptyArrayUInt32>();
factory.registerFunction<FunctionEmptyArrayUInt64>();
factory.registerFunction<FunctionEmptyArrayInt8>();
factory.registerFunction<FunctionEmptyArrayInt16>();
factory.registerFunction<FunctionEmptyArrayInt32>();
factory.registerFunction<FunctionEmptyArrayInt64>();
factory.registerFunction<FunctionEmptyArrayFloat32>();
factory.registerFunction<FunctionEmptyArrayFloat64>();
factory.registerFunction<FunctionEmptyArrayDate>();
factory.registerFunction<FunctionEmptyArrayDateTime>();
factory.registerFunction<FunctionEmptyArrayString>();
}
}

View File

@ -6,18 +6,14 @@ namespace DB
void registerFunctionsCoding(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction *
factory.registerFunction("toStringCutToZero", F { return new FunctionToStringCutToZero; });
factory.registerFunction("IPv6NumToString", F { return new FunctionIPv6NumToString; });
factory.registerFunction("IPv6StringToNum", F { return new FunctionIPv6StringToNum; });
factory.registerFunction("IPv4NumToString", F { return new FunctionIPv4NumToString; });
factory.registerFunction("IPv4StringToNum", F { return new FunctionIPv4StringToNum; });
factory.registerFunction("hex", F { return new FunctionHex; });
factory.registerFunction("unhex", F { return new FunctionUnhex; });
factory.registerFunction("bitmaskToArray", F { return new FunctionBitmaskToArray; });
#undef F
factory.registerFunction<FunctionToStringCutToZero>();
factory.registerFunction<FunctionIPv6NumToString>();
factory.registerFunction<FunctionIPv6StringToNum>();
factory.registerFunction<FunctionIPv4NumToString>();
factory.registerFunction<FunctionIPv4StringToNum>();
factory.registerFunction<FunctionHex>();
factory.registerFunction<FunctionUnhex>();
factory.registerFunction<FunctionBitmaskToArray>();
}
}

View File

@ -6,16 +6,12 @@ namespace DB
void registerFunctionsComparison(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction*
factory.registerFunction("equals", F { return new FunctionEquals; });
factory.registerFunction("notEquals", F { return new FunctionNotEquals; });
factory.registerFunction("less", F { return new FunctionLess; });
factory.registerFunction("greater", F { return new FunctionGreater; });
factory.registerFunction("lessOrEquals", F { return new FunctionLessOrEquals; });
factory.registerFunction("greaterOrEquals", F { return new FunctionGreaterOrEquals; });
#undef F
factory.registerFunction<FunctionEquals>();
factory.registerFunction<FunctionNotEquals>();
factory.registerFunction<FunctionLess>();
factory.registerFunction<FunctionGreater>();
factory.registerFunction<FunctionLessOrEquals>();
factory.registerFunction<FunctionGreaterOrEquals>();
}
}

View File

@ -6,11 +6,7 @@ namespace DB
void registerFunctionsConditional(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction*
factory.registerFunction("if", F { return new FunctionIf; });
#undef F
factory.registerFunction<FunctionIf>();
}
}

View File

@ -6,24 +6,20 @@ namespace DB
void registerFunctionsConversion(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction*
factory.registerFunction("toUInt8", F { return new FunctionToUInt8; });
factory.registerFunction("toUInt16", F { return new FunctionToUInt16; });
factory.registerFunction("toUInt32", F { return new FunctionToUInt32; });
factory.registerFunction("toUInt64", F { return new FunctionToUInt64; });
factory.registerFunction("toInt8", F { return new FunctionToInt8; });
factory.registerFunction("toInt16", F { return new FunctionToInt16; });
factory.registerFunction("toInt32", F { return new FunctionToInt32; });
factory.registerFunction("toInt64", F { return new FunctionToInt64; });
factory.registerFunction("toFloat32", F { return new FunctionToFloat32; });
factory.registerFunction("toFloat64", F { return new FunctionToFloat64; });
factory.registerFunction("toDate", F { return new FunctionToDate; });
factory.registerFunction("toDateTime", F { return new FunctionToDateTime; });
factory.registerFunction("toString", F { return new FunctionToString; });
factory.registerFunction("toFixedString", F { return new FunctionToFixedString; });
#undef F
factory.registerFunction<FunctionToUInt8>();
factory.registerFunction<FunctionToUInt16>();
factory.registerFunction<FunctionToUInt32>();
factory.registerFunction<FunctionToUInt64>();
factory.registerFunction<FunctionToInt8>();
factory.registerFunction<FunctionToInt16>();
factory.registerFunction<FunctionToInt32>();
factory.registerFunction<FunctionToInt64>();
factory.registerFunction<FunctionToFloat32>();
factory.registerFunction<FunctionToFloat64>();
factory.registerFunction<FunctionToDate>();
factory.registerFunction<FunctionToDateTime>();
factory.registerFunction<FunctionToString>();
factory.registerFunction<FunctionToFixedString>();
}
}

View File

@ -6,36 +6,32 @@ namespace DB
void registerFunctionsDateTime(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction*
factory.registerFunction("toYear", F { return new FunctionToYear; });
factory.registerFunction("toMonth", F { return new FunctionToMonth; });
factory.registerFunction("toDayOfMonth", F { return new FunctionToDayOfMonth; });
factory.registerFunction("toDayOfWeek", F { return new FunctionToDayOfWeek; });
factory.registerFunction("toHour", F { return new FunctionToHour; });
factory.registerFunction("toMinute", F { return new FunctionToMinute; });
factory.registerFunction("toSecond", F { return new FunctionToSecond; });
factory.registerFunction("toMonday", F { return new FunctionToMonday; });
factory.registerFunction("toStartOfMonth", F { return new FunctionToStartOfMonth; });
factory.registerFunction("toStartOfQuarter", F { return new FunctionToStartOfQuarter; });
factory.registerFunction("toStartOfYear", F { return new FunctionToStartOfYear; });
factory.registerFunction("toStartOfMinute", F { return new FunctionToStartOfMinute; });
factory.registerFunction("toStartOfHour", F { return new FunctionToStartOfHour; });
factory.registerFunction("toRelativeYearNum", F { return new FunctionToRelativeYearNum; });
factory.registerFunction("toRelativeMonthNum", F { return new FunctionToRelativeMonthNum; });
factory.registerFunction("toRelativeWeekNum", F { return new FunctionToRelativeWeekNum; });
factory.registerFunction("toRelativeDayNum", F { return new FunctionToRelativeDayNum; });
factory.registerFunction("toRelativeHourNum", F { return new FunctionToRelativeHourNum; });
factory.registerFunction("toRelativeMinuteNum", F { return new FunctionToRelativeMinuteNum; });
factory.registerFunction("toRelativeSecondNum", F { return new FunctionToRelativeSecondNum; });
factory.registerFunction("toTime", F { return new FunctionToTime; });
factory.registerFunction("now", F { return new FunctionNow; });
factory.registerFunction("today", F { return new FunctionToday; });
factory.registerFunction("yesterday", F { return new FunctionYesterday; });
factory.registerFunction("timeSlot", F { return new FunctionTimeSlot; });
factory.registerFunction("timeSlots", F { return new FunctionTimeSlots; });
#undef F
factory.registerFunction<FunctionToYear>();
factory.registerFunction<FunctionToMonth>();
factory.registerFunction<FunctionToDayOfMonth>();
factory.registerFunction<FunctionToDayOfWeek>();
factory.registerFunction<FunctionToHour>();
factory.registerFunction<FunctionToMinute>();
factory.registerFunction<FunctionToSecond>();
factory.registerFunction<FunctionToMonday>();
factory.registerFunction<FunctionToStartOfMonth>();
factory.registerFunction<FunctionToStartOfQuarter>();
factory.registerFunction<FunctionToStartOfYear>();
factory.registerFunction<FunctionToStartOfMinute>();
factory.registerFunction<FunctionToStartOfHour>();
factory.registerFunction<FunctionToRelativeYearNum>();
factory.registerFunction<FunctionToRelativeMonthNum>();
factory.registerFunction<FunctionToRelativeWeekNum>();
factory.registerFunction<FunctionToRelativeDayNum>();
factory.registerFunction<FunctionToRelativeHourNum>();
factory.registerFunction<FunctionToRelativeMinuteNum>();
factory.registerFunction<FunctionToRelativeSecondNum>();
factory.registerFunction<FunctionToTime>();
factory.registerFunction<FunctionNow>();
factory.registerFunction<FunctionToday>();
factory.registerFunction<FunctionYesterday>();
factory.registerFunction<FunctionTimeSlot>();
factory.registerFunction<FunctionTimeSlots>();
}
}

View File

@ -6,46 +6,24 @@ namespace DB
void registerFunctionsDictionaries(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction*
factory.registerFunction("regionToCity",
F { return new FunctionRegionToCity(context.getDictionaries().getRegionsHierarchies()); });
factory.registerFunction("regionToArea",
F { return new FunctionRegionToArea(context.getDictionaries().getRegionsHierarchies()); });
factory.registerFunction("regionToDistrict",
F { return new FunctionRegionToDistrict(context.getDictionaries().getRegionsHierarchies()); });
factory.registerFunction("regionToCountry",
F { return new FunctionRegionToCountry(context.getDictionaries().getRegionsHierarchies()); });
factory.registerFunction("regionToContinent",
F { return new FunctionRegionToContinent(context.getDictionaries().getRegionsHierarchies()); });
factory.registerFunction("OSToRoot",
F { return new FunctionOSToRoot(context.getDictionaries().getTechDataHierarchy()); });
factory.registerFunction("SEToRoot",
F { return new FunctionSEToRoot(context.getDictionaries().getTechDataHierarchy()); });
factory.registerFunction("categoryToRoot",
F { return new FunctionCategoryToRoot(context.getDictionaries().getCategoriesHierarchy()); });
factory.registerFunction("categoryToSecondLevel",
F { return new FunctionCategoryToSecondLevel(context.getDictionaries().getCategoriesHierarchy()); });
factory.registerFunction("regionIn",
F { return new FunctionRegionIn(context.getDictionaries().getRegionsHierarchies()); });
factory.registerFunction("OSIn",
F { return new FunctionOSIn(context.getDictionaries().getTechDataHierarchy()); });
factory.registerFunction("SEIn",
F { return new FunctionSEIn(context.getDictionaries().getTechDataHierarchy()); });
factory.registerFunction("categoryIn",
F { return new FunctionCategoryIn(context.getDictionaries().getCategoriesHierarchy()); });
factory.registerFunction("regionHierarchy",
F { return new FunctionRegionHierarchy(context.getDictionaries().getRegionsHierarchies()); });
factory.registerFunction("OSHierarchy",
F { return new FunctionOSHierarchy(context.getDictionaries().getTechDataHierarchy()); });
factory.registerFunction("SEHierarchy",
F { return new FunctionSEHierarchy(context.getDictionaries().getTechDataHierarchy()); });
factory.registerFunction("categoryHierarchy",
F { return new FunctionCategoryHierarchy(context.getDictionaries().getCategoriesHierarchy()); });
factory.registerFunction("regionToName",
F { return new FunctionRegionToName(context.getDictionaries().getRegionsNames()); });
#undef F
factory.registerFunction<FunctionRegionToCity>();
factory.registerFunction<FunctionRegionToArea>();
factory.registerFunction<FunctionRegionToDistrict>();
factory.registerFunction<FunctionRegionToCountry>();
factory.registerFunction<FunctionRegionToContinent>();
factory.registerFunction<FunctionOSToRoot>();
factory.registerFunction<FunctionSEToRoot>();
factory.registerFunction<FunctionCategoryToRoot>();
factory.registerFunction<FunctionCategoryToSecondLevel>();
factory.registerFunction<FunctionRegionIn>();
factory.registerFunction<FunctionOSIn>();
factory.registerFunction<FunctionSEIn>();
factory.registerFunction<FunctionCategoryIn>();
factory.registerFunction<FunctionRegionHierarchy>();
factory.registerFunction<FunctionOSHierarchy>();
factory.registerFunction<FunctionSEHierarchy>();
factory.registerFunction<FunctionCategoryHierarchy>();
factory.registerFunction<FunctionRegionToName>();
}
}

View File

@ -6,11 +6,7 @@ namespace DB
void registerFunctionsFormatting(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction*
factory.registerFunction("bitmaskToList", F { return new FunctionBitmaskToList; });
#undef F
factory.registerFunction<FunctionBitmaskToList>();
}
}

View File

@ -7,20 +7,16 @@ namespace DB
void registerFunctionsHashing(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction *
factory.registerFunction("halfMD5", F { return new FunctionHalfMD5; });
factory.registerFunction("MD5", F { return new FunctionMD5; });
factory.registerFunction("SHA1", F { return new FunctionSHA1; });
factory.registerFunction("SHA224", F { return new FunctionSHA224; });
factory.registerFunction("SHA256", F { return new FunctionSHA256; });
factory.registerFunction("sipHash64", F { return new FunctionSipHash64; });
factory.registerFunction("sipHash128", F { return new FunctionSipHash128; });
factory.registerFunction("cityHash64", F { return new FunctionCityHash64; });
factory.registerFunction("intHash32", F { return new FunctionIntHash32; });
factory.registerFunction("intHash64", F { return new FunctionIntHash64; });
#undef F
factory.registerFunction<FunctionHalfMD5>();
factory.registerFunction<FunctionMD5>();
factory.registerFunction<FunctionSHA1>();
factory.registerFunction<FunctionSHA224>();
factory.registerFunction<FunctionSHA256>();
factory.registerFunction<FunctionSipHash64>();
factory.registerFunction<FunctionSipHash128>();
factory.registerFunction<FunctionCityHash64>();
factory.registerFunction<FunctionIntHash32>();
factory.registerFunction<FunctionIntHash64>();
}
}

View File

@ -6,18 +6,14 @@ namespace DB
void registerFunctionsHigherOrder(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction *
factory.registerFunction("arrayMap", F { return new FunctionArrayMap; });
factory.registerFunction("arrayFilter", F { return new FunctionArrayFilter; });
factory.registerFunction("arrayCount", F { return new FunctionArrayCount; });
factory.registerFunction("arrayExists", F { return new FunctionArrayExists; });
factory.registerFunction("arrayAll", F { return new FunctionArrayAll; });
factory.registerFunction("arraySum", F { return new FunctionArraySum; });
factory.registerFunction("arrayFirst", F { return new FunctionArrayFirst; });
factory.registerFunction("arrayFirstIndex", F { return new FunctionArrayFirstIndex; });
#undef F
factory.registerFunction<FunctionArrayMap>();
factory.registerFunction<FunctionArrayFilter>();
factory.registerFunction<FunctionArrayCount>();
factory.registerFunction<FunctionArrayExists>();
factory.registerFunction<FunctionArrayAll>();
factory.registerFunction<FunctionArraySum>();
factory.registerFunction<FunctionArrayFirst>();
factory.registerFunction<FunctionArrayFirstIndex>();
}
}

View File

@ -6,14 +6,10 @@ namespace DB
void registerFunctionsLogical(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction*
factory.registerFunction("and", F { return new FunctionAnd; });
factory.registerFunction("or", F { return new FunctionOr; });
factory.registerFunction("xor", F { return new FunctionXor; });
factory.registerFunction("not", F { return new FunctionNot; });
#undef F
factory.registerFunction<FunctionAnd>();
factory.registerFunction<FunctionOr>();
factory.registerFunction<FunctionXor>();
factory.registerFunction<FunctionNot>();
}
}

View File

@ -305,27 +305,23 @@ namespace DB
void registerFunctionsMiscellaneous(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction*
factory.registerFunction<FunctionCurrentDatabase>();
factory.registerFunction<FunctionHostName>();
factory.registerFunction<FunctionVisibleWidth>();
factory.registerFunction<FunctionToTypeName>();
factory.registerFunction<FunctionBlockSize>();
factory.registerFunction<FunctionSleep>();
factory.registerFunction<FunctionMaterialize>();
factory.registerFunction<FunctionIgnore>();
factory.registerFunction<FunctionArrayJoin>();
factory.registerFunction<FunctionBar>();
factory.registerFunction("currentDatabase", F { return new FunctionCurrentDatabase{context.getCurrentDatabase()}; });
factory.registerFunction("hostName", F { return new FunctionHostName; });
factory.registerFunction("visibleWidth", F { return new FunctionVisibleWidth; });
factory.registerFunction("toTypeName", F { return new FunctionToTypeName; });
factory.registerFunction("blockSize", F { return new FunctionBlockSize; });
factory.registerFunction("sleep", F { return new FunctionSleep; });
factory.registerFunction("materialize", F { return new FunctionMaterialize; });
factory.registerFunction("ignore", F { return new FunctionIgnore; });
factory.registerFunction("arrayJoin", F { return new FunctionArrayJoin; });
factory.registerFunction("bar", F { return new FunctionBar; });
factory.registerFunction("tuple", F { return new FunctionTuple; });
factory.registerFunction("tupleElement", F { return new FunctionTupleElement; });
factory.registerFunction("in", F { return new FunctionIn(false, false); });
factory.registerFunction("notIn", F { return new FunctionIn(true, false); });
factory.registerFunction("globalIn", F { return new FunctionIn(false, true); });
factory.registerFunction("globalNotIn", F { return new FunctionIn(true, true); });
#undef F
factory.registerFunction<FunctionTuple>();
factory.registerFunction<FunctionTupleElement>();
factory.registerFunction<FunctionIn<false, false>>();
factory.registerFunction<FunctionIn<false, true>>();
factory.registerFunction<FunctionIn<true, false>>();
factory.registerFunction<FunctionIn<true, true>>();
}
}

View File

@ -6,12 +6,8 @@ namespace DB
void registerFunctionsRandom(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction*
factory.registerFunction("rand", F { return new FunctionRand; });
factory.registerFunction("rand64", F { return new FunctionRand64; });
#undef F
factory.registerFunction<FunctionRand>();
factory.registerFunction<FunctionRand64>();
}
}

View File

@ -6,23 +6,19 @@ namespace DB
void registerFunctionsReinterpret(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction*
factory.registerFunction("reinterpretAsUInt8", F { return new FunctionReinterpretAsUInt8; });
factory.registerFunction("reinterpretAsUInt16", F { return new FunctionReinterpretAsUInt16; });
factory.registerFunction("reinterpretAsUInt32", F { return new FunctionReinterpretAsUInt32; });
factory.registerFunction("reinterpretAsUInt64", F { return new FunctionReinterpretAsUInt64; });
factory.registerFunction("reinterpretAsInt8", F { return new FunctionReinterpretAsInt8; });
factory.registerFunction("reinterpretAsInt16", F { return new FunctionReinterpretAsInt16; });
factory.registerFunction("reinterpretAsInt32", F { return new FunctionReinterpretAsInt32; });
factory.registerFunction("reinterpretAsInt64", F { return new FunctionReinterpretAsInt64; });
factory.registerFunction("reinterpretAsFloat32", F { return new FunctionReinterpretAsFloat32; });
factory.registerFunction("reinterpretAsFloat64", F { return new FunctionReinterpretAsFloat64; });
factory.registerFunction("reinterpretAsDate", F { return new FunctionReinterpretAsDate; });
factory.registerFunction("reinterpretAsDateTime", F { return new FunctionReinterpretAsDateTime; });
factory.registerFunction("reinterpretAsString", F { return new FunctionReinterpretAsString; });
#undef F
factory.registerFunction<FunctionReinterpretAsUInt8>();
factory.registerFunction<FunctionReinterpretAsUInt16>();
factory.registerFunction<FunctionReinterpretAsUInt32>();
factory.registerFunction<FunctionReinterpretAsUInt64>();
factory.registerFunction<FunctionReinterpretAsInt8>();
factory.registerFunction<FunctionReinterpretAsInt16>();
factory.registerFunction<FunctionReinterpretAsInt32>();
factory.registerFunction<FunctionReinterpretAsInt64>();
factory.registerFunction<FunctionReinterpretAsFloat32>();
factory.registerFunction<FunctionReinterpretAsFloat64>();
factory.registerFunction<FunctionReinterpretAsDate>();
factory.registerFunction<FunctionReinterpretAsDateTime>();
factory.registerFunction<FunctionReinterpretAsString>();
}
}

View File

@ -6,13 +6,9 @@ namespace DB
void registerFunctionsRound(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction*
factory.registerFunction("roundToExp2", F { return new FunctionRoundToExp2; });
factory.registerFunction("roundDuration", F { return new FunctionRoundDuration; });
factory.registerFunction("roundAge", F { return new FunctionRoundAge; });
#undef F
factory.registerFunction<FunctionRoundToExp2>();
factory.registerFunction<FunctionRoundDuration>();
factory.registerFunction<FunctionRoundAge>();
}
}

View File

@ -6,23 +6,19 @@ namespace DB
void registerFunctionsString(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction*
factory.registerFunction("empty", F { return new FunctionEmpty; });
factory.registerFunction("notEmpty", F { return new FunctionNotEmpty; });
factory.registerFunction("length", F { return new FunctionLength; });
factory.registerFunction("lengthUTF8", F { return new FunctionLengthUTF8; });
factory.registerFunction("lower", F { return new FunctionLower; });
factory.registerFunction("upper", F { return new FunctionUpper; });
factory.registerFunction("lowerUTF8", F { return new FunctionLowerUTF8; });
factory.registerFunction("upperUTF8", F { return new FunctionUpperUTF8; });
factory.registerFunction("reverse", F { return new FunctionReverse; });
factory.registerFunction("reverseUTF8", F { return new FunctionReverseUTF8; });
factory.registerFunction("concat", F { return new FunctionConcat; });
factory.registerFunction("substring", F { return new FunctionSubstring; });
factory.registerFunction("substringUTF8", F { return new FunctionSubstringUTF8; });
#undef F
factory.registerFunction<FunctionEmpty>();
factory.registerFunction<FunctionNotEmpty>();
factory.registerFunction<FunctionLength>();
factory.registerFunction<FunctionLengthUTF8>();
factory.registerFunction<FunctionLower>();
factory.registerFunction<FunctionUpper>();
factory.registerFunction<FunctionLowerUTF8>();
factory.registerFunction<FunctionUpperUTF8>();
factory.registerFunction<FunctionReverse>();
factory.registerFunction<FunctionReverseUTF8>();
factory.registerFunction<FunctionConcat>();
factory.registerFunction<FunctionSubstring>();
factory.registerFunction<FunctionSubstringUTF8>();
}
}

View File

@ -6,14 +6,10 @@ namespace DB
void registerFunctionsStringArray(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction*
factory.registerFunction("extractAll", F { return new FunctionExtractAll; });
factory.registerFunction("alphaTokens", F { return new FunctionAlphaTokens; });
factory.registerFunction("splitByChar", F { return new FunctionSplitByChar; });
factory.registerFunction("splitByString", F { return new FunctionSplitByString; });
#undef F
factory.registerFunction<FunctionExtractAll>();
factory.registerFunction<FunctionAlphaTokens>();
factory.registerFunction<FunctionSplitByChar>();
factory.registerFunction<FunctionSplitByString>();
}
}

View File

@ -6,20 +6,16 @@ namespace DB
void registerFunctionsStringSearch(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction*
factory.registerFunction("replaceOne", F { return new FunctionReplaceOne; });
factory.registerFunction("replaceAll", F { return new FunctionReplaceAll; });
factory.registerFunction("replaceRegexpOne", F { return new FunctionReplaceRegexpOne; });
factory.registerFunction("replaceRegexpAll", F { return new FunctionReplaceRegexpAll; });
factory.registerFunction("position", F { return new FunctionPosition; });
factory.registerFunction("positionUTF8", F { return new FunctionPositionUTF8; });
factory.registerFunction("match", F { return new FunctionMatch; });
factory.registerFunction("like", F { return new FunctionLike; });
factory.registerFunction("notLike", F { return new FunctionNotLike; });
factory.registerFunction("extract", F { return new FunctionExtract; });
#undef F
factory.registerFunction<FunctionReplaceOne>();
factory.registerFunction<FunctionReplaceAll>();
factory.registerFunction<FunctionReplaceRegexpOne>();
factory.registerFunction<FunctionReplaceRegexpAll>();
factory.registerFunction<FunctionPosition>();
factory.registerFunction<FunctionPositionUTF8>();
factory.registerFunction<FunctionMatch>();
factory.registerFunction<FunctionLike>();
factory.registerFunction<FunctionNotLike>();
factory.registerFunction<FunctionExtract>();
}
}

View File

@ -6,30 +6,26 @@ namespace DB
void registerFunctionsURL(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction*
factory.registerFunction("protocol", F { return new FunctionProtocol; });
factory.registerFunction("domain", F { return new FunctionDomain; });
factory.registerFunction("domainWithoutWWW", F { return new FunctionDomainWithoutWWW; });
factory.registerFunction("firstSignificantSubdomain", F { return new FunctionFirstSignificantSubdomain; });
factory.registerFunction("topLevelDomain", F { return new FunctionTopLevelDomain; });
factory.registerFunction("path", F { return new FunctionPath; });
factory.registerFunction("queryString", F { return new FunctionQueryString; });
factory.registerFunction("fragment", F { return new FunctionFragment; });
factory.registerFunction("queryStringAndFragment", F { return new FunctionQueryStringAndFragment; });
factory.registerFunction("extractURLParameter", F { return new FunctionExtractURLParameter; });
factory.registerFunction("extractURLParameters", F { return new FunctionExtractURLParameters; });
factory.registerFunction("extractURLParameterNames", F { return new FunctionExtractURLParameterNames; });
factory.registerFunction("URLHierarchy", F { return new FunctionURLHierarchy; });
factory.registerFunction("URLPathHierarchy", F { return new FunctionURLPathHierarchy; });
factory.registerFunction("cutToFirstSignificantSubdomain", F { return new FunctionCutToFirstSignificantSubdomain; });
factory.registerFunction("cutWWW", F { return new FunctionCutWWW; });
factory.registerFunction("cutQueryString", F { return new FunctionCutQueryString; });
factory.registerFunction("cutFragment", F { return new FunctionCutFragment; });
factory.registerFunction("cutQueryStringAndFragment", F { return new FunctionCutQueryStringAndFragment; });
factory.registerFunction("cutURLParameter", F { return new FunctionCutURLParameter; });
#undef F
factory.registerFunction<FunctionProtocol>();
factory.registerFunction<FunctionDomain>();
factory.registerFunction<FunctionDomainWithoutWWW>();
factory.registerFunction<FunctionFirstSignificantSubdomain>();
factory.registerFunction<FunctionTopLevelDomain>();
factory.registerFunction<FunctionPath>();
factory.registerFunction<FunctionQueryString>();
factory.registerFunction<FunctionFragment>();
factory.registerFunction<FunctionQueryStringAndFragment>();
factory.registerFunction<FunctionExtractURLParameter>();
factory.registerFunction<FunctionExtractURLParameters>();
factory.registerFunction<FunctionExtractURLParameterNames>();
factory.registerFunction<FunctionURLHierarchy>();
factory.registerFunction<FunctionURLPathHierarchy>();
factory.registerFunction<FunctionCutToFirstSignificantSubdomain>();
factory.registerFunction<FunctionCutWWW>();
factory.registerFunction<FunctionCutQueryString>();
factory.registerFunction<FunctionCutFragment>();
factory.registerFunction<FunctionCutQueryStringAndFragment>();
factory.registerFunction<FunctionCutURLParameter>();
}
}

View File

@ -6,17 +6,13 @@ namespace DB
void registerFunctionsVisitParam(FunctionFactory & factory)
{
#define F [](const Context & context) -> IFunction*
factory.registerFunction("visitParamHas", F { return new FunctionVisitParamHas; });
factory.registerFunction("visitParamExtractUInt", F { return new FunctionVisitParamExtractUInt; });
factory.registerFunction("visitParamExtractInt", F { return new FunctionVisitParamExtractInt; });
factory.registerFunction("visitParamExtractFloat", F { return new FunctionVisitParamExtractFloat; });
factory.registerFunction("visitParamExtractBool", F { return new FunctionVisitParamExtractBool; });
factory.registerFunction("visitParamExtractRaw", F { return new FunctionVisitParamExtractRaw; });
factory.registerFunction("visitParamExtractString", F { return new FunctionVisitParamExtractString; });
#undef F
factory.registerFunction<FunctionVisitParamHas>();
factory.registerFunction<FunctionVisitParamExtractUInt>();
factory.registerFunction<FunctionVisitParamExtractInt>();
factory.registerFunction<FunctionVisitParamExtractFloat>();
factory.registerFunction<FunctionVisitParamExtractBool>();
factory.registerFunction<FunctionVisitParamExtractRaw>();
factory.registerFunction<FunctionVisitParamExtractString>();
}
}

View File

@ -63,8 +63,10 @@ void ExpressionAnalyzer::init()
{
select_query = typeid_cast<ASTSelectQuery *>(&*ast);
addStorageAliases();
/// Создаёт словарь aliases: alias -> ASTPtr
createAliasesDict(ast);
addASTAliases(ast);
/// Common subexpression elimination. Rewrite rules.
normalizeTree();
@ -235,9 +237,19 @@ NamesAndTypesList::iterator ExpressionAnalyzer::findColumn(const String & name,
}
void ExpressionAnalyzer::addStorageAliases()
{
if (!storage)
return;
for (const auto & alias : storage->alias_columns)
aliases[alias.name] = storage->column_defaults[alias.name].expression;
}
/// ignore_levels - алиасы в скольки верхних уровнях поддерева нужно игнорировать.
/// Например, при ignore_levels=1 ast не может быть занесен в словарь, но его дети могут.
void ExpressionAnalyzer::createAliasesDict(ASTPtr & ast, int ignore_levels)
void ExpressionAnalyzer::addASTAliases(ASTPtr & ast, int ignore_levels)
{
ASTSelectQuery * select = typeid_cast<ASTSelectQuery *>(&*ast);
@ -252,7 +264,7 @@ void ExpressionAnalyzer::createAliasesDict(ASTPtr & ast, int ignore_levels)
new_ignore_levels = 2;
if (!typeid_cast<ASTSelectQuery *>(&*child))
createAliasesDict(child, new_ignore_levels);
addASTAliases(child, new_ignore_levels);
}
if (ignore_levels > 0)
@ -1689,18 +1701,34 @@ void ExpressionAnalyzer::collectUsedColumns()
++it;
}
/// Возможно, среди неизвестных столбцов есть виртуальные. Удаляем их из списка неизвестных и добавляем
/// в columns list, чтобы при дальнейшей обработке запроса они воспринимались как настоящие.
for (NameSet::iterator it = unknown_required_columns.begin(); it != unknown_required_columns.end();)
for (NamesAndTypesList::iterator it = columns.begin(); it != columns.end();)
{
if (storage && storage->hasColumn(*it))
unknown_required_columns.erase(it->name);
if (!required.count(it->name))
{
columns.push_back(storage->getColumn(*it));
unknown_required_columns.erase(it++);
required.erase(it->name);
columns.erase(it++);
}
else
++it;
}
/// Возможно, среди неизвестных столбцов есть виртуальные. Удаляем их из списка неизвестных и добавляем
/// в columns list, чтобы при дальнейшей обработке запроса они воспринимались как настоящие.
if (storage)
{
for (auto it = unknown_required_columns.begin(); it != unknown_required_columns.end();)
{
if (storage->hasColumn(*it))
{
columns.push_back(storage->getColumn(*it));
unknown_required_columns.erase(it++);
}
else
++it;
}
}
}
void ExpressionAnalyzer::collectJoinedColumns(NameSet & joined_columns, NamesAndTypesList & joined_columns_name_type)

View File

@ -28,15 +28,15 @@ InterpreterAlterQuery::InterpreterAlterQuery(ASTPtr query_ptr_, Context & contex
void InterpreterAlterQuery::execute()
{
ASTAlterQuery & alter = typeid_cast<ASTAlterQuery &>(*query_ptr);
String & table_name = alter.table;
auto & alter = typeid_cast<ASTAlterQuery &>(*query_ptr);
const String & table_name = alter.table;
String database_name = alter.database.empty() ? context.getCurrentDatabase() : alter.database;
StoragePtr table = context.getTable(database_name, table_name);
AlterCommands alter_commands;
PartitionCommands partition_commands;
parseAlter(alter.parameters, context.getDataTypeFactory(), alter_commands, partition_commands);
StoragePtr table = context.getTable(database_name, table_name);
for (const PartitionCommand & command : partition_commands)
{
switch (command.type)
@ -62,8 +62,12 @@ void InterpreterAlterQuery::execute()
}
}
if (!alter_commands.empty())
table->alter(alter_commands, database_name, table_name, context);
if (alter_commands.empty())
return;
alter_commands.validate(table.get(), context);
table->alter(alter_commands, database_name, table_name, context);
}
void InterpreterAlterQuery::parseAlter(
@ -77,12 +81,20 @@ void InterpreterAlterQuery::parseAlter(
AlterCommand command;
command.type = AlterCommand::ADD;
const ASTNameTypePair & ast_name_type = typeid_cast<const ASTNameTypePair &>(*params.name_type);
StringRange type_range = ast_name_type.type->range;
String type_string = String(type_range.first, type_range.second - type_range.first);
const auto & ast_col_decl = typeid_cast<const ASTColumnDeclaration &>(*params.col_decl);
command.column_name = ast_name_type.name;
command.data_type = data_type_factory.get(type_string);
command.column_name = ast_col_decl.name;
if (ast_col_decl.type)
{
StringRange type_range = ast_col_decl.type->range;
String type_string(type_range.first, type_range.second - type_range.first);
command.data_type = data_type_factory.get(type_string);
}
if (ast_col_decl.default_expression)
{
command.default_type = columnDefaultTypeFromString(ast_col_decl.default_specifier);
command.default_expression = ast_col_decl.default_expression;
}
if (params.column)
command.after_column = typeid_cast<const ASTIdentifier &>(*params.column).name;
@ -102,12 +114,21 @@ void InterpreterAlterQuery::parseAlter(
AlterCommand command;
command.type = AlterCommand::MODIFY;
const ASTNameTypePair & ast_name_type = typeid_cast<const ASTNameTypePair &>(*params.name_type);
StringRange type_range = ast_name_type.type->range;
String type_string = String(type_range.first, type_range.second - type_range.first);
const auto & ast_col_decl = typeid_cast<const ASTColumnDeclaration &>(*params.col_decl);
command.column_name = ast_name_type.name;
command.data_type = data_type_factory.get(type_string);
command.column_name = ast_col_decl.name;
if (ast_col_decl.type)
{
StringRange type_range = ast_col_decl.type->range;
String type_string(type_range.first, type_range.second - type_range.first);
command.data_type = data_type_factory.get(type_string);
}
if (ast_col_decl.default_expression)
{
command.default_type = columnDefaultTypeFromString(ast_col_decl.default_specifier);
command.default_expression = ast_col_decl.default_expression;
}
out_alter_commands.push_back(command);
}
@ -137,7 +158,13 @@ void InterpreterAlterQuery::parseAlter(
}
void InterpreterAlterQuery::updateMetadata(
const String & database_name, const String & table_name, const NamesAndTypesList & columns, Context & context)
const String & database_name,
const String & table_name,
const NamesAndTypesList & columns,
const NamesAndTypesList & materialized_columns,
const NamesAndTypesList & alias_columns,
const ColumnDefaults & column_defaults,
Context & context)
{
String path = context.getPath();
@ -172,7 +199,7 @@ void InterpreterAlterQuery::updateMetadata(
ASTCreateQuery & attach = typeid_cast<ASTCreateQuery &>(*ast);
ASTPtr new_columns = InterpreterCreateQuery::formatColumns(columns);
ASTPtr new_columns = InterpreterCreateQuery::formatColumns(columns, materialized_columns, alias_columns, column_defaults);
*std::find(attach.children.begin(), attach.children.end(), attach.columns) = new_columns;
attach.columns = new_columns;

View File

@ -11,6 +11,7 @@
#include <DB/Parsers/ASTCreateQuery.h>
#include <DB/Parsers/ASTNameTypePair.h>
#include <DB/Parsers/ASTColumnDeclaration.h>
#include <DB/Storages/StorageLog.h>
#include <DB/Storages/StorageSystemNumbers.h>
@ -20,6 +21,8 @@
#include <DB/Interpreters/InterpreterSelectQuery.h>
#include <DB/Interpreters/InterpreterCreateQuery.h>
#include <DB/Interpreters/ExpressionAnalyzer.h>
#include <DB/DataTypes/DataTypesNumberFixed.h>
#include <DB/DataTypes/DataTypeNested.h>
@ -87,6 +90,9 @@ StoragePtr InterpreterCreateQuery::execute(bool assume_metadata_exists)
StoragePtr res;
String storage_name;
NamesAndTypesListPtr columns = new NamesAndTypesList;
NamesAndTypesList materialized_columns{};
NamesAndTypesList alias_columns{};
ColumnDefaults column_defaults{};
StoragePtr as_storage;
IStorage::TableStructureReadLockPtr as_storage_lock;
@ -115,10 +121,22 @@ StoragePtr InterpreterCreateQuery::execute(bool assume_metadata_exists)
/// Получаем список столбцов
if (create.columns)
{
columns = new NamesAndTypesList(parseColumns(create.columns, context.getDataTypeFactory()));
auto && columns_and_defaults = parseColumns(create.columns);
materialized_columns = removeAndReturnColumns(columns_and_defaults, ColumnDefaultType::Materialized);
alias_columns = removeAndReturnColumns(columns_and_defaults, ColumnDefaultType::Alias);
columns = new NamesAndTypesList{std::move(columns_and_defaults.first)};
column_defaults = std::move(columns_and_defaults.second);
if (columns->size() + materialized_columns.size() == 0)
throw Exception{"Cannot CREATE table without physical columns", ErrorCodes::EMPTY_LIST_OF_COLUMNS_PASSED};
}
else if (!create.as_table.empty())
columns = new NamesAndTypesList(as_storage->getColumnsList());
{
columns = new NamesAndTypesList(as_storage->getColumnsListNonMaterialized());
materialized_columns = as_storage->materialized_columns;
alias_columns = as_storage->alias_columns;
column_defaults = as_storage->column_defaults;
}
else if (create.select)
{
columns = new NamesAndTypesList;
@ -129,7 +147,7 @@ StoragePtr InterpreterCreateQuery::execute(bool assume_metadata_exists)
throw Exception("Incorrect CREATE query: required list of column descriptions or AS section or SELECT.", ErrorCodes::INCORRECT_QUERY);
/// Даже если в запросе был список столбцов, на всякий случай приведем его к стандартному виду (развернем Nested).
ASTPtr new_columns = formatColumns(*columns);
ASTPtr new_columns = formatColumns(*columns, materialized_columns, alias_columns, column_defaults);
if (create.columns)
{
auto it = std::find(create.children.begin(), create.children.end(), create.columns);
@ -178,7 +196,8 @@ StoragePtr InterpreterCreateQuery::execute(bool assume_metadata_exists)
res = context.getStorageFactory().get(
storage_name, data_path, table_name, database_name, context,
context.getGlobalContext(), query_ptr, columns, create.attach);
context.getGlobalContext(), query_ptr, columns,
materialized_columns, alias_columns, column_defaults, create.attach);
/// Проверка наличия метаданных таблицы на диске и создание метаданных
if (!assume_metadata_exists && !create.is_temporary)
@ -233,47 +252,195 @@ StoragePtr InterpreterCreateQuery::execute(bool assume_metadata_exists)
return res;
}
NamesAndTypesList InterpreterCreateQuery::parseColumns(ASTPtr expression_list, const DataTypeFactory & data_type_factory)
InterpreterCreateQuery::ColumnsAndDefaults InterpreterCreateQuery::parseColumns(ASTPtr expression_list)
{
NamesAndTypesList columns;
ASTExpressionList & columns_list = typeid_cast<ASTExpressionList &>(*expression_list);
for (const ASTPtr & ast : columns_list.children)
auto & column_list_ast = typeid_cast<ASTExpressionList &>(*expression_list);
/// list of table columns in correct order
NamesAndTypesList columns{};
ColumnDefaults defaults{};
/// Columns requiring type-deduction or default_expression type-check
std::vector<std::pair<NameAndTypePair *, ASTColumnDeclaration *>> defaulted_columns{};
/** all default_expressions as a single expression list,
* mixed with conversion-columns for each explicitly specified type */
ASTPtr default_expr_list{new ASTExpressionList};
default_expr_list->children.reserve(column_list_ast.children.size());
for (auto & ast : column_list_ast.children)
{
const ASTNameTypePair & name_and_type_pair = typeid_cast<const ASTNameTypePair &>(*ast);
StringRange type_range = name_and_type_pair.type->range;
columns.push_back(NameAndTypePair(
name_and_type_pair.name,
data_type_factory.get(String(type_range.first, type_range.second - type_range.first))));
auto & col_decl = typeid_cast<ASTColumnDeclaration &>(*ast);
if (col_decl.type)
{
const auto & type_range = col_decl.type->range;
columns.emplace_back(col_decl.name,
context.getDataTypeFactory().get({ type_range.first, type_range.second }));
}
else
/// we're creating dummy DataTypeUInt8 in order to prevent the NullPointerException in ExpressionActions
columns.emplace_back(col_decl.name, new DataTypeUInt8);
/// add column to postprocessing if there is a default_expression specified
if (col_decl.default_expression)
{
defaulted_columns.emplace_back(&columns.back(), &col_decl);
/** for columns with explicitly-specified type create two expressions:
* 1. default_expression aliased as column name with _tmp suffix
* 2. conversion of expression (1) to explicitly-specified type alias as column name */
if (col_decl.type)
{
const auto tmp_column_name = col_decl.name + "_tmp";
const auto & final_column_name = col_decl.name;
const auto conversion_function_name = "to" + columns.back().type->getName();
default_expr_list->children.emplace_back(setAlias(
makeASTFunction(conversion_function_name, ASTPtr{new ASTIdentifier{{}, tmp_column_name}}),
final_column_name));
default_expr_list->children.emplace_back(setAlias(col_decl.default_expression->clone(), tmp_column_name));
}
else
{
default_expr_list->children.emplace_back(setAlias(col_decl.default_expression->clone(), col_decl.name));
}
}
}
columns = *DataTypeNested::expandNestedColumns(columns);
return columns;
/// set missing types and wrap default_expression's in a conversion-function if necessary
if (!defaulted_columns.empty())
{
const auto actions = ExpressionAnalyzer{default_expr_list, context, columns}.getActions(true);
const auto block = actions->getSampleBlock();
for (auto & column : defaulted_columns)
{
const auto name_and_type_ptr = column.first;
const auto col_decl_ptr = column.second;
if (col_decl_ptr->type)
{
const auto & tmp_column = block.getByName(col_decl_ptr->name + "_tmp");
/// type mismatch between explicitly specified and deduced type, add conversion
if (typeid(*name_and_type_ptr->type) != typeid(*tmp_column.type))
{
col_decl_ptr->default_expression = makeASTFunction(
"to" + name_and_type_ptr->type->getName(),
col_decl_ptr->default_expression);
col_decl_ptr->children.clear();
col_decl_ptr->children.push_back(col_decl_ptr->type);
col_decl_ptr->children.push_back(col_decl_ptr->default_expression);
}
}
else
name_and_type_ptr->type = block.getByName(name_and_type_ptr->name).type;
defaults.emplace(col_decl_ptr->name, ColumnDefault{
columnDefaultTypeFromString(col_decl_ptr->default_specifier),
col_decl_ptr->default_expression
});
}
}
return { *DataTypeNested::expandNestedColumns(columns), defaults };
}
NamesAndTypesList InterpreterCreateQuery::removeAndReturnColumns(ColumnsAndDefaults & columns_and_defaults,
const ColumnDefaultType type)
{
auto & columns = columns_and_defaults.first;
auto & defaults = columns_and_defaults.second;
NamesAndTypesList removed{};
for (auto it = std::begin(columns); it != std::end(columns);)
{
const auto jt = defaults.find(it->name);
if (jt != std::end(defaults) && jt->second.type == type)
{
removed.push_back(*it);
it = columns.erase(it);
}
else
++it;
}
return removed;
}
ASTPtr InterpreterCreateQuery::formatColumns(const NamesAndTypesList & columns)
{
ASTPtr columns_list_ptr = new ASTExpressionList;
ASTPtr columns_list_ptr{new ASTExpressionList};
ASTExpressionList & columns_list = typeid_cast<ASTExpressionList &>(*columns_list_ptr);
for (const NameAndTypePair & it : columns)
for (const auto & column : columns)
{
ASTPtr name_and_type_pair_ptr = new ASTNameTypePair;
ASTNameTypePair & name_and_type_pair = typeid_cast<ASTNameTypePair &>(*name_and_type_pair_ptr);
name_and_type_pair.name = it.name;
StringPtr type_name = new String(it.type->getName());
const auto column_declaration = new ASTColumnDeclaration;
ASTPtr column_declaration_ptr{column_declaration};
column_declaration->name = column.name;
StringPtr type_name{new String(column.type->getName())};
auto pos = type_name->data();
const auto end = pos + type_name->size();
ParserIdentifierWithOptionalParameters storage_p;
Expected expected = "";
const char * pos = type_name->data();
const char * end = pos + type_name->size();
if (!storage_p.parse(pos, end, name_and_type_pair.type, expected))
Expected expected{""};
if (!storage_p.parse(pos, end, column_declaration->type, expected))
throw Exception("Cannot parse data type.", ErrorCodes::SYNTAX_ERROR);
name_and_type_pair.type->query_string = type_name;
columns_list.children.push_back(name_and_type_pair_ptr);
column_declaration->type->query_string = type_name;
columns_list.children.push_back(column_declaration_ptr);
}
return columns_list_ptr;
}
ASTPtr InterpreterCreateQuery::formatColumns(NamesAndTypesList columns,
const NamesAndTypesList & materialized_columns,
const NamesAndTypesList & alias_columns,
const ColumnDefaults & column_defaults)
{
columns.insert(std::end(columns), std::begin(materialized_columns), std::end(materialized_columns));
columns.insert(std::end(columns), std::begin(alias_columns), std::end(alias_columns));
ASTPtr columns_list_ptr{new ASTExpressionList};
ASTExpressionList & columns_list = typeid_cast<ASTExpressionList &>(*columns_list_ptr);
for (const auto & column : columns)
{
const auto column_declaration = new ASTColumnDeclaration;
ASTPtr column_declaration_ptr{column_declaration};
column_declaration->name = column.name;
StringPtr type_name{new String(column.type->getName())};
auto pos = type_name->data();
const auto end = pos + type_name->size();
ParserIdentifierWithOptionalParameters storage_p;
Expected expected{""};
if (!storage_p.parse(pos, end, column_declaration->type, expected))
throw Exception("Cannot parse data type.", ErrorCodes::SYNTAX_ERROR);
column_declaration->type->query_string = type_name;
const auto it = column_defaults.find(column.name);
if (it != std::end(column_defaults))
{
column_declaration->default_specifier = toString(it->second.type);
column_declaration->default_expression = it->second.expression->clone();
}
columns_list.children.push_back(column_declaration_ptr);
}
return columns_list_ptr;
}
}

Some files were not shown because too many files have changed in this diff Show More