// 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/rowid_fetcher.h"

#include <brpc/callback.h>
#include <butil/endpoint.h>
#include <fmt/format.h>
#include <gen_cpp/data.pb.h>
#include <gen_cpp/internal_service.pb.h>
#include <gen_cpp/olap_file.pb.h>
#include <gen_cpp/types.pb.h>
#include <glog/logging.h>
#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <cstdint>
#include <memory>
#include <ostream>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include "bthread/countdown_event.h"
#include "common/config.h"
#include "common/consts.h"
#include "common/exception.h"
#include "common/signal_handler.h"
#include "core/assert_cast.h"
#include "core/block/block.h" // Block
#include "core/column/column.h"
#include "core/column/column_nullable.h"
#include "core/column/column_string.h"
#include "core/data_type/data_type_struct.h"
#include "core/data_type_serde/data_type_serde.h"
#include "core/string_ref.h"
#include "exec/scan/file_scanner.h"
#include "format/orc/vorc_reader.h"
#include "format/parquet/vparquet_reader.h"
#include "runtime/descriptors.h"
#include "runtime/exec_env.h"      // ExecEnv
#include "runtime/fragment_mgr.h"  // FragmentMgr
#include "runtime/runtime_state.h" // RuntimeState
#include "runtime/workload_group/workload_group_manager.h"
#include "semaphore"
#include "storage/olap_common.h"
#include "storage/rowset/beta_rowset.h"
#include "storage/segment/column_reader.h"
#include "storage/storage_engine.h"
#include "storage/tablet/tablet_fwd.h"
#include "storage/tablet/tablet_schema.h"
#include "storage/tablet_info.h" // DorisNodesInfo
#include "storage/utils.h"
#include "util/brpc_client_cache.h" // BrpcClientCache
#include "util/defer_op.h"
#include "util/jsonb/serialize.h"

namespace doris {

Status RowIDFetcher::init() {
    DorisNodesInfo nodes_info;
    nodes_info.setNodes(_fetch_option.t_fetch_opt.nodes_info);
    for (auto [node_id, node_info] : nodes_info.nodes_info()) {
        auto client = ExecEnv::GetInstance()->brpc_internal_client_cache()->get_client(
                node_info.host, node_info.brpc_port);
        if (!client) {
            LOG(WARNING) << "Get rpc stub failed, host=" << node_info.host
                         << ", port=" << node_info.brpc_port;
            return Status::InternalError("RowIDFetcher failed to init rpc client, host={}, port={}",
                                         node_info.host, node_info.brpc_port);
        }
        _stubs.push_back(client);
    }
    return Status::OK();
}

PMultiGetRequest RowIDFetcher::_init_fetch_request(const ColumnString& row_locs) const {
    PMultiGetRequest mget_req;
    _fetch_option.desc->to_protobuf(mget_req.mutable_desc());
    for (SlotDescriptor* slot : _fetch_option.desc->slots()) {
        // ignore rowid
        if (slot->col_name() == BeConsts::ROWID_COL) {
            continue;
        }
        slot->to_protobuf(mget_req.add_slots());
    }
    for (size_t i = 0; i < row_locs.size(); ++i) {
        PRowLocation row_loc;
        StringRef row_id_rep = row_locs.get_data_at(i);
        // TODO: When transferring data between machines with different byte orders (endianness),
        // not performing proper handling may lead to issues in parsing and exchanging the data.
        auto location = reinterpret_cast<const GlobalRowLoacation*>(row_id_rep.data);
        row_loc.set_tablet_id(location->tablet_id);
        row_loc.set_rowset_id(location->row_location.rowset_id.to_string());
        row_loc.set_segment_id(location->row_location.segment_id);
        row_loc.set_ordinal_id(location->row_location.row_id);
        *mget_req.add_row_locs() = std::move(row_loc);
    }
    // Set column desc
    for (const TColumn& tcolumn : _fetch_option.t_fetch_opt.column_desc) {
        TabletColumn column(tcolumn);
        column.to_schema_pb(mget_req.add_column_desc());
    }
    PUniqueId& query_id = *mget_req.mutable_query_id();
    query_id.set_hi(_fetch_option.runtime_state->query_id().hi);
    query_id.set_lo(_fetch_option.runtime_state->query_id().lo);
    mget_req.set_be_exec_version(_fetch_option.runtime_state->be_exec_version());
    mget_req.set_fetch_row_store(_fetch_option.t_fetch_opt.fetch_row_store);
    return mget_req;
}

Status RowIDFetcher::_merge_rpc_results(const PMultiGetRequest& request,
                                        const std::vector<PMultiGetResponse>& rsps,
                                        const std::vector<brpc::Controller>& cntls,
                                        Block* output_block,
                                        std::vector<PRowLocation>* rows_id) const {
    output_block->clear();
    for (const auto& cntl : cntls) {
        if (cntl.Failed()) {
            LOG(WARNING) << "Failed to fetch meet rpc error:" << cntl.ErrorText()
                         << ", host:" << cntl.remote_side();
            return Status::InternalError(cntl.ErrorText());
        }
    }
    DataTypeSerDeSPtrs serdes;
    std::unordered_map<uint32_t, uint32_t> col_uid_to_idx;
    std::vector<std::string> default_values;
    default_values.resize(_fetch_option.desc->slots().size());
    auto merge_function = [&](const PMultiGetResponse& resp) {
        Status st(Status::create(resp.status()));
        if (!st.ok()) {
            LOG(WARNING) << "Failed to fetch " << st.to_string();
            return st;
        }
        for (const PRowLocation& row_id : resp.row_locs()) {
            rows_id->push_back(row_id);
        }
        // Merge binary rows
        if (request.fetch_row_store()) {
            CHECK(resp.row_locs().size() == resp.binary_row_data_size());
            if (output_block->is_empty_column()) {
                *output_block = Block(_fetch_option.desc->slots(), 1);
            }
            if (serdes.empty() && col_uid_to_idx.empty()) {
                serdes = create_data_type_serdes(_fetch_option.desc->slots());
                for (int i = 0; i < _fetch_option.desc->slots().size(); ++i) {
                    col_uid_to_idx[_fetch_option.desc->slots()[i]->col_unique_id()] = i;
                    default_values[i] = _fetch_option.desc->slots()[i]->col_default_value();
                }
            }
            auto output_columns_guard = output_block->mutate_columns_scoped();
            MutableColumns& output_columns = output_columns_guard.mutable_columns();
            for (int i = 0; i < resp.binary_row_data_size(); ++i) {
                RETURN_IF_ERROR(JsonbSerializeUtil::jsonb_to_columns(
                        serdes, resp.binary_row_data(i).data(), resp.binary_row_data(i).size(),
                        col_uid_to_idx, output_columns, default_values, {}));
            }
            return Status::OK();
        }
        // Merge partial blocks
        Block partial_block;
        [[maybe_unused]] size_t uncompressed_size = 0;
        [[maybe_unused]] int64_t uncompressed_time = 0;

        RETURN_IF_ERROR(
                partial_block.deserialize(resp.block(), &uncompressed_size, &uncompressed_time));
        if (partial_block.is_empty_column()) {
            return Status::OK();
        }
        CHECK(resp.row_locs().size() == partial_block.rows());
        if (output_block->is_empty_column()) {
            output_block->swap(partial_block);
        } else if (partial_block.columns() != output_block->columns()) {
            return Status::Error<ErrorCode::INTERNAL_ERROR>(
                    "Merge block not match, self:[{}], input:[{}], ", output_block->dump_types(),
                    partial_block.dump_types());
        } else {
            for (int i = 0; i < output_block->columns(); ++i) {
                auto column_guard = output_block->mutate_column_scoped(i);
                MutableColumnPtr& column = column_guard.mutable_column();
                column->insert_range_from(
                        *partial_block.get_by_position(i).column->convert_to_full_column_if_const(),
                        0, partial_block.rows());
            }
        }
        return Status::OK();
    };

    for (const auto& resp : rsps) {
        RETURN_IF_ERROR(merge_function(resp));
    }
    return Status::OK();
}

Status RowIDFetcher::fetch(const ColumnPtr& column_row_ids, Block* res_block) {
    CHECK(!_stubs.empty());
    PMultiGetRequest mget_req = _init_fetch_request(
            assert_cast<const ColumnString&>(*remove_nullable(column_row_ids).get()));
    std::vector<PMultiGetResponse> resps(_stubs.size());
    std::vector<brpc::Controller> cntls(_stubs.size());
    bthread::CountdownEvent counter(cast_set<int>(_stubs.size()));
    for (size_t i = 0; i < _stubs.size(); ++i) {
        cntls[i].set_timeout_ms(_fetch_option.runtime_state->execution_timeout() * 1000);
        auto callback = brpc::NewCallback(fetch_callback, &counter);
        _stubs[i]->multiget_data(&cntls[i], &mget_req, &resps[i], callback);
    }
    counter.wait();

    // Merge
    std::vector<PRowLocation> rows_locs;
    rows_locs.reserve(rows_locs.size());
    RETURN_IF_ERROR(_merge_rpc_results(mget_req, resps, cntls, res_block, &rows_locs));
    if (rows_locs.size() < column_row_ids->size()) {
        return Status::InternalError("Miss matched return row loc count {}, expected {}, input {}",
                                     rows_locs.size(), res_block->rows(), column_row_ids->size());
    }
    // Final sort by row_ids sequence, since row_ids is already sorted if need
    std::map<GlobalRowLoacation, size_t> positions;
    for (size_t i = 0; i < rows_locs.size(); ++i) {
        RowsetId rowset_id;
        rowset_id.init(rows_locs[i].rowset_id());
        GlobalRowLoacation grl(rows_locs[i].tablet_id(), rowset_id,
                               cast_set<uint32_t>(rows_locs[i].segment_id()),
                               cast_set<uint32_t>(rows_locs[i].ordinal_id()));
        positions[grl] = i;
    };
    // TODO remove this warning code
    if (positions.size() < rows_locs.size()) {
        LOG(WARNING) << "cwntains duplicated row entry";
    }
    IColumn::Permutation permutation;
    permutation.reserve(column_row_ids->size());
    for (size_t i = 0; i < column_row_ids->size(); ++i) {
        auto location =
                reinterpret_cast<const GlobalRowLoacation*>(column_row_ids->get_data_at(i).data);
        permutation.push_back(positions[*location]);
    }
    for (size_t i = 0; i < res_block->columns(); ++i) {
        res_block->get_by_position(i).column =
                res_block->get_by_position(i).column->permute(permutation, permutation.size());
    }
    // Check row consistency
    RETURN_IF_CATCH_EXCEPTION(res_block->check_number_of_rows());
    VLOG_DEBUG << "dump block:" << res_block->dump_data(0, 10);
    return Status::OK();
}

struct IteratorKey {
    int64_t tablet_id;
    RowsetId rowset_id;
    uint64_t segment_id;
    int slot_id;

    // unordered map std::equal_to
    bool operator==(const IteratorKey& rhs) const {
        return tablet_id == rhs.tablet_id && rowset_id == rhs.rowset_id &&
               segment_id == rhs.segment_id && slot_id == rhs.slot_id;
    }
};

struct SegKey {
    int64_t tablet_id;
    RowsetId rowset_id;
    uint64_t segment_id;

    // unordered map std::equal_to
    bool operator==(const SegKey& rhs) const {
        return tablet_id == rhs.tablet_id && rowset_id == rhs.rowset_id &&
               segment_id == rhs.segment_id;
    }
};

struct HashOfSegKey {
    size_t operator()(const SegKey& key) const {
        size_t seed = 0;
        seed = HashUtil::hash64(&key.tablet_id, sizeof(key.tablet_id), seed);
        seed = HashUtil::hash64(&key.rowset_id.hi, sizeof(key.rowset_id.hi), seed);
        seed = HashUtil::hash64(&key.rowset_id.mi, sizeof(key.rowset_id.mi), seed);
        seed = HashUtil::hash64(&key.rowset_id.lo, sizeof(key.rowset_id.lo), seed);
        seed = HashUtil::hash64(&key.segment_id, sizeof(key.segment_id), seed);
        return seed;
    }
};

struct HashOfIteratorKey {
    size_t operator()(const IteratorKey& key) const {
        size_t seed = 0;
        seed = HashUtil::hash64(&key.tablet_id, sizeof(key.tablet_id), seed);
        seed = HashUtil::hash64(&key.rowset_id.hi, sizeof(key.rowset_id.hi), seed);
        seed = HashUtil::hash64(&key.rowset_id.mi, sizeof(key.rowset_id.mi), seed);
        seed = HashUtil::hash64(&key.rowset_id.lo, sizeof(key.rowset_id.lo), seed);
        seed = HashUtil::hash64(&key.segment_id, sizeof(key.segment_id), seed);
        seed = HashUtil::hash64(&key.slot_id, sizeof(key.slot_id), seed);
        return seed;
    }
};

struct IteratorItem {
    std::unique_ptr<ColumnIterator> iterator;
    SegmentSharedPtr segment;
    // for holding the reference of storage read options to avoid use after release
    StorageReadOptions storage_read_options;
};

static void set_slot_access_paths(const SlotDescriptor& slot, const TabletSchema& schema,
                                  StorageReadOptions& storage_read_options) {
    int32_t unique_id = slot.col_unique_id();
    const int field_index =
            unique_id >= 0 ? schema.field_index(unique_id) : schema.field_index(slot.col_name());
    if (field_index >= 0) {
        const auto& column = schema.column(field_index);
        unique_id = column.unique_id() >= 0 ? column.unique_id() : column.parent_unique_id();
    }
    if (unique_id < 0) {
        return;
    }

    if (!slot.all_access_paths().empty()) {
        storage_read_options.all_access_paths[unique_id] = slot.all_access_paths();
    }

    if (!slot.predicate_access_paths().empty()) {
        storage_read_options.predicate_access_paths[unique_id] = slot.predicate_access_paths();
    }
}

struct SegItem {
    BaseTabletSPtr tablet;
    BetaRowsetSharedPtr rowset;
    // for holding the reference of segment to avoid use after release
    SegmentSharedPtr segment;
};

// Groups all row_ids belonging to the same segment for batched reading.
// Position index tracks where each row_id originated in the original request,
// so results can be scattered back to the correct output positions.
struct DorisFormatReadBatch {
    std::shared_ptr<FileMapping> file_mapping;
    // (row_id, index_in_request) pairs for all rows in this segment.
    std::vector<std::pair<segment_v2::rowid_t, size_t>> row_ids_with_positions;
};

static void scatter_scan_blocks_to_result_block(
        const std::vector<std::pair<size_t, size_t>>& row_id_block_idx,
        const std::vector<Block>& scan_blocks, Block& result_block) {
    for (size_t column_id = 0; column_id < result_block.columns(); ++column_id) {
        auto dst_col_guard = result_block.mutate_column_scoped(column_id);
        MutableColumnPtr& dst_col = dst_col_guard.mutable_column();

        std::vector<const IColumn*> scan_src_columns;
        scan_src_columns.reserve(row_id_block_idx.size());
        std::vector<size_t> scan_positions;
        scan_positions.reserve(row_id_block_idx.size());
        for (const auto& [pos_block, block_idx] : row_id_block_idx) {
            DCHECK(scan_blocks.size() > pos_block);
            DCHECK(scan_blocks[pos_block].columns() > column_id);
            scan_src_columns.emplace_back(
                    scan_blocks[pos_block].get_by_position(column_id).column.get());
            scan_positions.emplace_back(block_idx);
        }
        dst_col->insert_from_multi_column(scan_src_columns, scan_positions);
    }
}

Status RowIdStorageReader::read_by_rowids(const PMultiGetRequest& request,
                                          PMultiGetResponse* response) {
    // read from storage engine row id by row id
    OlapReaderStatistics stats;
    Block result_block;
    int64_t acquire_tablet_ms = 0;
    int64_t acquire_rowsets_ms = 0;
    int64_t acquire_segments_ms = 0;
    int64_t lookup_row_data_ms = 0;

    // init desc
    std::vector<SlotDescriptor> slots;
    slots.reserve(request.slots().size());
    for (const auto& pslot : request.slots()) {
        slots.push_back(SlotDescriptor(pslot));
    }

    // init read schema
    TabletSchema full_read_schema;
    for (const ColumnPB& column_pb : request.column_desc()) {
        full_read_schema.append_column(TabletColumn(column_pb));
    }

    std::unordered_map<IteratorKey, IteratorItem, HashOfIteratorKey> iterator_map;
    // read row by row
    for (int i = 0; i < request.row_locs_size(); ++i) {
        const auto& row_loc = request.row_locs(i);
        MonotonicStopWatch watch;
        watch.start();
        BaseTabletSPtr tablet = scope_timer_run(
                [&]() {
                    auto res = ExecEnv::get_tablet(row_loc.tablet_id(), nullptr, true);
                    return !res.has_value() ? nullptr
                                            : std::dynamic_pointer_cast<BaseTablet>(res.value());
                },
                &acquire_tablet_ms);
        RowsetId rowset_id;
        rowset_id.init(row_loc.rowset_id());
        if (!tablet) {
            continue;
        }
        // We ensured it's rowset is not released when init Tablet reader param, rowset->update_delayed_expired_timestamp();
        BetaRowsetSharedPtr rowset = std::static_pointer_cast<BetaRowset>(scope_timer_run(
                [&]() {
                    return ExecEnv::GetInstance()->storage_engine().get_quering_rowset(rowset_id);
                },
                &acquire_rowsets_ms));
        if (!rowset) {
            LOG(INFO) << "no such rowset " << rowset_id;
            continue;
        }
        size_t row_size = 0;
        Defer _defer([&]() {
            LOG_EVERY_N(INFO, 100)
                    << "multiget_data single_row, cost(us):" << watch.elapsed_time() / 1000
                    << ", row_size:" << row_size;
            *response->add_row_locs() = row_loc;
        });
        // TODO: supoort session variable enable_page_cache and disable_file_cache if necessary.
        SegmentCacheHandle segment_cache;
        RETURN_IF_ERROR(scope_timer_run(
                [&]() {
                    return SegmentLoader::instance()->load_segments(rowset, &segment_cache, true);
                },
                &acquire_segments_ms));
        // find segment
        auto it = std::find_if(segment_cache.get_segments().cbegin(),
                               segment_cache.get_segments().cend(),
                               [&row_loc](const segment_v2::SegmentSharedPtr& seg) {
                                   return seg->id() == row_loc.segment_id();
                               });
        if (it == segment_cache.get_segments().end()) {
            continue;
        }
        segment_v2::SegmentSharedPtr segment = *it;
        GlobalRowLoacation row_location(row_loc.tablet_id(), rowset->rowset_id(),
                                        cast_set<uint32_t>(row_loc.segment_id()),
                                        cast_set<uint32_t>(row_loc.ordinal_id()));
        // fetch by row store, more effcient way
        if (request.fetch_row_store()) {
            if (!tablet->tablet_schema()->has_row_store_for_all_columns()) {
                return Status::InternalError("Tablet {} does not have row store for all columns",
                                             tablet->tablet_id());
            }
            RowLocation loc(rowset_id, segment->id(), cast_set<uint32_t>(row_loc.ordinal_id()));
            std::string* value = response->add_binary_row_data();
            RETURN_IF_ERROR(scope_timer_run(
                    [&]() { return tablet->lookup_row_data({}, loc, rowset, stats, *value); },
                    &lookup_row_data_ms));
            row_size = value->size();
            continue;
        }

        // fetch by column store
        if (result_block.is_empty_column()) {
            result_block = Block(slots, request.row_locs().size());
        }
        VLOG_DEBUG << "Read row location "
                   << fmt::format("{}, {}, {}, {}", row_location.tablet_id,
                                  row_location.row_location.rowset_id.to_string(),
                                  row_location.row_location.segment_id,
                                  row_location.row_location.row_id);
        for (int x = 0; x < slots.size(); ++x) {
            std::vector<segment_v2::rowid_t> row_ids {
                    static_cast<segment_v2::rowid_t>(row_loc.ordinal_id())};
            MutableColumnPtr column = result_block.get_by_position(x).column->assert_mutable();
            IteratorKey iterator_key {.tablet_id = tablet->tablet_id(),
                                      .rowset_id = rowset_id,
                                      .segment_id = row_loc.segment_id(),
                                      .slot_id = slots[x].id()};
            IteratorItem& iterator_item = iterator_map[iterator_key];
            if (iterator_item.segment == nullptr) {
                // hold the reference
                iterator_map[iterator_key].segment = segment;
                iterator_item.storage_read_options.stats = &stats;
                iterator_item.storage_read_options.io_ctx.reader_type = ReaderType::READER_QUERY;
            }
            segment = iterator_item.segment;
            set_slot_access_paths(slots[x], full_read_schema, iterator_item.storage_read_options);
            RETURN_IF_ERROR(segment->seek_and_read_by_rowid(
                    full_read_schema, &slots[x], row_ids, column,
                    iterator_item.storage_read_options, iterator_item.iterator));
        }
    }
    // serialize block if not empty
    if (!result_block.is_empty_column()) {
        VLOG_DEBUG << "dump block:" << result_block.dump_data(0, 10)
                   << ", be_exec_version:" << request.be_exec_version();
        [[maybe_unused]] size_t compressed_size = 0;
        [[maybe_unused]] size_t uncompressed_size = 0;
        [[maybe_unused]] int64_t compress_time = 0;
        int be_exec_version = request.has_be_exec_version() ? request.be_exec_version() : 0;
        RETURN_IF_ERROR(result_block.serialize(be_exec_version, response->mutable_block(),
                                               &uncompressed_size, &compressed_size, &compress_time,
                                               segment_v2::CompressionTypePB::LZ4));
    }

    LOG(INFO) << "Query stats: "
              << fmt::format(
                         "query_id:{}, "
                         "hit_cached_pages:{}, total_pages_read:{}, compressed_bytes_read:{}, "
                         "io_latency:{}ns, "
                         "uncompressed_bytes_read:{},"
                         "bytes_read:{},"
                         "acquire_tablet_ms:{}, acquire_rowsets_ms:{}, acquire_segments_ms:{}, "
                         "lookup_row_data_ms:{}",
                         print_id(request.query_id()), stats.cached_pages_num,
                         stats.total_pages_num, stats.compressed_bytes_read, stats.io_ns,
                         stats.uncompressed_bytes_read, stats.bytes_read, acquire_tablet_ms,
                         acquire_rowsets_ms, acquire_segments_ms, lookup_row_data_ms);
    return Status::OK();
}

Status RowIdStorageReader::read_by_rowids(const PMultiGetRequestV2& request,
                                          PMultiGetResponseV2* response) {
    if (request.request_block_descs_size()) {
        auto tquery_id = ((UniqueId)request.query_id()).to_thrift();
        // todo: use mutableBlock instead of block
        std::vector<Block> result_blocks(request.request_block_descs_size());

        OlapReaderStatistics stats;
        int64_t acquire_tablet_ms = 0;
        int64_t acquire_rowsets_ms = 0;
        int64_t acquire_segments_ms = 0;
        int64_t lookup_row_data_ms = 0;

        int64_t external_init_reader_avg_ms = 0;
        int64_t external_get_block_avg_ms = 0;
        size_t external_scan_range_cnt = 0;

        // Add counters for different file mapping types
        std::unordered_map<FileMappingType, int64_t> file_type_counts;

        auto id_file_map =
                ExecEnv::GetInstance()->get_id_manager()->get_id_file_map(request.query_id());
        // if id_file_map is null, means the BE not have scan range, just return ok
        if (!id_file_map) {
            // padding empty block to response
            LOG(INFO) << "id_file_map not found for query_id: " << print_id(request.query_id());
            for (int i = 0; i < request.request_block_descs_size(); ++i) {
                response->add_blocks();
            }
            return Status::OK();
        }

        for (int i = 0; i < request.request_block_descs_size(); ++i) {
            const auto& request_block_desc = request.request_block_descs(i);
            PMultiGetBlockV2* pblock = response->add_blocks();
            if (request_block_desc.row_id_size() >= 1) {
                // Since this block belongs to the same table, we only need to take the first type for judgment.
                auto first_file_id = request_block_desc.file_id(0);
                auto first_file_mapping = id_file_map->get_file_mapping(first_file_id);
                if (!first_file_mapping) {
                    return Status::InternalError(
                            "Backend:{} file_mapping not found, query_id: {}, file_id: {}",
                            BackendOptions::get_localhost(), print_id(request.query_id()),
                            first_file_id);
                }
                file_type_counts[first_file_mapping->type] += request_block_desc.row_id_size();

                // prepare slots to build block
                std::vector<SlotDescriptor> slots;
                slots.reserve(request_block_desc.slots_size());
                for (const auto& pslot : request_block_desc.slots()) {
                    slots.push_back(SlotDescriptor(pslot));
                }
                try {
                    if (first_file_mapping->type == FileMappingType::INTERNAL) {
                        RETURN_IF_ERROR(read_batch_doris_format_row(
                                request_block_desc, id_file_map, slots, tquery_id, result_blocks[i],
                                stats, &acquire_tablet_ms, &acquire_rowsets_ms,
                                &acquire_segments_ms, &lookup_row_data_ms));
                    } else {
                        RETURN_IF_ERROR(read_batch_external_row(
                                request.wg_id(), request_block_desc, id_file_map, slots,
                                first_file_mapping, tquery_id, result_blocks[i],
                                pblock->mutable_profile(), &external_init_reader_avg_ms,
                                &external_get_block_avg_ms, &external_scan_range_cnt));
                    }
                } catch (const Exception& e) {
                    return Status::Error<false>(e.code(), "Row id fetch failed because {}",
                                                e.what());
                }
            }

            [[maybe_unused]] size_t compressed_size = 0;
            [[maybe_unused]] size_t uncompressed_size = 0;
            [[maybe_unused]] int64_t compress_time = 0;
            int be_exec_version = request.has_be_exec_version() ? request.be_exec_version() : 0;
            RETURN_IF_ERROR(result_blocks[i].serialize(
                    be_exec_version, pblock->mutable_block(), &uncompressed_size, &compressed_size,
                    &compress_time, segment_v2::CompressionTypePB::LZ4));
        }

        // Build file type statistics string
        std::string file_type_stats;
        for (const auto& [type, count] : file_type_counts) {
            if (!file_type_stats.empty()) {
                file_type_stats += ", ";
            }
            file_type_stats += fmt::format("{}:{}", type, count);
        }

        LOG(INFO) << "Query stats: "
                  << fmt::format(
                             "query_id:{}, "
                             "Internal table:"
                             "hit_cached_pages:{}, total_pages_read:{}, compressed_bytes_read:{}, "
                             "io_latency:{}ns, uncompressed_bytes_read:{}, bytes_read:{}, "
                             "acquire_tablet_ms:{}, acquire_rowsets_ms:{}, acquire_segments_ms:{}, "
                             "lookup_row_data_ms:{}, file_types:[{}]; "
                             "External table : init_reader_ms:{}, get_block_ms:{}, "
                             "external_scan_range_cnt:{}",
                             print_id(request.query_id()), stats.cached_pages_num,
                             stats.total_pages_num, stats.compressed_bytes_read, stats.io_ns,
                             stats.uncompressed_bytes_read, stats.bytes_read, acquire_tablet_ms,
                             acquire_rowsets_ms, acquire_segments_ms, lookup_row_data_ms,
                             file_type_stats, external_init_reader_avg_ms,
                             external_get_block_avg_ms, external_scan_range_cnt);
    }

    return Status::OK();
}

Status RowIdStorageReader::read_batch_doris_format_row(
        const PRequestBlockDesc& request_block_desc, std::shared_ptr<IdFileMap> id_file_map,
        std::vector<SlotDescriptor>& slots, const TUniqueId& query_id, Block& result_block,
        OlapReaderStatistics& stats, int64_t* acquire_tablet_ms, int64_t* acquire_rowsets_ms,
        int64_t* acquire_segments_ms, int64_t* lookup_row_data_ms) {
    if (result_block.is_empty_column()) [[likely]] {
        result_block = Block(slots, request_block_desc.row_id_size());
    }
    TabletSchema full_read_schema;
    for (const ColumnPB& column_pb : request_block_desc.column_descs()) {
        full_read_schema.append_column(TabletColumn(column_pb));
    }

    std::unordered_map<IteratorKey, IteratorItem, HashOfIteratorKey> iterator_map;
    std::unordered_map<SegKey, SegItem, HashOfSegKey> seg_map;
    std::string row_store_buffer;
    RowStoreReadStruct row_store_read_struct(row_store_buffer);
    if (request_block_desc.fetch_row_store()) {
        for (int i = 0; i < request_block_desc.slots_size(); ++i) {
            row_store_read_struct.serdes.emplace_back(slots[i].get_data_type_ptr()->get_serde());
            row_store_read_struct.col_uid_to_idx[slots[i].col_unique_id()] = i;
            row_store_read_struct.default_values.emplace_back(slots[i].col_default_value());
        }
    }

    // Phase 1: Group all row_ids by their (tablet_id, rowset_id, segment_id) key.
    // Unlike the old code which only batched adjacent rows with the same file_id,
    // this merges non-contiguous same-segment requests into a single batch,
    // maximizing the number of rows read per seek_and_read_by_rowid call.
    std::vector<DorisFormatReadBatch> scan_batches;
    std::unordered_map<SegKey, size_t, HashOfSegKey> batch_idx_by_seg;
    // (batch_idx, position_in_batch) for each row in the original request.
    std::vector<std::pair<size_t, size_t>> row_id_block_idx(request_block_desc.row_id_size());
    for (int j = 0; j < request_block_desc.row_id_size(); ++j) {
        auto file_id = request_block_desc.file_id(j);
        auto file_mapping = id_file_map->get_file_mapping(file_id);
        if (!file_mapping) {
            return Status::InternalError(
                    "Backend:{} file_mapping not found, query_id: {}, file_id: {}",
                    BackendOptions::get_localhost(), print_id(query_id), file_id);
        }

        // Derive segment key and group by it — rows from the same segment are batched together
        // even if they are interleaved with rows from other segments in the request.
        auto [tablet_id, rowset_id, segment_id] = file_mapping->get_doris_format_info();
        SegKey seg_key {.tablet_id = tablet_id, .rowset_id = rowset_id, .segment_id = segment_id};
        auto [it, inserted] = batch_idx_by_seg.emplace(seg_key, scan_batches.size());
        if (inserted) {
            // First time seeing this segment, create a new batch for it.
            scan_batches.emplace_back();
            scan_batches.back().file_mapping = file_mapping;
        }
        // Record (row_id, original_request_index) for later sorting and scattering.
        scan_batches[it->second].row_ids_with_positions.emplace_back(request_block_desc.row_id(j),
                                                                     j);
    }

    // Phase 2: For each segment, sort row_ids ascending (required by ColumnIterator),
    // deduplicate, then read all rows in a single batch call.
    std::vector<Block> scan_blocks(scan_batches.size());
    for (size_t batch_idx = 0; batch_idx < scan_batches.size(); ++batch_idx) {
        auto& scan_batch = scan_batches[batch_idx];
        auto& row_ids_with_positions = scan_batch.row_ids_with_positions;
        std::sort(row_ids_with_positions.begin(), row_ids_with_positions.end(),
                  [](const auto& lhs, const auto& rhs) { return lhs.first < rhs.first; });

        // Column iterators read rowids monotonically. Deduplicate consecutive identical row_ids
        // (different file_ids may map to the same row), then scatter rows back to their original
        // request positions.
        std::vector<uint32_t> row_ids;
        row_ids.reserve(row_ids_with_positions.size());

        // Also builds the scatter map: row_id_block_idx[original_request_idx] ->
        // (batch_idx, deduplicated_position_in_batch).
        for (const auto& [row_id, result_idx] : row_ids_with_positions) {
            if (row_ids.empty() || row_ids.back() != row_id) {
                row_ids.emplace_back(row_id);
            }
            row_id_block_idx[result_idx] = std::make_pair(batch_idx, row_ids.size() - 1);
        }

        scan_blocks[batch_idx] = Block(slots, row_ids.size());
        RETURN_IF_ERROR(read_doris_format_row(id_file_map, scan_batch.file_mapping, row_ids, slots,
                                              full_read_schema, row_store_read_struct, stats,
                                              acquire_tablet_ms, acquire_rowsets_ms,
                                              acquire_segments_ms, lookup_row_data_ms, seg_map,
                                              iterator_map, scan_blocks[batch_idx]));
    }

    scatter_scan_blocks_to_result_block(row_id_block_idx, scan_blocks, result_block);

    return Status::OK();
}

const std::string RowIdStorageReader::ScannersRunningTimeProfile = "ScannersRunningTime";
const std::string RowIdStorageReader::InitReaderAvgTimeProfile = "InitReaderAvgTime";
const std::string RowIdStorageReader::GetBlockAvgTimeProfile = "GetBlockAvgTime";
const std::string RowIdStorageReader::FileReadLinesProfile = "FileReadLines";

Status RowIdStorageReader::read_external_row_from_file_mapping(
        size_t idx, const std::multimap<segment_v2::rowid_t, size_t>& row_ids,
        const std::shared_ptr<FileMapping>& file_mapping, const std::vector<SlotDescriptor>& slots,
        const TUniqueId& query_id, const std::shared_ptr<RuntimeState>& runtime_state,
        std::vector<Block>& scan_blocks, std::vector<std::pair<size_t, size_t>>& row_id_block_idx,
        std::vector<RowIdStorageReader::ExternalFetchStatistics>& fetch_statistics,
        const TFileScanRangeParams& rpc_scan_params,
        const std::unordered_map<std::string, int>& colname_to_slot_id,
        std::atomic<int>& producer_count, size_t scan_rows_count,
        std::counting_semaphore<>& semaphore, std::condition_variable& cv, std::mutex& mtx,
        TupleDescriptor& tuple_desc) {
    SCOPED_ATTACH_TASK(ExecEnv::GetInstance()->rowid_storage_reader_tracker());
    signal::set_signal_task_id(query_id);

    std::list<int64_t> read_ids;
    //Generate an ordered list with the help of the orderliness of the map.
    for (const auto& [row_id, result_block_idx] : row_ids) {
        if (read_ids.empty() || read_ids.back() != row_id) {
            read_ids.emplace_back(row_id);
        }
        row_id_block_idx[result_block_idx] = std::make_pair(idx, read_ids.size() - 1);
    }

    scan_blocks[idx] = Block(slots, read_ids.size());

    auto& external_info = file_mapping->get_external_file_info();
    auto& scan_range_desc = external_info.scan_range_desc;

    // Clear to avoid reading iceberg position delete file...
    scan_range_desc.table_format_params.iceberg_params = TIcebergFileDesc {};

    // Clear to avoid reading hive transactional delete delta file...
    scan_range_desc.table_format_params.transactional_hive_params = TTransactionalHiveDesc {};

    std::unique_ptr<RuntimeProfile> sub_runtime_profile =
            std::make_unique<RuntimeProfile>("ExternalRowIDFetcher");
    {
        std::unique_ptr<FileScanner> vfile_scanner_ptr =
                FileScanner::create_unique(runtime_state.get(), sub_runtime_profile.get(),
                                           &rpc_scan_params, &colname_to_slot_id, &tuple_desc);

        RETURN_IF_ERROR(vfile_scanner_ptr->prepare_for_read_lines(scan_range_desc));
        RETURN_IF_ERROR(vfile_scanner_ptr->read_lines_from_range(
                scan_range_desc, read_ids, &scan_blocks[idx], external_info,
                &fetch_statistics[idx].init_reader_ms, &fetch_statistics[idx].get_block_ms));
    }

    auto file_read_bytes_counter =
            sub_runtime_profile->get_counter(FileScanner::FileReadBytesProfile);

    if (file_read_bytes_counter != nullptr) {
        fetch_statistics[idx].file_read_bytes = PrettyPrinter::print(
                file_read_bytes_counter->value(), file_read_bytes_counter->type());
    }

    auto file_read_times_counter =
            sub_runtime_profile->get_counter(FileScanner::FileReadTimeProfile);
    if (file_read_times_counter != nullptr) {
        fetch_statistics[idx].file_read_times = PrettyPrinter::print(
                file_read_times_counter->value(), file_read_times_counter->type());
    }

    semaphore.release();
    if (++producer_count == scan_rows_count) {
        std::lock_guard<std::mutex> lock(mtx);
        cv.notify_one();
    }
    return Status::OK();
}

Status RowIdStorageReader::read_batch_external_row(
        const uint64_t workload_group_id, const PRequestBlockDesc& request_block_desc,
        std::shared_ptr<IdFileMap> id_file_map, std::vector<SlotDescriptor>& slots,
        std::shared_ptr<FileMapping> first_file_mapping, const TUniqueId& query_id,
        Block& result_block, PRuntimeProfileTree* pprofile, int64_t* init_reader_avg_ms,
        int64_t* get_block_avg_ms, size_t* scan_range_cnt) {
    TFileScanRangeParams rpc_scan_params;
    TupleDescriptor tuple_desc(request_block_desc.desc(), false);
    std::unordered_map<std::string, int> colname_to_slot_id;
    std::shared_ptr<RuntimeState> runtime_state = nullptr;

    int max_file_scanners = 0;
    {
        if (result_block.is_empty_column()) [[likely]] {
            result_block = Block(slots, request_block_desc.row_id_size());
        }

        auto& external_info = first_file_mapping->get_external_file_info();
        int plan_node_id = external_info.plan_node_id;
        const auto& first_scan_range_desc = external_info.scan_range_desc;

        DCHECK(id_file_map->get_external_scan_params().contains(plan_node_id));
        const auto* old_scan_params = &(id_file_map->get_external_scan_params().at(plan_node_id));
        rpc_scan_params = *old_scan_params;

        rpc_scan_params.required_slots.clear();
        rpc_scan_params.column_idxs.clear();
        rpc_scan_params.slot_name_to_schema_pos.clear();

        std::set partition_name_set(first_scan_range_desc.columns_from_path_keys.begin(),
                                    first_scan_range_desc.columns_from_path_keys.end());
        for (auto slot_idx = 0; slot_idx < slots.size(); ++slot_idx) {
            auto& slot = slots[slot_idx];
            tuple_desc.add_slot(&slot);
            colname_to_slot_id.emplace(slot.col_name(), slot.id());
            TFileScanSlotInfo slot_info;
            slot_info.slot_id = slot.id();
            auto column_idx = request_block_desc.column_idxs(slot_idx);
            if (partition_name_set.contains(slot.col_name())) {
                //This is partition column.
                slot_info.is_file_slot = false;
            } else {
                rpc_scan_params.column_idxs.emplace_back(column_idx);
                slot_info.is_file_slot = true;
            }
            rpc_scan_params.default_value_of_src_slot.emplace(slot.id(), TExpr {});
            rpc_scan_params.required_slots.emplace_back(slot_info);
            rpc_scan_params.slot_name_to_schema_pos.emplace(slot.col_name(), column_idx);
        }

        const auto& query_options = id_file_map->get_query_options();
        const auto& query_globals = id_file_map->get_query_globals();
        /*
         * The scan stage needs the information in query_options to generate different behaviors according to the specific variables:
         *  query_options.hive_parquet_use_column_names, query_options.truncate_char_or_varchar_columns,query_globals.time_zone ...
         *
         * To ensure the same behavior as the scan stage, I get query_options query_globals from id_file_map, then create runtime_state
         * and pass it to vfile_scanner so that the runtime_state information is the same as the scan stage and the behavior is also consistent.
         */
        runtime_state = RuntimeState::create_shared(
                query_id, -1, query_options, query_globals, ExecEnv::GetInstance(),
                ExecEnv::GetInstance()->rowid_storage_reader_tracker());

        max_file_scanners = id_file_map->get_max_file_scanners();
    }

    // Hash(TFileRangeDesc) => { all the rows that need to be read and their positions in the result block. } +  file mapping
    // std::multimap<segment_v2::rowid_t, size_t> : The reason for using multimap is: may need the same row of data multiple times.
    std::map<std::string,
             std::pair<std::multimap<segment_v2::rowid_t, size_t>, std::shared_ptr<FileMapping>>>
            scan_rows;

    // Block corresponding to the order of `scan_rows` map.
    std::vector<Block> scan_blocks;

    // row_id (Indexing of vectors) => < In which block, which line in the block >
    std::vector<std::pair<size_t, size_t>> row_id_block_idx;

    // Count the time/bytes it takes to read each TFileRangeDesc. (for profile)
    std::vector<ExternalFetchStatistics> fetch_statistics;

    auto hash_file_range = [](const TFileRangeDesc& file_range_desc) {
        std::string value;
        value.resize(file_range_desc.path.size() + sizeof(file_range_desc.start_offset));
        auto* ptr = value.data();

        memcpy(ptr, &file_range_desc.start_offset, sizeof(file_range_desc.start_offset));
        ptr += sizeof(file_range_desc.start_offset);
        memcpy(ptr, file_range_desc.path.data(), file_range_desc.path.size());
        return value;
    };

    for (int j = 0; j < request_block_desc.row_id_size(); ++j) {
        auto file_id = request_block_desc.file_id(j);
        auto file_mapping = id_file_map->get_file_mapping(file_id);
        if (!file_mapping) {
            return Status::InternalError(
                    "Backend:{} file_mapping not found, query_id: {}, file_id: {}",
                    BackendOptions::get_localhost(), print_id(query_id), file_id);
        }

        const auto& external_info = file_mapping->get_external_file_info();
        const auto& scan_range_desc = external_info.scan_range_desc;

        auto scan_range_hash = hash_file_range(scan_range_desc);
        if (scan_rows.contains(scan_range_hash)) {
            scan_rows.at(scan_range_hash).first.emplace(request_block_desc.row_id(j), j);
        } else {
            std::multimap<segment_v2::rowid_t, size_t> tmp {{request_block_desc.row_id(j), j}};
            scan_rows.emplace(scan_range_hash, std::make_pair(tmp, file_mapping));
        }
    }

    scan_blocks.resize(scan_rows.size());
    row_id_block_idx.resize(request_block_desc.row_id_size());
    fetch_statistics.resize(scan_rows.size());

    // Get the workload group for subsequent scan task submission.
    std::vector<uint64_t> workload_group_ids;
    workload_group_ids.emplace_back(workload_group_id);
    auto wg = ExecEnv::GetInstance()->workload_group_mgr()->get_group(workload_group_ids);
    doris::TaskScheduler* exec_sched = nullptr;
    ScannerScheduler* scan_sched = nullptr;
    ScannerScheduler* remote_scan_sched = nullptr;
    wg->get_query_scheduler(&exec_sched, &scan_sched, &remote_scan_sched);
    DCHECK(remote_scan_sched);

    int64_t scan_running_time = 0;
    RETURN_IF_ERROR(scope_timer_run(
            [&]() -> Status {
                // Make sure to insert data into result_block only after all scan tasks have been executed.
                std::atomic<int> producer_count {0};
                std::condition_variable cv;
                std::mutex mtx;

                //semaphore: Limit the number of scan tasks submitted at one time
                std::counting_semaphore semaphore {max_file_scanners};

                size_t idx = 0;
                for (const auto& [_, scan_info] : scan_rows) {
                    semaphore.acquire();
                    RETURN_IF_ERROR(remote_scan_sched->submit_scan_task(
                            SimplifiedScanTask(
                                    [&, idx, scan_info]() -> Status {
                                        const auto& [row_ids, file_mapping] = scan_info;
                                        return read_external_row_from_file_mapping(
                                                idx, row_ids, file_mapping, slots, query_id,
                                                runtime_state, scan_blocks, row_id_block_idx,
                                                fetch_statistics, rpc_scan_params,
                                                colname_to_slot_id, producer_count,
                                                scan_rows.size(), semaphore, cv, mtx, tuple_desc);
                                    },
                                    nullptr, nullptr),
                            fmt::format("{}-read_batch_external_row-{}", print_id(query_id), idx)));
                    idx++;
                }

                {
                    std::unique_lock<std::mutex> lock(mtx);
                    cv.wait(lock, [&] { return producer_count == scan_rows.size(); });
                }
                return Status::OK();
            },
            &scan_running_time));

    scatter_scan_blocks_to_result_block(row_id_block_idx, scan_blocks, result_block);

    // Statistical runtime profile information.
    std::unique_ptr<RuntimeProfile> runtime_profile =
            std::make_unique<RuntimeProfile>("ExternalRowIDFetcher");
    {
        runtime_profile->add_info_string(ScannersRunningTimeProfile,
                                         std::to_string(scan_running_time) + "ms");
        fmt::memory_buffer file_read_lines_buffer;
        format_to(file_read_lines_buffer, "[");
        fmt::memory_buffer file_read_bytes_buffer;
        format_to(file_read_bytes_buffer, "[");
        fmt::memory_buffer file_read_times_buffer;
        format_to(file_read_times_buffer, "[");

        size_t idx = 0;
        for (const auto& [_, scan_info] : scan_rows) {
            format_to(file_read_lines_buffer, "{}, ", scan_info.first.size());
            *init_reader_avg_ms = fetch_statistics[idx].init_reader_ms;
            *get_block_avg_ms += fetch_statistics[idx].get_block_ms;
            format_to(file_read_bytes_buffer, "{}, ", fetch_statistics[idx].file_read_bytes);
            format_to(file_read_times_buffer, "{}, ", fetch_statistics[idx].file_read_times);
            idx++;
        }

        format_to(file_read_lines_buffer, "]");
        format_to(file_read_bytes_buffer, "]");
        format_to(file_read_times_buffer, "]");

        *init_reader_avg_ms /= fetch_statistics.size();
        *get_block_avg_ms /= fetch_statistics.size();
        runtime_profile->add_info_string(InitReaderAvgTimeProfile,
                                         std::to_string(*init_reader_avg_ms) + "ms");
        runtime_profile->add_info_string(GetBlockAvgTimeProfile,
                                         std::to_string(*init_reader_avg_ms) + "ms");
        runtime_profile->add_info_string(FileReadLinesProfile,
                                         fmt::to_string(file_read_lines_buffer));
        runtime_profile->add_info_string(FileScanner::FileReadBytesProfile,
                                         fmt::to_string(file_read_bytes_buffer));
        runtime_profile->add_info_string(FileScanner::FileReadTimeProfile,
                                         fmt::to_string(file_read_times_buffer));
    }

    runtime_profile->to_proto(pprofile, 2);

    *scan_range_cnt = scan_rows.size();

    return Status::OK();
}

Status RowIdStorageReader::read_doris_format_row(
        const std::shared_ptr<IdFileMap>& id_file_map,
        const std::shared_ptr<FileMapping>& file_mapping, const std::vector<uint32_t>& row_ids,
        std::vector<SlotDescriptor>& slots, const TabletSchema& full_read_schema,
        RowStoreReadStruct& row_store_read_struct, OlapReaderStatistics& stats,
        int64_t* acquire_tablet_ms, int64_t* acquire_rowsets_ms, int64_t* acquire_segments_ms,
        int64_t* lookup_row_data_ms, std::unordered_map<SegKey, SegItem, HashOfSegKey>& seg_map,
        std::unordered_map<IteratorKey, IteratorItem, HashOfIteratorKey>& iterator_map,
        Block& result_block) {
    auto [tablet_id, rowset_id, segment_id] = file_mapping->get_doris_format_info();
    SegKey seg_key {.tablet_id = tablet_id, .rowset_id = rowset_id, .segment_id = segment_id};

    BaseTabletSPtr tablet;
    BetaRowsetSharedPtr rowset;
    SegmentSharedPtr segment;
    if (seg_map.find(seg_key) == seg_map.end()) {
        tablet = scope_timer_run(
                [&]() {
                    auto res = ExecEnv::get_tablet(tablet_id);
                    return !res.has_value() ? nullptr
                                            : std::dynamic_pointer_cast<BaseTablet>(res.value());
                },
                acquire_tablet_ms);
        if (!tablet) {
            return Status::InternalError(
                    "Backend:{} tablet not found, tablet_id: {}, rowset_id: {}, segment_id: {}, "
                    "row_id: {}",
                    BackendOptions::get_localhost(), tablet_id, rowset_id.to_string(), segment_id,
                    row_ids[0]);
        }

        rowset = std::static_pointer_cast<BetaRowset>(scope_timer_run(
                [&]() { return id_file_map->get_temp_rowset(tablet_id, rowset_id); },
                acquire_rowsets_ms));
        if (!rowset) {
            return Status::InternalError(
                    "Backend:{} rowset_id not found, tablet_id: {}, rowset_id: {}, segment_id: {}, "
                    "row_id: {}",
                    BackendOptions::get_localhost(), tablet_id, rowset_id.to_string(), segment_id,
                    row_ids[0]);
        }

        SegmentCacheHandle segment_cache;
        RETURN_IF_ERROR(scope_timer_run(
                [&]() {
                    return SegmentLoader::instance()->load_segments(rowset, &segment_cache, true);
                },
                acquire_segments_ms));

        auto it = std::find_if(segment_cache.get_segments().cbegin(),
                               segment_cache.get_segments().cend(),
                               [segment_id](const segment_v2::SegmentSharedPtr& seg) {
                                   return seg->id() == segment_id;
                               });
        if (it == segment_cache.get_segments().end()) {
            return Status::InternalError(
                    "Backend:{} segment not found, tablet_id: {}, rowset_id: {}, segment_id: {}, "
                    "row_id: {}",
                    BackendOptions::get_localhost(), tablet_id, rowset_id.to_string(), segment_id,
                    row_ids[0]);
        }
        segment = *it;
        seg_map[seg_key] = SegItem {.tablet = tablet, .rowset = rowset, .segment = segment};
    } else {
        auto& seg_item = seg_map[seg_key];
        tablet = seg_item.tablet;
        rowset = seg_item.rowset;
        segment = seg_item.segment;
    }

    // if row_store_read_struct not empty, means the line we should read from row_store
    if (!row_store_read_struct.default_values.empty()) {
        if (!tablet->tablet_schema()->has_row_store_for_all_columns()) {
            return Status::InternalError("Tablet {} does not have row store for all columns",
                                         tablet->tablet_id());
        }
        auto result_columns_guard = result_block.mutate_columns_scoped();
        MutableColumns& result_columns = result_columns_guard.mutable_columns();
        for (auto row_id : row_ids) {
            RowLocation loc(rowset_id, segment->id(), cast_set<uint32_t>(row_id));
            row_store_read_struct.row_store_buffer.clear();
            RETURN_IF_ERROR(scope_timer_run(
                    [&]() {
                        return tablet->lookup_row_data({}, loc, rowset, stats,
                                                       row_store_read_struct.row_store_buffer);
                    },
                    lookup_row_data_ms));

            RETURN_IF_ERROR(JsonbSerializeUtil::jsonb_to_columns(
                    row_store_read_struct.serdes, row_store_read_struct.row_store_buffer.data(),
                    row_store_read_struct.row_store_buffer.size(),
                    row_store_read_struct.col_uid_to_idx, result_columns,
                    row_store_read_struct.default_values, {}));
        }
    } else {
        for (int x = 0; x < slots.size(); ++x) {
            auto column_guard = result_block.mutate_column_scoped(x);
            MutableColumnPtr& column = column_guard.mutable_column();
            IteratorKey iterator_key {.tablet_id = tablet_id,
                                      .rowset_id = rowset_id,
                                      .segment_id = segment_id,
                                      .slot_id = slots[x].id()};
            IteratorItem& iterator_item = iterator_map[iterator_key];
            if (iterator_item.segment == nullptr) {
                iterator_map[iterator_key].segment = segment;
                iterator_item.storage_read_options.stats = &stats;
                iterator_item.storage_read_options.io_ctx.reader_type = ReaderType::READER_QUERY;
            }
            set_slot_access_paths(slots[x], full_read_schema, iterator_item.storage_read_options);
            RETURN_IF_ERROR(segment->seek_and_read_by_rowid(
                    full_read_schema, &slots[x], row_ids, column,
                    iterator_item.storage_read_options, iterator_item.iterator));
        }
    }
    return Status::OK();
}

} // namespace doris
