Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
94c434a
test: add test cases for nested columns
zhf999 Jun 16, 2026
4cdf107
Merge branch 'main' into nested-col-fallback
zhf999 Jun 17, 2026
30ea1d8
walkaround: fallback nested field to RowGroup reading
zhf999 Jun 17, 2026
bed9fdf
style: add comments
zhf999 Jun 17, 2026
dfe419d
fix: judge has_nested_field on read-schema
zhf999 Jun 17, 2026
2ceaf60
fix: make tests clearer
zhf999 Jun 17, 2026
cb1a632
feat: support page-level bitmap pushdown
zhf999 Jun 17, 2026
9a5f4ee
fix: fallback bitmap pushdown to rowgroup-level
zhf999 Jun 17, 2026
09d2121
style: update tests names
zhf999 Jun 17, 2026
3ea428d
stye: update comments
zhf999 Jun 17, 2026
76e7282
fix: set 'SupportPreciseBitmapSelection to true'
zhf999 Jun 17, 2026
72be706
Merge branch 'main' into paged-bitmap2
zhf999 Jun 18, 2026
8078ca4
fxi: set 'SupportPreciseBitmapSelection to false'
zhf999 Jun 18, 2026
48cd610
fix: add assign operator for TargetRowGroup
zhf999 Jun 22, 2026
246e854
fix: use PARQUET_READ_ENABLE_PAGE_INDEX_FILTER to control bitmap filt…
zhf999 Jun 22, 2026
d9c952d
fix: use bitmap to get row ranges instead of the first column with pa…
zhf999 Jun 22, 2026
1c495e4
fix: test
zhf999 Jun 22, 2026
5d534db
fix: FileBatchReader returns discontinuous batch, and change GetPrevi…
zhf999 Jun 26, 2026
ad03498
style: change interface name
zhf999 Jun 26, 2026
cd7bd44
update header files
zhf999 Jun 26, 2026
f9721a8
Merge branch 'main' into fix-rowid
zhf999 Jun 26, 2026
41f932d
fix: return Status::Invalid intead of returning max value
zhf999 Jun 26, 2026
6bd98d8
fix: lance and blob return NotImplemented
zhf999 Jun 26, 2026
a694567
fix: add inclusive extend for fully matched rowgroup in SetReadSchema
zhf999 Jun 26, 2026
eb48e42
fix: calling SetReadSchema many time do not clear row_mapping
zhf999 Jun 26, 2026
7b00794
test: add test for PrefetchFileBatchReaderImpl
zhf999 Jun 26, 2026
5b28d56
Merge branch 'main' into fix-rowid
zhf999 Jun 26, 2026
0d9a174
style: replace auto in assigning macro with explicit type
zhf999 Jun 26, 2026
7edf5c1
Merge branch 'main' into paged-bitmap2
zhf999 Jun 26, 2026
09c3ef5
fix: mismatched Create function call
zhf999 Jun 26, 2026
17a3e90
Merge branch 'fix-rowid' into paged-bitmap-tmp
zhf999 Jun 26, 2026
1336922
style: rename interfaces and parameters
zhf999 Jun 29, 2026
8f82f44
fix: use a more efficient way to apply bitmap
zhf999 Jun 29, 2026
d3b73e1
update headers
zhf999 Jun 29, 2026
fcc1ac8
fix: use iterator to apply bitmap
zhf999 Jun 29, 2026
0fb2dec
test: add assertion
zhf999 Jun 29, 2026
a3e37bd
test: use '.value()' directly to validate the result.
zhf999 Jun 29, 2026
8820e7c
update comments
zhf999 Jun 29, 2026
376a312
style: change method name
zhf999 Jun 29, 2026
f1c02db
fix: small fixes
zhf999 Jun 29, 2026
ad66b22
fix: blob test
zhf999 Jun 29, 2026
25ef3d0
fix: blob and lance tests
zhf999 Jun 29, 2026
4409afb
fix: unittest
zhf999 Jun 29, 2026
5bdca4a
Merge branch 'fix-rowid' into paged-bitmap-tmp
zhf999 Jun 29, 2026
8482e90
fix: blob
zhf999 Jun 29, 2026
a2d7036
Merge branch 'fix-rowid' into paged-bitmap-tmp
zhf999 Jun 29, 2026
9e2ed67
feat: use java-like bitmap pushing down stratagy
zhf999 Jul 6, 2026
2e8365c
fix: bitmap filtering logic
zhf999 Jul 6, 2026
a27a87e
style: modify function interfaces and comments
zhf999 Jul 6, 2026
d780597
test: add test
zhf999 Jul 6, 2026
cfe72e9
refractor
zhf999 Jul 6, 2026
8b96b96
Merge branch 'main' into paged-bitmap2
zhf999 Jul 6, 2026
3a132b6
resolve conflics
zhf999 Jul 6, 2026
37b8989
fix: enable page level filtering in parquet_file_batch_reader_test.cpp
zhf999 Jul 6, 2026
acd3912
Merge branch 'main' into paged-bitmap2
zhf999 Jul 6, 2026
becc3a8
update comments
zhf999 Jul 7, 2026
1244b5f
code style
zhf999 Jul 8, 2026
15f7158
pre-commit
zhf999 Jul 8, 2026
7c9dc47
style comment
zhf999 Jul 9, 2026
3be534b
modify for pr review 1
zhf999 Jul 9, 2026
74c658d
fix: modify for pr review 2
zhf999 Jul 9, 2026
bc53d6a
fix: comments
zhf999 Jul 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/paimon/utils/roaring_bitmap32.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <cstddef>
#include <cstdint>
#include <limits>
#include <optional>
#include <string>
#include <vector>

Expand Down Expand Up @@ -135,6 +136,10 @@ class PAIMON_EXPORT RoaringBitmap32 {
Iterator End() const;
/// @return the iterator moved to the value which is equal or larger than key
Iterator EqualOrLarger(int32_t key) const;
/// @return the first value which is equal or larger than x
std::optional<int32_t> NextValue(int32_t x) const;
/// @return the largest value which is smaller than x
std::optional<int32_t> PreviousValue(int32_t x) const;

/// Computes the intersection between two bitmaps and returns new bitmap.
/// The current bitmap and the provided bitmap are unchanged.
Expand Down
29 changes: 29 additions & 0 deletions src/paimon/common/utils/roaring_bitmap32.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,4 +310,33 @@ RoaringBitmap32::Iterator RoaringBitmap32::EqualOrLarger(int32_t key) const {
return iter;
}

std::optional<int32_t> RoaringBitmap32::NextValue(int32_t x) const {
auto iter = EqualOrLarger(x);
if (iter == End()) {
return std::nullopt;
}
return *iter;
}

std::optional<int32_t> RoaringBitmap32::PreviousValue(int32_t x) const {
if (IsEmpty()) {
return std::nullopt;
}

auto& bitmap = GetRoaringBitmap(roaring_bitmap_);
if (x <= static_cast<int32_t>(bitmap.minimum())) {
return std::nullopt;
}

const uint64_t rank = bitmap.rank(static_cast<uint32_t>(x - 1));
if (rank == 0) {
return std::nullopt;
}

uint32_t value = 0;
[[maybe_unused]] bool found = bitmap.select(static_cast<uint32_t>(rank - 1), &value);
assert(found);
return static_cast<int32_t>(value);
}

} // namespace paimon
19 changes: 19 additions & 0 deletions src/paimon/common/utils/roaring_bitmap32_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,25 @@ TEST(RoaringBitmap32Test, TestIterator) {
ASSERT_EQ(iter, roaring.End());
}

TEST(RoaringBitmap32Test, TestNextAndPreviousValue) {
RoaringBitmap32 roaring = RoaringBitmap32::From({10, 20, 30});

ASSERT_EQ(roaring.NextValue(5), std::optional<int32_t>(10));
ASSERT_EQ(roaring.NextValue(10), std::optional<int32_t>(10));
ASSERT_EQ(roaring.NextValue(25), std::optional<int32_t>(30));
ASSERT_EQ(roaring.NextValue(31), std::nullopt);

ASSERT_EQ(roaring.PreviousValue(10), std::nullopt);
ASSERT_EQ(roaring.PreviousValue(11), std::optional<int32_t>(10));
ASSERT_EQ(roaring.PreviousValue(20), std::optional<int32_t>(10));
ASSERT_EQ(roaring.PreviousValue(21), std::optional<int32_t>(20));
ASSERT_EQ(roaring.PreviousValue(100), std::optional<int32_t>(30));

RoaringBitmap32 empty;
ASSERT_EQ(empty.NextValue(0), std::nullopt);
ASSERT_EQ(empty.PreviousValue(0), std::nullopt);
}

TEST(RoaringBitmap32Test, TestIteratorAssignAndMove) {
RoaringBitmap32 roaring = RoaringBitmap32::From({10, 100, 200});

Expand Down
44 changes: 23 additions & 21 deletions src/paimon/format/parquet/file_reader_wrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -164,14 +164,15 @@ void FileReaderWrapper::AdvanceToNextRowGroup() {
current_row_group_idx_++;
// Skip row groups excluded by read range.
while (current_row_group_idx_ < target_row_groups_.size() &&
target_row_groups_[current_row_group_idx_].excluded_by_read_range) {
target_row_groups_[current_row_group_idx_].IsExcludedByReadRange()) {
current_row_group_idx_++;
}
if (current_row_group_idx_ >= target_row_groups_.size()) {
next_row_to_read_ = num_rows_;
} else {
next_row_to_read_ =
all_row_group_ranges_[target_row_groups_[current_row_group_idx_].row_group_index].first;
all_row_group_ranges_[target_row_groups_[current_row_group_idx_].GetRowGroupIndex()]
.first;
}
}

Expand All @@ -181,10 +182,10 @@ Status FileReaderWrapper::SeekToRow(uint64_t row_number) {
filtered_global_offset_ = 0;

for (uint64_t i = 0; i < target_row_groups_.size(); i++) {
if (target_row_groups_[i].excluded_by_read_range) {
if (target_row_groups_[i].IsExcludedByReadRange()) {
continue;
}
int32_t rg_id = target_row_groups_[i].row_group_index;
int32_t rg_id = target_row_groups_[i].GetRowGroupIndex();
uint64_t rg_start = all_row_group_ranges_[rg_id].first;
uint64_t rg_end = all_row_group_ranges_[rg_id].second;
if (row_number > rg_start && row_number < rg_end) {
Expand All @@ -200,9 +201,9 @@ Status FileReaderWrapper::SeekToRow(uint64_t row_number) {
// Rebuild batch_reader_ for non-page-filtered RGs at/after seek position.
std::vector<int32_t> fully_matched_indices;
for (uint64_t j = i; j < target_row_groups_.size(); j++) {
if (!target_row_groups_[j].excluded_by_read_range &&
!target_row_groups_[j].is_partially_matched) {
fully_matched_indices.push_back(target_row_groups_[j].row_group_index);
if (!target_row_groups_[j].IsExcludedByReadRange() &&
!target_row_groups_[j].IsPartiallyMatched()) {
fully_matched_indices.push_back(target_row_groups_[j].GetRowGroupIndex());
}
}
if (!fully_matched_indices.empty()) {
Expand All @@ -222,7 +223,7 @@ Status FileReaderWrapper::SeekToRow(uint64_t row_number) {
}

Result<std::shared_ptr<arrow::RecordBatch>> FileReaderWrapper::NextPageFiltered() {
int32_t rg_id = target_row_groups_[current_row_group_idx_].row_group_index;
int32_t rg_id = target_row_groups_[current_row_group_idx_].GetRowGroupIndex();

// Construct the per-RG streaming reader on demand.
if (!current_page_filtered_reader_) {
Expand All @@ -237,7 +238,7 @@ Result<std::shared_ptr<arrow::RecordBatch>> FileReaderWrapper::NextPageFiltered(
file_reader_->parquet_reader(), target_rg, target_column_indices_,
page_filtered_read_schema_, file_reader_->properties().cache_options(),
pre_buffered, page_ranges, max_chunksize, pool_));
current_filtered_row_ranges_ = target_rg.row_ranges;
current_filtered_row_ranges_ = target_rg.GetRowRanges();
current_filtered_rg_start_ = all_row_group_ranges_[rg_id].first;
filtered_global_offset_ = 0;
}
Expand Down Expand Up @@ -273,7 +274,7 @@ Result<std::shared_ptr<arrow::RecordBatch>> FileReaderWrapper::NextFullyMatched(
return std::shared_ptr<arrow::RecordBatch>();
}

int32_t rg_id = target_row_groups_[current_row_group_idx_].row_group_index;
int32_t rg_id = target_row_groups_[current_row_group_idx_].GetRowGroupIndex();
uint64_t rg_end = all_row_group_ranges_[rg_id].second;
int64_t num_rows = record_batch->num_rows();

Expand All @@ -298,7 +299,7 @@ Result<std::shared_ptr<arrow::RecordBatch>> FileReaderWrapper::Next() {

while (current_row_group_idx_ < target_row_groups_.size()) {
bool is_partially_matched =
target_row_groups_[current_row_group_idx_].is_partially_matched;
target_row_groups_[current_row_group_idx_].IsPartiallyMatched();
PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<arrow::RecordBatch> batch,
is_partially_matched ? NextPageFiltered() : NextFullyMatched());
if (batch) {
Expand Down Expand Up @@ -368,17 +369,17 @@ std::vector<::arrow::io::ReadRange> FileReaderWrapper::CollectPreBufferRanges(
auto file_metadata = file_reader_->parquet_reader()->metadata();

for (const auto& trg : target_row_groups_) {
if (trg.excluded_by_read_range) continue;
if (trg.IsExcludedByReadRange()) continue;

if (trg.is_partially_matched) {
if (trg.IsPartiallyMatched()) {
// Page-filtered RGs: only matching page byte ranges.
auto page_ranges = PageFilteredRowGroupReader::ComputePageRanges(
file_reader_->parquet_reader(), trg, column_indices);
ranges.insert(ranges.end(), std::make_move_iterator(page_ranges.begin()),
std::make_move_iterator(page_ranges.end()));
} else {
// Fully-matched RGs: entire column chunk ranges.
auto rg_metadata = file_metadata->RowGroup(trg.row_group_index);
auto rg_metadata = file_metadata->RowGroup(trg.GetRowGroupIndex());
for (int32_t col_idx : column_indices) {
auto col_chunk = rg_metadata->ColumnChunk(col_idx);
int64_t offset = col_chunk->data_page_offset();
Expand Down Expand Up @@ -416,12 +417,12 @@ Status FileReaderWrapper::PrepareForReading(const std::vector<TargetRowGroup>& t
std::vector<int32_t> fully_matched_row_groups;
uint64_t active_count = 0;
for (const auto& trg : target_row_groups_) {
if (trg.excluded_by_read_range) {
if (trg.IsExcludedByReadRange()) {
continue;
}
active_count++;
if (!trg.is_partially_matched) {
fully_matched_row_groups.push_back(trg.row_group_index);
if (!trg.IsPartiallyMatched()) {
fully_matched_row_groups.push_back(trg.GetRowGroupIndex());
}
}

Expand Down Expand Up @@ -455,14 +456,15 @@ Status FileReaderWrapper::PrepareForReading(const std::vector<TargetRowGroup>& t
// Reset read state. Find the first non-excluded row group.
uint64_t first_active_idx = 0;
while (first_active_idx < target_row_groups_.size() &&
target_row_groups_[first_active_idx].excluded_by_read_range) {
target_row_groups_[first_active_idx].IsExcludedByReadRange()) {
first_active_idx++;
}
if (first_active_idx >= target_row_groups_.size()) {
next_row_to_read_ = num_rows_;
} else {
next_row_to_read_ =
all_row_group_ranges_[target_row_groups_[first_active_idx].row_group_index].first;
all_row_group_ranges_[target_row_groups_[first_active_idx].GetRowGroupIndex()]
.first;
}
previous_first_row_ = std::numeric_limits<uint64_t>::max();
current_row_group_idx_ = first_active_idx;
Expand All @@ -476,7 +478,7 @@ Status FileReaderWrapper::ApplyReadRanges(
const std::vector<std::pair<uint64_t, uint64_t>>& read_ranges) {
if (read_ranges.empty()) {
for (auto& trg : target_row_groups_) {
trg.excluded_by_read_range = true;
trg.SetExcludedByReadRange(true);
}
reader_initialized_ = false;
return Status::OK();
Expand All @@ -492,7 +494,7 @@ Status FileReaderWrapper::ApplyReadRanges(
}
// Mark each target row group as excluded or not based on the matching set.
for (auto& trg : target_row_groups_) {
trg.excluded_by_read_range = matching_rg_indices.count(trg.row_group_index) == 0;
trg.SetExcludedByReadRange(matching_rg_indices.count(trg.GetRowGroupIndex()) == 0);
}
reader_initialized_ = false;
return Status::OK();
Expand Down
1 change: 1 addition & 0 deletions src/paimon/format/parquet/file_reader_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "arrow/type_fwd.h"
#include "paimon/common/utils/arrow/status_utils.h"
#include "paimon/format/parquet/row_ranges.h"
#include "paimon/format/parquet/target_row_group.h"
#include "paimon/result.h"
#include "paimon/status.h"
#include "parquet/arrow/reader.h"
Expand Down
8 changes: 4 additions & 4 deletions src/paimon/format/parquet/page_filtered_row_group_reader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,8 @@ Result<std::unique_ptr<arrow::RecordBatchReader>> PageFilteredRowGroupReader::Re
const ::arrow::io::CacheOptions& cache_options, bool pre_buffered,
const std::vector<::arrow::io::ReadRange>& page_ranges, int64_t max_chunksize,
std::shared_ptr<::arrow::MemoryPool> pool) {
const auto& row_ranges = target_row_group.row_ranges;
int32_t row_group_index = target_row_group.row_group_index;
const auto& row_ranges = target_row_group.GetRowRanges();
int32_t row_group_index = target_row_group.GetRowGroupIndex();

if (row_ranges.IsEmpty()) {
PAIMON_ASSIGN_OR_RAISE_FROM_ARROW(std::shared_ptr<arrow::Table> empty_table,
Expand Down Expand Up @@ -289,8 +289,8 @@ Result<std::unique_ptr<arrow::RecordBatchReader>> PageFilteredRowGroupReader::Re
std::vector<::arrow::io::ReadRange> PageFilteredRowGroupReader::ComputePageRanges(
::parquet::ParquetFileReader* parquet_reader, const TargetRowGroup& target_row_group,
const std::vector<int32_t>& column_indices) {
int32_t row_group_index = target_row_group.row_group_index;
const auto& row_ranges = target_row_group.row_ranges;
int32_t row_group_index = target_row_group.GetRowGroupIndex();
const auto& row_ranges = target_row_group.GetRowRanges();

std::vector<::arrow::io::ReadRange> ranges;
auto file_metadata = parquet_reader->metadata();
Expand Down
1 change: 1 addition & 0 deletions src/paimon/format/parquet/page_filtered_row_group_reader.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "arrow/record_batch.h"
#include "arrow/type.h"
#include "paimon/format/parquet/row_ranges.h"
#include "paimon/format/parquet/target_row_group.h"
#include "paimon/result.h"
#include "parquet/column_reader.h"
#include "parquet/file_reader.h"
Expand Down
Loading
Loading