// 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.

#include "exec/tablet_info.h"

#include <butil/logging.h>
#include <gen_cpp/Descriptors_types.h>
#include <gen_cpp/Exprs_types.h>
#include <gen_cpp/Partitions_types.h>
#include <gen_cpp/Types_types.h>
#include <gen_cpp/descriptors.pb.h>
#include <gen_cpp/olap_file.pb.h>
#include <glog/logging.h>

#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <ostream>
#include <string>
#include <tuple>

#include "common/exception.h"
#include "common/logging.h"
#include "common/status.h"
#include "olap/tablet_schema.h"
#include "runtime/define_primitive_type.h"
#include "runtime/descriptors.h"
#include "runtime/large_int_value.h"
#include "runtime/memory/mem_tracker.h"
#include "runtime/primitive_type.h"
#include "runtime/raw_value.h"
#include "runtime/types.h"
#include "util/string_parser.hpp"
#include "util/string_util.h"
#include "vec/columns/column.h"
#include "vec/data_types/data_type.h"
#include "vec/data_types/data_type_factory.hpp"
// NOLINTNEXTLINE(unused-includes)
#include "vec/exprs/vexpr_context.h" // IWYU pragma: keep
#include "vec/exprs/vliteral.h"
#include "vec/functions/cast/cast_to_timestamptz.h"
#include "vec/runtime/vdatetime_value.h"

namespace doris {
#include "common/compile_check_begin.h"

void OlapTableIndexSchema::to_protobuf(POlapTableIndexSchema* pindex) const {
    pindex->set_id(index_id);
    pindex->set_schema_hash(schema_hash);
    for (auto* slot : slots) {
        pindex->add_columns(slot->col_name());
    }
    for (auto* column : columns) {
        column->to_schema_pb(pindex->add_columns_desc());
    }
    for (auto* index : indexes) {
        index->to_schema_pb(pindex->add_indexes_desc());
    }
}

bool VOlapTablePartKeyComparator::operator()(const BlockRowWithIndicator& lhs,
                                             const BlockRowWithIndicator& rhs) const {
    vectorized::Block* l_block = std::get<0>(lhs);
    vectorized::Block* r_block = std::get<0>(rhs);
    int32_t l_row = std::get<1>(lhs);
    int32_t r_row = std::get<1>(rhs);
    bool l_use_new = std::get<2>(lhs);
    bool r_use_new = std::get<2>(rhs);

    VLOG_TRACE << '\n' << l_block->dump_data() << '\n' << r_block->dump_data();

    if (l_row == -1) {
        return false;
    } else if (r_row == -1) {
        return true;
    }

    if (_param_locs.empty()) { // no transform, use origin column
        for (auto slot_loc : _slot_locs) {
            auto res = l_block->get_by_position(slot_loc).column->compare_at(
                    l_row, r_row, *r_block->get_by_position(slot_loc).column, -1);
            if (res != 0) {
                return res < 0;
            }
        }
    } else { // use transformed column to compare
        DCHECK(_slot_locs.size() == _param_locs.size())
                << _slot_locs.size() << ' ' << _param_locs.size();

        const std::vector<uint16_t>* l_index = l_use_new ? &_param_locs : &_slot_locs;
        const std::vector<uint16_t>* r_index = r_use_new ? &_param_locs : &_slot_locs;

        for (int i = 0; i < _slot_locs.size(); i++) {
            vectorized::ColumnPtr l_col = l_block->get_by_position((*l_index)[i]).column;
            vectorized::ColumnPtr r_col = r_block->get_by_position((*r_index)[i]).column;

            auto res = l_col->compare_at(l_row, r_row, *r_col, -1);
            if (res != 0) {
                return res < 0;
            }
        }
    }

    // equal, return false
    return false;
}

Status OlapTableSchemaParam::init(const POlapTableSchemaParam& pschema) {
    _db_id = pschema.db_id();
    _table_id = pschema.table_id();
    _version = pschema.version();
    if (pschema.has_unique_key_update_mode()) {
        _unique_key_update_mode = pschema.unique_key_update_mode();
        if (pschema.has_sequence_map_col_unique_id()) {
            _sequence_map_col_uid = pschema.sequence_map_col_unique_id();
        }
    } else {
        // for backward compatibility
        if (pschema.has_partial_update() && pschema.partial_update()) {
            _unique_key_update_mode = UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS;
        } else {
            _unique_key_update_mode = UniqueKeyUpdateModePB::UPSERT;
        }
    }
    _is_strict_mode = pschema.is_strict_mode();
    if (_unique_key_update_mode == UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS) {
        _auto_increment_column = pschema.auto_increment_column();
        if (!_auto_increment_column.empty() && pschema.auto_increment_column_unique_id() == -1) {
            return Status::InternalError(
                    "Auto increment column id is not set in FE. Maybe FE is an older version "
                    "different from BE.");
        }
        _auto_increment_column_unique_id = pschema.auto_increment_column_unique_id();
    }
    if (_unique_key_update_mode != UniqueKeyUpdateModePB::UPSERT) {
        if (pschema.has_partial_update_new_key_policy()) {
            _partial_update_new_row_policy = pschema.partial_update_new_key_policy();
        }
    }
    _timestamp_ms = pschema.timestamp_ms();
    if (pschema.has_nano_seconds()) {
        _nano_seconds = pschema.nano_seconds();
    }
    _timezone = pschema.timezone();

    for (const auto& col : pschema.partial_update_input_columns()) {
        _partial_update_input_columns.insert(col);
    }
    std::unordered_map<std::string, SlotDescriptor*> slots_map;

    _tuple_desc = _obj_pool.add(new TupleDescriptor(pschema.tuple_desc()));

    for (const auto& p_slot_desc : pschema.slot_descs()) {
        auto* slot_desc = _obj_pool.add(new SlotDescriptor(p_slot_desc));
        _tuple_desc->add_slot(slot_desc);
        std::string data_type;
        EnumToString(TPrimitiveType, to_thrift(slot_desc->col_type()), data_type);
        std::string is_null_str = slot_desc->is_nullable() ? "true" : "false";
        std::string data_type_str =
                std::to_string(int64_t(TabletColumn::get_field_type_by_string(data_type)));
        slots_map.emplace(to_lower(slot_desc->col_name()) + "+" + data_type_str + is_null_str,
                          slot_desc);
    }

    for (const auto& p_index : pschema.indexes()) {
        auto* index = _obj_pool.add(new OlapTableIndexSchema());
        index->index_id = p_index.id();
        index->schema_hash = p_index.schema_hash();
        for (const auto& pcolumn_desc : p_index.columns_desc()) {
            if (_unique_key_update_mode != UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS ||
                _partial_update_input_columns.contains(pcolumn_desc.name())) {
                std::string is_null_str = pcolumn_desc.is_nullable() ? "true" : "false";
                std::string data_type_str = std::to_string(
                        int64_t(TabletColumn::get_field_type_by_string(pcolumn_desc.type())));
                auto it = slots_map.find(to_lower(pcolumn_desc.name()) + "+" + data_type_str +
                                         is_null_str);
                if (it == std::end(slots_map)) {
                    std::string keys {};
                    for (const auto& [key, _] : slots_map) {
                        keys += fmt::format("{},", key);
                    }
                    LOG_EVERY_SECOND(WARNING) << fmt::format(
                            "[OlapTableSchemaParam::init(const POlapTableSchemaParam& pschema)]: "
                            "unknown index column, column={}, type={}, data_type_str={}, "
                            "is_null_str={}, slots_map.keys()=[{}], {}\npschema={}",
                            pcolumn_desc.name(), pcolumn_desc.type(), data_type_str, is_null_str,
                            keys, debug_string(), pschema.ShortDebugString());

                    return Status::InternalError("unknown index column, column={}, type={}",
                                                 pcolumn_desc.name(), pcolumn_desc.type());
                }
                index->slots.emplace_back(it->second);
            }
            TabletColumn* tc = _obj_pool.add(new TabletColumn());
            tc->init_from_pb(pcolumn_desc);
            index->columns.emplace_back(tc);
        }
        for (const auto& pindex_desc : p_index.indexes_desc()) {
            TabletIndex* ti = _obj_pool.add(new TabletIndex());
            ti->init_from_pb(pindex_desc);
            index->indexes.emplace_back(ti);
        }
        _indexes.emplace_back(index);
    }

    std::sort(_indexes.begin(), _indexes.end(),
              [](const OlapTableIndexSchema* lhs, const OlapTableIndexSchema* rhs) {
                  return lhs->index_id < rhs->index_id;
              });
    return Status::OK();
}

Status OlapTableSchemaParam::init_unique_key_update_mode(const TOlapTableSchemaParam& tschema) {
    if (tschema.__isset.unique_key_update_mode) {
        switch (tschema.unique_key_update_mode) {
        case doris::TUniqueKeyUpdateMode::UPSERT: {
            _unique_key_update_mode = UniqueKeyUpdateModePB::UPSERT;
            break;
        }
        case doris::TUniqueKeyUpdateMode::UPDATE_FIXED_COLUMNS: {
            _unique_key_update_mode = UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS;
            break;
        }
        case doris::TUniqueKeyUpdateMode::UPDATE_FLEXIBLE_COLUMNS: {
            _unique_key_update_mode = UniqueKeyUpdateModePB::UPDATE_FLEXIBLE_COLUMNS;
            break;
        }
        default: {
            return Status::InternalError(
                    "Unknown unique_key_update_mode: {}, should be one of "
                    "UPSERT/UPDATE_FIXED_COLUMNS/UPDATE_FLEXIBLE_COLUMNS",
                    tschema.unique_key_update_mode);
        }
        }
        if (tschema.__isset.sequence_map_col_unique_id) {
            _sequence_map_col_uid = tschema.sequence_map_col_unique_id;
        }
    } else {
        // for backward compatibility
        if (tschema.__isset.is_partial_update && tschema.is_partial_update) {
            _unique_key_update_mode = UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS;
        } else {
            _unique_key_update_mode = UniqueKeyUpdateModePB::UPSERT;
        }
    }
    return Status::OK();
}

Status OlapTableSchemaParam::init(const TOlapTableSchemaParam& tschema) {
    _db_id = tschema.db_id;
    _table_id = tschema.table_id;
    _version = tschema.version;
    RETURN_IF_ERROR(init_unique_key_update_mode(tschema));
    if (tschema.__isset.is_strict_mode) {
        _is_strict_mode = tschema.is_strict_mode;
    }
    if (_unique_key_update_mode == UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS) {
        _auto_increment_column = tschema.auto_increment_column;
        if (!_auto_increment_column.empty() && tschema.auto_increment_column_unique_id == -1) {
            return Status::InternalError(
                    "Auto increment column id is not set in FE. Maybe FE is an older version "
                    "different from BE.");
        }
        _auto_increment_column_unique_id = tschema.auto_increment_column_unique_id;
    }

    if (_unique_key_update_mode != UniqueKeyUpdateModePB::UPSERT) {
        if (tschema.__isset.partial_update_new_key_policy) {
            switch (tschema.partial_update_new_key_policy) {
            case doris::TPartialUpdateNewRowPolicy::APPEND: {
                _partial_update_new_row_policy = PartialUpdateNewRowPolicyPB::APPEND;
                break;
            }
            case doris::TPartialUpdateNewRowPolicy::ERROR: {
                _partial_update_new_row_policy = PartialUpdateNewRowPolicyPB::ERROR;
                break;
            }
            default: {
                return Status::InvalidArgument(
                        "Unknown partial_update_new_key_behavior: {}, should be one of "
                        "'APPEND' or 'ERROR'",
                        tschema.partial_update_new_key_policy);
            }
            }
        }
    }

    for (const auto& tcolumn : tschema.partial_update_input_columns) {
        _partial_update_input_columns.insert(tcolumn);
    }
    std::unordered_map<std::string, SlotDescriptor*> slots_map;
    _tuple_desc = _obj_pool.add(new TupleDescriptor(tschema.tuple_desc));
    for (const auto& t_slot_desc : tschema.slot_descs) {
        auto* slot_desc = _obj_pool.add(new SlotDescriptor(t_slot_desc));
        _tuple_desc->add_slot(slot_desc);
        std::string is_null_str = slot_desc->is_nullable() ? "true" : "false";
        std::string data_type_str = std::to_string(int64_t(slot_desc->col_type()));
        slots_map.emplace(to_lower(slot_desc->col_name()) + "+" + data_type_str + is_null_str,
                          slot_desc);
    }

    for (const auto& t_index : tschema.indexes) {
        std::unordered_map<std::string, int32_t> index_slots_map;
        auto* index = _obj_pool.add(new OlapTableIndexSchema());
        index->index_id = t_index.id;
        index->schema_hash = t_index.schema_hash;
        for (const auto& tcolumn_desc : t_index.columns_desc) {
            if (_unique_key_update_mode != UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS ||
                _partial_update_input_columns.contains(tcolumn_desc.column_name)) {
                std::string is_null_str = tcolumn_desc.is_allow_null ? "true" : "false";
                std::string data_type_str =
                        std::to_string(int64_t(thrift_to_type(tcolumn_desc.column_type.type)));
                auto it = slots_map.find(to_lower(tcolumn_desc.column_name) + "+" + data_type_str +
                                         is_null_str);
                if (it == slots_map.end()) {
                    std::stringstream ss;
                    ss << tschema;
                    std::string keys {};
                    for (const auto& [key, _] : slots_map) {
                        keys += fmt::format("{},", key);
                    }
                    LOG_EVERY_SECOND(WARNING) << fmt::format(
                            "[OlapTableSchemaParam::init(const TOlapTableSchemaParam& tschema)]: "
                            "unknown index column, column={}, type={}, data_type_str={}, "
                            "is_null_str={}, slots_map.keys()=[{}], {}\ntschema={}",
                            tcolumn_desc.column_name, tcolumn_desc.column_type.type, data_type_str,
                            is_null_str, keys, debug_string(), ss.str());
                    return Status::InternalError("unknown index column, column={}, type={}",
                                                 tcolumn_desc.column_name,
                                                 tcolumn_desc.column_type.type);
                }
                index->slots.emplace_back(it->second);
            }
            index_slots_map.emplace(to_lower(tcolumn_desc.column_name), tcolumn_desc.col_unique_id);
            TabletColumn* tc = _obj_pool.add(new TabletColumn());
            tc->init_from_thrift(tcolumn_desc);
            index->columns.emplace_back(tc);
        }
        if (t_index.__isset.indexes_desc) {
            for (const auto& tindex_desc : t_index.indexes_desc) {
                std::vector<int32_t> column_unique_ids(tindex_desc.columns.size());
                for (size_t i = 0; i < tindex_desc.columns.size(); i++) {
                    auto it = index_slots_map.find(to_lower(tindex_desc.columns[i]));
                    if (it != index_slots_map.end()) {
                        column_unique_ids[i] = it->second;
                    }
                }
                TabletIndex* ti = _obj_pool.add(new TabletIndex());
                ti->init_from_thrift(tindex_desc, column_unique_ids);
                index->indexes.emplace_back(ti);
            }
        }
        if (t_index.__isset.where_clause) {
            RETURN_IF_ERROR(
                    vectorized::VExpr::create_expr_tree(t_index.where_clause, index->where_clause));
        }
        _indexes.emplace_back(index);
    }

    std::sort(_indexes.begin(), _indexes.end(),
              [](const OlapTableIndexSchema* lhs, const OlapTableIndexSchema* rhs) {
                  return lhs->index_id < rhs->index_id;
              });
    return Status::OK();
}

void OlapTableSchemaParam::to_protobuf(POlapTableSchemaParam* pschema) const {
    pschema->set_db_id(_db_id);
    pschema->set_table_id(_table_id);
    pschema->set_version(_version);
    pschema->set_unique_key_update_mode(_unique_key_update_mode);
    if (_unique_key_update_mode == UniqueKeyUpdateModePB::UPDATE_FIXED_COLUMNS) {
        // for backward compatibility
        pschema->set_partial_update(true);
    }
    pschema->set_partial_update_new_key_policy(_partial_update_new_row_policy);
    pschema->set_is_strict_mode(_is_strict_mode);
    pschema->set_auto_increment_column(_auto_increment_column);
    pschema->set_auto_increment_column_unique_id(_auto_increment_column_unique_id);
    pschema->set_timestamp_ms(_timestamp_ms);
    pschema->set_timezone(_timezone);
    pschema->set_nano_seconds(_nano_seconds);
    pschema->set_sequence_map_col_unique_id(_sequence_map_col_uid);
    for (auto col : _partial_update_input_columns) {
        *pschema->add_partial_update_input_columns() = col;
    }
    _tuple_desc->to_protobuf(pschema->mutable_tuple_desc());
    for (auto* slot : _tuple_desc->slots()) {
        slot->to_protobuf(pschema->add_slot_descs());
    }
    for (auto* index : _indexes) {
        index->to_protobuf(pschema->add_indexes());
    }
}

std::string OlapTableSchemaParam::debug_string() const {
    std::stringstream ss;
    ss << "tuple_desc=" << _tuple_desc->debug_string();
    return ss.str();
}

VOlapTablePartitionParam::VOlapTablePartitionParam(std::shared_ptr<OlapTableSchemaParam>& schema,
                                                   const TOlapTablePartitionParam& t_param)
        : _schema(schema),
          _t_param(t_param),
          _slots(_schema->tuple_desc()->slots()),
          _mem_tracker(std::make_unique<MemTracker>("OlapTablePartitionParam")),
          _part_type(t_param.partition_type) {
    if (t_param.__isset.enable_automatic_partition && t_param.enable_automatic_partition) {
        _is_auto_partition = true;
        auto size = t_param.partition_function_exprs.size();
        _part_func_ctx.resize(size);
        _partition_function.resize(size);
        DCHECK((t_param.partition_type == TPartitionType::RANGE_PARTITIONED && size == 1) ||
               (t_param.partition_type == TPartitionType::LIST_PARTITIONED && size >= 1))
                << "now support only 1 partition column for auto range partitions. "
                << t_param.partition_type << " " << size;
        for (int i = 0; i < size; ++i) {
            Status st = vectorized::VExpr::create_expr_tree(t_param.partition_function_exprs[i],
                                                            _part_func_ctx[i]);
            if (!st.ok()) {
                throw Exception(Status::InternalError("Partition function expr is not valid"),
                                "Partition function expr is not valid");
            }
            _partition_function[i] = _part_func_ctx[i]->root();
        }
    }

    if (t_param.__isset.enable_auto_detect_overwrite && t_param.enable_auto_detect_overwrite) {
        _is_auto_detect_overwrite = true;
        DCHECK(t_param.__isset.overwrite_group_id);
        _overwrite_group_id = t_param.overwrite_group_id;
    }

    if (_is_auto_partition) {
        // the nullable mode depends on partition_exprs. not column slots. so use them.
        DCHECK(_partition_function.size() <= _slots.size())
                << _partition_function.size() << ", " << _slots.size();

        // suppose (k0, [k1], [k2]), so get [k1, 0], [k2, 1]
        std::map<std::string, int> partition_slots_map; // name to idx in part_exprs
        for (size_t i = 0; i < t_param.partition_columns.size(); i++) {
            partition_slots_map.emplace(t_param.partition_columns[i], i);
        }

        // here we rely on the same order and number of the _part_funcs and _slots in the prefix
        // _part_block contains all slots of table.
        for (auto* slot : _slots) {
            // try to replace with partition expr.
            if (auto it = partition_slots_map.find(slot->col_name());
                it != partition_slots_map.end()) { // it's a partition column slot
                auto& expr_type = _partition_function[it->second]->data_type();
                _partition_block.insert({expr_type->create_column(), expr_type, slot->col_name()});
            } else {
                _partition_block.insert({slot->get_empty_mutable_column(),
                                         slot->get_data_type_ptr(), slot->col_name()});
            }
        }
        VLOG_TRACE << _partition_block.dump_structure();
    } else {
        // we insert all. but not all will be used. it will controlled by _partition_slot_locs
        for (auto* slot : _slots) {
            _partition_block.insert({slot->get_empty_mutable_column(), slot->get_data_type_ptr(),
                                     slot->col_name()});
        }
    }
}

VOlapTablePartitionParam::~VOlapTablePartitionParam() {
    _mem_tracker->release(_mem_usage);
}

Status VOlapTablePartitionParam::init() {
    std::vector<std::string> slot_column_names;
    for (auto* slot_desc : _schema->tuple_desc()->slots()) {
        slot_column_names.emplace_back(slot_desc->col_name());
    }

    auto find_slot_locs = [&slot_column_names](const std::string& slot_name,
                                               std::vector<uint16_t>& locs,
                                               const std::string& column_type) {
        auto it = std::find(slot_column_names.begin(), slot_column_names.end(), slot_name);
        if (it == slot_column_names.end()) {
            return Status::InternalError("{} column not found, column ={}", column_type, slot_name);
        }
        locs.emplace_back(it - slot_column_names.begin());
        return Status::OK();
    };

    // here we find the partition columns. others maybe non-partition columns/special columns.
    if (_t_param.__isset.partition_columns) {
        for (auto& part_col : _t_param.partition_columns) {
            RETURN_IF_ERROR(find_slot_locs(part_col, _partition_slot_locs, "partition"));
        }
    }

    _partitions_map = std::make_unique<
            std::map<BlockRowWithIndicator, VOlapTablePartition*, VOlapTablePartKeyComparator>>(
            VOlapTablePartKeyComparator(_partition_slot_locs, _transformed_slot_locs));
    if (_t_param.__isset.distributed_columns) {
        for (auto& col : _t_param.distributed_columns) {
            RETURN_IF_ERROR(find_slot_locs(col, _distributed_slot_locs, "distributed"));
        }
    }

    // for both auto/non-auto partition table.
    _is_in_partition = _part_type == TPartitionType::type::LIST_PARTITIONED;

    // initial partitions. if meet dummy partitions only for open BE nodes, not generate key of them for finding
    for (const auto& t_part : _t_param.partitions) {
        VOlapTablePartition* part = nullptr;
        RETURN_IF_ERROR(generate_partition_from(t_part, part));
        _partitions.emplace_back(part);

        if (!_t_param.partitions_is_fake) {
            if (_is_in_partition) {
                for (auto& in_key : part->in_keys) {
                    _partitions_map->emplace(std::tuple {in_key.first, in_key.second, false}, part);
                }
            } else {
                _partitions_map->emplace(
                        std::tuple {part->end_key.first, part->end_key.second, false}, part);
            }
        }
    }

    _mem_usage = _partition_block.allocated_bytes();
    _mem_tracker->consume(_mem_usage);
    return Status::OK();
}

bool VOlapTablePartitionParam::_part_contains(VOlapTablePartition* part,
                                              BlockRowWithIndicator key) const {
    VOlapTablePartKeyComparator comparator(_partition_slot_locs, _transformed_slot_locs);
    // we have used upper_bound to find to ensure key < part.right and this part is closest(right - key is min)
    // now we only have to check (key >= part.left). the comparator(a,b) means a < b, so we use anti
    return part->start_key.second == -1 /* spj: start_key.second == -1 means only single partition*/
           || !comparator(key, std::tuple {part->start_key.first, part->start_key.second, false});
}

// insert value into _partition_block's column
// NOLINTBEGIN(readability-function-size)
static Status _create_partition_key(const TExprNode& t_expr, BlockRow* part_key, uint16_t pos) {
    auto column = std::move(*part_key->first->get_by_position(pos).column).mutate();
    //TODO: use assert_cast before insert_data
    switch (t_expr.node_type) {
    case TExprNodeType::DATE_LITERAL: {
        auto primitive_type = vectorized::DataTypeFactory::instance()
                                      .create_data_type(t_expr.type)
                                      ->get_primitive_type();
        if (primitive_type == TYPE_DATEV2) {
            DateV2Value<DateV2ValueType> dt;
            if (!dt.from_date_str(t_expr.date_literal.value.c_str(),
                                  t_expr.date_literal.value.size())) {
                std::stringstream ss;
                ss << "invalid date literal in partition column, date=" << t_expr.date_literal;
                return Status::InternalError(ss.str());
            }
            column->insert_data(reinterpret_cast<const char*>(&dt), 0);
        } else if (primitive_type == TYPE_DATETIMEV2) {
            DateV2Value<DateTimeV2ValueType> dt;
            const int32_t scale =
                    t_expr.type.types.empty() ? -1 : t_expr.type.types.front().scalar_type.scale;
            if (!dt.from_date_str(t_expr.date_literal.value.c_str(),
                                  t_expr.date_literal.value.size(), scale)) {
                std::stringstream ss;
                ss << "invalid date literal in partition column, date=" << t_expr.date_literal;
                return Status::InternalError(ss.str());
            }
            column->insert_data(reinterpret_cast<const char*>(&dt), 0);
        } else if (primitive_type == TYPE_TIMESTAMPTZ) {
            TimestampTzValue res;
            vectorized::CastParameters params {.status = Status::OK(), .is_strict = true};
            const int32_t scale =
                    t_expr.type.types.empty() ? -1 : t_expr.type.types.front().scalar_type.scale;
            if (!vectorized::CastToTimstampTz::from_string(
                        {t_expr.date_literal.value.c_str(), t_expr.date_literal.value.size()}, res,
                        params, nullptr, scale)) [[unlikely]] {
                std::stringstream ss;
                ss << "invalid timestamptz literal in partition column, value="
                   << t_expr.date_literal;
                return Status::InternalError(ss.str());
            } else {
                column->insert_data(reinterpret_cast<const char*>(&res), 0);
            }
        } else {
            // TYPE_DATE (DATEV1) or TYPE_DATETIME (DATETIMEV1)
            VecDateTimeValue dt;
            if (!dt.from_date_str(t_expr.date_literal.value.c_str(),
                                  t_expr.date_literal.value.size())) {
                std::stringstream ss;
                ss << "invalid date literal in partition column, date=" << t_expr.date_literal;
                return Status::InternalError(ss.str());
            }
            if (vectorized::DataTypeFactory::instance()
                        .create_data_type(t_expr.type)
                        ->get_primitive_type() == TYPE_DATE) {
                dt.cast_to_date();
            }
            column->insert_data(reinterpret_cast<const char*>(&dt), 0);
        }
        break;
    }
    case TExprNodeType::INT_LITERAL: {
        switch (t_expr.type.types[0].scalar_type.type) {
        case TPrimitiveType::TINYINT: {
            auto value = cast_set<int8_t>(t_expr.int_literal.value);
            column->insert_data(reinterpret_cast<const char*>(&value), 0);
            break;
        }
        case TPrimitiveType::SMALLINT: {
            auto value = cast_set<int16_t>(t_expr.int_literal.value);
            column->insert_data(reinterpret_cast<const char*>(&value), 0);
            break;
        }
        case TPrimitiveType::INT: {
            auto value = cast_set<int32_t>(t_expr.int_literal.value);
            column->insert_data(reinterpret_cast<const char*>(&value), 0);
            break;
        }
        default:
            int64_t value = t_expr.int_literal.value;
            column->insert_data(reinterpret_cast<const char*>(&value), 0);
        }
        break;
    }
    case TExprNodeType::LARGE_INT_LITERAL: {
        StringParser::ParseResult parse_result = StringParser::PARSE_SUCCESS;
        auto value = StringParser::string_to_int<__int128>(t_expr.large_int_literal.value.c_str(),
                                                           t_expr.large_int_literal.value.size(),
                                                           &parse_result);
        if (parse_result != StringParser::PARSE_SUCCESS) {
            value = MAX_INT128;
        }
        column->insert_data(reinterpret_cast<const char*>(&value), 0);
        break;
    }
    case TExprNodeType::STRING_LITERAL: {
        size_t len = t_expr.string_literal.value.size();
        const char* str_val = t_expr.string_literal.value.c_str();
        column->insert_data(str_val, len);
        break;
    }
    case TExprNodeType::BOOL_LITERAL: {
        column->insert_data(reinterpret_cast<const char*>(&t_expr.bool_literal.value), 0);
        break;
    }
    case TExprNodeType::NULL_LITERAL: {
        // insert a null literal
        if (!column->is_nullable()) {
            // https://github.com/apache/doris/pull/39449 have forbid this cause. always add this check as protective measures
            return Status::InternalError("The column {} is not null, can't insert into NULL value.",
                                         part_key->first->get_by_position(pos).name);
        }
        column->insert_data(nullptr, 0);
        break;
    }
    default: {
        return Status::InternalError("unsupported partition column node type, type={}",
                                     t_expr.node_type);
    }
    }
    part_key->second = cast_set<int32_t>(column->size() - 1);
    return Status::OK();
}
// NOLINTEND(readability-function-size)

Status VOlapTablePartitionParam::_create_partition_keys(const std::vector<TExprNode>& t_exprs,
                                                        BlockRow* part_key) {
    for (int i = 0; i < t_exprs.size(); i++) {
        RETURN_IF_ERROR(_create_partition_key(t_exprs[i], part_key, _partition_slot_locs[i]));
    }
    return Status::OK();
}

Status VOlapTablePartitionParam::generate_partition_from(const TOlapTablePartition& t_part,
                                                         VOlapTablePartition*& part_result) {
    DCHECK(part_result == nullptr);
    // here we set the default value of partition bounds first! if it doesn't have some key, it will be -1.
    part_result = _obj_pool.add(new VOlapTablePartition(&_partition_block));
    part_result->id = t_part.id;
    part_result->is_mutable = t_part.is_mutable;
    // only load_to_single_tablet = true will set load_tablet_idx
    if (t_part.__isset.load_tablet_idx) {
        part_result->load_tablet_idx = t_part.load_tablet_idx;
    }

    if (_is_in_partition) {
        for (const auto& keys : t_part.in_keys) {
            RETURN_IF_ERROR(_create_partition_keys(
                    keys, &part_result->in_keys.emplace_back(&_partition_block, -1)));
        }
        if (t_part.__isset.is_default_partition && t_part.is_default_partition &&
            _default_partition == nullptr) {
            _default_partition = part_result;
        }
    } else { // range
        if (t_part.__isset.start_keys) {
            RETURN_IF_ERROR(_create_partition_keys(t_part.start_keys, &part_result->start_key));
        }
        // we generate the right bound but not insert into partition map
        if (t_part.__isset.end_keys) {
            RETURN_IF_ERROR(_create_partition_keys(t_part.end_keys, &part_result->end_key));
        }
    }

    part_result->num_buckets = t_part.num_buckets;
    auto num_indexes = _schema->indexes().size();
    if (t_part.indexes.size() != num_indexes) {
        return Status::InternalError(
                "number of partition's index is not equal with schema's"
                ", num_part_indexes={}, num_schema_indexes={}",
                t_part.indexes.size(), num_indexes);
    }
    part_result->indexes = t_part.indexes;
    std::sort(part_result->indexes.begin(), part_result->indexes.end(),
              [](const OlapTableIndexTablets& lhs, const OlapTableIndexTablets& rhs) {
                  return lhs.index_id < rhs.index_id;
              });
    // check index
    for (int j = 0; j < num_indexes; ++j) {
        if (part_result->indexes[j].index_id != _schema->indexes()[j]->index_id) {
            return Status::InternalError(
                    "partition's index is not equal with schema's"
                    ", part_index={}, schema_index={}",
                    part_result->indexes[j].index_id, _schema->indexes()[j]->index_id);
        }
    }
    if (t_part.__isset.total_replica_num) {
        part_result->total_replica_num = t_part.total_replica_num;
    }
    if (t_part.__isset.load_required_replica_num) {
        part_result->load_required_replica_num = t_part.load_required_replica_num;
    }
    return Status::OK();
}

Status VOlapTablePartitionParam::add_partitions(
        const std::vector<TOlapTablePartition>& partitions) {
    for (const auto& t_part : partitions) {
        auto* part = _obj_pool.add(new VOlapTablePartition(&_partition_block));
        part->id = t_part.id;
        part->is_mutable = t_part.is_mutable;

        // we dont pass right keys when it's MAX_VALUE. so there's possibility we only have start_key but not end_key
        // range partition
        if (t_part.__isset.start_keys) {
            RETURN_IF_ERROR(_create_partition_keys(t_part.start_keys, &part->start_key));
        }
        if (t_part.__isset.end_keys) {
            RETURN_IF_ERROR(_create_partition_keys(t_part.end_keys, &part->end_key));
        }
        // list partition - we only set 1 value in 1 partition for new created ones
        if (t_part.__isset.in_keys) {
            for (const auto& keys : t_part.in_keys) {
                RETURN_IF_ERROR(_create_partition_keys(
                        keys, &part->in_keys.emplace_back(&_partition_block, -1)));
            }
            if (t_part.__isset.is_default_partition && t_part.is_default_partition) {
                _default_partition = part;
            }
        }

        part->num_buckets = t_part.num_buckets;
        auto num_indexes = _schema->indexes().size();
        if (t_part.indexes.size() != num_indexes) {
            return Status::InternalError(
                    "number of partition's index is not equal with schema's"
                    ", num_part_indexes={}, num_schema_indexes={}",
                    t_part.indexes.size(), num_indexes);
        }
        part->indexes = t_part.indexes;
        std::sort(part->indexes.begin(), part->indexes.end(),
                  [](const OlapTableIndexTablets& lhs, const OlapTableIndexTablets& rhs) {
                      return lhs.index_id < rhs.index_id;
                  });
        // check index
        for (int j = 0; j < num_indexes; ++j) {
            if (part->indexes[j].index_id != _schema->indexes()[j]->index_id) {
                return Status::InternalError(
                        "partition's index is not equal with schema's"
                        ", part_index={}, schema_index={}",
                        part->indexes[j].index_id, _schema->indexes()[j]->index_id);
            }
        }
        _partitions.emplace_back(part);
        // after _creating_partiton_keys
        if (_is_in_partition) {
            for (auto& in_key : part->in_keys) {
                _partitions_map->emplace(std::tuple {in_key.first, in_key.second, false}, part);
            }
        } else {
            _partitions_map->emplace(std::tuple {part->end_key.first, part->end_key.second, false},
                                     part);
        }
    }

    return Status::OK();
}

Status VOlapTablePartitionParam::replace_partitions(
        std::vector<int64_t>& old_partition_ids,
        const std::vector<TOlapTablePartition>& new_partitions) {
    // remove old replaced partitions
    DCHECK(old_partition_ids.size() == new_partitions.size());

    // init and add new partitions. insert into _partitions
    for (int i = 0; i < new_partitions.size(); i++) {
        const auto& t_part = new_partitions[i];
        // pair old_partition_ids and new_partitions one by one. TODO: sort to opt performance
        VOlapTablePartition* old_part = nullptr;
        auto old_part_id = old_partition_ids[i];
        if (auto it = std::find_if(
                    _partitions.begin(), _partitions.end(),
                    [=](const VOlapTablePartition* lhs) { return lhs->id == old_part_id; });
            it != _partitions.end()) {
            old_part = *it;
        } else {
            return Status::InternalError("Cannot find old tablet {} in replacing", old_part_id);
        }

        auto* part = _obj_pool.add(new VOlapTablePartition(&_partition_block));
        part->id = t_part.id;
        part->is_mutable = t_part.is_mutable;

        /// just substitute directly. no need to remove and reinsert keys.
        // range partition
        part->start_key = std::move(old_part->start_key);
        part->end_key = std::move(old_part->end_key);
        // list partition
        part->in_keys = std::move(old_part->in_keys);
        if (t_part.__isset.is_default_partition && t_part.is_default_partition) {
            _default_partition = part;
        }

        part->num_buckets = t_part.num_buckets;
        auto num_indexes = _schema->indexes().size();
        if (t_part.indexes.size() != num_indexes) {
            return Status::InternalError(
                    "number of partition's index is not equal with schema's"
                    ", num_part_indexes={}, num_schema_indexes={}",
                    t_part.indexes.size(), num_indexes);
        }
        part->indexes = t_part.indexes;
        std::sort(part->indexes.begin(), part->indexes.end(),
                  [](const OlapTableIndexTablets& lhs, const OlapTableIndexTablets& rhs) {
                      return lhs.index_id < rhs.index_id;
                  });
        // check index
        for (int j = 0; j < num_indexes; ++j) {
            if (part->indexes[j].index_id != _schema->indexes()[j]->index_id) {
                return Status::InternalError(
                        "partition's index is not equal with schema's"
                        ", part_index={}, schema_index={}",
                        part->indexes[j].index_id, _schema->indexes()[j]->index_id);
            }
        }

        // add new partitions with new id.
        _partitions.emplace_back(part);
        VLOG_NOTICE << "params add new partition " << part->id;

        // replace items in _partition_maps
        if (_is_in_partition) {
            for (auto& in_key : part->in_keys) {
                (*_partitions_map)[std::tuple {in_key.first, in_key.second, false}] = part;
            }
        } else {
            (*_partitions_map)[std::tuple {part->end_key.first, part->end_key.second, false}] =
                    part;
        }
    }
    // remove old partitions by id
    std::ranges::sort(old_partition_ids);
    for (auto it = _partitions.begin(); it != _partitions.end();) {
        if (std::ranges::binary_search(old_partition_ids, (*it)->id)) {
            it = _partitions.erase(it);
        } else {
            it++;
        }
    }

    return Status::OK();
}
#include "common/compile_check_end.h"

} // namespace doris
