diff options
| author | vitalyisaev <[email protected]> | 2023-11-14 09:58:56 +0300 |
|---|---|---|
| committer | vitalyisaev <[email protected]> | 2023-11-14 10:20:20 +0300 |
| commit | c2b2dfd9827a400a8495e172a56343462e3ceb82 (patch) | |
| tree | cd4e4f597d01bede4c82dffeb2d780d0a9046bd0 /contrib/clickhouse/src/Functions/array/arrayFill.cpp | |
| parent | d4ae8f119e67808cb0cf776ba6e0cf95296f2df7 (diff) | |
YQ Connector: move tests from yql to ydb (OSS)
Перенос папки с тестами на Коннектор из папки yql в папку ydb (синхронизируется с github).
Diffstat (limited to 'contrib/clickhouse/src/Functions/array/arrayFill.cpp')
| -rw-r--r-- | contrib/clickhouse/src/Functions/array/arrayFill.cpp | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/contrib/clickhouse/src/Functions/array/arrayFill.cpp b/contrib/clickhouse/src/Functions/array/arrayFill.cpp new file mode 100644 index 00000000000..89b5dce2331 --- /dev/null +++ b/contrib/clickhouse/src/Functions/array/arrayFill.cpp @@ -0,0 +1,135 @@ +#include <Columns/ColumnsNumber.h> +#include <DataTypes/DataTypesNumber.h> +#include <Functions/FunctionFactory.h> + +#include "FunctionArrayMapped.h" + + +namespace DB +{ +namespace ErrorCodes +{ + extern const int ILLEGAL_COLUMN; +} + + +/** Replaces values where condition is met with the previous value that have condition not met + * (or with the first value if condition was true for all elements before). + * Looks somewhat similar to arrayFilter, but instead removing elements, it fills gaps with the value of previous element. + */ +template <bool reverse> +struct ArrayFillImpl +{ + static bool needBoolean() { return true; } + static bool needExpression() { return true; } + static bool needOneArray() { return false; } + + static DataTypePtr getReturnType(const DataTypePtr & /*expression_return*/, const DataTypePtr & array_element) + { + return std::make_shared<DataTypeArray>(array_element); + } + + static ColumnPtr execute(const ColumnArray & array, ColumnPtr mapped) + { + const ColumnUInt8 * column_fill = typeid_cast<const ColumnUInt8 *>(&*mapped); + + const IColumn & in_data = array.getData(); + const IColumn::Offsets & in_offsets = array.getOffsets(); + auto column_data = in_data.cloneEmpty(); + IColumn & out_data = *column_data.get(); + + if (column_fill) + { + const IColumn::Filter & fill = column_fill->getData(); + + size_t array_begin = 0; + size_t array_end = 0; + size_t begin = 0; + size_t end = 0; + + out_data.reserve(in_data.size()); + + for (auto in_offset : in_offsets) + { + array_end = in_offset; + + for (; end < array_end; ++end) + { + if (end + 1 == array_end || fill[end + 1] != fill[begin]) + { + if (fill[begin]) + out_data.insertRangeFrom(in_data, begin, end + 1 - begin); + else + { + if constexpr (reverse) + { + if (end + 1 == array_end) + out_data.insertManyFrom(in_data, end, end + 1 - begin); + else + out_data.insertManyFrom(in_data, end + 1, end + 1 - begin); + } + else + { + if (begin == array_begin) + out_data.insertManyFrom(in_data, array_begin, end + 1 - begin); + else + out_data.insertManyFrom(in_data, begin - 1, end + 1 - begin); + } + } + + begin = end + 1; + } + } + + array_begin = array_end; + } + } + else + { + const auto * column_fill_const = checkAndGetColumnConst<ColumnUInt8>(&*mapped); + + if (!column_fill_const) + throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Unexpected type of cut column"); + + if (column_fill_const->getValue<UInt8>()) + return ColumnArray::create( + array.getDataPtr(), + array.getOffsetsPtr()); + + size_t array_begin = 0; + size_t array_end = 0; + + out_data.reserve(in_data.size()); + + for (auto in_offset : in_offsets) + { + array_end = in_offset - 1; + + if constexpr (reverse) + out_data.insertManyFrom(in_data, array_end, array_end + 1 - array_begin); + else + out_data.insertManyFrom(in_data, array_begin, array_end + 1 - array_begin); + + array_begin = array_end + 1; + } + } + + return ColumnArray::create( + std::move(column_data), + array.getOffsetsPtr() + ); + } +}; + +struct NameArrayFill { static constexpr auto name = "arrayFill"; }; +struct NameArrayReverseFill { static constexpr auto name = "arrayReverseFill"; }; +using FunctionArrayFill = FunctionArrayMapped<ArrayFillImpl<false>, NameArrayFill>; +using FunctionArrayReverseFill = FunctionArrayMapped<ArrayFillImpl<true>, NameArrayReverseFill>; + +REGISTER_FUNCTION(ArrayFill) +{ + factory.registerFunction<FunctionArrayFill>(); + factory.registerFunction<FunctionArrayReverseFill>(); +} + +} |
