// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
// This file is copied from
// https://github.com/ClickHouse/ClickHouse/blob/master/src/Columns/ColumnArray.cpp
// and modified by Doris

#include "vec/columns/column_array.h"

#include <algorithm>
#include <boost/iterator/iterator_facade.hpp>
#include <cstring>
#include <vector>

#include "common/status.h"
#include "runtime/define_primitive_type.h"
#include "runtime/primitive_type.h"
#include "util/simd/bits.h"
#include "util/simd/vstring_function.h"
#include "vec/columns/column.h"
#include "vec/columns/column_const.h"
#include "vec/columns/column_decimal.h"
#include "vec/columns/column_nullable.h"
#include "vec/columns/column_string.h"
#include "vec/columns/columns_common.h"
#include "vec/common/arena.h"
#include "vec/common/assert_cast.h"
#include "vec/common/memcpy_small.h"
#include "vec/common/typeid_cast.h"
#include "vec/common/unaligned.h"
#include "vec/core/sort_block.h"
#include "vec/data_types/data_type.h"

class SipHash;

namespace doris::vectorized {

ColumnArray::ColumnArray(MutableColumnPtr&& nested_column, MutableColumnPtr&& offsets_column)
        : data(std::move(nested_column)), offsets(std::move(offsets_column)) {
    // TODO(lihangyu) : we need to check the nullable attribute of array's data column.
    // but currently ColumnMap<ColumnString, ColumnString> is used to store sparse data of variant type,
    // so I temporarily disable this check.
    // #ifndef BE_TEST
    //     // This is a known problem.
    //     // We often do not consider the nullable attribute of array's data column in beut.
    //     // Considering that beut is just a test, it will not be checked at present, but this problem needs to be considered in the future.
    //     if (!data->is_nullable() && check_nullable) {
    //         throw doris::Exception(ErrorCode::INTERNAL_ERROR,
    //                                "nested_column must be nullable, but got {}", data->get_name());
    //     }
    // #endif

    data = data->convert_to_full_column_if_const();
    offsets = offsets->convert_to_full_column_if_const();
    const auto* offsets_concrete = typeid_cast<const ColumnOffsets*>(offsets.get());

    if (!offsets_concrete) {
        throw doris::Exception(ErrorCode::INTERNAL_ERROR, "offsets_column must be a ColumnUInt64");
        __builtin_unreachable();
    }

    if (!offsets_concrete->empty() && data) {
        auto last_offset = offsets_concrete->get_data().back();

        /// This will also prevent possible overflow in offset.
        if (data->size() != last_offset) {
            throw doris::Exception(
                    ErrorCode::INTERNAL_ERROR,
                    "nested_column's size {}, is not consistent with offsets_column's {}",
                    data->size(), last_offset);
        }
    }

    /** NOTE
      * Arrays with constant value are possible and used in implementation of higher order functions (see FunctionReplicate).
      * But in most cases, arrays with constant value are unexpected and code will work wrong. Use with caution.
      */
}

ColumnArray::ColumnArray(MutableColumnPtr&& nested_column) : data(std::move(nested_column)) {
    data = data->convert_to_full_column_if_const();
    if (!data->empty()) {
        throw doris::Exception(ErrorCode::INTERNAL_ERROR,
                               "Not empty data passed to ColumnArray, but no offsets passed");
        __builtin_unreachable();
    }
    offsets = ColumnOffsets::create();
}

void ColumnArray::shrink_padding_chars() {
    data->shrink_padding_chars();
}

std::string ColumnArray::get_name() const {
    return "Array(" + get_data().get_name() + ")";
}

MutableColumnPtr ColumnArray::clone_resized(size_t to_size) const {
    auto res = ColumnArray::create(get_data().clone_empty());

    if (to_size == 0) return res;
    size_t from_size = size();

    if (to_size <= from_size) {
        /// Just cut column.
        res->get_offsets().assign(get_offsets().begin(), get_offsets().begin() + to_size);
        res->get_data().insert_range_from(get_data(), 0, get_offsets()[to_size - 1]);
    } else {
        /// Copy column and append empty arrays for extra elements.
        Offset64 offset = 0;
        if (from_size > 0) {
            res->get_offsets().assign(get_offsets().begin(), get_offsets().end());
            res->get_data().insert_range_from(get_data(), 0, get_data().size());
            offset = get_offsets().back();
        }

        res->get_offsets().resize(to_size);
        for (size_t i = from_size; i < to_size; ++i) res->get_offsets()[i] = offset;
    }

    return res;
}

size_t ColumnArray::size() const {
    return get_offsets().size();
}

Field ColumnArray::operator[](size_t n) const {
    size_t offset = offset_at(n);
    size_t size = size_at(n);

    if (size > max_array_size_as_field)
        throw doris::Exception(ErrorCode::INVALID_ARGUMENT,
                               "Array of size {} in row {}, is too large to be manipulated as "
                               "single field, maximum size {}",
                               size, n, max_array_size_as_field);

    Array res(size);

    for (size_t i = 0; i < size; ++i) res[i] = get_data()[offset + i];

    return Field::create_field<TYPE_ARRAY>(res);
}

void ColumnArray::get(size_t n, Field& res) const {
    size_t offset = offset_at(n);
    size_t size = size_at(n);

    if (size > max_array_size_as_field)
        throw doris::Exception(ErrorCode::INVALID_ARGUMENT,
                               "Array of size {} in row {}, is too large to be manipulated as "
                               "single field, maximum size {}",
                               size, n, max_array_size_as_field);

    res = Field::create_field<TYPE_ARRAY>(Array(size));
    Array& res_arr = doris::vectorized::get<Array&>(res);

    for (size_t i = 0; i < size; ++i) get_data().get(offset + i, res_arr[i]);
}

bool ColumnArray::is_default_at(size_t n) const {
    const auto& offsets_data = get_offsets();
    return offsets_data[n] == offsets_data[static_cast<ssize_t>(n) - 1];
}

size_t ColumnArray::serialize_size_at(size_t row) const {
    size_t array_size = size_at(row);
    size_t offset = offset_at(row);

    size_t sz = 0;

    for (size_t i = 0; i < array_size; ++i) {
        sz += get_data().serialize_size_at(offset + i);
    }

    return sz + sizeof(size_t);
}

size_t ColumnArray::serialize_impl(char* pos, const size_t row) const {
    size_t array_size = size_at(row);
    size_t offset = offset_at(row);

    memcpy_fixed<size_t>(pos, (char*)&array_size);

    size_t sz = sizeof(array_size);

    for (size_t i = 0; i < array_size; ++i) {
        sz += get_data().serialize_impl(pos + sz, offset + i);
    }

    DCHECK_EQ(sz, serialize_size_at(row));
    return sz;
}

StringRef ColumnArray::serialize_value_into_arena(size_t n, Arena& arena,
                                                  char const*& begin) const {
    char* pos = arena.alloc_continue(serialize_size_at(n), begin);
    return {pos, serialize_impl(pos, n)};
}

template <bool positive>
struct ColumnArray::less {
    const ColumnArray& parent;
    const int nan_direction_hint;
    explicit less(const ColumnArray& parent_, int nan_direction_hint_)
            : parent(parent_), nan_direction_hint(nan_direction_hint_) {}
    bool operator()(size_t lhs, size_t rhs) const {
        size_t lhs_size = parent.size_at(lhs);
        size_t rhs_size = parent.size_at(rhs);
        size_t min_size = std::min(lhs_size, rhs_size);
        int res = 0;
        for (size_t i = 0; i < min_size; ++i) {
            if (res = parent.get_data().compare_at(
                        parent.offset_at(lhs) + i, parent.offset_at(rhs) + i,
                        *parent.get_data_ptr().get(), nan_direction_hint);
                res) {
                // if res != 0 , here is something different ,just return
                break;
            }
        }
        if (res == 0) {
            // then we check size of array
            res = lhs_size < rhs_size ? -1 : (lhs_size == rhs_size ? 0 : 1);
        }

        return positive ? (res < 0) : (res > 0);
    }
};

void ColumnArray::get_permutation(bool reverse, size_t limit, int nan_direction_hint,
                                  IColumn::Permutation& res) const {
    size_t s = size();
    res.resize(s);
    for (size_t i = 0; i < s; ++i) {
        res[i] = i;
    }

    if (reverse) {
        pdqsort(res.begin(), res.end(), ColumnArray::less<false>(*this, nan_direction_hint));
    } else {
        pdqsort(res.begin(), res.end(), ColumnArray::less<true>(*this, nan_direction_hint));
    }
}

void ColumnArray::sort_column(const ColumnSorter* sorter, EqualFlags& flags,
                              IColumn::Permutation& perms, EqualRange& range,
                              bool last_column) const {
    sorter->sort_column(static_cast<const ColumnArray&>(*this), flags, perms, range, last_column);
}

int ColumnArray::compare_at(size_t n, size_t m, const IColumn& rhs_, int nan_direction_hint) const {
    // since column type is complex, we can't use this function
    const auto& rhs = assert_cast<const ColumnArray&, TypeCheckOnRelease::DISABLE>(rhs_);

    size_t lhs_size = size_at(n);
    size_t rhs_size = rhs.size_at(m);
    size_t min_size = std::min(lhs_size, rhs_size);
    for (size_t i = 0; i < min_size; ++i) {
        if (int res = get_data().compare_at(offset_at(n) + i, rhs.offset_at(m) + i, *rhs.data.get(),
                                            nan_direction_hint);
            res) {
            // if res != 0 , here is something different ,just return
            return res;
        }
    }

    // then we check size of array
    return lhs_size < rhs_size ? -1 : (lhs_size == rhs_size ? 0 : 1);
}

size_t ColumnArray::get_max_row_byte_size() const {
    size_t max_size = 0;
    size_t num_rows = size();
    auto sz = data->get_max_row_byte_size();
    for (size_t i = 0; i < num_rows; ++i) {
        max_size = std::max(max_size, size_at(i) * sz);
    }

    return sizeof(size_t) + max_size;
}

void ColumnArray::serialize(StringRef* keys, size_t num_rows) const {
    for (size_t i = 0; i < num_rows; ++i) {
        // Used in hash_map_context.h, this address is allocated via Arena,
        // but passed through StringRef, so using const_cast is acceptable.
        keys[i].size += serialize_impl(const_cast<char*>(keys[i].data + keys[i].size), i);
    }
}

size_t ColumnArray::deserialize_impl(const char* pos) {
    size_t sz = 0;
    size_t array_size = unaligned_load<size_t>(pos);
    sz += sizeof(size_t);
    for (size_t j = 0; j < array_size; j++) {
        sz += get_data().deserialize_impl(pos + sz);
    }
    get_offsets().push_back(get_offsets().back() + array_size);
    return sz;
}

void ColumnArray::deserialize(StringRef* keys, const size_t num_rows) {
    for (size_t i = 0; i != num_rows; ++i) {
        auto sz = deserialize_impl(keys[i].data);
        keys[i].data += sz;
        keys[i].size -= sz;
    }
}

const char* ColumnArray::deserialize_and_insert_from_arena(const char* pos) {
    return pos + deserialize_impl(pos);
}

void ColumnArray::update_hash_with_value(size_t n, SipHash& hash) const {
    size_t array_size = size_at(n);
    size_t offset = offset_at(n);

    for (size_t i = 0; i < array_size; ++i) get_data().update_hash_with_value(offset + i, hash);
}

// for every array row calculate xxHash
void ColumnArray::update_xxHash_with_value(size_t start, size_t end, uint64_t& hash,
                                           const uint8_t* __restrict null_data) const {
    auto& offsets_column = get_offsets();
    if (null_data) {
        for (size_t i = start; i < end; ++i) {
            if (null_data[i] == 0) {
                size_t elem_size = offsets_column[i] - offsets_column[i - 1];
                if (elem_size == 0) {
                    hash = HashUtil::xxHash64WithSeed(reinterpret_cast<const char*>(&elem_size),
                                                      sizeof(elem_size), hash);
                } else {
                    get_data().update_xxHash_with_value(offsets_column[i - 1], offsets_column[i],
                                                        hash, nullptr);
                }
            }
        }
    } else {
        for (size_t i = start; i < end; ++i) {
            size_t elem_size = offsets_column[i] - offsets_column[i - 1];
            if (elem_size == 0) {
                hash = HashUtil::xxHash64WithSeed(reinterpret_cast<const char*>(&elem_size),
                                                  sizeof(elem_size), hash);
            } else {
                get_data().update_xxHash_with_value(offsets_column[i - 1], offsets_column[i], hash,
                                                    nullptr);
            }
        }
    }
}

// for every array row calculate crcHash
void ColumnArray::update_crc_with_value(size_t start, size_t end, uint32_t& hash,
                                        const uint8_t* __restrict null_data) const {
    auto& offsets_column = get_offsets();
    if (null_data) {
        for (size_t i = start; i < end; ++i) {
            if (null_data[i] == 0) {
                size_t elem_size = offsets_column[i] - offsets_column[i - 1];
                if (elem_size == 0) {
                    hash = HashUtil::zlib_crc_hash(reinterpret_cast<const char*>(&elem_size),
                                                   sizeof(elem_size), hash);
                } else {
                    get_data().update_crc_with_value(offsets_column[i - 1], offsets_column[i], hash,
                                                     nullptr);
                }
            }
        }
    } else {
        for (size_t i = start; i < end; ++i) {
            size_t elem_size = offsets_column[i] - offsets_column[i - 1];
            if (elem_size == 0) {
                hash = HashUtil::zlib_crc_hash(reinterpret_cast<const char*>(&elem_size),
                                               sizeof(elem_size), hash);
            } else {
                get_data().update_crc_with_value(offsets_column[i - 1], offsets_column[i], hash,
                                                 nullptr);
            }
        }
    }
}

void ColumnArray::update_hashes_with_value(uint64_t* __restrict hashes,
                                           const uint8_t* __restrict null_data) const {
    auto s = size();
    if (null_data) {
        for (size_t i = 0; i < s; ++i) {
            if (null_data[i] == 0) {
                update_xxHash_with_value(i, i + 1, hashes[i], nullptr);
            }
        }
    } else {
        for (size_t i = 0; i < s; ++i) {
            update_xxHash_with_value(i, i + 1, hashes[i], nullptr);
        }
    }
}

void ColumnArray::update_crcs_with_value(uint32_t* __restrict hash, PrimitiveType type,
                                         uint32_t rows, uint32_t offset,
                                         const uint8_t* __restrict null_data) const {
    auto s = rows;
    DCHECK(s == size());

    if (null_data) {
        for (size_t i = 0; i < s; ++i) {
            // every row
            if (null_data[i] == 0) {
                update_crc_with_value(i, i + 1, hash[i], nullptr);
            }
        }
    } else {
        for (size_t i = 0; i < s; ++i) {
            update_crc_with_value(i, i + 1, hash[i], nullptr);
        }
    }
}

void ColumnArray::update_crc32c_batch(uint32_t* __restrict hashes,
                                      const uint8_t* __restrict null_map) const {
    auto s = size();
    if (null_map) {
        for (size_t i = 0; i < s; ++i) {
            if (null_map[i] == 0) {
                update_crc32c_single(i, i + 1, hashes[i], nullptr);
            }
        }
    } else {
        for (size_t i = 0; i < s; ++i) {
            update_crc32c_single(i, i + 1, hashes[i], nullptr);
        }
    }
}

void ColumnArray::update_crc32c_single(size_t start, size_t end, uint32_t& hash,
                                       const uint8_t* __restrict null_map) const {
    const auto& offsets_column = get_offsets();
    if (null_map) {
        for (size_t i = start; i < end; ++i) {
            if (null_map[i] == 0) {
                size_t elem_size = offsets_column[i] - offsets_column[i - 1];
                if (elem_size == 0) {
                    hash = HashUtil::crc32c_null(hash);
                } else {
                    get_data().update_crc32c_single(offsets_column[i - 1], offsets_column[i], hash,
                                                    nullptr);
                }
            }
        }
    } else {
        for (size_t i = start; i < end; ++i) {
            size_t elem_size = offsets_column[i] - offsets_column[i - 1];
            if (elem_size == 0) {
                hash = HashUtil::crc32c_null(hash);
            } else {
                get_data().update_crc32c_single(offsets_column[i - 1], offsets_column[i], hash,
                                                nullptr);
            }
        }
    }
}

void ColumnArray::insert(const Field& x) {
    DCHECK_EQ(x.get_type(), PrimitiveType::TYPE_ARRAY);
    if (x.is_null()) {
        get_data().insert(Field::create_field<TYPE_NULL>(Null()));
        get_offsets().push_back(get_offsets().back() + 1);
    } else {
        const auto& array = doris::vectorized::get<const Array&>(x);
        size_t size = array.size();
        for (size_t i = 0; i < size; ++i) {
            get_data().insert(array[i]);
        }
        get_offsets().push_back(get_offsets().back() + size);
    }
}

void ColumnArray::insert_from(const IColumn& src_, size_t n) {
    DCHECK_LT(n, src_.size());
    const ColumnArray& src = assert_cast<const ColumnArray&>(src_);
    size_t size = src.size_at(n);
    size_t offset = src.offset_at(n);

    if ((!get_data().is_nullable() && src.get_data().is_nullable()) ||
        (get_data().is_nullable() && !src.get_data().is_nullable())) {
        // Note: we can't process the case of 'Array(Nullable(nest))' or 'Array(NotNullable(nest))'
        throw Exception(ErrorCode::INTERNAL_ERROR, "insert '{}' into '{}'", src.get_name(),
                        get_name());
    } else {
        get_data().insert_range_from(src.get_data(), offset, size);
    }
    get_offsets().push_back(get_offsets().back() + size);
}

void ColumnArray::insert_default() {
    /// NOTE 1: We can use back() even if the array is empty (due to zero -1th element in PODArray).
    /// NOTE 2: We cannot use reference in push_back, because reference get invalidated if array is reallocated.
    auto last_offset = get_offsets().back();
    get_offsets().push_back(last_offset);
}

void ColumnArray::pop_back(size_t n) {
    auto& offsets_data = get_offsets();
    DCHECK(n <= offsets_data.size()) << " n:" << n << " with offsets size: " << offsets_data.size();
    size_t nested_n = offsets_data.back() - offset_at(offsets_data.size() - n);
    if (nested_n) get_data().pop_back(nested_n);
    offsets_data.resize_assume_reserved(offsets_data.size() - n);
}

void ColumnArray::reserve(size_t n) {
    get_offsets().reserve(n);
    get_data().reserve(
            n); /// The average size of arrays is not taken into account here. Or it is considered to be no more than 1.
}

//please check you real need size in data column, because it's maybe need greater size when data is string column
void ColumnArray::resize(size_t n) {
    auto last_off = get_offsets().back();
    get_offsets().resize_fill(n, last_off);
    // make new size of data column
    get_data().resize(get_offsets().back());
}

size_t ColumnArray::byte_size() const {
    return get_data().byte_size() + get_offsets().size() * sizeof(get_offsets()[0]);
}

size_t ColumnArray::allocated_bytes() const {
    return get_data().allocated_bytes() + get_offsets().allocated_bytes();
}

bool ColumnArray::has_enough_capacity(const IColumn& src) const {
    const auto& src_concrete = assert_cast<const ColumnArray&>(src);
    return get_data().has_enough_capacity(src_concrete.get_data()) &&
           get_offsets_column().has_enough_capacity(src_concrete.get_offsets_column());
}

bool ColumnArray::has_equal_offsets(const ColumnArray& other) const {
    const Offsets64& offsets1 = get_offsets();
    const Offsets64& offsets2 = other.get_offsets();
    return offsets1.size() == offsets2.size() &&
           (offsets1.empty() ||
            0 == memcmp(offsets1.data(), offsets2.data(), sizeof(offsets1[0]) * offsets1.size()));
}

void ColumnArray::insert_range_from(const IColumn& src, size_t start, size_t length) {
    if (length == 0) return;

    const ColumnArray& src_concrete = assert_cast<const ColumnArray&>(src);

    if (start + length > src_concrete.get_offsets().size()) {
        throw doris::Exception(doris::ErrorCode::INTERNAL_ERROR,
                               "Parameter out of bound in ColumnArray::insert_range_from method. "
                               "[start({}) + length({}) > offsets.size({})]",
                               std::to_string(start), std::to_string(length),
                               std::to_string(src_concrete.get_offsets().size()));
    }

    size_t nested_offset = src_concrete.offset_at(start);
    size_t nested_length = src_concrete.get_offsets()[start + length - 1] - nested_offset;

    get_data().insert_range_from(src_concrete.get_data(), nested_offset, nested_length);

    auto& cur_offsets = get_offsets();
    const auto& src_offsets = src_concrete.get_offsets();

    if (start == 0 && cur_offsets.empty()) {
        cur_offsets.assign(src_offsets.begin(), src_offsets.begin() + length);
    } else {
        size_t old_size = cur_offsets.size();
        // -1 is ok, because PaddedPODArray pads zeros on the left.
        size_t prev_max_offset = cur_offsets.back();
        cur_offsets.resize(old_size + length);

        for (size_t i = 0; i < length; ++i)
            cur_offsets[old_size + i] = src_offsets[start + i] - nested_offset + prev_max_offset;
    }
}

void ColumnArray::insert_range_from_ignore_overflow(const IColumn& src, size_t start,
                                                    size_t length) {
    const ColumnArray& src_concrete = assert_cast<const ColumnArray&>(src);

    if (start + length > src_concrete.get_offsets().size()) {
        throw doris::Exception(doris::ErrorCode::INTERNAL_ERROR,
                               "Parameter out of bound in ColumnArray::insert_range_from method. "
                               "[start({}) + length({}) > offsets.size({})]",
                               std::to_string(start), std::to_string(length),
                               std::to_string(src_concrete.get_offsets().size()));
    }

    size_t nested_offset = src_concrete.offset_at(start);
    size_t nested_length = src_concrete.get_offsets()[start + length - 1] - nested_offset;

    get_data().insert_range_from_ignore_overflow(src_concrete.get_data(), nested_offset,
                                                 nested_length);

    auto& cur_offsets = get_offsets();
    const auto& src_offsets = src_concrete.get_offsets();

    if (start == 0 && cur_offsets.empty()) {
        cur_offsets.assign(src_offsets.begin(), src_offsets.begin() + length);
    } else {
        size_t old_size = cur_offsets.size();
        // -1 is ok, because PaddedPODArray pads zeros on the left.
        size_t prev_max_offset = cur_offsets.back();
        cur_offsets.resize(old_size + length);

        for (size_t i = 0; i < length; ++i)
            cur_offsets[old_size + i] = src_offsets[start + i] - nested_offset + prev_max_offset;
    }
}

using Offset64 = IColumn::Offset64;
using Offsets64 = IColumn::Offsets64;
using Filter = IColumn::Filter;
using ColumnOffsets = ColumnArray::ColumnOffsets;

struct ColumnArrayDataOffsets {
    ColumnPtr data;
    ColumnOffsets::Ptr offsets;
};

template <PrimitiveType T>
ColumnArrayDataOffsets filter_number_return_new(const Filter& filt, ssize_t result_size_hint,
                                                const ColumnPtr& src_data,
                                                const ColumnOffsets* src_offsets) {
    if (src_offsets->empty()) {
        return ColumnArrayDataOffsets {.data = src_data->clone_empty(),
                                       .offsets = ColumnOffsets::create()};
    }

    auto dst_data = src_data->clone_empty();
    auto dst_offset = ColumnOffsets::create();

    auto& res_elems = assert_cast<ColumnVector<T>&>(*dst_data).get_data();
    auto& res_offsets = dst_offset->get_data();

    filter_arrays_impl<typename PrimitiveTypeTraits<T>::ColumnItemType, IColumn::Offset64>(
            assert_cast<const ColumnVector<T>&, TypeCheckOnRelease::DISABLE>(*src_data).get_data(),
            src_offsets->get_data(), res_elems, res_offsets, filt, result_size_hint);

    return ColumnArrayDataOffsets {.data = std::move(dst_data), .offsets = std::move(dst_offset)};
}

template <PrimitiveType T>
size_t filter_number_inplace(const Filter& filter, IColumn& src_data, ColumnOffsets& src_offsets) {
    return filter_arrays_impl<typename PrimitiveTypeTraits<T>::ColumnItemType, Offset64>(
            assert_cast<ColumnVector<T>&, TypeCheckOnRelease::DISABLE>(src_data).get_data(),
            src_offsets.get_data(), filter);
}

ColumnArrayDataOffsets filter_string_return_new(const Filter& filt, ssize_t result_size_hint,
                                                const ColumnPtr& src_data,
                                                const ColumnOffsets* src_offsets) {
    size_t col_size = src_offsets->size();
    column_match_filter_size(col_size, filt.size());

    if (col_size == 0) {
        return ColumnArrayDataOffsets {.data = src_data->clone_empty(),
                                       .offsets = ColumnOffsets::create()};
    }

    const auto& src_string = assert_cast<const ColumnString&>(*src_data);
    const ColumnString::Chars& src_chars = src_string.get_chars();
    const auto& src_string_offsets = src_string.get_offsets();
    const auto& offsets = src_offsets->get_data();

    auto dst_data = src_data->clone_empty();
    ColumnString::Chars& res_chars = assert_cast<ColumnString&>(*dst_data).get_chars();
    auto& res_string_offsets = assert_cast<ColumnString&>(*dst_data).get_offsets();
    auto dst_offset = ColumnOffsets::create();
    auto& res_offsets = dst_offset->get_data();

    if (result_size_hint < 0) {
        res_chars.reserve(src_chars.size());
        res_string_offsets.reserve(src_string_offsets.size());
        res_offsets.reserve(col_size);
    }

    Offset64 prev_src_offset = 0;
    IColumn::Offset prev_src_string_offset = 0;

    Offset64 prev_res_offset = 0;
    IColumn::Offset prev_res_string_offset = 0;

    for (size_t i = 0; i < col_size; ++i) {
        /// Number of rows in the array.
        size_t array_size = offsets[i] - prev_src_offset;

        if (filt[i]) {
            /// If the array is not empty - copy content.
            if (array_size) {
                size_t chars_to_copy = src_string_offsets[array_size + prev_src_offset - 1] -
                                       prev_src_string_offset;
                size_t res_chars_prev_size = res_chars.size();
                res_chars.resize(res_chars_prev_size + chars_to_copy);
                memcpy(&res_chars[res_chars_prev_size], &src_chars[prev_src_string_offset],
                       chars_to_copy);

                for (size_t j = 0; j < array_size; ++j) {
                    res_string_offsets.push_back(src_string_offsets[j + prev_src_offset] +
                                                 prev_res_string_offset - prev_src_string_offset);
                }

                prev_res_string_offset = res_string_offsets.back();
            }

            prev_res_offset += array_size;
            res_offsets.push_back(prev_res_offset);
        }

        if (array_size) {
            prev_src_offset += array_size;
            prev_src_string_offset = src_string_offsets[prev_src_offset - 1];
        }
    }

    return ColumnArrayDataOffsets {.data = std::move(dst_data), .offsets = std::move(dst_offset)};
}

ColumnArrayDataOffsets filter_generic_return_new(const Filter& filt, ssize_t result_size_hint,
                                                 const ColumnPtr& src_data,
                                                 const ColumnOffsets* src_offsets) {
    size_t size = src_offsets->size();
    column_match_filter_size(size, filt.size());

    if (size == 0) {
        return ColumnArrayDataOffsets {.data = src_data->clone_empty(),
                                       .offsets = ColumnOffsets::create()};
    }

    const auto& offsets = src_offsets->get_data();
    Filter nested_filt(offsets.back());
    ssize_t nested_result_size_hint = 0;
    for (size_t i = 0; i < size; ++i) {
        const auto offset_at = offsets[i - 1];
        const auto size_at = offsets[i] - offsets[i - 1];
        if (filt[i]) {
            memset(&nested_filt[offset_at], 1, size_at);
            nested_result_size_hint += size_at;
        } else {
            memset(&nested_filt[offset_at], 0, size_at);
        }
    }

    ColumnPtr dst_data = src_data->filter(nested_filt, nested_result_size_hint);
    auto dst_offsets = ColumnOffsets::create();
    auto& res_offsets = dst_offsets->get_data();

    if (result_size_hint) {
        res_offsets.reserve(result_size_hint > 0 ? result_size_hint : size);
    }

    size_t current_offset = 0;
    for (size_t i = 0; i < size; ++i) {
        if (filt[i]) {
            current_offset += offsets[i] - offsets[i - 1];
            res_offsets.push_back(current_offset);
        }
    }
    return ColumnArrayDataOffsets {.data = dst_data, .offsets = std::move(dst_offsets)};
}

size_t filter_generic_inplace(const Filter& filter, IColumn& src_data, ColumnOffsets& src_offsets) {
    const size_t size = src_offsets.size();
    column_match_filter_size(size, filter.size());

    if (size == 0) {
        return 0;
    }

    auto& offsets = src_offsets.get_data();

    Filter nested_filter(offsets.back());
    for (size_t i = 0; i < size; ++i) {
        const auto offset_at = offsets[i - 1];
        const auto size_at = offsets[i] - offsets[i - 1];
        if (filter[i]) {
            memset(&nested_filter[offset_at], 1, size_at);
        } else {
            memset(&nested_filter[offset_at], 0, size_at);
        }
    }

    src_data.filter(nested_filter);
    // Make a new offset to avoid inplace operation
    auto res_offset = ColumnOffsets::create();
    auto& res_offset_data = res_offset->get_data();
    res_offset_data.reserve(size);
    size_t current_offset = 0;
    for (size_t i = 0; i < size; ++i) {
        if (filter[i]) {
            current_offset += offsets[i] - offsets[i - 1];
            res_offset_data.push_back(current_offset);
        }
    }
    offsets.swap(res_offset_data);
    return offsets.size();
}

/// TODO: We need to consider reconstructing here.
// The distribution type here should not be enumerated in this way.
// We can consider adding a function to return type to the column.
ColumnArrayDataOffsets filter_return_new_dispatch(const Filter& filt, ssize_t result_size_hint,
                                                  const ColumnPtr& data,
                                                  const ColumnOffsets* offsets) {
    if (typeid_cast<const ColumnUInt8*>(data.get()))
        return filter_number_return_new<TYPE_BOOLEAN>(filt, result_size_hint, data, offsets);
    if (typeid_cast<const ColumnInt8*>(data.get()))
        return filter_number_return_new<TYPE_TINYINT>(filt, result_size_hint, data, offsets);
    if (typeid_cast<const ColumnInt16*>(data.get()))
        return filter_number_return_new<TYPE_SMALLINT>(filt, result_size_hint, data, offsets);
    if (typeid_cast<const ColumnInt32*>(data.get()))
        return filter_number_return_new<TYPE_INT>(filt, result_size_hint, data, offsets);
    if (typeid_cast<const ColumnInt64*>(data.get()))
        return filter_number_return_new<TYPE_BIGINT>(filt, result_size_hint, data, offsets);
    if (typeid_cast<const ColumnFloat32*>(data.get()))
        return filter_number_return_new<TYPE_FLOAT>(filt, result_size_hint, data, offsets);
    if (typeid_cast<const ColumnFloat64*>(data.get()))
        return filter_number_return_new<TYPE_DOUBLE>(filt, result_size_hint, data, offsets);
    if (typeid_cast<const ColumnDate*>(data.get()))
        return filter_number_return_new<TYPE_DATE>(filt, result_size_hint, data, offsets);
    if (typeid_cast<const ColumnDateV2*>(data.get()))
        return filter_number_return_new<TYPE_DATEV2>(filt, result_size_hint, data, offsets);
    if (typeid_cast<const ColumnDateTime*>(data.get()))
        return filter_number_return_new<TYPE_DATETIME>(filt, result_size_hint, data, offsets);
    if (typeid_cast<const ColumnDateTimeV2*>(data.get()))
        return filter_number_return_new<TYPE_DATETIMEV2>(filt, result_size_hint, data, offsets);
    if (typeid_cast<const ColumnTimeStampTz*>(data.get()))
        return filter_number_return_new<TYPE_TIMESTAMPTZ>(filt, result_size_hint, data, offsets);
    if (typeid_cast<const ColumnTimeV2*>(data.get()))
        return filter_number_return_new<TYPE_TIMEV2>(filt, result_size_hint, data, offsets);
    if (typeid_cast<const ColumnTime*>(data.get()))
        return filter_number_return_new<TYPE_TIME>(filt, result_size_hint, data, offsets);
    if (typeid_cast<const ColumnIPv4*>(data.get()))
        return filter_number_return_new<TYPE_IPV4>(filt, result_size_hint, data, offsets);
    if (typeid_cast<const ColumnString*>(data.get()))
        return filter_string_return_new(filt, result_size_hint, data, offsets);
    return filter_generic_return_new(filt, result_size_hint, data, offsets);
}

ColumnPtr ColumnArray::filter(const Filter& filt, ssize_t result_size_hint) const {
    // return empty
    if (this->empty()) {
        return ColumnArray::create(data);
    }

    if (const auto* nullable_data_column = check_and_get_column<ColumnNullable>(*data)) {
        auto res_null_map = ColumnUInt8::create();
        // filter null map
        filter_arrays_impl_only_data(nullable_data_column->get_null_map_data(), get_offsets(),
                                     res_null_map->get_data(), filt, result_size_hint);

        auto src_data = nullable_data_column->get_nested_column_ptr();
        const auto* src_offsets = assert_cast<const ColumnOffsets*>(offsets.get());
        auto array_of_nested =
                filter_return_new_dispatch(filt, result_size_hint, src_data, src_offsets);

        return ColumnArray::create(
                ColumnNullable::create(array_of_nested.data, std::move(res_null_map)),
                array_of_nested.offsets);
    } else {
        // filter offsets
        const auto* src_offsets = assert_cast<const ColumnOffsets*>(offsets.get());
        auto array_of_nested =
                filter_return_new_dispatch(filt, result_size_hint, data, src_offsets);
        return ColumnArray::create(array_of_nested.data, std::move(array_of_nested.offsets));
    }
}

// There is a strange thing here. It didn't implement the type of string?
// In order not to destroy the original logic, the original logic is still retained here.
size_t filter_inplace_dispatch(const Filter& filter, IColumn& src_data,
                               ColumnOffsets& src_offsets) {
    if (typeid_cast<ColumnUInt8*>(&src_data))
        return filter_number_inplace<TYPE_BOOLEAN>(filter, src_data, src_offsets);
    if (typeid_cast<ColumnInt8*>(&src_data))
        return filter_number_inplace<TYPE_TINYINT>(filter, src_data, src_offsets);
    if (typeid_cast<ColumnInt16*>(&src_data))
        return filter_number_inplace<TYPE_SMALLINT>(filter, src_data, src_offsets);
    if (typeid_cast<ColumnInt32*>(&src_data))
        return filter_number_inplace<TYPE_INT>(filter, src_data, src_offsets);
    if (typeid_cast<ColumnInt64*>(&src_data))
        return filter_number_inplace<TYPE_BIGINT>(filter, src_data, src_offsets);
    if (typeid_cast<ColumnFloat32*>(&src_data))
        return filter_number_inplace<TYPE_FLOAT>(filter, src_data, src_offsets);
    if (typeid_cast<ColumnFloat64*>(&src_data))
        return filter_number_inplace<TYPE_DOUBLE>(filter, src_data, src_offsets);
    if (typeid_cast<ColumnDate*>(&src_data))
        return filter_number_inplace<TYPE_DATE>(filter, src_data, src_offsets);
    if (typeid_cast<ColumnDateV2*>(&src_data))
        return filter_number_inplace<TYPE_DATEV2>(filter, src_data, src_offsets);
    if (typeid_cast<ColumnDateTime*>(&src_data))
        return filter_number_inplace<TYPE_DATETIME>(filter, src_data, src_offsets);
    if (typeid_cast<ColumnDateTimeV2*>(&src_data))
        return filter_number_inplace<TYPE_DATETIMEV2>(filter, src_data, src_offsets);
    if (typeid_cast<ColumnTimeStampTz*>(&src_data))
        return filter_number_inplace<TYPE_TIMESTAMPTZ>(filter, src_data, src_offsets);
    if (typeid_cast<ColumnTimeV2*>(&src_data))
        return filter_number_inplace<TYPE_TIMEV2>(filter, src_data, src_offsets);
    if (typeid_cast<ColumnTime*>(&src_data))
        return filter_number_inplace<TYPE_TIME>(filter, src_data, src_offsets);
    if (typeid_cast<ColumnIPv4*>(&src_data))
        return filter_number_inplace<TYPE_IPV4>(filter, src_data, src_offsets);
    return filter_generic_inplace(filter, src_data, src_offsets);
}

size_t ColumnArray::filter(const Filter& filter) {
    if (this->empty()) {
        return 0;
    }

    if (auto* nullable_data_column = typeid_cast<ColumnNullable*>(data.get())) {
        const auto result_size = filter_arrays_impl_only_data(
                nullable_data_column->get_null_map_data(), get_offsets(), filter);

        auto& src_data = nullable_data_column->get_nested_column();
        auto& src_offsets = assert_cast<ColumnOffsets&>(*offsets);
        filter_inplace_dispatch(filter, src_data, src_offsets);
        return result_size;
    } else {
        auto& src_data = get_data();
        auto& src_offsets = assert_cast<ColumnOffsets&>(*offsets);

        return filter_inplace_dispatch(filter, src_data, src_offsets);
    }
}

void ColumnArray::insert_indices_from(const IColumn& src, const uint32_t* indices_begin,
                                      const uint32_t* indices_end) {
    for (const auto* x = indices_begin; x != indices_end; ++x) {
        ColumnArray::insert_from(src, *x);
    }
}

void ColumnArray::insert_many_from(const IColumn& src, size_t position, size_t length) {
    for (auto x = 0; x != length; ++x) {
        ColumnArray::insert_from(src, position);
    }
}

MutableColumnPtr ColumnArray::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 doris::Exception(ErrorCode::INTERNAL_ERROR,
                               "Size of permutation is less than required.");
        __builtin_unreachable();
    }
    if (limit == 0) {
        return ColumnArray::create(data);
    }

    auto res = ColumnArray::create(data->clone_empty());
    auto& res_offsets = res->get_offsets();
    res_offsets.resize(limit);

    Permutation nested_perm;
    nested_perm.reserve(data->size());

    for (size_t i = 0; i < limit; ++i) {
        res_offsets[i] = res_offsets[i - 1] + size_at(perm[i]);
        for (size_t j = 0; j < size_at(perm[i]); ++j) {
            nested_perm.push_back(offset_at(perm[i]) + j);
        }
    }
    if (nested_perm.size() != 0) {
        res->data = data->permute(nested_perm, nested_perm.size());
    }
    return res;
}

void ColumnArray::erase(size_t start, size_t length) {
    if (start >= size() || length == 0) {
        return;
    }
    length = std::min(length, size() - start);

    const auto& offsets_data = get_offsets();
    auto data_start = offsets_data[start - 1];
    auto data_end = offsets_data[start + length - 1];
    auto data_length = data_end - data_start;
    data->erase(data_start, data_length);
    offsets->erase(start, length);

    for (auto i = start; i < size(); ++i) {
        get_offsets()[i] -= data_length;
    }
}

void ColumnArray::replace_float_special_values() {
    get_data().replace_float_special_values();
}

} // namespace doris::vectorized
