Allowed hash functions to be constant expressions [#CLICKHOUSE-2819].

This commit is contained in:
Alexey Milovidov 2017-02-08 23:33:50 +03:00
parent 9bbe8fe5c4
commit 40e71651e5
3 changed files with 23 additions and 6 deletions

View File

@ -552,7 +552,7 @@ private:
void executeForArgument(const IDataType * type, const IColumn * column, ColumnUInt64::Container_t & vec_to, bool & is_first) void executeForArgument(const IDataType * type, const IColumn * column, ColumnUInt64::Container_t & vec_to, bool & is_first)
{ {
/// Раскрытие кортежей. /// Flattening of tuples.
if (const ColumnTuple * tuple = typeid_cast<const ColumnTuple *>(column)) if (const ColumnTuple * tuple = typeid_cast<const ColumnTuple *>(column))
{ {
const Block & tuple_data = tuple->getData(); const Block & tuple_data = tuple->getData();
@ -579,7 +579,6 @@ private:
} }
public: public:
/// Получить имя функции.
String getName() const override String getName() const override
{ {
return name; return name;
@ -588,13 +587,11 @@ public:
bool isVariadic() const override { return true; } bool isVariadic() const override { return true; }
size_t getNumberOfArguments() const override { return 0; } size_t getNumberOfArguments() const override { return 0; }
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
{ {
return std::make_shared<DataTypeUInt64>(); return std::make_shared<DataTypeUInt64>();
} }
/// Выполнить функцию над блоком.
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
{ {
size_t rows = block.rows(); size_t rows = block.rows();
@ -605,11 +602,11 @@ public:
if (arguments.empty()) if (arguments.empty())
{ {
/// Случайное число из /dev/urandom используется как хеш пустого количества аргументов. /// Constant random number from /dev/urandom is used as a hash value of empty list of arguments.
vec_to.assign(rows, 0xe28dbde7fe22e41c); vec_to.assign(rows, 0xe28dbde7fe22e41c);
} }
/// Функция поддерживает произвольное количество аргументов всевозможных типов. /// The function supports arbitary number of arguments of arbitary types.
bool is_first_argument = true; bool is_first_argument = true;
for (size_t i = 0; i < arguments.size(); ++i) for (size_t i = 0; i < arguments.size(); ++i)
@ -617,6 +614,21 @@ public:
const ColumnWithTypeAndName & col = block.safeGetByPosition(arguments[i]); const ColumnWithTypeAndName & col = block.safeGetByPosition(arguments[i]);
executeForArgument(col.type.get(), col.column.get(), vec_to, is_first_argument); executeForArgument(col.type.get(), col.column.get(), vec_to, is_first_argument);
} }
/// If all arguments are constants, we should return constant result.
bool all_constants = true;
for (size_t arg_idx : arguments)
{
if (!block.getByPosition(arg_idx).column->isConst())
{
all_constants = false;
break;
}
}
if (all_constants && block.rows() > 0)
block.getByPosition(result).column = block.getByPosition(result).type->createConstColumn(1, (*block.getByPosition(result).column)[0]);
} }
}; };

View File

@ -0,0 +1,3 @@
1
1
0

View File

@ -0,0 +1,2 @@
SELECT cityHash64('abc') IN cityHash64('abc');
SELECT cityHash64(arrayJoin(['abc', 'def'])) IN cityHash64('abc');