mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 09:02:00 +00:00
Support for NULLs in function if: continued [#CLICKHOUSE-2873].
This commit is contained in:
parent
169fc988b7
commit
f9a5902e76
@ -1,14 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <string.h> // memcpy
|
||||
|
||||
#include <DB/Common/Exception.h>
|
||||
#include <DB/Common/Arena.h>
|
||||
#include <DB/Common/SipHash.h>
|
||||
|
||||
#include <DB/Columns/IColumn.h>
|
||||
#include <DB/Columns/ColumnsNumber.h>
|
||||
#include <DB/Columns/ColumnString.h>
|
||||
#include <DB/Columns/ColumnVector.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
@ -32,261 +25,35 @@ public:
|
||||
using ColumnOffsets_t = ColumnVector<Offset_t>;
|
||||
|
||||
/** Создать пустой столбец массивов, с типом значений, как в столбце nested_column */
|
||||
explicit ColumnArray(ColumnPtr nested_column, ColumnPtr offsets_column = nullptr)
|
||||
: data(nested_column), offsets(offsets_column)
|
||||
{
|
||||
if (!offsets_column)
|
||||
{
|
||||
offsets = std::make_shared<ColumnOffsets_t>();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!typeid_cast<ColumnOffsets_t *>(&*offsets_column))
|
||||
throw Exception("offsets_column must be a ColumnUInt64", ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
|
||||
if (nested_column->isConst())
|
||||
throw Exception{"ColumnArray cannot have constant nested column", ErrorCodes::LOGICAL_ERROR};
|
||||
}
|
||||
|
||||
std::string getName() const override { return "ColumnArray(" + getData().getName() + ")"; }
|
||||
|
||||
ColumnPtr cloneResized(size_t size) const override
|
||||
{
|
||||
ColumnPtr new_col_holder = std::make_shared<ColumnArray>(getData().cloneEmpty());
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
auto & new_col = static_cast<ColumnArray &>(*new_col_holder);
|
||||
size_t count = std::min(this->size(), size);
|
||||
|
||||
/// First create the offsets.
|
||||
const auto & from_offsets = getOffsets();
|
||||
auto & new_offsets = new_col.getOffsets();
|
||||
new_offsets.resize(size);
|
||||
new_offsets.assign(from_offsets.begin(), from_offsets.begin() + count);
|
||||
|
||||
if (size > count)
|
||||
{
|
||||
for (size_t i = count; i < size; ++i)
|
||||
new_offsets[i] = new_offsets[i - 1];
|
||||
}
|
||||
|
||||
/// Then store the data.
|
||||
new_col.getData().insertRangeFrom(getData(), 0, count);
|
||||
}
|
||||
|
||||
return new_col_holder;
|
||||
}
|
||||
|
||||
size_t size() const override
|
||||
{
|
||||
return getOffsets().size();
|
||||
}
|
||||
|
||||
Field operator[](size_t n) const override
|
||||
{
|
||||
size_t offset = offsetAt(n);
|
||||
size_t size = sizeAt(n);
|
||||
Array res(size);
|
||||
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
res[i] = getData()[offset + i];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void get(size_t n, Field & res) const override
|
||||
{
|
||||
size_t offset = offsetAt(n);
|
||||
size_t size = sizeAt(n);
|
||||
res = Array(size);
|
||||
Array & res_arr = DB::get<Array &>(res);
|
||||
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
getData().get(offset + i, res_arr[i]);
|
||||
}
|
||||
|
||||
StringRef getDataAt(size_t n) const override
|
||||
{
|
||||
/** Возвращает диапазон памяти, покрывающий все элементы массива.
|
||||
* Работает для массивов значений фиксированной длины.
|
||||
* Для массивов строк и массивов массивов полученный кусок памяти может не взаимно-однозначно соответствовать элементам,
|
||||
* так как содержит лишь уложенные подряд данные, но не смещения.
|
||||
*/
|
||||
|
||||
size_t array_size = sizeAt(n);
|
||||
if (array_size == 0)
|
||||
return StringRef();
|
||||
|
||||
size_t offset_of_first_elem = offsetAt(n);
|
||||
StringRef first = getData().getDataAtWithTerminatingZero(offset_of_first_elem);
|
||||
|
||||
size_t offset_of_last_elem = getOffsets()[n] - 1;
|
||||
StringRef last = getData().getDataAtWithTerminatingZero(offset_of_last_elem);
|
||||
|
||||
return StringRef(first.data, last.data + last.size - first.data);
|
||||
}
|
||||
|
||||
void insertData(const char * pos, size_t length) override
|
||||
{
|
||||
/** Аналогично - только для массивов значений фиксированной длины.
|
||||
*/
|
||||
IColumn * data_ = data.get();
|
||||
if (!data_->isFixed())
|
||||
throw Exception("Method insertData is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
||||
|
||||
size_t field_size = data_->sizeOfField();
|
||||
|
||||
const char * end = pos + length;
|
||||
size_t elems = 0;
|
||||
for (; pos + field_size <= end; pos += field_size, ++elems)
|
||||
data_->insertData(pos, field_size);
|
||||
|
||||
if (pos != end)
|
||||
throw Exception("Incorrect length argument for method ColumnArray::insertData", ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
getOffsets().push_back((getOffsets().size() == 0 ? 0 : getOffsets().back()) + elems);
|
||||
}
|
||||
|
||||
StringRef serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const override
|
||||
{
|
||||
size_t array_size = sizeAt(n);
|
||||
size_t offset = offsetAt(n);
|
||||
|
||||
char * pos = arena.allocContinue(sizeof(array_size), begin);
|
||||
memcpy(pos, &array_size, sizeof(array_size));
|
||||
|
||||
size_t values_size = 0;
|
||||
for (size_t i = 0; i < array_size; ++i)
|
||||
values_size += getData().serializeValueIntoArena(offset + i, arena, begin).size;
|
||||
|
||||
return StringRef(begin, sizeof(array_size) + values_size);
|
||||
}
|
||||
|
||||
const char * deserializeAndInsertFromArena(const char * pos) override
|
||||
{
|
||||
size_t array_size = *reinterpret_cast<const size_t *>(pos);
|
||||
pos += sizeof(array_size);
|
||||
|
||||
for (size_t i = 0; i < array_size; ++i)
|
||||
pos = getData().deserializeAndInsertFromArena(pos);
|
||||
|
||||
getOffsets().push_back((getOffsets().size() == 0 ? 0 : getOffsets().back()) + array_size);
|
||||
return pos;
|
||||
}
|
||||
|
||||
void updateHashWithValue(size_t n, SipHash & hash) const override
|
||||
{
|
||||
size_t array_size = sizeAt(n);
|
||||
size_t offset = offsetAt(n);
|
||||
|
||||
hash.update(reinterpret_cast<const char *>(&array_size), sizeof(array_size));
|
||||
for (size_t i = 0; i < array_size; ++i)
|
||||
getData().updateHashWithValue(offset + i, hash);
|
||||
}
|
||||
explicit ColumnArray(ColumnPtr nested_column, ColumnPtr offsets_column = nullptr);
|
||||
|
||||
std::string getName() const override;
|
||||
ColumnPtr cloneResized(size_t size) const override;
|
||||
size_t size() const override;
|
||||
Field operator[](size_t n) const override;
|
||||
void get(size_t n, Field & res) const override;
|
||||
StringRef getDataAt(size_t n) const override;
|
||||
void insertData(const char * pos, size_t length) override;
|
||||
StringRef serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const override;
|
||||
const char * deserializeAndInsertFromArena(const char * pos) override;
|
||||
void updateHashWithValue(size_t n, SipHash & hash) const override;
|
||||
void insertRangeFrom(const IColumn & src, size_t start, size_t length) override;
|
||||
|
||||
void insert(const Field & x) override
|
||||
{
|
||||
const Array & array = DB::get<const Array &>(x);
|
||||
size_t size = array.size();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
getData().insert(array[i]);
|
||||
getOffsets().push_back((getOffsets().size() == 0 ? 0 : getOffsets().back()) + size);
|
||||
}
|
||||
|
||||
void insertFrom(const IColumn & src_, size_t n) override
|
||||
{
|
||||
const ColumnArray & src = static_cast<const ColumnArray &>(src_);
|
||||
size_t size = src.sizeAt(n);
|
||||
size_t offset = src.offsetAt(n);
|
||||
|
||||
getData().insertRangeFrom(src.getData(), offset, size);
|
||||
getOffsets().push_back((getOffsets().size() == 0 ? 0 : getOffsets().back()) + size);
|
||||
}
|
||||
|
||||
void insertDefault() override
|
||||
{
|
||||
getOffsets().push_back(getOffsets().size() == 0 ? 0 : getOffsets().back());
|
||||
}
|
||||
|
||||
void popBack(size_t n) override
|
||||
{
|
||||
auto & offsets = getOffsets();
|
||||
size_t nested_n = offsets.back() - offsetAt(offsets.size() - n);
|
||||
if (nested_n)
|
||||
getData().popBack(nested_n);
|
||||
offsets.resize_assume_reserved(offsets.size() - n);
|
||||
}
|
||||
|
||||
void insert(const Field & x) override;
|
||||
void insertFrom(const IColumn & src_, size_t n) override;
|
||||
void insertDefault() override;
|
||||
void popBack(size_t n) override;
|
||||
ColumnPtr filter(const Filter & filt, ssize_t result_size_hint) const override;
|
||||
|
||||
ColumnPtr permute(const Permutation & perm, size_t limit) const override;
|
||||
|
||||
int compareAt(size_t n, size_t m, const IColumn & rhs_, int nan_direction_hint) const override
|
||||
{
|
||||
const ColumnArray & rhs = static_cast<const ColumnArray &>(rhs_);
|
||||
|
||||
/// Не оптимально
|
||||
size_t lhs_size = sizeAt(n);
|
||||
size_t rhs_size = rhs.sizeAt(m);
|
||||
size_t min_size = std::min(lhs_size, rhs_size);
|
||||
for (size_t i = 0; i < min_size; ++i)
|
||||
if (int res = getData().compareAt(offsetAt(n) + i, rhs.offsetAt(m) + i, *rhs.data.get(), nan_direction_hint))
|
||||
return res;
|
||||
|
||||
return lhs_size < rhs_size
|
||||
? -1
|
||||
: (lhs_size == rhs_size
|
||||
? 0
|
||||
: 1);
|
||||
}
|
||||
|
||||
template <bool positive>
|
||||
struct less
|
||||
{
|
||||
const ColumnArray & parent;
|
||||
|
||||
less(const ColumnArray & parent_) : parent(parent_) {}
|
||||
|
||||
bool operator()(size_t lhs, size_t rhs) const
|
||||
{
|
||||
if (positive)
|
||||
return parent.compareAt(lhs, rhs, parent, 1) < 0;
|
||||
else
|
||||
return parent.compareAt(lhs, rhs, parent, -1) > 0;
|
||||
}
|
||||
};
|
||||
|
||||
int compareAt(size_t n, size_t m, const IColumn & rhs_, int nan_direction_hint) const override;
|
||||
void getPermutation(bool reverse, size_t limit, Permutation & res) const override;
|
||||
void reserve(size_t n) override;
|
||||
size_t byteSize() const override;
|
||||
size_t allocatedSize() const override;
|
||||
ColumnPtr replicate(const Offsets_t & replicate_offsets) const override;
|
||||
ColumnPtr convertToFullColumnIfConst() const override;
|
||||
void getExtremes(Field & min, Field & max) const override;
|
||||
|
||||
void reserve(size_t n) override
|
||||
{
|
||||
getOffsets().reserve(n);
|
||||
getData().reserve(n); /// Средний размер массивов тут никак не учитывается. Или считается, что он не больше единицы.
|
||||
}
|
||||
|
||||
size_t byteSize() const override
|
||||
{
|
||||
return getData().byteSize() + getOffsets().size() * sizeof(getOffsets()[0]);
|
||||
}
|
||||
|
||||
size_t allocatedSize() const override
|
||||
{
|
||||
return getData().allocatedSize() + getOffsets().allocated_size() * sizeof(getOffsets()[0]);
|
||||
}
|
||||
|
||||
bool hasEqualOffsets(const ColumnArray & other) const
|
||||
{
|
||||
if (offsets == other.offsets)
|
||||
return true;
|
||||
|
||||
const Offsets_t & offsets1 = getOffsets();
|
||||
const Offsets_t & offsets2 = other.getOffsets();
|
||||
return offsets1.size() == offsets2.size() && 0 == memcmp(&offsets1[0], &offsets2[0], sizeof(offsets1[0]) * offsets1.size());
|
||||
}
|
||||
bool hasEqualOffsets(const ColumnArray & other) const;
|
||||
|
||||
/** Более эффективные методы манипуляции */
|
||||
IColumn & getData() { return *data.get(); }
|
||||
@ -308,38 +75,11 @@ public:
|
||||
ColumnPtr & getOffsetsColumn() { return offsets; }
|
||||
const ColumnPtr & getOffsetsColumn() const { return offsets; }
|
||||
|
||||
|
||||
ColumnPtr replicate(const Offsets_t & replicate_offsets) const override;
|
||||
|
||||
Columns scatter(ColumnIndex num_columns, const Selector & selector) const override
|
||||
{
|
||||
return scatterImpl<ColumnArray>(num_columns, selector);
|
||||
}
|
||||
|
||||
ColumnPtr convertToFullColumnIfConst() const override
|
||||
{
|
||||
ColumnPtr new_data;
|
||||
ColumnPtr new_offsets;
|
||||
|
||||
if (auto full_column = getData().convertToFullColumnIfConst())
|
||||
new_data = full_column;
|
||||
else
|
||||
new_data = data;
|
||||
|
||||
if (auto full_column = offsets.get()->convertToFullColumnIfConst())
|
||||
new_offsets = full_column;
|
||||
else
|
||||
new_offsets = offsets;
|
||||
|
||||
return std::make_shared<ColumnArray>(new_data, new_offsets);
|
||||
}
|
||||
|
||||
void getExtremes(Field & min, Field & max) const override
|
||||
{
|
||||
min = Array();
|
||||
max = Array();
|
||||
}
|
||||
|
||||
private:
|
||||
ColumnPtr data;
|
||||
ColumnPtr offsets; /// Смещения могут быть разделяемыми для нескольких столбцов - для реализации вложенных структур данных.
|
||||
|
@ -2,10 +2,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <DB/Core/Defines.h>
|
||||
|
||||
#include <DB/Columns/IColumn.h>
|
||||
#include <DB/Columns/ColumnsCommon.h>
|
||||
#include <DB/Common/PODArray.h>
|
||||
#include <DB/Common/Arena.h>
|
||||
#include <DB/Common/SipHash.h>
|
||||
@ -18,14 +15,7 @@ class Collator;
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int PARAMETER_OUT_OF_BOUND;
|
||||
extern const int SIZES_OF_COLUMNS_DOESNT_MATCH;
|
||||
}
|
||||
|
||||
|
||||
/** Cтолбeц значений типа "строка".
|
||||
/** Column for String values.
|
||||
*/
|
||||
class ColumnString final : public IColumn
|
||||
{
|
||||
@ -33,24 +23,25 @@ public:
|
||||
using Chars_t = PaddedPODArray<UInt8>;
|
||||
|
||||
private:
|
||||
/// По индексу i находится смещение до начала i + 1 -го элемента.
|
||||
/// Maps i'th position to offset to i+1'th element. Last offset maps to the end of all chars (is the size of all chars).
|
||||
Offsets_t offsets;
|
||||
|
||||
/// Байты строк, уложенные подряд. Строки хранятся с завершающим нулевым байтом.
|
||||
/// Bytes of strings, placed contiguously.
|
||||
/// For convenience, every string ends with terminating zero byte. Note that strings could contain zero bytes in the middle.
|
||||
Chars_t chars;
|
||||
|
||||
size_t __attribute__((__always_inline__)) offsetAt(size_t i) const { return i == 0 ? 0 : offsets[i - 1]; }
|
||||
|
||||
/// Размер, включая завершающий нулевой байт.
|
||||
/// Size of i-th element, including terminating zero.
|
||||
size_t __attribute__((__always_inline__)) sizeAt(size_t i) const { return i == 0 ? offsets[0] : (offsets[i] - offsets[i - 1]); }
|
||||
|
||||
template <bool positive>
|
||||
friend struct lessWithCollation;
|
||||
struct less;
|
||||
|
||||
template <bool positive>
|
||||
struct lessWithCollation;
|
||||
|
||||
public:
|
||||
/** Создать пустой столбец строк */
|
||||
ColumnString() {}
|
||||
|
||||
std::string getName() const override { return "ColumnString"; }
|
||||
|
||||
size_t size() const override
|
||||
@ -68,48 +59,7 @@ public:
|
||||
return chars.allocated_size() + offsets.allocated_size() * sizeof(offsets[0]);
|
||||
}
|
||||
|
||||
ColumnPtr cloneResized(size_t to_size) const override
|
||||
{
|
||||
auto res = std::make_shared<ColumnString>();
|
||||
|
||||
if (to_size == 0)
|
||||
return res;
|
||||
|
||||
size_t from_size = size();
|
||||
|
||||
if (to_size <= from_size)
|
||||
{
|
||||
/// Just cut column.
|
||||
|
||||
res->offsets.assign(offsets.begin(), offsets.begin() + to_size);
|
||||
res->chars.assign(chars.begin(), chars.begin() + offsets[to_size - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Copy column and append empty strings for extra elements.
|
||||
|
||||
Offset_t offset = 0;
|
||||
if (from_size > 0)
|
||||
{
|
||||
res->offsets.assign(offsets.begin(), offsets.end());
|
||||
res->chars.assign(chars.begin(), chars.end());
|
||||
offset = offsets.back();
|
||||
}
|
||||
|
||||
/// Empty strings are just zero terminating bytes.
|
||||
|
||||
res->chars.resize_fill(res->chars.size() + to_size - from_size);
|
||||
|
||||
res->offsets.resize(to_size);
|
||||
for (size_t i = from_size; i < to_size; ++i)
|
||||
{
|
||||
++offset;
|
||||
res->offsets[i] = offset;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
ColumnPtr cloneResized(size_t to_size) const override;
|
||||
|
||||
Field operator[](size_t n) const override
|
||||
{
|
||||
@ -246,101 +196,11 @@ public:
|
||||
hash.update(reinterpret_cast<const char *>(&chars[offset]), string_size);
|
||||
}
|
||||
|
||||
void insertRangeFrom(const IColumn & src, size_t start, size_t length) override
|
||||
{
|
||||
if (length == 0)
|
||||
return;
|
||||
void insertRangeFrom(const IColumn & src, size_t start, size_t length) override;
|
||||
|
||||
const ColumnString & src_concrete = static_cast<const ColumnString &>(src);
|
||||
ColumnPtr filter(const Filter & filt, ssize_t result_size_hint) const override;
|
||||
|
||||
if (start + length > src_concrete.offsets.size())
|
||||
throw Exception("Parameter out of bound in IColumnString::insertRangeFrom method.",
|
||||
ErrorCodes::PARAMETER_OUT_OF_BOUND);
|
||||
|
||||
size_t nested_offset = src_concrete.offsetAt(start);
|
||||
size_t nested_length = src_concrete.offsets[start + length - 1] - nested_offset;
|
||||
|
||||
size_t old_chars_size = chars.size();
|
||||
chars.resize(old_chars_size + nested_length);
|
||||
memcpy(&chars[old_chars_size], &src_concrete.chars[nested_offset], nested_length);
|
||||
|
||||
if (start == 0 && offsets.empty())
|
||||
{
|
||||
offsets.assign(src_concrete.offsets.begin(), src_concrete.offsets.begin() + length);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t old_size = offsets.size();
|
||||
size_t prev_max_offset = old_size ? offsets.back() : 0;
|
||||
offsets.resize(old_size + length);
|
||||
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
offsets[old_size + i] = src_concrete.offsets[start + i] - nested_offset + prev_max_offset;
|
||||
}
|
||||
}
|
||||
|
||||
ColumnPtr filter(const Filter & filt, ssize_t result_size_hint) const override
|
||||
{
|
||||
if (offsets.size() == 0)
|
||||
return std::make_shared<ColumnString>();
|
||||
|
||||
auto res = std::make_shared<ColumnString>();
|
||||
|
||||
Chars_t & res_chars = res->chars;
|
||||
Offsets_t & res_offsets = res->offsets;
|
||||
|
||||
filterArraysImpl<UInt8>(chars, offsets, res_chars, res_offsets, filt, result_size_hint);
|
||||
return res;
|
||||
}
|
||||
|
||||
ColumnPtr permute(const Permutation & perm, size_t limit) const override
|
||||
{
|
||||
size_t size = offsets.size();
|
||||
|
||||
if (limit == 0)
|
||||
limit = size;
|
||||
else
|
||||
limit = std::min(size, limit);
|
||||
|
||||
if (perm.size() < limit)
|
||||
throw Exception("Size of permutation is less than required.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
|
||||
|
||||
if (limit == 0)
|
||||
return std::make_shared<ColumnString>();
|
||||
|
||||
std::shared_ptr<ColumnString> res = std::make_shared<ColumnString>();
|
||||
|
||||
Chars_t & res_chars = res->chars;
|
||||
Offsets_t & res_offsets = res->offsets;
|
||||
|
||||
if (limit == size)
|
||||
res_chars.resize(chars.size());
|
||||
else
|
||||
{
|
||||
size_t new_chars_size = 0;
|
||||
for (size_t i = 0; i < limit; ++i)
|
||||
new_chars_size += sizeAt(perm[i]);
|
||||
res_chars.resize(new_chars_size);
|
||||
}
|
||||
|
||||
res_offsets.resize(limit);
|
||||
|
||||
Offset_t current_new_offset = 0;
|
||||
|
||||
for (size_t i = 0; i < limit; ++i)
|
||||
{
|
||||
size_t j = perm[i];
|
||||
size_t string_offset = j == 0 ? 0 : offsets[j - 1];
|
||||
size_t string_size = offsets[j] - string_offset;
|
||||
|
||||
memcpySmallAllowReadWriteOverflow15(&res_chars[current_new_offset], &chars[string_offset], string_size);
|
||||
|
||||
current_new_offset += string_size;
|
||||
res_offsets[i] = current_new_offset;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
ColumnPtr permute(const Permutation & perm, size_t limit) const override;
|
||||
|
||||
void insertDefault() override
|
||||
{
|
||||
@ -361,117 +221,30 @@ public:
|
||||
reinterpret_cast<const char *>(&rhs.chars[rhs.offsetAt(m)]));
|
||||
}
|
||||
|
||||
/// Версия compareAt для locale-sensitive сравнения строк
|
||||
/// Variant of compareAt for string comparison with respect of collation.
|
||||
int compareAtWithCollation(size_t n, size_t m, const IColumn & rhs_, const Collator & collator) const;
|
||||
|
||||
template <bool positive>
|
||||
struct less
|
||||
{
|
||||
const ColumnString & parent;
|
||||
less(const ColumnString & parent_) : parent(parent_) {}
|
||||
bool operator()(size_t lhs, size_t rhs) const
|
||||
{
|
||||
int res = strcmp(
|
||||
reinterpret_cast<const char *>(&parent.chars[parent.offsetAt(lhs)]),
|
||||
reinterpret_cast<const char *>(&parent.chars[parent.offsetAt(rhs)]));
|
||||
void getPermutation(bool reverse, size_t limit, Permutation & res) const override;
|
||||
|
||||
return positive ? (res < 0) : (res > 0);
|
||||
}
|
||||
};
|
||||
|
||||
void getPermutation(bool reverse, size_t limit, Permutation & res) const override
|
||||
{
|
||||
size_t s = offsets.size();
|
||||
res.resize(s);
|
||||
for (size_t i = 0; i < s; ++i)
|
||||
res[i] = i;
|
||||
|
||||
if (limit >= s)
|
||||
limit = 0;
|
||||
|
||||
if (limit)
|
||||
{
|
||||
if (reverse)
|
||||
std::partial_sort(res.begin(), res.begin() + limit, res.end(), less<false>(*this));
|
||||
else
|
||||
std::partial_sort(res.begin(), res.begin() + limit, res.end(), less<true>(*this));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reverse)
|
||||
std::sort(res.begin(), res.end(), less<false>(*this));
|
||||
else
|
||||
std::sort(res.begin(), res.end(), less<true>(*this));
|
||||
}
|
||||
}
|
||||
|
||||
/// Сортировка с учетом Collation
|
||||
/// Sorting with respect of collation.
|
||||
void getPermutationWithCollation(const Collator & collator, bool reverse, size_t limit, Permutation & res) const;
|
||||
|
||||
ColumnPtr replicate(const Offsets_t & replicate_offsets) const override
|
||||
{
|
||||
size_t col_size = size();
|
||||
if (col_size != replicate_offsets.size())
|
||||
throw Exception("Size of offsets doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
|
||||
|
||||
std::shared_ptr<ColumnString> res = std::make_shared<ColumnString>();
|
||||
|
||||
if (0 == col_size)
|
||||
return res;
|
||||
|
||||
Chars_t & res_chars = res->chars;
|
||||
Offsets_t & res_offsets = res->offsets;
|
||||
res_chars.reserve(chars.size() / col_size * replicate_offsets.back());
|
||||
res_offsets.reserve(replicate_offsets.back());
|
||||
|
||||
Offset_t prev_replicate_offset = 0;
|
||||
Offset_t prev_string_offset = 0;
|
||||
Offset_t current_new_offset = 0;
|
||||
|
||||
for (size_t i = 0; i < col_size; ++i)
|
||||
{
|
||||
size_t size_to_replicate = replicate_offsets[i] - prev_replicate_offset;
|
||||
size_t string_size = offsets[i] - prev_string_offset;
|
||||
|
||||
for (size_t j = 0; j < size_to_replicate; ++j)
|
||||
{
|
||||
current_new_offset += string_size;
|
||||
res_offsets.push_back(current_new_offset);
|
||||
|
||||
res_chars.resize(res_chars.size() + string_size);
|
||||
memcpySmallAllowReadWriteOverflow15(
|
||||
&res_chars[res_chars.size() - string_size], &chars[prev_string_offset], string_size);
|
||||
}
|
||||
|
||||
prev_replicate_offset = replicate_offsets[i];
|
||||
prev_string_offset = offsets[i];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
ColumnPtr replicate(const Offsets_t & replicate_offsets) const override;
|
||||
|
||||
Columns scatter(ColumnIndex num_columns, const Selector & selector) const override
|
||||
{
|
||||
return scatterImpl<ColumnString>(num_columns, selector);
|
||||
}
|
||||
|
||||
void reserve(size_t n) override
|
||||
{
|
||||
offsets.reserve(n);
|
||||
chars.reserve(n * DBMS_APPROX_STRING_SIZE);
|
||||
}
|
||||
void reserve(size_t n) override;
|
||||
|
||||
void getExtremes(Field & min, Field & max) const override;
|
||||
|
||||
Chars_t & getChars() { return chars; }
|
||||
const Chars_t & getChars() const { return chars; }
|
||||
|
||||
Offsets_t & getOffsets() { return offsets; }
|
||||
const Offsets_t & getOffsets() const { return offsets; }
|
||||
|
||||
void getExtremes(Field & min, Field & max) const override
|
||||
{
|
||||
min = String();
|
||||
max = String();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
@ -7,8 +7,10 @@
|
||||
#include <DB/DataTypes/DataTypeArray.h>
|
||||
#include <DB/Columns/ColumnVector.h>
|
||||
#include <DB/Columns/ColumnArray.h>
|
||||
#include <DB/Common/memcpySmall.h>
|
||||
#include <DB/Functions/NumberTraits.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
|
@ -699,7 +699,6 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -707,7 +706,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 2; }
|
||||
|
||||
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
DataTypePtr type_res;
|
||||
@ -730,7 +728,6 @@ public:
|
||||
return type_res;
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
if (!( executeLeftType<DataTypeDate>(block, arguments, result)
|
||||
@ -809,7 +806,6 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -818,7 +814,6 @@ public:
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
bool isInjective(const Block &) override { return is_injective; }
|
||||
|
||||
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
DataTypePtr result;
|
||||
@ -839,7 +834,6 @@ public:
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
if (!( executeType<UInt8>(block, arguments, result)
|
||||
|
@ -73,14 +73,11 @@ public:
|
||||
bool isVariadic() const override { return true; }
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override;
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override;
|
||||
|
||||
private:
|
||||
/// Получить имя функции.
|
||||
String getName() const override;
|
||||
|
||||
bool addField(DataTypePtr type_res, const Field & f, Array & arr) const;
|
||||
@ -102,15 +99,12 @@ public:
|
||||
static constexpr auto name = "arrayElement";
|
||||
static FunctionPtr create(const Context & context);
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override;
|
||||
|
||||
size_t getNumberOfArguments() const override { return 2; }
|
||||
|
||||
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override;
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override;
|
||||
|
||||
private:
|
||||
@ -1178,15 +1172,12 @@ public:
|
||||
static constexpr auto name = "arrayEnumerate";
|
||||
static FunctionPtr create(const Context & context);
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override;
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override;
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override;
|
||||
};
|
||||
|
||||
@ -1199,16 +1190,13 @@ public:
|
||||
static constexpr auto name = "arrayUniq";
|
||||
static FunctionPtr create(const Context & context);
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override;
|
||||
|
||||
bool isVariadic() const override { return true; }
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override;
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override;
|
||||
|
||||
private:
|
||||
@ -1242,16 +1230,13 @@ public:
|
||||
static constexpr auto name = "arrayEnumerateUniq";
|
||||
static FunctionPtr create(const Context & context);
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override;
|
||||
|
||||
bool isVariadic() const override { return true; }
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override;
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override;
|
||||
|
||||
private:
|
||||
@ -1346,15 +1331,12 @@ public:
|
||||
static constexpr auto name = "emptyArrayToSingle";
|
||||
static FunctionPtr create(const Context & context);
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override;
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override;
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override;
|
||||
|
||||
private:
|
||||
@ -1387,15 +1369,12 @@ public:
|
||||
static constexpr auto name = "reverse";
|
||||
static FunctionPtr create(const Context & context);
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override;
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override;
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override;
|
||||
|
||||
private:
|
||||
@ -1434,7 +1413,6 @@ public:
|
||||
static constexpr auto name = "arrayReduce";
|
||||
static FunctionPtr create(const Context & context);
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override;
|
||||
|
||||
bool isVariadic() const override { return true; }
|
||||
|
@ -640,7 +640,6 @@ public:
|
||||
static constexpr auto name = "IPv4NumToString";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionIPv4NumToString>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -649,7 +648,6 @@ public:
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
bool isInjective(const Block &) override { return true; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeUInt32 *>(&*arguments[0]))
|
||||
@ -693,7 +691,6 @@ public:
|
||||
*(out++) = '\0';
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
const ColumnPtr & column = block.safeGetByPosition(arguments[0]).column;
|
||||
@ -744,7 +741,6 @@ public:
|
||||
static constexpr auto name = "IPv4StringToNum";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionIPv4StringToNum>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -752,7 +748,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeString *>(&*arguments[0]))
|
||||
@ -785,7 +780,6 @@ public:
|
||||
return res;
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
const ColumnPtr & column = block.safeGetByPosition(arguments[0]).column;
|
||||
@ -827,7 +821,6 @@ public:
|
||||
static constexpr auto name = "IPv4NumToStringClassC";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionIPv4NumToStringClassC>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -835,7 +828,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeUInt32 *>(&*arguments[0]))
|
||||
@ -882,7 +874,6 @@ public:
|
||||
*(out++) = '\0';
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
const ColumnPtr & column = block.safeGetByPosition(arguments[0]).column;
|
||||
@ -1272,7 +1263,6 @@ public:
|
||||
static constexpr auto name = "hex";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionHex>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -1281,7 +1271,6 @@ public:
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
bool isInjective(const Block &) override { return true; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeString *>(&*arguments[0]) &&
|
||||
@ -1491,7 +1480,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
const IColumn * column = block.safeGetByPosition(arguments[0]).column.get();
|
||||
@ -1518,7 +1506,6 @@ public:
|
||||
static constexpr auto name = "unhex";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionUnhex>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -1527,7 +1514,6 @@ public:
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
bool isInjective(const Block &) override { return true; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeString *>(&*arguments[0]))
|
||||
@ -1561,7 +1547,6 @@ public:
|
||||
*(out++) = '\0';
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
const ColumnPtr & column = block.safeGetByPosition(arguments[0]).column;
|
||||
@ -1624,7 +1609,6 @@ public:
|
||||
static constexpr auto name = "bitmaskToArray";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionBitmaskToArray>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -1633,7 +1617,6 @@ public:
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
bool isInjective(const Block &) override { return true; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeUInt8 *>(&*arguments[0]) &&
|
||||
@ -1707,7 +1690,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
const IColumn * in_column = block.safeGetByPosition(arguments[0]).column.get();
|
||||
@ -1735,7 +1717,6 @@ public:
|
||||
static constexpr auto name = "toStringCutToZero";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionToStringCutToZero>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -1743,7 +1724,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeFixedString *>(&*arguments[0]) &&
|
||||
@ -1854,7 +1834,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
const IColumn * column = block.safeGetByPosition(arguments[0]).column.get();
|
||||
|
@ -776,7 +776,6 @@ private:
|
||||
|
||||
|
||||
public:
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -853,7 +852,6 @@ public:
|
||||
return std::make_shared<DataTypeUInt8>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
const auto & col_with_type_and_name_left = block.safeGetByPosition(arguments[0]);
|
||||
|
@ -1573,7 +1573,6 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
|
@ -670,7 +670,6 @@ public:
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
bool isInjective(const Block &) override { return std::is_same<Name, NameToString>::value; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
return getReturnTypeInternal(arguments);
|
||||
@ -891,7 +890,6 @@ public:
|
||||
static constexpr auto name = "toFixedString";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionToFixedString>(); };
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -919,7 +917,6 @@ public:
|
||||
out_return_type = std::make_shared<DataTypeFixedString>(n);
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, const size_t result) override
|
||||
{
|
||||
const auto n = getSize(block.safeGetByPosition(arguments[1]));
|
||||
|
@ -484,7 +484,6 @@ public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionDateOrDateTimeToSomething>(); };
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -493,7 +492,6 @@ public:
|
||||
bool isVariadic() const override { return true; }
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (arguments.size() == 1)
|
||||
@ -523,7 +521,6 @@ public:
|
||||
return std::make_shared<ToDataType>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
IDataType * from_type = block.safeGetByPosition(arguments[0]).type.get();
|
||||
@ -582,7 +579,6 @@ public:
|
||||
static constexpr auto name = "now";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionNow>(); };
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -590,13 +586,11 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
return std::make_shared<DataTypeDateTime>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
block.safeGetByPosition(result).column = std::make_shared<ColumnConstUInt32>(
|
||||
@ -612,7 +606,6 @@ public:
|
||||
static constexpr auto name = "today";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionToday>(); };
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -620,13 +613,11 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
return std::make_shared<DataTypeDate>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
block.safeGetByPosition(result).column = std::make_shared<ColumnConstUInt16>(
|
||||
@ -642,7 +633,6 @@ public:
|
||||
static constexpr auto name = "yesterday";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionYesterday>(); };
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -650,13 +640,11 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
return std::make_shared<DataTypeDate>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
block.safeGetByPosition(result).column = std::make_shared<ColumnConstUInt16>(
|
||||
@ -672,7 +660,6 @@ public:
|
||||
static constexpr auto name = "timeSlot";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionTimeSlot>(); };
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -680,7 +667,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeDateTime *>(arguments[0].get()))
|
||||
@ -690,7 +676,6 @@ public:
|
||||
return std::make_shared<DataTypeDateTime>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
if (const ColumnUInt32 * times = typeid_cast<const ColumnUInt32 *>(block.safeGetByPosition(arguments[0]).column.get()))
|
||||
@ -805,7 +790,6 @@ public:
|
||||
static constexpr auto name = "timeSlots";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionTimeSlots>(); };
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -813,7 +797,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 2; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeDateTime *>(arguments[0].get()))
|
||||
@ -827,7 +810,6 @@ public:
|
||||
return std::make_shared<DataTypeArray>(std::make_shared<DataTypeDateTime>());
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
const ColumnUInt32 * starts = typeid_cast<const ColumnUInt32 *>(block.safeGetByPosition(arguments[0]).column.get());
|
||||
|
@ -201,7 +201,6 @@ public:
|
||||
throw Exception("Dictionaries was not loaded. You need to check configuration file.", ErrorCodes::DICTIONARIES_WAS_NOT_LOADED);
|
||||
}
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -210,7 +209,6 @@ public:
|
||||
bool isVariadic() const override { return true; }
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (arguments.size() != 1 && arguments.size() != 2)
|
||||
@ -231,7 +229,6 @@ public:
|
||||
return arguments[0];
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
/// Ключ словаря, определяющий "точку зрения".
|
||||
@ -297,7 +294,6 @@ public:
|
||||
throw Exception("Dictionaries was not loaded. You need to check configuration file.", ErrorCodes::DICTIONARIES_WAS_NOT_LOADED);
|
||||
}
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -306,7 +302,6 @@ public:
|
||||
bool isVariadic() const override { return true; }
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (arguments.size() != 2 && arguments.size() != 3)
|
||||
@ -332,7 +327,6 @@ public:
|
||||
return std::make_shared<DataTypeUInt8>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
/// Ключ словаря, определяющий "точку зрения".
|
||||
@ -433,7 +427,6 @@ public:
|
||||
throw Exception("Dictionaries was not loaded. You need to check configuration file.", ErrorCodes::DICTIONARIES_WAS_NOT_LOADED);
|
||||
}
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -442,7 +435,6 @@ public:
|
||||
bool isVariadic() const override { return true; }
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (arguments.size() != 1 && arguments.size() != 2)
|
||||
@ -463,7 +455,6 @@ public:
|
||||
return std::make_shared<DataTypeArray>(arguments[0]);
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
/// Ключ словаря, определяющий "точку зрения".
|
||||
@ -709,7 +700,6 @@ public:
|
||||
throw Exception("Dictionaries was not loaded. You need to check configuration file.", ErrorCodes::DICTIONARIES_WAS_NOT_LOADED);
|
||||
}
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -722,7 +712,6 @@ public:
|
||||
/// even in face of fact that there are many different cities named Moscow.
|
||||
bool isInjective(const Block &) override { return true; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (arguments.size() != 1 && arguments.size() != 2)
|
||||
@ -743,7 +732,6 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
RegionsNames::Language language = RegionsNames::Language::RU;
|
||||
|
@ -24,8 +24,7 @@ public:
|
||||
static constexpr auto name = "bitmaskToList";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionBitmaskToList>(); }
|
||||
|
||||
/// Получить основное имя функции.
|
||||
virtual String getName() const override
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
}
|
||||
@ -33,8 +32,7 @@ public:
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
bool isInjective(const Block &) override { return true; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
virtual DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
const IDataType * type = &*arguments[0];
|
||||
|
||||
@ -51,7 +49,6 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
if (!( executeType<UInt8>(block, arguments, result)
|
||||
@ -135,16 +132,14 @@ public:
|
||||
static constexpr auto name = "formatReadableSize";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionFormatReadableSize>(); }
|
||||
|
||||
/// Получить основное имя функции.
|
||||
virtual String getName() const override
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
virtual DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
const IDataType & type = *arguments[0];
|
||||
|
||||
@ -154,7 +149,6 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
if (!( executeType<UInt8>(block, arguments, result)
|
||||
|
@ -173,7 +173,6 @@ public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionStringHash64>(); };
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -181,7 +180,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeString *>(&*arguments[0]))
|
||||
@ -191,7 +189,6 @@ public:
|
||||
return std::make_shared<DataTypeUInt64>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
if (const ColumnString * col_from = typeid_cast<const ColumnString *>(block.safeGetByPosition(arguments[0]).column.get()))
|
||||
@ -231,7 +228,6 @@ public:
|
||||
static constexpr auto name = Impl::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionStringHashFixedString>(); };
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -239,7 +235,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeString *>(&*arguments[0]))
|
||||
@ -249,7 +244,6 @@ public:
|
||||
return std::make_shared<DataTypeFixedString>(Impl::length);
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
if (const ColumnString * col_from = typeid_cast<const ColumnString *>(block.safeGetByPosition(arguments[0]).column.get()))
|
||||
@ -326,7 +320,6 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -334,7 +327,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!arguments[0]->isNumeric())
|
||||
@ -344,7 +336,6 @@ public:
|
||||
return std::make_shared<typename DataTypeFromFieldType<typename Impl::ReturnType>::Type>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
IDataType * from_type = block.safeGetByPosition(arguments[0]).type.get();
|
||||
|
@ -601,7 +601,6 @@ public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionArrayMapped>(); };
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -689,17 +688,17 @@ public:
|
||||
|
||||
/// Попросим добавить в блок все столбцы, упоминаемые в выражении, размноженные в массив, параллельный обрабатываемому.
|
||||
const ExpressionActions & expression = *column_expression->getExpression();
|
||||
Names required_columns = expression.getRequiredColumns();
|
||||
const NamesAndTypesList & required_columns = expression.getRequiredColumnsWithTypes();
|
||||
|
||||
Names argument_name_vector = column_expression->getArgumentNames();
|
||||
NameSet argument_names(argument_name_vector.begin(), argument_name_vector.end());
|
||||
|
||||
for (size_t i = 0; i < required_columns.size(); ++i)
|
||||
for (const auto & required_column : required_columns)
|
||||
{
|
||||
if (argument_names.count(required_columns[i]))
|
||||
if (argument_names.count(required_column.name))
|
||||
continue;
|
||||
Names replicate_arguments;
|
||||
replicate_arguments.push_back(required_columns[i]);
|
||||
replicate_arguments.push_back(required_column.name);
|
||||
replicate_arguments.push_back(arguments[1].name);
|
||||
out_prerequisites.push_back(ExpressionAction::applyFunction(std::make_shared<FunctionReplicate>(), replicate_arguments));
|
||||
}
|
||||
@ -715,7 +714,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, const ColumnNumbers & prerequisites, size_t result) override
|
||||
{
|
||||
if (arguments.size() == 1)
|
||||
|
@ -241,7 +241,6 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -270,7 +269,6 @@ public:
|
||||
return std::make_shared<DataTypeUInt8>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
ColumnPlainPtrs in(arguments.size());
|
||||
@ -398,7 +396,6 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -406,7 +403,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!arguments[0]->isNumeric())
|
||||
@ -418,7 +414,6 @@ public:
|
||||
return std::make_shared<DataTypeUInt8>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
if (!( executeType<UInt8>(block, arguments, result)
|
||||
|
@ -120,7 +120,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
return std::make_shared<DataTypeString>();
|
||||
@ -149,7 +148,6 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -157,13 +155,11 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
return std::make_shared<DataTypeUInt64>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override;
|
||||
};
|
||||
|
||||
@ -187,13 +183,11 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
block.safeGetByPosition(result).column = std::make_shared<ColumnConstString>(
|
||||
@ -240,7 +234,6 @@ public:
|
||||
static constexpr auto name = "blockSize";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionBlockSize>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -250,13 +243,11 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
return std::make_shared<DataTypeUInt64>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
size_t size = block.rows();
|
||||
@ -271,7 +262,6 @@ public:
|
||||
static constexpr auto name = "rowNumberInBlock";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionRowNumberInBlock>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -281,13 +271,11 @@ public:
|
||||
|
||||
bool isDeterministicInScopeOfQuery() override { return false; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
return std::make_shared<DataTypeUInt64>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
size_t size = block.rows();
|
||||
@ -312,7 +300,6 @@ public:
|
||||
static constexpr auto name = "blockNumber";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionBlockNumber>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -322,13 +309,11 @@ public:
|
||||
|
||||
bool isDeterministicInScopeOfQuery() override { return false; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
return std::make_shared<DataTypeUInt64>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
size_t current_block_number = block_number++;
|
||||
@ -347,7 +332,6 @@ public:
|
||||
static constexpr auto name = "rowNumberInAllBlocks";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionRowNumberInAllBlocks>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -357,13 +341,11 @@ public:
|
||||
|
||||
bool isDeterministicInScopeOfQuery() override { return false; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
return std::make_shared<DataTypeUInt64>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
size_t rows_in_block = block.rows();
|
||||
@ -386,7 +368,6 @@ public:
|
||||
static constexpr auto name = "sleep";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionSleep>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -397,7 +378,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeFloat64 *>(&*arguments[0]) &&
|
||||
@ -412,7 +392,6 @@ public:
|
||||
return std::make_shared<DataTypeUInt8>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
IColumn * col = block.safeGetByPosition(arguments[0]).column.get();
|
||||
@ -456,7 +435,6 @@ public:
|
||||
static constexpr auto name = "materialize";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionMaterialize>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -464,13 +442,11 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
return arguments[0];
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
const auto & src = block.safeGetByPosition(arguments[0]).column;
|
||||
@ -501,13 +477,11 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 2; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
return std::make_shared<DataTypeUInt8>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
/// Second argument must be ColumnSet.
|
||||
@ -552,7 +526,6 @@ public:
|
||||
|
||||
bool hasSpecialSupportForNulls() const override { return true; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (arguments.size() < 1)
|
||||
@ -561,7 +534,6 @@ public:
|
||||
return std::make_shared<DataTypeTuple>(arguments);
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
Block tuple_block;
|
||||
@ -647,7 +619,6 @@ public:
|
||||
out_return_type = elems[index - 1]->clone();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
const ColumnTuple * tuple_col = typeid_cast<const ColumnTuple *>(block.safeGetByPosition(arguments[0]).column.get());
|
||||
@ -697,7 +668,6 @@ public:
|
||||
String getName() const override { return name; }
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override { return std::make_shared<DataTypeUInt8>(); }
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
block.safeGetByPosition(result).column = std::make_shared<ColumnConstUInt8>(block.rows(), 0);
|
||||
@ -731,7 +701,6 @@ public:
|
||||
String getName() const override { return name; }
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override { return std::make_shared<DataTypeUInt8>(); }
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
block.safeGetByPosition(result).column = std::make_shared<ColumnConstUInt8>(block.rows(), 1);
|
||||
@ -745,7 +714,6 @@ public:
|
||||
static constexpr auto name = "identity";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionIdentity>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -753,13 +721,11 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
return arguments.front()->clone();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
block.safeGetByPosition(result).column = block.safeGetByPosition(arguments.front()).column;
|
||||
@ -773,8 +739,6 @@ public:
|
||||
static constexpr auto name = "arrayJoin";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionArrayJoin>(); }
|
||||
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -785,7 +749,6 @@ public:
|
||||
/** It could return many different values for single argument. */
|
||||
bool isDeterministicInScopeOfQuery() override { return false; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
const DataTypeArray * arr = typeid_cast<const DataTypeArray *>(&*arguments[0]);
|
||||
@ -795,7 +758,6 @@ public:
|
||||
return arr->getNestedType()->clone();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
throw Exception("Function " + getName() + " must not be executed directly.", ErrorCodes::FUNCTION_IS_SPECIAL);
|
||||
@ -815,7 +777,6 @@ public:
|
||||
static constexpr auto name = "replicate";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionReplicate>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -823,7 +784,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 2; }
|
||||
|
||||
/// Получить типы результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
const DataTypeArray * array_type = typeid_cast<const DataTypeArray *>(&*arguments[1]);
|
||||
@ -833,7 +793,6 @@ public:
|
||||
return std::make_shared<DataTypeArray>(arguments[0]->clone());
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
ColumnPtr first_column = block.safeGetByPosition(arguments[0]).column;
|
||||
@ -873,7 +832,6 @@ public:
|
||||
bool isVariadic() const override { return true; }
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (arguments.size() != 3 && arguments.size() != 4)
|
||||
@ -888,7 +846,6 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
Int64 min = extractConstant<Int64>(block, arguments, 1, "Second"); /// Уровень значения, при котором полоска имеет нулевую длину.
|
||||
|
@ -152,7 +152,6 @@ public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionRandom>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -162,7 +161,6 @@ public:
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
bool isDeterministicInScopeOfQuery() override { return false; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (arguments.size() > 1)
|
||||
@ -173,7 +171,6 @@ public:
|
||||
return std::make_shared<typename DataTypeFromFieldType<typename Impl::ReturnType>::Type>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
auto col_to = std::make_shared<ColumnVector<ToType>>();
|
||||
@ -202,7 +199,6 @@ public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionRandomConstant>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -211,7 +207,6 @@ public:
|
||||
bool isVariadic() const override { return true; }
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (arguments.size() > 1)
|
||||
@ -222,7 +217,6 @@ public:
|
||||
return std::make_shared<typename DataTypeFromFieldType<typename Impl::ReturnType>::Type>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
if (!is_initialized)
|
||||
|
@ -26,7 +26,6 @@ public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionReinterpretAsStringImpl>(); };
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -34,7 +33,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
const IDataType * type = &*arguments[0];
|
||||
@ -93,7 +91,6 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
if (!( executeType<UInt8>(block, arguments, result)
|
||||
@ -121,7 +118,6 @@ public:
|
||||
|
||||
using ToFieldType = typename ToDataType::FieldType;
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -129,7 +125,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
const IDataType * type = &*arguments[0];
|
||||
@ -140,7 +135,6 @@ public:
|
||||
return std::make_shared<ToDataType>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
if (ColumnString * col_from = typeid_cast<ColumnString *>(block.safeGetByPosition(arguments[0]).column.get()))
|
||||
|
@ -13,7 +13,7 @@
|
||||
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.
|
||||
@ -28,42 +28,42 @@ namespace DB
|
||||
* - N = 0: округлять до целого числа
|
||||
*/
|
||||
|
||||
template<typename A>
|
||||
struct RoundToExp2Impl
|
||||
{
|
||||
template<typename A>
|
||||
struct RoundToExp2Impl
|
||||
{
|
||||
using ResultType = A;
|
||||
|
||||
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>
|
||||
{
|
||||
template<>
|
||||
struct RoundToExp2Impl<Float32>
|
||||
{
|
||||
using ResultType = Float32;
|
||||
|
||||
static inline Float32 apply(Float32 x)
|
||||
{
|
||||
return static_cast<Float32>(x < 1 ? 0. : pow(2., floor(log2(x))));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<>
|
||||
struct RoundToExp2Impl<Float64>
|
||||
{
|
||||
template<>
|
||||
struct RoundToExp2Impl<Float64>
|
||||
{
|
||||
using ResultType = Float64;
|
||||
|
||||
static inline Float64 apply(Float64 x)
|
||||
{
|
||||
return x < 1 ? 0. : pow(2., floor(log2(x)));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<typename A>
|
||||
struct RoundDurationImpl
|
||||
{
|
||||
template<typename A>
|
||||
struct RoundDurationImpl
|
||||
{
|
||||
using ResultType = UInt16;
|
||||
|
||||
static inline ResultType apply(A x)
|
||||
@ -85,11 +85,11 @@ namespace DB
|
||||
: (x < 36000 ? 18000
|
||||
: 36000))))))))))))));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<typename A>
|
||||
struct RoundAgeImpl
|
||||
{
|
||||
template<typename A>
|
||||
struct RoundAgeImpl
|
||||
{
|
||||
using ResultType = UInt8;
|
||||
|
||||
static inline ResultType apply(A x)
|
||||
@ -101,18 +101,18 @@ namespace DB
|
||||
: (x < 45 ? 35
|
||||
: 45))));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/** Быстрое вычисление остатка от деления для применения к округлению целых чисел.
|
||||
/** Быстрое вычисление остатка от деления для применения к округлению целых чисел.
|
||||
* Без проверки, потому что делитель всегда положительный.
|
||||
*/
|
||||
template<typename T, typename Enable = void>
|
||||
struct FastModulo;
|
||||
template<typename T, typename Enable = void>
|
||||
struct FastModulo;
|
||||
|
||||
template<typename T>
|
||||
struct FastModulo<T, typename std::enable_if<std::is_integral<T>::value>::type>
|
||||
{
|
||||
private:
|
||||
template<typename T>
|
||||
struct FastModulo<T, typename std::enable_if<std::is_integral<T>::value>::type>
|
||||
{
|
||||
private:
|
||||
template<typename InputType, typename Enable = void>
|
||||
struct Extend;
|
||||
|
||||
@ -142,7 +142,7 @@ namespace DB
|
||||
|
||||
using U = typename Extend<T>::Type;
|
||||
|
||||
public:
|
||||
public:
|
||||
using Divisor = std::pair<size_t, typename libdivide::divider<U> >;
|
||||
|
||||
static inline Divisor prepare(size_t b)
|
||||
@ -156,34 +156,34 @@ namespace DB
|
||||
U rem = val - (val / divisor.second) * static_cast<U>(divisor.first);
|
||||
return static_cast<T>(rem);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/** Этот параметр контролирует поведение функций округления.
|
||||
/** Этот параметр контролирует поведение функций округления.
|
||||
*/
|
||||
enum ScaleMode
|
||||
{
|
||||
enum ScaleMode
|
||||
{
|
||||
PositiveScale, // округлять до числа с N десятичными знаками после запятой
|
||||
NegativeScale, // окурглять до целого числа с N нулевыми знаками
|
||||
ZeroScale, // округлять до целого числа
|
||||
NullScale // возвращать нулевое значение
|
||||
};
|
||||
};
|
||||
|
||||
#if !defined(_MM_FROUND_NINT)
|
||||
#define _MM_FROUND_NINT 0
|
||||
#define _MM_FROUND_FLOOR 1
|
||||
#define _MM_FROUND_CEIL 2
|
||||
#define _MM_FROUND_NINT 0
|
||||
#define _MM_FROUND_FLOOR 1
|
||||
#define _MM_FROUND_CEIL 2
|
||||
#endif
|
||||
|
||||
/** Реализация низкоуровневых функций округления для целочисленных значений.
|
||||
/** Реализация низкоуровневых функций округления для целочисленных значений.
|
||||
*/
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode, typename Enable = void>
|
||||
struct IntegerRoundingComputation;
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode, typename Enable = void>
|
||||
struct IntegerRoundingComputation;
|
||||
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
struct IntegerRoundingComputation<T, rounding_mode, scale_mode,
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
struct IntegerRoundingComputation<T, rounding_mode, scale_mode,
|
||||
typename std::enable_if<std::is_integral<T>::value
|
||||
&& ((scale_mode == PositiveScale) || (scale_mode == ZeroScale))>::type>
|
||||
{
|
||||
{
|
||||
using Divisor = int;
|
||||
|
||||
static inline Divisor prepare(size_t scale)
|
||||
@ -195,12 +195,12 @@ namespace DB
|
||||
{
|
||||
return in;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct IntegerRoundingComputation<T, _MM_FROUND_NINT, NegativeScale,
|
||||
template<typename T>
|
||||
struct IntegerRoundingComputation<T, _MM_FROUND_NINT, NegativeScale,
|
||||
typename std::enable_if<std::is_integral<T>::value>::type>
|
||||
{
|
||||
{
|
||||
using Op = FastModulo<T>;
|
||||
using Divisor = typename Op::Divisor;
|
||||
|
||||
@ -222,12 +222,12 @@ namespace DB
|
||||
res = in + scale.first;
|
||||
return factor * res;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct IntegerRoundingComputation<T, _MM_FROUND_CEIL, NegativeScale,
|
||||
template<typename T>
|
||||
struct IntegerRoundingComputation<T, _MM_FROUND_CEIL, NegativeScale,
|
||||
typename std::enable_if<std::is_integral<T>::value>::type>
|
||||
{
|
||||
{
|
||||
using Op = FastModulo<T>;
|
||||
using Divisor = typename Op::Divisor;
|
||||
|
||||
@ -244,12 +244,12 @@ namespace DB
|
||||
T res = in - rem + scale.first;
|
||||
return factor * res;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct IntegerRoundingComputation<T, _MM_FROUND_FLOOR, NegativeScale,
|
||||
template<typename T>
|
||||
struct IntegerRoundingComputation<T, _MM_FROUND_FLOOR, NegativeScale,
|
||||
typename std::enable_if<std::is_integral<T>::value>::type>
|
||||
{
|
||||
{
|
||||
using Op = FastModulo<T>;
|
||||
using Divisor = typename Op::Divisor;
|
||||
|
||||
@ -266,20 +266,20 @@ namespace DB
|
||||
T res = in - rem;
|
||||
return factor * res;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
#if __SSE4_1__
|
||||
template <typename T>
|
||||
class BaseFloatRoundingComputation;
|
||||
template <typename T>
|
||||
class BaseFloatRoundingComputation;
|
||||
|
||||
template <>
|
||||
class BaseFloatRoundingComputation<Float32>
|
||||
{
|
||||
public:
|
||||
template <>
|
||||
class BaseFloatRoundingComputation<Float32>
|
||||
{
|
||||
public:
|
||||
using Scale = __m128;
|
||||
static const size_t data_count = 4;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
/// Предотвратить появление отрицательных нолей определённых в стандарте IEEE-754.
|
||||
static inline void normalize(__m128 & val, const __m128 & mask)
|
||||
{
|
||||
@ -308,16 +308,16 @@ namespace DB
|
||||
static const __m128 two = _mm_set1_ps(2.0);
|
||||
return two;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <>
|
||||
class BaseFloatRoundingComputation<Float64>
|
||||
{
|
||||
public:
|
||||
template <>
|
||||
class BaseFloatRoundingComputation<Float64>
|
||||
{
|
||||
public:
|
||||
using Scale = __m128d;
|
||||
static const size_t data_count = 2;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
/// Предотвратить появление отрицательных нолей определённых в стандарте IEEE-754.
|
||||
static inline void normalize(__m128d & val, const __m128d & mask)
|
||||
{
|
||||
@ -346,18 +346,18 @@ namespace DB
|
||||
static const __m128d two = _mm_set1_pd(2.0);
|
||||
return two;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/** Реализация низкоуровневых функций округления для значений с плавающей точкой.
|
||||
/** Реализация низкоуровневых функций округления для значений с плавающей точкой.
|
||||
*/
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
class FloatRoundingComputation;
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
class FloatRoundingComputation;
|
||||
|
||||
template<int rounding_mode>
|
||||
class FloatRoundingComputation<Float32, rounding_mode, PositiveScale>
|
||||
template<int rounding_mode>
|
||||
class FloatRoundingComputation<Float32, rounding_mode, PositiveScale>
|
||||
: public BaseFloatRoundingComputation<Float32>
|
||||
{
|
||||
public:
|
||||
{
|
||||
public:
|
||||
static inline void prepare(size_t scale, Scale & mm_scale)
|
||||
{
|
||||
Float32 fscale = static_cast<Float32>(scale);
|
||||
@ -377,13 +377,13 @@ namespace DB
|
||||
normalize(val, mask);
|
||||
_mm_storeu_ps(out, val);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<int rounding_mode>
|
||||
class FloatRoundingComputation<Float32, rounding_mode, NegativeScale>
|
||||
template<int rounding_mode>
|
||||
class FloatRoundingComputation<Float32, rounding_mode, NegativeScale>
|
||||
: public BaseFloatRoundingComputation<Float32>
|
||||
{
|
||||
public:
|
||||
{
|
||||
public:
|
||||
static inline void prepare(size_t scale, Scale & mm_scale)
|
||||
{
|
||||
Float32 fscale = static_cast<Float32>(scale);
|
||||
@ -415,19 +415,19 @@ namespace DB
|
||||
_mm_storeu_ps(out, val);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
static inline const __m128 & getOneTenth()
|
||||
{
|
||||
static const __m128 one_tenth = _mm_set1_ps(0.1);
|
||||
return one_tenth;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<int rounding_mode>
|
||||
class FloatRoundingComputation<Float32, rounding_mode, ZeroScale>
|
||||
template<int rounding_mode>
|
||||
class FloatRoundingComputation<Float32, rounding_mode, ZeroScale>
|
||||
: public BaseFloatRoundingComputation<Float32>
|
||||
{
|
||||
public:
|
||||
{
|
||||
public:
|
||||
static inline void prepare(size_t scale, Scale & mm_scale)
|
||||
{
|
||||
}
|
||||
@ -442,13 +442,13 @@ namespace DB
|
||||
normalize(val, mask);
|
||||
_mm_storeu_ps(out, val);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<int rounding_mode>
|
||||
class FloatRoundingComputation<Float64, rounding_mode, PositiveScale>
|
||||
template<int rounding_mode>
|
||||
class FloatRoundingComputation<Float64, rounding_mode, PositiveScale>
|
||||
: public BaseFloatRoundingComputation<Float64>
|
||||
{
|
||||
public:
|
||||
{
|
||||
public:
|
||||
static inline void prepare(size_t scale, Scale & mm_scale)
|
||||
{
|
||||
Float64 fscale = static_cast<Float64>(scale);
|
||||
@ -468,13 +468,13 @@ namespace DB
|
||||
normalize(val, mask);
|
||||
_mm_storeu_pd(out, val);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<int rounding_mode>
|
||||
class FloatRoundingComputation<Float64, rounding_mode, NegativeScale>
|
||||
template<int rounding_mode>
|
||||
class FloatRoundingComputation<Float64, rounding_mode, NegativeScale>
|
||||
: public BaseFloatRoundingComputation<Float64>
|
||||
{
|
||||
public:
|
||||
{
|
||||
public:
|
||||
static inline void prepare(size_t scale, Scale & mm_scale)
|
||||
{
|
||||
Float64 fscale = static_cast<Float64>(scale);
|
||||
@ -506,19 +506,19 @@ namespace DB
|
||||
_mm_storeu_pd(out, val);
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
static inline const __m128d & getOneTenth()
|
||||
{
|
||||
static const __m128d one_tenth = _mm_set1_pd(0.1);
|
||||
return one_tenth;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<int rounding_mode>
|
||||
class FloatRoundingComputation<Float64, rounding_mode, ZeroScale>
|
||||
template<int rounding_mode>
|
||||
class FloatRoundingComputation<Float64, rounding_mode, ZeroScale>
|
||||
: public BaseFloatRoundingComputation<Float64>
|
||||
{
|
||||
public:
|
||||
{
|
||||
public:
|
||||
static inline void prepare(size_t scale, Scale & mm_scale)
|
||||
{
|
||||
}
|
||||
@ -533,32 +533,32 @@ namespace DB
|
||||
normalize(val, mask);
|
||||
_mm_storeu_pd(out, val);
|
||||
}
|
||||
};
|
||||
};
|
||||
#else
|
||||
/// Реализация для ARM. Не векторизована. Не исправляет отрицательные нули.
|
||||
/// Реализация для ARM. Не векторизована. Не исправляет отрицательные нули.
|
||||
|
||||
template <int mode>
|
||||
float roundWithMode(float x)
|
||||
{
|
||||
template <int mode>
|
||||
float roundWithMode(float x)
|
||||
{
|
||||
if (mode == _MM_FROUND_NINT) return roundf(x);
|
||||
if (mode == _MM_FROUND_FLOOR) return floorf(x);
|
||||
if (mode == _MM_FROUND_CEIL) return ceilf(x);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
template <int mode>
|
||||
double roundWithMode(double x)
|
||||
{
|
||||
template <int mode>
|
||||
double roundWithMode(double x)
|
||||
{
|
||||
if (mode == _MM_FROUND_NINT) return round(x);
|
||||
if (mode == _MM_FROUND_FLOOR) return floor(x);
|
||||
if (mode == _MM_FROUND_CEIL) return ceil(x);
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class BaseFloatRoundingComputation
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
class BaseFloatRoundingComputation
|
||||
{
|
||||
public:
|
||||
using Scale = T;
|
||||
static const size_t data_count = 1;
|
||||
|
||||
@ -566,38 +566,38 @@ namespace DB
|
||||
{
|
||||
mm_scale = static_cast<T>(scale);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
class FloatRoundingComputation;
|
||||
template <typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
class FloatRoundingComputation;
|
||||
|
||||
template <typename T, int rounding_mode>
|
||||
class FloatRoundingComputation<T, rounding_mode, PositiveScale>
|
||||
template <typename T, int rounding_mode>
|
||||
class FloatRoundingComputation<T, rounding_mode, PositiveScale>
|
||||
: public BaseFloatRoundingComputation<T>
|
||||
{
|
||||
public:
|
||||
{
|
||||
public:
|
||||
static inline void compute(const T * __restrict in, const T & scale, T * __restrict out)
|
||||
{
|
||||
out[0] = roundWithMode<rounding_mode>(in[0] * scale) / scale;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T, int rounding_mode>
|
||||
class FloatRoundingComputation<T, rounding_mode, NegativeScale>
|
||||
template <typename T, int rounding_mode>
|
||||
class FloatRoundingComputation<T, rounding_mode, NegativeScale>
|
||||
: public BaseFloatRoundingComputation<T>
|
||||
{
|
||||
public:
|
||||
{
|
||||
public:
|
||||
static inline void compute(const T * __restrict in, const T & scale, T * __restrict out)
|
||||
{
|
||||
out[0] = roundWithMode<rounding_mode>(in[0] / scale) * scale;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <typename T, int rounding_mode>
|
||||
class FloatRoundingComputation<T, rounding_mode, ZeroScale>
|
||||
template <typename T, int rounding_mode>
|
||||
class FloatRoundingComputation<T, rounding_mode, ZeroScale>
|
||||
: public BaseFloatRoundingComputation<T>
|
||||
{
|
||||
public:
|
||||
{
|
||||
public:
|
||||
static inline void prepare(size_t scale, T & mm_scale)
|
||||
{
|
||||
}
|
||||
@ -606,25 +606,25 @@ namespace DB
|
||||
{
|
||||
out[0] = roundWithMode<rounding_mode>(in[0]);
|
||||
}
|
||||
};
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/** Реализация высокоуровневых функций округления.
|
||||
/** Реализация высокоуровневых функций округления.
|
||||
*/
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode, typename Enable = void>
|
||||
struct FunctionRoundingImpl;
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode, typename Enable = void>
|
||||
struct FunctionRoundingImpl;
|
||||
|
||||
/** Реализация высокоуровневых функций округления для целочисленных значений.
|
||||
/** Реализация высокоуровневых функций округления для целочисленных значений.
|
||||
*/
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
struct FunctionRoundingImpl<T, rounding_mode, scale_mode,
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
struct FunctionRoundingImpl<T, rounding_mode, scale_mode,
|
||||
typename std::enable_if<std::is_integral<T>::value && (scale_mode != NullScale)>::type>
|
||||
{
|
||||
private:
|
||||
{
|
||||
private:
|
||||
using Op = IntegerRoundingComputation<T, rounding_mode, scale_mode>;
|
||||
|
||||
public:
|
||||
public:
|
||||
static inline void apply(const PaddedPODArray<T> & in, size_t scale, typename ColumnVector<T>::Container_t & out)
|
||||
{
|
||||
auto divisor = Op::prepare(scale);
|
||||
@ -645,20 +645,20 @@ namespace DB
|
||||
auto divisor = Op::prepare(scale);
|
||||
return Op::compute(val, divisor);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/** Реализация высокоуровневых функций округления для значений с плавающей точкой.
|
||||
/** Реализация высокоуровневых функций округления для значений с плавающей точкой.
|
||||
*/
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
struct FunctionRoundingImpl<T, rounding_mode, scale_mode,
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
struct FunctionRoundingImpl<T, rounding_mode, scale_mode,
|
||||
typename std::enable_if<std::is_floating_point<T>::value && (scale_mode != NullScale)>::type>
|
||||
{
|
||||
private:
|
||||
{
|
||||
private:
|
||||
using Op = FloatRoundingComputation<T, rounding_mode, scale_mode>;
|
||||
using Data = std::array<T, Op::data_count>;
|
||||
using Scale = typename Op::Scale;
|
||||
|
||||
public:
|
||||
public:
|
||||
static inline void apply(const PaddedPODArray<T> & in, size_t scale, typename ColumnVector<T>::Container_t & out)
|
||||
{
|
||||
Scale mm_scale;
|
||||
@ -725,15 +725,15 @@ namespace DB
|
||||
return res[0];
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/** Реализация высокоуровневых функций округления в том случае, когда возвращается нулевое значение.
|
||||
/** Реализация высокоуровневых функций округления в том случае, когда возвращается нулевое значение.
|
||||
*/
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
struct FunctionRoundingImpl<T, rounding_mode, scale_mode,
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
struct FunctionRoundingImpl<T, rounding_mode, scale_mode,
|
||||
typename std::enable_if<scale_mode == NullScale>::type>
|
||||
{
|
||||
public:
|
||||
{
|
||||
public:
|
||||
static inline void apply(const PaddedPODArray<T> & in, size_t scale, typename ColumnVector<T>::Container_t & out)
|
||||
{
|
||||
::memset(reinterpret_cast<T *>(&out[0]), 0, in.size() * sizeof(T));
|
||||
@ -743,9 +743,9 @@ namespace DB
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/// Следующий код генерирует во время сборки таблицу степеней числа 10.
|
||||
/// Следующий код генерирует во время сборки таблицу степеней числа 10.
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -764,50 +764,50 @@ namespace
|
||||
};
|
||||
}
|
||||
|
||||
/// Объявление и определение контейнера содержащего таблицу степеней числа 10.
|
||||
/// Объявление и определение контейнера содержащего таблицу степеней числа 10.
|
||||
|
||||
template<size_t... TArgs>
|
||||
struct TableContainer
|
||||
{
|
||||
template<size_t... TArgs>
|
||||
struct TableContainer
|
||||
{
|
||||
static const std::array<size_t, sizeof...(TArgs)> values;
|
||||
};
|
||||
};
|
||||
|
||||
template<size_t... TArgs>
|
||||
const std::array<size_t, sizeof...(TArgs)> TableContainer<TArgs...>::values {{ TArgs... }};
|
||||
template<size_t... TArgs>
|
||||
const std::array<size_t, sizeof...(TArgs)> TableContainer<TArgs...>::values {{ TArgs... }};
|
||||
|
||||
/// Генератор первых N степеней.
|
||||
/// Генератор первых N степеней.
|
||||
|
||||
template<size_t N, size_t... TArgs>
|
||||
struct FillArrayImpl
|
||||
{
|
||||
template<size_t N, size_t... TArgs>
|
||||
struct FillArrayImpl
|
||||
{
|
||||
using result = typename FillArrayImpl<N - 1, PowerOf10<N>::value, TArgs...>::result;
|
||||
};
|
||||
};
|
||||
|
||||
template<size_t... TArgs>
|
||||
struct FillArrayImpl<0, TArgs...>
|
||||
{
|
||||
template<size_t... TArgs>
|
||||
struct FillArrayImpl<0, TArgs...>
|
||||
{
|
||||
using result = TableContainer<PowerOf10<0>::value, TArgs...>;
|
||||
};
|
||||
};
|
||||
|
||||
template<size_t N>
|
||||
struct FillArray
|
||||
{
|
||||
template<size_t N>
|
||||
struct FillArray
|
||||
{
|
||||
using result = typename FillArrayImpl<N - 1>::result;
|
||||
};
|
||||
};
|
||||
|
||||
/** Этот шаблон определяет точность, которую используют функции round/ceil/floor,
|
||||
/** Этот шаблон определяет точность, которую используют функции round/ceil/floor,
|
||||
* затем преобразовывает её в значение, которое можно использовать в операциях
|
||||
* умножения и деления. Поэтому оно называется масштабом.
|
||||
*/
|
||||
template<typename T, typename U, typename Enable = void>
|
||||
struct ScaleForRightType;
|
||||
template<typename T, typename U, typename Enable = void>
|
||||
struct ScaleForRightType;
|
||||
|
||||
template<typename T, typename U>
|
||||
struct ScaleForRightType<T, U,
|
||||
template<typename T, typename U>
|
||||
struct ScaleForRightType<T, U,
|
||||
typename std::enable_if<
|
||||
std::is_floating_point<T>::value
|
||||
&& std::is_signed<U>::value>::type>
|
||||
{
|
||||
{
|
||||
static inline bool apply(const ColumnPtr & column, ScaleMode & scale_mode, size_t & scale)
|
||||
{
|
||||
using PowersOf10 = typename FillArray<std::numeric_limits<T>::digits10 + 1>::result;
|
||||
@ -846,14 +846,14 @@ namespace
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct ScaleForRightType<T, U,
|
||||
template<typename T, typename U>
|
||||
struct ScaleForRightType<T, U,
|
||||
typename std::enable_if<
|
||||
std::is_floating_point<T>::value
|
||||
&& std::is_unsigned<U>::value>::type>
|
||||
{
|
||||
{
|
||||
static inline bool apply(const ColumnPtr & column, ScaleMode & scale_mode, size_t & scale)
|
||||
{
|
||||
using PowersOf10 = typename FillArray<std::numeric_limits<T>::digits10 + 1>::result;
|
||||
@ -879,14 +879,14 @@ namespace
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct ScaleForRightType<T, U,
|
||||
template<typename T, typename U>
|
||||
struct ScaleForRightType<T, U,
|
||||
typename std::enable_if<
|
||||
std::is_integral<T>::value
|
||||
&& std::is_signed<U>::value>::type>
|
||||
{
|
||||
{
|
||||
static inline bool apply(const ColumnPtr & column, ScaleMode & scale_mode, size_t & scale)
|
||||
{
|
||||
using PowersOf10 = typename FillArray<std::numeric_limits<T>::digits10 + 1>::result;
|
||||
@ -918,14 +918,14 @@ namespace
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T, typename U>
|
||||
struct ScaleForRightType<T, U,
|
||||
template<typename T, typename U>
|
||||
struct ScaleForRightType<T, U,
|
||||
typename std::enable_if<
|
||||
std::is_integral<T>::value
|
||||
&& std::is_unsigned<U>::value>::type>
|
||||
{
|
||||
{
|
||||
static inline bool apply(const ColumnPtr & column, ScaleMode & scale_mode, size_t & scale)
|
||||
{
|
||||
using ColumnType = ColumnConst<U>;
|
||||
@ -939,13 +939,13 @@ namespace
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/** Превратить параметр точности в масштаб.
|
||||
/** Превратить параметр точности в масштаб.
|
||||
*/
|
||||
template<typename T>
|
||||
struct ScaleForLeftType
|
||||
{
|
||||
template<typename T>
|
||||
struct ScaleForLeftType
|
||||
{
|
||||
static inline void apply(const ColumnPtr & column, ScaleMode & scale_mode, size_t & scale)
|
||||
{
|
||||
if (!( ScaleForRightType<T, UInt8>::apply(column, scale_mode, scale)
|
||||
@ -963,13 +963,13 @@ namespace
|
||||
throw Exception("Internal error", ErrorCodes::LOGICAL_ERROR);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/** Главный шаблон применяющий функцию округления к значению или столбцу.
|
||||
/** Главный шаблон применяющий функцию округления к значению или столбцу.
|
||||
*/
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
struct Cruncher
|
||||
{
|
||||
template<typename T, int rounding_mode, ScaleMode scale_mode>
|
||||
struct Cruncher
|
||||
{
|
||||
using Op = FunctionRoundingImpl<T, rounding_mode, scale_mode>;
|
||||
|
||||
static inline void apply(Block & block, ColumnVector<T> * col, const ColumnNumbers & arguments, size_t result, size_t scale)
|
||||
@ -992,13 +992,13 @@ namespace
|
||||
auto col_res = std::make_shared<ColumnConst<T>>(col->size(), res);
|
||||
block.safeGetByPosition(result).column = col_res;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/** Выбрать подходящий алгоритм обработки в зависимости от масштаба.
|
||||
/** Выбрать подходящий алгоритм обработки в зависимости от масштаба.
|
||||
*/
|
||||
template<typename T, template <typename> class U, int rounding_mode>
|
||||
struct Dispatcher
|
||||
{
|
||||
template<typename T, template <typename> class U, int rounding_mode>
|
||||
struct Dispatcher
|
||||
{
|
||||
static inline void apply(Block & block, U<T> * col, const ColumnNumbers & arguments, size_t result)
|
||||
{
|
||||
ScaleMode scale_mode;
|
||||
@ -1023,20 +1023,20 @@ namespace
|
||||
else
|
||||
throw Exception("Illegal operation", ErrorCodes::LOGICAL_ERROR);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/** Шаблон для функций, которые округляют значение входного параметра типа
|
||||
/** Шаблон для функций, которые округляют значение входного параметра типа
|
||||
* (U)Int8/16/32/64 или Float32/64, и принимают дополнительный необязятельный
|
||||
* параметр (по умолчанию - 0).
|
||||
*/
|
||||
template<typename Name, int rounding_mode>
|
||||
class FunctionRounding : public IFunction
|
||||
{
|
||||
public:
|
||||
template<typename Name, int rounding_mode>
|
||||
class FunctionRounding : public IFunction
|
||||
{
|
||||
public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionRounding>(); }
|
||||
|
||||
private:
|
||||
private:
|
||||
template<typename T>
|
||||
bool checkType(const IDataType * type) const
|
||||
{
|
||||
@ -1060,8 +1060,7 @@ namespace
|
||||
return false;
|
||||
}
|
||||
|
||||
public:
|
||||
/// Получить имя функции.
|
||||
public:
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -1105,7 +1104,6 @@ namespace
|
||||
return arguments[0];
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
if (!( executeForType<UInt8>(block, arguments, result)
|
||||
@ -1134,34 +1132,35 @@ namespace
|
||||
{
|
||||
return { true };
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
struct NameRoundToExp2 { static constexpr auto name = "roundToExp2"; };
|
||||
struct NameRoundDuration { static constexpr auto name = "roundDuration"; };
|
||||
struct NameRoundAge { static constexpr auto name = "roundAge"; };
|
||||
struct NameRound { static constexpr auto name = "round"; };
|
||||
struct NameCeil { static constexpr auto name = "ceil"; };
|
||||
struct NameFloor { static constexpr auto name = "floor"; };
|
||||
struct NameRoundToExp2 { static constexpr auto name = "roundToExp2"; };
|
||||
struct NameRoundDuration { static constexpr auto name = "roundDuration"; };
|
||||
struct NameRoundAge { static constexpr auto name = "roundAge"; };
|
||||
struct NameRound { static constexpr auto name = "round"; };
|
||||
struct NameCeil { static constexpr auto name = "ceil"; };
|
||||
struct NameFloor { static constexpr auto name = "floor"; };
|
||||
|
||||
using FunctionRoundToExp2 = FunctionUnaryArithmetic<RoundToExp2Impl, NameRoundToExp2, false>;
|
||||
using FunctionRoundDuration = FunctionUnaryArithmetic<RoundDurationImpl, NameRoundDuration, false>;
|
||||
using FunctionRoundAge = FunctionUnaryArithmetic<RoundAgeImpl, NameRoundAge, false>;
|
||||
using FunctionRoundToExp2 = FunctionUnaryArithmetic<RoundToExp2Impl, NameRoundToExp2, false>;
|
||||
using FunctionRoundDuration = FunctionUnaryArithmetic<RoundDurationImpl, NameRoundDuration, false>;
|
||||
using FunctionRoundAge = FunctionUnaryArithmetic<RoundAgeImpl, NameRoundAge, false>;
|
||||
|
||||
using FunctionRound = FunctionRounding<NameRound, _MM_FROUND_NINT>;
|
||||
using FunctionFloor = FunctionRounding<NameFloor, _MM_FROUND_FLOOR>;
|
||||
using FunctionCeil = FunctionRounding<NameCeil, _MM_FROUND_CEIL>;
|
||||
using FunctionRound = FunctionRounding<NameRound, _MM_FROUND_NINT>;
|
||||
using FunctionFloor = FunctionRounding<NameFloor, _MM_FROUND_FLOOR>;
|
||||
using FunctionCeil = FunctionRounding<NameCeil, _MM_FROUND_CEIL>;
|
||||
|
||||
|
||||
struct PositiveMonotonicity
|
||||
{
|
||||
struct PositiveMonotonicity
|
||||
{
|
||||
static bool has() { return true; }
|
||||
static IFunction::Monotonicity get(const Field & left, const Field & right)
|
||||
{
|
||||
return { true };
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template <> struct FunctionUnaryArithmeticMonotonicity<NameRoundToExp2> : PositiveMonotonicity {};
|
||||
template <> struct FunctionUnaryArithmeticMonotonicity<NameRoundDuration> : PositiveMonotonicity {};
|
||||
template <> struct FunctionUnaryArithmeticMonotonicity<NameRoundAge> : PositiveMonotonicity {};
|
||||
|
||||
template <> struct FunctionUnaryArithmeticMonotonicity<NameRoundToExp2> : PositiveMonotonicity {};
|
||||
template <> struct FunctionUnaryArithmeticMonotonicity<NameRoundDuration> : PositiveMonotonicity {};
|
||||
template <> struct FunctionUnaryArithmeticMonotonicity<NameRoundAge> : PositiveMonotonicity {};
|
||||
}
|
||||
|
@ -772,7 +772,6 @@ public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionStringOrArrayToT>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -780,7 +779,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeString *>(&*arguments[0]) && !typeid_cast<const DataTypeFixedString *>(&*arguments[0])
|
||||
@ -791,7 +789,6 @@ public:
|
||||
return std::make_shared<typename DataTypeFromFieldType<ResultType>::Type>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
const ColumnPtr column = block.safeGetByPosition(arguments[0]).column;
|
||||
@ -865,7 +862,6 @@ public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionStringToString>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -874,7 +870,6 @@ public:
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
bool isInjective(const Block &) override { return is_injective; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeString *>(&*arguments[0]) && !typeid_cast<const DataTypeFixedString *>(&*arguments[0]))
|
||||
@ -884,7 +879,6 @@ public:
|
||||
return arguments[0]->clone();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
const ColumnPtr column = block.safeGetByPosition(arguments[0]).column;
|
||||
@ -924,14 +918,12 @@ public:
|
||||
static constexpr auto name = "reverse";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionReverse>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override;
|
||||
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
bool isInjective(const Block &) override { return true; }
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override;
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override;
|
||||
};
|
||||
|
||||
@ -943,7 +935,6 @@ public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<ConcatImpl>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -953,7 +944,6 @@ public:
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
bool isInjective(const Block &) override { return is_injective; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (arguments.size() < 2)
|
||||
@ -1426,7 +1416,6 @@ public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionStringNumNumToString>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -1434,7 +1423,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 3; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeString *>(&*arguments[0]) && !typeid_cast<const DataTypeFixedString *>(&*arguments[0]))
|
||||
@ -1448,7 +1436,6 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
const ColumnPtr column_string = block.safeGetByPosition(arguments[0]).column;
|
||||
|
@ -310,7 +310,6 @@ public:
|
||||
static constexpr auto name = Generator::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionTokens>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -318,7 +317,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return Generator::getNumberOfArguments(); }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
Generator::checkArguments(arguments);
|
||||
@ -326,7 +324,6 @@ public:
|
||||
return std::make_shared<DataTypeArray>(std::make_shared<DataTypeString>());
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
Generator generator;
|
||||
@ -477,7 +474,6 @@ public:
|
||||
static constexpr auto name = "arrayStringConcat";
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionArrayStringConcat>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -486,7 +482,6 @@ public:
|
||||
bool isVariadic() const override { return true; }
|
||||
size_t getNumberOfArguments() const override { return 0; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (arguments.size() != 1 && arguments.size() != 2)
|
||||
@ -505,7 +500,6 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
String delimiter;
|
||||
|
@ -1038,7 +1038,6 @@ public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionStringReplace>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -1046,7 +1045,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 3; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeString *>(&*arguments[0]) && !typeid_cast<const DataTypeFixedString *>(&*arguments[0]))
|
||||
@ -1064,7 +1062,6 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
const ColumnPtr column_src = block.safeGetByPosition(arguments[0]).column;
|
||||
@ -1122,7 +1119,6 @@ public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionsStringSearch>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -1130,7 +1126,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 2; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeString *>(&*arguments[0]))
|
||||
@ -1144,7 +1139,6 @@ public:
|
||||
return std::make_shared<typename DataTypeFromFieldType<typename Impl::ResultType>::Type>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
using ResultType = typename Impl::ResultType;
|
||||
@ -1204,7 +1198,6 @@ public:
|
||||
static constexpr auto name = Name::name;
|
||||
static FunctionPtr create(const Context & context) { return std::make_shared<FunctionsStringSearchToString>(); }
|
||||
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return name;
|
||||
@ -1212,7 +1205,6 @@ public:
|
||||
|
||||
size_t getNumberOfArguments() const override { return 2; }
|
||||
|
||||
/// Получить тип результата по типам аргументов. Если функция неприменима для данных аргументов - кинуть исключение.
|
||||
DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
|
||||
{
|
||||
if (!typeid_cast<const DataTypeString *>(&*arguments[0]))
|
||||
@ -1226,7 +1218,6 @@ public:
|
||||
return std::make_shared<DataTypeString>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
const ColumnPtr column = block.safeGetByPosition(arguments[0]).column;
|
||||
|
@ -135,7 +135,10 @@ private:
|
||||
|
||||
ClusterPtr getCluster() const;
|
||||
|
||||
private:
|
||||
/// Get monotonically increasing string to name files with data to be written to remote servers.
|
||||
String getMonotonicFileName();
|
||||
|
||||
|
||||
String name;
|
||||
NamesAndTypesListPtr columns;
|
||||
String remote_database;
|
||||
|
@ -1,10 +1,337 @@
|
||||
#include <string.h> // memcpy
|
||||
|
||||
#include <DB/Columns/ColumnArray.h>
|
||||
#include <DB/Columns/ColumnsNumber.h>
|
||||
#include <DB/Columns/ColumnString.h>
|
||||
#include <DB/Columns/ColumnsCommon.h>
|
||||
|
||||
#include <DB/Common/Exception.h>
|
||||
#include <DB/Common/Arena.h>
|
||||
#include <DB/Common/SipHash.h>
|
||||
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int ILLEGAL_COLUMN;
|
||||
extern const int NOT_IMPLEMENTED;
|
||||
extern const int BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
|
||||
ColumnArray::ColumnArray(ColumnPtr nested_column, ColumnPtr offsets_column)
|
||||
: data(nested_column), offsets(offsets_column)
|
||||
{
|
||||
if (!offsets_column)
|
||||
{
|
||||
offsets = std::make_shared<ColumnOffsets_t>();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!typeid_cast<ColumnOffsets_t *>(&*offsets_column))
|
||||
throw Exception("offsets_column must be a ColumnUInt64", ErrorCodes::ILLEGAL_COLUMN);
|
||||
}
|
||||
|
||||
/** NOTE
|
||||
* Arrays with constant value are possible and used in implementation of higher order functions and in ARRAY JOIN.
|
||||
* But in most cases, arrays with constant value are unexpected and code will work wrong. Use with caution.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
std::string ColumnArray::getName() const { return "ColumnArray(" + getData().getName() + ")"; }
|
||||
|
||||
|
||||
ColumnPtr ColumnArray::cloneResized(size_t to_size) const
|
||||
{
|
||||
auto res = std::make_shared<ColumnArray>(getData().cloneEmpty());
|
||||
|
||||
if (to_size == 0)
|
||||
return res;
|
||||
|
||||
size_t from_size = size();
|
||||
|
||||
if (to_size <= from_size)
|
||||
{
|
||||
/// Just cut column.
|
||||
|
||||
res->getOffsets().assign(getOffsets().begin(), getOffsets().begin() + to_size);
|
||||
res->getData().insertRangeFrom(getData(), 0, getOffsets()[to_size - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Copy column and append empty arrays for extra elements.
|
||||
|
||||
Offset_t offset = 0;
|
||||
if (from_size > 0)
|
||||
{
|
||||
res->getOffsets().assign(getOffsets().begin(), getOffsets().end());
|
||||
res->getDataPtr() = getData().clone();
|
||||
offset = getOffsets().back();
|
||||
}
|
||||
|
||||
res->getOffsets().resize(to_size);
|
||||
for (size_t i = from_size; i < to_size; ++i)
|
||||
{
|
||||
++offset;
|
||||
res->getOffsets()[i] = offset;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
size_t ColumnArray::size() const
|
||||
{
|
||||
return getOffsets().size();
|
||||
}
|
||||
|
||||
|
||||
Field ColumnArray::operator[](size_t n) const
|
||||
{
|
||||
size_t offset = offsetAt(n);
|
||||
size_t size = sizeAt(n);
|
||||
Array res(size);
|
||||
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
res[i] = getData()[offset + i];
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void ColumnArray::get(size_t n, Field & res) const
|
||||
{
|
||||
size_t offset = offsetAt(n);
|
||||
size_t size = sizeAt(n);
|
||||
res = Array(size);
|
||||
Array & res_arr = DB::get<Array &>(res);
|
||||
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
getData().get(offset + i, res_arr[i]);
|
||||
}
|
||||
|
||||
|
||||
StringRef ColumnArray::getDataAt(size_t n) const
|
||||
{
|
||||
/** Возвращает диапазон памяти, покрывающий все элементы массива.
|
||||
* Работает для массивов значений фиксированной длины.
|
||||
* Для массивов строк и массивов массивов полученный кусок памяти может не взаимно-однозначно соответствовать элементам,
|
||||
* так как содержит лишь уложенные подряд данные, но не смещения.
|
||||
*/
|
||||
|
||||
size_t array_size = sizeAt(n);
|
||||
if (array_size == 0)
|
||||
return StringRef();
|
||||
|
||||
size_t offset_of_first_elem = offsetAt(n);
|
||||
StringRef first = getData().getDataAtWithTerminatingZero(offset_of_first_elem);
|
||||
|
||||
size_t offset_of_last_elem = getOffsets()[n] - 1;
|
||||
StringRef last = getData().getDataAtWithTerminatingZero(offset_of_last_elem);
|
||||
|
||||
return StringRef(first.data, last.data + last.size - first.data);
|
||||
}
|
||||
|
||||
|
||||
void ColumnArray::insertData(const char * pos, size_t length)
|
||||
{
|
||||
/** Аналогично - только для массивов значений фиксированной длины.
|
||||
*/
|
||||
IColumn * data_ = data.get();
|
||||
if (!data_->isFixed())
|
||||
throw Exception("Method insertData is not supported for " + getName(), ErrorCodes::NOT_IMPLEMENTED);
|
||||
|
||||
size_t field_size = data_->sizeOfField();
|
||||
|
||||
const char * end = pos + length;
|
||||
size_t elems = 0;
|
||||
for (; pos + field_size <= end; pos += field_size, ++elems)
|
||||
data_->insertData(pos, field_size);
|
||||
|
||||
if (pos != end)
|
||||
throw Exception("Incorrect length argument for method ColumnArray::insertData", ErrorCodes::BAD_ARGUMENTS);
|
||||
|
||||
getOffsets().push_back((getOffsets().size() == 0 ? 0 : getOffsets().back()) + elems);
|
||||
}
|
||||
|
||||
|
||||
StringRef ColumnArray::serializeValueIntoArena(size_t n, Arena & arena, char const *& begin) const
|
||||
{
|
||||
size_t array_size = sizeAt(n);
|
||||
size_t offset = offsetAt(n);
|
||||
|
||||
char * pos = arena.allocContinue(sizeof(array_size), begin);
|
||||
memcpy(pos, &array_size, sizeof(array_size));
|
||||
|
||||
size_t values_size = 0;
|
||||
for (size_t i = 0; i < array_size; ++i)
|
||||
values_size += getData().serializeValueIntoArena(offset + i, arena, begin).size;
|
||||
|
||||
return StringRef(begin, sizeof(array_size) + values_size);
|
||||
}
|
||||
|
||||
|
||||
const char * ColumnArray::deserializeAndInsertFromArena(const char * pos)
|
||||
{
|
||||
size_t array_size = *reinterpret_cast<const size_t *>(pos);
|
||||
pos += sizeof(array_size);
|
||||
|
||||
for (size_t i = 0; i < array_size; ++i)
|
||||
pos = getData().deserializeAndInsertFromArena(pos);
|
||||
|
||||
getOffsets().push_back((getOffsets().size() == 0 ? 0 : getOffsets().back()) + array_size);
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
void ColumnArray::updateHashWithValue(size_t n, SipHash & hash) const
|
||||
{
|
||||
size_t array_size = sizeAt(n);
|
||||
size_t offset = offsetAt(n);
|
||||
|
||||
hash.update(reinterpret_cast<const char *>(&array_size), sizeof(array_size));
|
||||
for (size_t i = 0; i < array_size; ++i)
|
||||
getData().updateHashWithValue(offset + i, hash);
|
||||
}
|
||||
|
||||
|
||||
void ColumnArray::insert(const Field & x)
|
||||
{
|
||||
const Array & array = DB::get<const Array &>(x);
|
||||
size_t size = array.size();
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
getData().insert(array[i]);
|
||||
getOffsets().push_back((getOffsets().size() == 0 ? 0 : getOffsets().back()) + size);
|
||||
}
|
||||
|
||||
|
||||
void ColumnArray::insertFrom(const IColumn & src_, size_t n)
|
||||
{
|
||||
const ColumnArray & src = static_cast<const ColumnArray &>(src_);
|
||||
size_t size = src.sizeAt(n);
|
||||
size_t offset = src.offsetAt(n);
|
||||
|
||||
getData().insertRangeFrom(src.getData(), offset, size);
|
||||
getOffsets().push_back((getOffsets().size() == 0 ? 0 : getOffsets().back()) + size);
|
||||
}
|
||||
|
||||
|
||||
void ColumnArray::insertDefault()
|
||||
{
|
||||
getOffsets().push_back(getOffsets().size() == 0 ? 0 : getOffsets().back());
|
||||
}
|
||||
|
||||
|
||||
void ColumnArray::popBack(size_t n)
|
||||
{
|
||||
auto & offsets = getOffsets();
|
||||
size_t nested_n = offsets.back() - offsetAt(offsets.size() - n);
|
||||
if (nested_n)
|
||||
getData().popBack(nested_n);
|
||||
offsets.resize_assume_reserved(offsets.size() - n);
|
||||
}
|
||||
|
||||
|
||||
int ColumnArray::compareAt(size_t n, size_t m, const IColumn & rhs_, int nan_direction_hint) const
|
||||
{
|
||||
const ColumnArray & rhs = static_cast<const ColumnArray &>(rhs_);
|
||||
|
||||
/// Не оптимально
|
||||
size_t lhs_size = sizeAt(n);
|
||||
size_t rhs_size = rhs.sizeAt(m);
|
||||
size_t min_size = std::min(lhs_size, rhs_size);
|
||||
for (size_t i = 0; i < min_size; ++i)
|
||||
if (int res = getData().compareAt(offsetAt(n) + i, rhs.offsetAt(m) + i, *rhs.data.get(), nan_direction_hint))
|
||||
return res;
|
||||
|
||||
return lhs_size < rhs_size
|
||||
? -1
|
||||
: (lhs_size == rhs_size
|
||||
? 0
|
||||
: 1);
|
||||
}
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
template <bool positive>
|
||||
struct less
|
||||
{
|
||||
const ColumnArray & parent;
|
||||
|
||||
less(const ColumnArray & parent_) : parent(parent_) {}
|
||||
|
||||
bool operator()(size_t lhs, size_t rhs) const
|
||||
{
|
||||
if (positive)
|
||||
return parent.compareAt(lhs, rhs, parent, 1) < 0;
|
||||
else
|
||||
return parent.compareAt(lhs, rhs, parent, -1) > 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void ColumnArray::reserve(size_t n)
|
||||
{
|
||||
getOffsets().reserve(n);
|
||||
getData().reserve(n); /// Средний размер массивов тут никак не учитывается. Или считается, что он не больше единицы.
|
||||
}
|
||||
|
||||
|
||||
size_t ColumnArray::byteSize() const
|
||||
{
|
||||
return getData().byteSize() + getOffsets().size() * sizeof(getOffsets()[0]);
|
||||
}
|
||||
|
||||
|
||||
size_t ColumnArray::allocatedSize() const
|
||||
{
|
||||
return getData().allocatedSize() + getOffsets().allocated_size() * sizeof(getOffsets()[0]);
|
||||
}
|
||||
|
||||
|
||||
bool ColumnArray::hasEqualOffsets(const ColumnArray & other) const
|
||||
{
|
||||
if (offsets == other.offsets)
|
||||
return true;
|
||||
|
||||
const Offsets_t & offsets1 = getOffsets();
|
||||
const Offsets_t & offsets2 = other.getOffsets();
|
||||
return offsets1.size() == offsets2.size() && 0 == memcmp(&offsets1[0], &offsets2[0], sizeof(offsets1[0]) * offsets1.size());
|
||||
}
|
||||
|
||||
|
||||
ColumnPtr ColumnArray::convertToFullColumnIfConst() const
|
||||
{
|
||||
ColumnPtr new_data;
|
||||
ColumnPtr new_offsets;
|
||||
|
||||
if (auto full_column = getData().convertToFullColumnIfConst())
|
||||
new_data = full_column;
|
||||
else
|
||||
new_data = data;
|
||||
|
||||
if (auto full_column = offsets.get()->convertToFullColumnIfConst())
|
||||
new_offsets = full_column;
|
||||
else
|
||||
new_offsets = offsets;
|
||||
|
||||
return std::make_shared<ColumnArray>(new_data, new_offsets);
|
||||
}
|
||||
|
||||
|
||||
void ColumnArray::getExtremes(Field & min, Field & max) const
|
||||
{
|
||||
min = Array();
|
||||
max = Array();
|
||||
}
|
||||
|
||||
|
||||
void ColumnArray::insertRangeFrom(const IColumn & src, size_t start, size_t length)
|
||||
{
|
||||
|
@ -1,10 +1,262 @@
|
||||
#include <DB/Core/Defines.h>
|
||||
|
||||
#include <DB/Common/Collator.h>
|
||||
#include <DB/Columns/ColumnString.h>
|
||||
#include <DB/Columns/ColumnsCommon.h>
|
||||
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int PARAMETER_OUT_OF_BOUND;
|
||||
extern const int SIZES_OF_COLUMNS_DOESNT_MATCH;
|
||||
}
|
||||
|
||||
|
||||
ColumnPtr ColumnString::cloneResized(size_t to_size) const
|
||||
{
|
||||
auto res = std::make_shared<ColumnString>();
|
||||
|
||||
if (to_size == 0)
|
||||
return res;
|
||||
|
||||
size_t from_size = size();
|
||||
|
||||
if (to_size <= from_size)
|
||||
{
|
||||
/// Just cut column.
|
||||
|
||||
res->offsets.assign(offsets.begin(), offsets.begin() + to_size);
|
||||
res->chars.assign(chars.begin(), chars.begin() + offsets[to_size - 1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
/// Copy column and append empty strings for extra elements.
|
||||
|
||||
Offset_t offset = 0;
|
||||
if (from_size > 0)
|
||||
{
|
||||
res->offsets.assign(offsets.begin(), offsets.end());
|
||||
res->chars.assign(chars.begin(), chars.end());
|
||||
offset = offsets.back();
|
||||
}
|
||||
|
||||
/// Empty strings are just zero terminating bytes.
|
||||
|
||||
res->chars.resize_fill(res->chars.size() + to_size - from_size);
|
||||
|
||||
res->offsets.resize(to_size);
|
||||
for (size_t i = from_size; i < to_size; ++i)
|
||||
{
|
||||
++offset;
|
||||
res->offsets[i] = offset;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void ColumnString::insertRangeFrom(const IColumn & src, size_t start, size_t length)
|
||||
{
|
||||
if (length == 0)
|
||||
return;
|
||||
|
||||
const ColumnString & src_concrete = static_cast<const ColumnString &>(src);
|
||||
|
||||
if (start + length > src_concrete.offsets.size())
|
||||
throw Exception("Parameter out of bound in IColumnString::insertRangeFrom method.",
|
||||
ErrorCodes::PARAMETER_OUT_OF_BOUND);
|
||||
|
||||
size_t nested_offset = src_concrete.offsetAt(start);
|
||||
size_t nested_length = src_concrete.offsets[start + length - 1] - nested_offset;
|
||||
|
||||
size_t old_chars_size = chars.size();
|
||||
chars.resize(old_chars_size + nested_length);
|
||||
memcpy(&chars[old_chars_size], &src_concrete.chars[nested_offset], nested_length);
|
||||
|
||||
if (start == 0 && offsets.empty())
|
||||
{
|
||||
offsets.assign(src_concrete.offsets.begin(), src_concrete.offsets.begin() + length);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t old_size = offsets.size();
|
||||
size_t prev_max_offset = old_size ? offsets.back() : 0;
|
||||
offsets.resize(old_size + length);
|
||||
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
offsets[old_size + i] = src_concrete.offsets[start + i] - nested_offset + prev_max_offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ColumnPtr ColumnString::filter(const Filter & filt, ssize_t result_size_hint) const
|
||||
{
|
||||
if (offsets.size() == 0)
|
||||
return std::make_shared<ColumnString>();
|
||||
|
||||
auto res = std::make_shared<ColumnString>();
|
||||
|
||||
Chars_t & res_chars = res->chars;
|
||||
Offsets_t & res_offsets = res->offsets;
|
||||
|
||||
filterArraysImpl<UInt8>(chars, offsets, res_chars, res_offsets, filt, result_size_hint);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
ColumnPtr ColumnString::permute(const Permutation & perm, size_t limit) const
|
||||
{
|
||||
size_t size = offsets.size();
|
||||
|
||||
if (limit == 0)
|
||||
limit = size;
|
||||
else
|
||||
limit = std::min(size, limit);
|
||||
|
||||
if (perm.size() < limit)
|
||||
throw Exception("Size of permutation is less than required.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
|
||||
|
||||
if (limit == 0)
|
||||
return std::make_shared<ColumnString>();
|
||||
|
||||
std::shared_ptr<ColumnString> res = std::make_shared<ColumnString>();
|
||||
|
||||
Chars_t & res_chars = res->chars;
|
||||
Offsets_t & res_offsets = res->offsets;
|
||||
|
||||
if (limit == size)
|
||||
res_chars.resize(chars.size());
|
||||
else
|
||||
{
|
||||
size_t new_chars_size = 0;
|
||||
for (size_t i = 0; i < limit; ++i)
|
||||
new_chars_size += sizeAt(perm[i]);
|
||||
res_chars.resize(new_chars_size);
|
||||
}
|
||||
|
||||
res_offsets.resize(limit);
|
||||
|
||||
Offset_t current_new_offset = 0;
|
||||
|
||||
for (size_t i = 0; i < limit; ++i)
|
||||
{
|
||||
size_t j = perm[i];
|
||||
size_t string_offset = j == 0 ? 0 : offsets[j - 1];
|
||||
size_t string_size = offsets[j] - string_offset;
|
||||
|
||||
memcpySmallAllowReadWriteOverflow15(&res_chars[current_new_offset], &chars[string_offset], string_size);
|
||||
|
||||
current_new_offset += string_size;
|
||||
res_offsets[i] = current_new_offset;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
template <bool positive>
|
||||
struct ColumnString::less
|
||||
{
|
||||
const ColumnString & parent;
|
||||
less(const ColumnString & parent_) : parent(parent_) {}
|
||||
bool operator()(size_t lhs, size_t rhs) const
|
||||
{
|
||||
int res = strcmp(
|
||||
reinterpret_cast<const char *>(&parent.chars[parent.offsetAt(lhs)]),
|
||||
reinterpret_cast<const char *>(&parent.chars[parent.offsetAt(rhs)]));
|
||||
|
||||
return positive ? (res < 0) : (res > 0);
|
||||
}
|
||||
};
|
||||
|
||||
void ColumnString::getPermutation(bool reverse, size_t limit, Permutation & res) const
|
||||
{
|
||||
size_t s = offsets.size();
|
||||
res.resize(s);
|
||||
for (size_t i = 0; i < s; ++i)
|
||||
res[i] = i;
|
||||
|
||||
if (limit >= s)
|
||||
limit = 0;
|
||||
|
||||
if (limit)
|
||||
{
|
||||
if (reverse)
|
||||
std::partial_sort(res.begin(), res.begin() + limit, res.end(), less<false>(*this));
|
||||
else
|
||||
std::partial_sort(res.begin(), res.begin() + limit, res.end(), less<true>(*this));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reverse)
|
||||
std::sort(res.begin(), res.end(), less<false>(*this));
|
||||
else
|
||||
std::sort(res.begin(), res.end(), less<true>(*this));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ColumnPtr ColumnString::replicate(const Offsets_t & replicate_offsets) const
|
||||
{
|
||||
size_t col_size = size();
|
||||
if (col_size != replicate_offsets.size())
|
||||
throw Exception("Size of offsets doesn't match size of column.", ErrorCodes::SIZES_OF_COLUMNS_DOESNT_MATCH);
|
||||
|
||||
std::shared_ptr<ColumnString> res = std::make_shared<ColumnString>();
|
||||
|
||||
if (0 == col_size)
|
||||
return res;
|
||||
|
||||
Chars_t & res_chars = res->chars;
|
||||
Offsets_t & res_offsets = res->offsets;
|
||||
res_chars.reserve(chars.size() / col_size * replicate_offsets.back());
|
||||
res_offsets.reserve(replicate_offsets.back());
|
||||
|
||||
Offset_t prev_replicate_offset = 0;
|
||||
Offset_t prev_string_offset = 0;
|
||||
Offset_t current_new_offset = 0;
|
||||
|
||||
for (size_t i = 0; i < col_size; ++i)
|
||||
{
|
||||
size_t size_to_replicate = replicate_offsets[i] - prev_replicate_offset;
|
||||
size_t string_size = offsets[i] - prev_string_offset;
|
||||
|
||||
for (size_t j = 0; j < size_to_replicate; ++j)
|
||||
{
|
||||
current_new_offset += string_size;
|
||||
res_offsets.push_back(current_new_offset);
|
||||
|
||||
res_chars.resize(res_chars.size() + string_size);
|
||||
memcpySmallAllowReadWriteOverflow15(
|
||||
&res_chars[res_chars.size() - string_size], &chars[prev_string_offset], string_size);
|
||||
}
|
||||
|
||||
prev_replicate_offset = replicate_offsets[i];
|
||||
prev_string_offset = offsets[i];
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void ColumnString::reserve(size_t n)
|
||||
{
|
||||
offsets.reserve(n);
|
||||
chars.reserve(n * DBMS_APPROX_STRING_SIZE);
|
||||
}
|
||||
|
||||
|
||||
void ColumnString::getExtremes(Field & min, Field & max) const
|
||||
{
|
||||
min = String();
|
||||
max = String();
|
||||
}
|
||||
|
||||
|
||||
int ColumnString::compareAtWithCollation(size_t n, size_t m, const IColumn & rhs_, const Collator & collator) const
|
||||
{
|
||||
const ColumnString & rhs = static_cast<const ColumnString &>(rhs_);
|
||||
@ -16,7 +268,7 @@ int ColumnString::compareAtWithCollation(size_t n, size_t m, const IColumn & rhs
|
||||
|
||||
|
||||
template <bool positive>
|
||||
struct lessWithCollation
|
||||
struct ColumnString::lessWithCollation
|
||||
{
|
||||
const ColumnString & parent;
|
||||
const Collator & collator;
|
||||
@ -33,7 +285,6 @@ struct lessWithCollation
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void ColumnString::getPermutationWithCollation(const Collator & collator, bool reverse, size_t limit, Permutation & res) const
|
||||
{
|
||||
size_t s = offsets.size();
|
||||
|
@ -1068,7 +1068,6 @@ DataTypePtr FunctionArrayElement::getReturnTypeImpl(const DataTypes & arguments)
|
||||
return array_type->getNestedType();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void FunctionArrayElement::executeImpl(Block & block, const ColumnNumbers & arguments, size_t result)
|
||||
{
|
||||
/// Check nullability.
|
||||
@ -1599,7 +1598,6 @@ FunctionPtr FunctionArrayEnumerateUniq::create(const Context & context)
|
||||
return std::make_shared<FunctionArrayEnumerateUniq>();
|
||||
}
|
||||
|
||||
/// Получить имя функции.
|
||||
String FunctionArrayEnumerateUniq::getName() const
|
||||
{
|
||||
return name;
|
||||
|
@ -184,7 +184,6 @@ private:
|
||||
}
|
||||
|
||||
public:
|
||||
/// Получить имя функции.
|
||||
String getName() const override
|
||||
{
|
||||
return Name::get();
|
||||
@ -213,7 +212,6 @@ public:
|
||||
return std::make_shared<DataTypeUInt8>();
|
||||
}
|
||||
|
||||
/// Выполнить функцию над блоком.
|
||||
void execute(Block & block, const ColumnNumbers & arguments, size_t result)
|
||||
{
|
||||
//Stopwatch sw;
|
||||
|
@ -98,6 +98,7 @@ StorageDistributed::StorageDistributed(
|
||||
createDirectoryMonitors();
|
||||
}
|
||||
|
||||
|
||||
StorageDistributed::StorageDistributed(
|
||||
const std::string & name_,
|
||||
NamesAndTypesListPtr columns_,
|
||||
@ -121,6 +122,7 @@ StorageDistributed::StorageDistributed(
|
||||
createDirectoryMonitors();
|
||||
}
|
||||
|
||||
|
||||
StoragePtr StorageDistributed::create(
|
||||
const std::string & name_,
|
||||
NamesAndTypesListPtr columns_,
|
||||
@ -162,6 +164,7 @@ StoragePtr StorageDistributed::create(
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
BlockInputStreams StorageDistributed::read(
|
||||
const Names & column_names,
|
||||
ASTPtr query,
|
||||
@ -203,6 +206,7 @@ BlockInputStreams StorageDistributed::read(
|
||||
context, settings, enable_shard_multiplexing}.execute();
|
||||
}
|
||||
|
||||
|
||||
BlockOutputStreamPtr StorageDistributed::write(ASTPtr query, const Settings & settings)
|
||||
{
|
||||
auto cluster = context.getCluster(cluster_name);
|
||||
@ -214,14 +218,14 @@ BlockOutputStreamPtr StorageDistributed::write(ASTPtr query, const Settings & se
|
||||
throw Exception{
|
||||
"Method write is not supported by storage " + getName() +
|
||||
" with more than one shard and no sharding key provided",
|
||||
ErrorCodes::STORAGE_REQUIRES_PARAMETER
|
||||
};
|
||||
ErrorCodes::STORAGE_REQUIRES_PARAMETER};
|
||||
|
||||
/// DistributedBlockOutputStream will not own cluster, but will own ConnectionPools of the cluster
|
||||
return std::make_shared<DistributedBlockOutputStream>(
|
||||
*this, rewriteInsertQuery(query, remote_database, remote_table), cluster);
|
||||
}
|
||||
|
||||
|
||||
void StorageDistributed::alter(const AlterCommands & params, const String & database_name, const String & table_name, const Context & context)
|
||||
{
|
||||
for (const auto & param : params)
|
||||
@ -236,11 +240,13 @@ void StorageDistributed::alter(const AlterCommands & params, const String & data
|
||||
*columns, materialized_columns, alias_columns, column_defaults, {});
|
||||
}
|
||||
|
||||
|
||||
void StorageDistributed::shutdown()
|
||||
{
|
||||
directory_monitors.clear();
|
||||
}
|
||||
|
||||
|
||||
void StorageDistributed::reshardPartitions(ASTPtr query, const String & database_name,
|
||||
const Field & first_partition, const Field & last_partition,
|
||||
const WeightedZooKeeperPaths & weighted_zookeeper_paths,
|
||||
@ -383,6 +389,7 @@ void StorageDistributed::reshardPartitions(ASTPtr query, const String & database
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
BlockInputStreams StorageDistributed::describe(const Context & context, const Settings & settings)
|
||||
{
|
||||
/// Создать запрос DESCRIBE TABLE.
|
||||
@ -406,6 +413,7 @@ BlockInputStreams StorageDistributed::describe(const Context & context, const Se
|
||||
context, settings, enable_shard_multiplexing}.execute();
|
||||
}
|
||||
|
||||
|
||||
NameAndTypePair StorageDistributed::getColumn(const String & column_name) const
|
||||
{
|
||||
if (const auto & type = VirtualColumnFactory::tryGetType(column_name))
|
||||
@ -414,16 +422,19 @@ NameAndTypePair StorageDistributed::getColumn(const String & column_name) const
|
||||
return getRealColumn(column_name);
|
||||
}
|
||||
|
||||
|
||||
bool StorageDistributed::hasColumn(const String & column_name) const
|
||||
{
|
||||
return VirtualColumnFactory::hasColumn(column_name) || IStorage::hasColumn(column_name);
|
||||
}
|
||||
|
||||
|
||||
void StorageDistributed::createDirectoryMonitor(const std::string & name)
|
||||
{
|
||||
directory_monitors.emplace(name, std::make_unique<StorageDistributedDirectoryMonitor>(*this, name));
|
||||
}
|
||||
|
||||
|
||||
void StorageDistributed::createDirectoryMonitors()
|
||||
{
|
||||
if (path.empty())
|
||||
@ -437,6 +448,7 @@ void StorageDistributed::createDirectoryMonitors()
|
||||
createDirectoryMonitor(it.name());
|
||||
}
|
||||
|
||||
|
||||
void StorageDistributed::requireDirectoryMonitor(const std::string & name)
|
||||
{
|
||||
if (!directory_monitors.count(name))
|
||||
@ -448,6 +460,7 @@ size_t StorageDistributed::getShardCount() const
|
||||
return getCluster()->getRemoteShardCount();
|
||||
}
|
||||
|
||||
|
||||
ClusterPtr StorageDistributed::getCluster() const
|
||||
{
|
||||
return (owned_cluster) ? owned_cluster : context.getCluster(cluster_name);
|
||||
|
Loading…
Reference in New Issue
Block a user