// 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;
};

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;
            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;
            }
            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
