@@ -40,6 +40,19 @@ class Schema;
4040
4141namespace paimon {
4242
43+ namespace {
44+
45+ std::pair<int64_t , int64_t > ComputeBatchSliceByReadRange (
46+ const std::vector<uint64_t >& global_row_ids, const std::pair<uint64_t , uint64_t >& read_range) {
47+ auto begin_it =
48+ std::lower_bound (global_row_ids.begin (), global_row_ids.end (), read_range.first );
49+ auto end_it = std::lower_bound (global_row_ids.begin (), global_row_ids.end (), read_range.second );
50+ return {static_cast <int64_t >(std::distance (global_row_ids.begin (), begin_it)),
51+ static_cast <int64_t >(std::distance (global_row_ids.begin (), end_it))};
52+ }
53+
54+ } // namespace
55+
4356Result<std::unique_ptr<PrefetchFileBatchReaderImpl>> PrefetchFileBatchReaderImpl::Create (
4457 const std::string& data_file_path, const ReaderBuilder* reader_builder,
4558 const std::shared_ptr<FileSystem>& fs, uint32_t prefetch_max_parallel_num, int32_t batch_size,
@@ -265,6 +278,7 @@ Status PrefetchFileBatchReaderImpl::CleanUp() {
265278
266279 read_ranges_.clear ();
267280 read_ranges_in_group_.clear ();
281+ current_batch_global_row_ids_.clear ();
268282 clean_prefetch_queue ();
269283 for (size_t i = 0 ; i < readers_pos_.size (); i++) {
270284 readers_pos_[i]->store (0 );
@@ -409,28 +423,44 @@ Status PrefetchFileBatchReaderImpl::EnsureReaderPosition(
409423Status PrefetchFileBatchReaderImpl::HandleReadResult (
410424 size_t reader_idx, const std::pair<uint64_t , uint64_t >& read_range,
411425 ReadBatchWithBitmap&& read_batch_with_bitmap) {
412- PAIMON_ASSIGN_OR_RAISE (uint64_t first_row_number,
413- readers_[reader_idx]->GetPreviousBatchFirstRowNumber ());
414426 auto & prefetch_queue = prefetch_queues_[reader_idx];
415427 if (!BatchReader::IsEofBatch (read_batch_with_bitmap)) {
416428 auto & [read_batch, bitmap] = read_batch_with_bitmap;
417429 auto & [c_array, c_schema] = read_batch;
430+ std::vector<uint64_t > global_row_ids;
431+ global_row_ids.reserve (c_array->length );
432+ for (int64_t i = 0 ; i < c_array->length ; ++i) {
433+ PAIMON_ASSIGN_OR_RAISE (uint64_t global_row_id,
434+ readers_[reader_idx]->GetPreviousBatchFileRowId (i));
435+ global_row_ids.push_back (global_row_id);
436+ }
437+ if (global_row_ids.empty ()) {
438+ ReaderUtils::ReleaseReadBatch (std::move (read_batch));
439+ return Status::OK ();
440+ }
441+ auto [slice_begin, slice_end] = ComputeBatchSliceByReadRange (global_row_ids, read_range);
442+ // slice_begin should always be 0, records before read_range.first have been consumed or
443+ // filtered out.
444+ if (slice_begin != 0 ) {
445+ return Status::Invalid (fmt::format (" Slice begin is {}, which is not 0." , slice_begin));
446+ }
418447
419- if (first_row_number >= read_range. second ) {
420- // fully out of range, data before first_row_number has been filtered out
421- readers_pos_[reader_idx]->store (first_row_number );
448+ if (0 == slice_end ) {
449+ // fully out of range, data before global_row_ids has been filtered out
450+ readers_pos_[reader_idx]->store (global_row_ids[ 0 ] );
422451 ReaderUtils::ReleaseReadBatch (std::move (read_batch));
423452 return Status::OK ();
424- } else if (first_row_number + c_array->length > read_range. second ) {
453+ } else if (slice_end < c_array->length ) {
425454 // partially out of range, data before read_range.second has been effectively consumed
426455 readers_pos_[reader_idx]->store (read_range.second );
427456 PAIMON_ASSIGN_OR_RAISE_FROM_ARROW (std::shared_ptr<arrow::Array> src_array,
428457 arrow::ImportArray (c_array.get (), c_schema.get ()));
429- int32_t target_length = read_range.second - first_row_number;
430- auto array = src_array->Slice (/* offset=*/ 0 , target_length);
458+ auto array = src_array->Slice (0 , slice_end);
431459 PAIMON_RETURN_NOT_OK_FROM_ARROW (
432460 arrow::ExportArray (*array, c_array.get (), c_schema.get ()));
433- bitmap.RemoveRange (target_length, src_array->length ());
461+ bitmap.RemoveRange (slice_end, src_array->length ());
462+ global_row_ids =
463+ std::vector<uint64_t >(global_row_ids.begin (), global_row_ids.begin () + slice_end);
434464 } else {
435465 // all within the range, data before readers_[reader_idx]->GetNextRowToRead() has been
436466 // effectively consumed
@@ -440,11 +470,12 @@ Status PrefetchFileBatchReaderImpl::HandleReadResult(
440470 ReaderUtils::ReleaseReadBatch (std::move (read_batch));
441471 return Status::OK ();
442472 }
443- prefetch_queue->push ({read_range, std::move (read_batch_with_bitmap), first_row_number});
473+ prefetch_queue->push (
474+ {read_range, std::move (read_batch_with_bitmap), std::move (global_row_ids)});
444475 } else {
445476 std::pair<uint64_t , uint64_t > eof_range;
446477 PAIMON_ASSIGN_OR_RAISE (eof_range, EofRange ());
447- prefetch_queue->push ({eof_range, std::move (read_batch_with_bitmap), first_row_number });
478+ prefetch_queue->push ({eof_range, std::move (read_batch_with_bitmap), {} });
448479 readers_pos_[reader_idx]->store (std::numeric_limits<uint64_t >::max ());
449480 }
450481 return Status::OK ();
@@ -527,7 +558,7 @@ Result<BatchReader::ReadBatchWithBitmap> PrefetchFileBatchReaderImpl::NextBatchW
527558 std::unique_lock<std::mutex> lock (working_mutex_);
528559 cv_.notify_one ();
529560 }
530- previous_batch_first_row_num_ = prefetch_batch.value ().previous_batch_first_row_num ;
561+ current_batch_global_row_ids_ = std::move ( prefetch_batch.value ().global_row_ids ) ;
531562 return std::move (prefetch_batch).value ().batch ;
532563 }
533564 }
@@ -537,7 +568,7 @@ Result<BatchReader::ReadBatchWithBitmap> PrefetchFileBatchReaderImpl::NextBatchW
537568 assert (false );
538569 return Status::Invalid (" peek batch not suppose to be nullptr" );
539570 }
540- previous_batch_first_row_num_ = peek_batch-> previous_batch_first_row_num ;
571+ current_batch_global_row_ids_. clear () ;
541572 return BatchReader::MakeEofBatchWithBitmap ();
542573 }
543574 if (value_count == prefetch_queues_.size ()) {
@@ -571,8 +602,19 @@ Result<std::unique_ptr<::ArrowSchema>> PrefetchFileBatchReaderImpl::GetFileSchem
571602 return readers_[0 ]->GetFileSchema ();
572603}
573604
574- Result<uint64_t > PrefetchFileBatchReaderImpl::GetPreviousBatchFirstRowNumber () const {
575- return previous_batch_first_row_num_;
605+ Result<uint64_t > PrefetchFileBatchReaderImpl::GetPreviousBatchFileRowId (
606+ uint64_t batch_row_id) const {
607+ if (current_batch_global_row_ids_.empty ()) {
608+ return Status::Invalid (
609+ " Last batch is not read or last batch is empty, cannot get previous batch global row "
610+ " id" );
611+ }
612+ if (batch_row_id >= current_batch_global_row_ids_.size ()) {
613+ return Status::Invalid (
614+ fmt::format (" batch_row_id {} is out of range, last batch row count is {}" , batch_row_id,
615+ current_batch_global_row_ids_.size ()));
616+ }
617+ return current_batch_global_row_ids_[batch_row_id];
576618}
577619
578620Result<uint64_t > PrefetchFileBatchReaderImpl::GetNumberOfRows () const {
0 commit comments