This is an automated email from the ASF dual-hosted git repository.
JingsongLi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/paimon-rust.git
The following commit(s) were added to refs/heads/main by this push:
new 78ae3fe0 test(file_index): verify Java range-bitmap table reads (#953)
78ae3fe0 is described below
commit 78ae3fe0e0186505f968d90297b3f42e5e800c8b
Author: Wuhen- Li <[email protected]>
AuthorDate: Fri Sep 25 20:50:04 2026 +0800
test(file_index): verify Java range-bitmap table reads (#953)
---
crates/paimon/testdata/file_index/README.md | 19 ++++++----
...-791a54a7-4d19-43c3-8752-31cd6073433a-0.parquet | Bin 0 -> 565 bytes
...manifest-155640a3-e50d-4be7-ba72-de0afe2a8fec-0 | Bin 0 -> 2302 bytes
...est-list-ecab87c6-de6d-44d0-a6ae-3705321d971d-0 | Bin 0 -> 1158 bytes
...est-list-ecab87c6-de6d-44d0-a6ae-3705321d971d-1 | Bin 0 -> 1263 bytes
.../range_bitmap_embedded/schema/schema-0 | 25 ++++++++++++
.../range_bitmap_embedded/snapshot/EARLIEST | 1 +
.../range_bitmap_embedded/snapshot/LATEST | 1 +
.../range_bitmap_embedded/snapshot/snapshot-1 | 18 +++++++++
...-9db69c4d-d10c-4f94-aed9-c16cd7fbe1e1-0.parquet | Bin 0 -> 565 bytes
...c4d-d10c-4f94-aed9-c16cd7fbe1e1-0.parquet.index | Bin 0 -> 191 bytes
...manifest-e1c11d52-6e22-4d10-b62a-833b60216bf2-0 | Bin 0 -> 2211 bytes
...est-list-107ca82a-e4a8-4a88-8439-b15d770f0474-0 | Bin 0 -> 1158 bytes
...est-list-107ca82a-e4a8-4a88-8439-b15d770f0474-1 | Bin 0 -> 1263 bytes
.../range_bitmap_sidecar/schema/schema-0 | 25 ++++++++++++
.../range_bitmap_sidecar/snapshot/EARLIEST | 1 +
.../range_bitmap_sidecar/snapshot/LATEST | 1 +
.../range_bitmap_sidecar/snapshot/snapshot-1 | 18 +++++++++
.../JavaFileIndexTableFixtureGeneratorTest.java | 8 +++-
.../paimon/tests/file_index_java_fixture_test.rs | 42 ++++++++++++++++++---
20 files changed, 145 insertions(+), 14 deletions(-)
diff --git a/crates/paimon/testdata/file_index/README.md
b/crates/paimon/testdata/file_index/README.md
index dee46286..7dc86b00 100644
--- a/crates/paimon/testdata/file_index/README.md
+++ b/crates/paimon/testdata/file_index/README.md
@@ -1,6 +1,6 @@
# Java FileIndex table fixtures
-These four committed tables were produced through Apache Paimon Java's normal
+These six committed tables were produced through Apache Paimon Java's normal
catalog, append writer, commit, snapshot, and manifest paths. No index bytes or
metadata were assembled or edited by hand.
@@ -9,19 +9,22 @@ Provenance:
- Apache Paimon Java commit: `1d368b4a5932f8221fd28e2555001abdb8fb12ee`
(`2.2-SNAPSHOT`).
- Generator: `java/JavaFileIndexTableFixtureGeneratorTest.java`.
-- Tables: Bitmap and Bloom Filter, each with an embedded (`1 MB` threshold) and
- `.index` sidecar (`1 B` threshold) form.
+- Tables: Bitmap, Bloom Filter, and Range Bitmap, each with an embedded (`1 MB`
+ threshold) and `.index` sidecar (`1 B` threshold) form.
- Common options: `bucket=1`, `bucket-key=id`, `file.format=parquet`, and
`file-index.read.enabled=true`.
- Bloom options: `items=16`, `fpp=0.01`.
-- Rows, in physical order: `(1, "keep")`, `(1, "drop")`,
- `(NULL, "null-id")`, `(3, "three")`.
+- Rows, in physical order: `(1, "keep")`, `(1, "drop")`, and
+ `(NULL, "null-id")`, followed by `(3, "three")` for Bitmap and Bloom Filter
+ or `(9, "nine")` for Range Bitmap.
The Rust test expects `id = 1` to return both duplicate rows, `id IS NULL` to
return the null row, `id = 1 AND payload = 'keep'` to retain only the residual
-match, and `id = 2` to return no rows. The last predicate lies inside the data
-file's `[1, 3]` min/max range, so manifest statistics cannot prune it; it is
also
-the observable FileIndex skip case.
+match, and `id = 2` to return no rows for Bitmap and Bloom Filter. Range Bitmap
+also checks `id BETWEEN 1 AND 3` returns both duplicate rows and `id BETWEEN 3
+AND 7` returns no rows. Each missing-value predicate lies inside its data
+file's min/max range (`[1, 3]` or `[1, 9]`), so manifest statistics cannot
+prune it; these are the observable FileIndex skip cases.
To regenerate into an empty temporary directory:
diff --git
a/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/bucket-0/data-791a54a7-4d19-43c3-8752-31cd6073433a-0.parquet
b/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/bucket-0/data-791a54a7-4d19-43c3-8752-31cd6073433a-0.parquet
new file mode 100644
index 00000000..51874a62
Binary files /dev/null and
b/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/bucket-0/data-791a54a7-4d19-43c3-8752-31cd6073433a-0.parquet
differ
diff --git
a/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/manifest/manifest-155640a3-e50d-4be7-ba72-de0afe2a8fec-0
b/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/manifest/manifest-155640a3-e50d-4be7-ba72-de0afe2a8fec-0
new file mode 100644
index 00000000..3f15ad7c
Binary files /dev/null and
b/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/manifest/manifest-155640a3-e50d-4be7-ba72-de0afe2a8fec-0
differ
diff --git
a/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/manifest/manifest-list-ecab87c6-de6d-44d0-a6ae-3705321d971d-0
b/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/manifest/manifest-list-ecab87c6-de6d-44d0-a6ae-3705321d971d-0
new file mode 100644
index 00000000..a3367dad
Binary files /dev/null and
b/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/manifest/manifest-list-ecab87c6-de6d-44d0-a6ae-3705321d971d-0
differ
diff --git
a/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/manifest/manifest-list-ecab87c6-de6d-44d0-a6ae-3705321d971d-1
b/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/manifest/manifest-list-ecab87c6-de6d-44d0-a6ae-3705321d971d-1
new file mode 100644
index 00000000..b7653984
Binary files /dev/null and
b/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/manifest/manifest-list-ecab87c6-de6d-44d0-a6ae-3705321d971d-1
differ
diff --git
a/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/schema/schema-0
b/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/schema/schema-0
new file mode 100644
index 00000000..dbc24ab0
--- /dev/null
+++
b/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/schema/schema-0
@@ -0,0 +1,25 @@
+{
+ "version" : 3,
+ "id" : 0,
+ "fields" : [ {
+ "id" : 0,
+ "name" : "id",
+ "type" : "INT"
+ }, {
+ "id" : 1,
+ "name" : "payload",
+ "type" : "STRING"
+ } ],
+ "highestFieldId" : 1,
+ "partitionKeys" : [ ],
+ "primaryKeys" : [ ],
+ "options" : {
+ "bucket" : "1",
+ "file-index.range-bitmap.columns" : "id",
+ "bucket-key" : "id",
+ "file-index.read.enabled" : "true",
+ "file.format" : "parquet",
+ "file-index.in-manifest-threshold" : "1 MB"
+ },
+ "timeMillis" : 1790306753711
+}
\ No newline at end of file
diff --git
a/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/snapshot/EARLIEST
b/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/snapshot/EARLIEST
new file mode 100644
index 00000000..56a6051c
--- /dev/null
+++
b/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/snapshot/EARLIEST
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git
a/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/snapshot/LATEST
b/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/snapshot/LATEST
new file mode 100644
index 00000000..56a6051c
--- /dev/null
+++
b/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/snapshot/LATEST
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git
a/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/snapshot/snapshot-1
b/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/snapshot/snapshot-1
new file mode 100644
index 00000000..1164e594
--- /dev/null
+++
b/crates/paimon/testdata/file_index/default.db/range_bitmap_embedded/snapshot/snapshot-1
@@ -0,0 +1,18 @@
+{
+ "version" : 3,
+ "uuid" : "eb6639ec-eb6f-405b-8525-3612fabf030f",
+ "id" : 1,
+ "schemaId" : 0,
+ "baseManifestList" : "manifest-list-ecab87c6-de6d-44d0-a6ae-3705321d971d-0",
+ "baseManifestListSize" : 1158,
+ "deltaManifestList" : "manifest-list-ecab87c6-de6d-44d0-a6ae-3705321d971d-1",
+ "deltaManifestListSize" : 1263,
+ "commitUser" : "aa888b6c-37dc-49f1-82c6-7067442974e3",
+ "writerVersion" :
"java-2.2-SNAPSHOT-1d368b4a5932f8221fd28e2555001abdb8fb12ee",
+ "commitIdentifier" : 9223372036854775807,
+ "commitKind" : "APPEND",
+ "timeMillis" : 1790306753723,
+ "totalRecordCount" : 4,
+ "deltaRecordCount" : 4,
+ "nextRowId" : 0
+}
\ No newline at end of file
diff --git
a/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/bucket-0/data-9db69c4d-d10c-4f94-aed9-c16cd7fbe1e1-0.parquet
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/bucket-0/data-9db69c4d-d10c-4f94-aed9-c16cd7fbe1e1-0.parquet
new file mode 100644
index 00000000..51874a62
Binary files /dev/null and
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/bucket-0/data-9db69c4d-d10c-4f94-aed9-c16cd7fbe1e1-0.parquet
differ
diff --git
a/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/bucket-0/data-9db69c4d-d10c-4f94-aed9-c16cd7fbe1e1-0.parquet.index
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/bucket-0/data-9db69c4d-d10c-4f94-aed9-c16cd7fbe1e1-0.parquet.index
new file mode 100644
index 00000000..846b7156
Binary files /dev/null and
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/bucket-0/data-9db69c4d-d10c-4f94-aed9-c16cd7fbe1e1-0.parquet.index
differ
diff --git
a/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/manifest/manifest-e1c11d52-6e22-4d10-b62a-833b60216bf2-0
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/manifest/manifest-e1c11d52-6e22-4d10-b62a-833b60216bf2-0
new file mode 100644
index 00000000..d3ff990c
Binary files /dev/null and
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/manifest/manifest-e1c11d52-6e22-4d10-b62a-833b60216bf2-0
differ
diff --git
a/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/manifest/manifest-list-107ca82a-e4a8-4a88-8439-b15d770f0474-0
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/manifest/manifest-list-107ca82a-e4a8-4a88-8439-b15d770f0474-0
new file mode 100644
index 00000000..0abb57be
Binary files /dev/null and
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/manifest/manifest-list-107ca82a-e4a8-4a88-8439-b15d770f0474-0
differ
diff --git
a/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/manifest/manifest-list-107ca82a-e4a8-4a88-8439-b15d770f0474-1
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/manifest/manifest-list-107ca82a-e4a8-4a88-8439-b15d770f0474-1
new file mode 100644
index 00000000..1c0e7842
Binary files /dev/null and
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/manifest/manifest-list-107ca82a-e4a8-4a88-8439-b15d770f0474-1
differ
diff --git
a/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/schema/schema-0
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/schema/schema-0
new file mode 100644
index 00000000..285454bd
--- /dev/null
+++
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/schema/schema-0
@@ -0,0 +1,25 @@
+{
+ "version" : 3,
+ "id" : 0,
+ "fields" : [ {
+ "id" : 0,
+ "name" : "id",
+ "type" : "INT"
+ }, {
+ "id" : 1,
+ "name" : "payload",
+ "type" : "STRING"
+ } ],
+ "highestFieldId" : 1,
+ "partitionKeys" : [ ],
+ "primaryKeys" : [ ],
+ "options" : {
+ "bucket" : "1",
+ "file-index.range-bitmap.columns" : "id",
+ "bucket-key" : "id",
+ "file-index.read.enabled" : "true",
+ "file.format" : "parquet",
+ "file-index.in-manifest-threshold" : "1 B"
+ },
+ "timeMillis" : 1790306753724
+}
\ No newline at end of file
diff --git
a/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/snapshot/EARLIEST
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/snapshot/EARLIEST
new file mode 100644
index 00000000..56a6051c
--- /dev/null
+++
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/snapshot/EARLIEST
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git
a/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/snapshot/LATEST
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/snapshot/LATEST
new file mode 100644
index 00000000..56a6051c
--- /dev/null
+++
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/snapshot/LATEST
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git
a/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/snapshot/snapshot-1
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/snapshot/snapshot-1
new file mode 100644
index 00000000..bdb3e6f9
--- /dev/null
+++
b/crates/paimon/testdata/file_index/default.db/range_bitmap_sidecar/snapshot/snapshot-1
@@ -0,0 +1,18 @@
+{
+ "version" : 3,
+ "uuid" : "0780e80a-3837-4b40-876e-29a9579141c0",
+ "id" : 1,
+ "schemaId" : 0,
+ "baseManifestList" : "manifest-list-107ca82a-e4a8-4a88-8439-b15d770f0474-0",
+ "baseManifestListSize" : 1158,
+ "deltaManifestList" : "manifest-list-107ca82a-e4a8-4a88-8439-b15d770f0474-1",
+ "deltaManifestListSize" : 1263,
+ "commitUser" : "1a7d1612-bcc4-4552-b69a-8b603f9c2646",
+ "writerVersion" :
"java-2.2-SNAPSHOT-1d368b4a5932f8221fd28e2555001abdb8fb12ee",
+ "commitIdentifier" : 9223372036854775807,
+ "commitKind" : "APPEND",
+ "timeMillis" : 1790306753730,
+ "totalRecordCount" : 4,
+ "deltaRecordCount" : 4,
+ "nextRowId" : 0
+}
\ No newline at end of file
diff --git
a/crates/paimon/testdata/file_index/java/JavaFileIndexTableFixtureGeneratorTest.java
b/crates/paimon/testdata/file_index/java/JavaFileIndexTableFixtureGeneratorTest.java
index 6c592f7b..b411d82a 100644
---
a/crates/paimon/testdata/file_index/java/JavaFileIndexTableFixtureGeneratorTest.java
+++
b/crates/paimon/testdata/file_index/java/JavaFileIndexTableFixtureGeneratorTest.java
@@ -64,6 +64,8 @@ public class JavaFileIndexTableFixtureGeneratorTest {
writeTable(catalog, "bitmap_sidecar", "bitmap", "1 B");
writeTable(catalog, "bloom_filter_embedded", "bloom-filter", "1 MB");
writeTable(catalog, "bloom_filter_sidecar", "bloom-filter", "1 B");
+ writeTable(catalog, "range_bitmap_embedded", "range-bitmap", "1 MB");
+ writeTable(catalog, "range_bitmap_sidecar", "range-bitmap", "1 B");
}
private static void writeTable(
@@ -97,7 +99,11 @@ public class JavaFileIndexTableFixtureGeneratorTest {
write.write(row(1, "keep"));
write.write(row(1, "drop"));
write.write(row(null, "null-id"));
- write.write(row(3, "three"));
+ if ("range-bitmap".equals(indexType)) {
+ write.write(row(9, "nine"));
+ } else {
+ write.write(row(3, "three"));
+ }
commit.commit(write.prepareCommit());
}
}
diff --git a/crates/paimon/tests/file_index_java_fixture_test.rs
b/crates/paimon/tests/file_index_java_fixture_test.rs
index 87a86fed..7268dd1e 100644
--- a/crates/paimon/tests/file_index_java_fixture_test.rs
+++ b/crates/paimon/tests/file_index_java_fixture_test.rs
@@ -40,24 +40,39 @@ const FIXTURE: &str = "testdata/file_index/default.db";
struct FixtureCase {
table: &'static str,
embedded: bool,
+ range_bitmap: bool,
}
const CASES: &[FixtureCase] = &[
FixtureCase {
table: "bitmap_embedded",
embedded: true,
+ range_bitmap: false,
},
FixtureCase {
table: "bitmap_sidecar",
embedded: false,
+ range_bitmap: false,
},
FixtureCase {
table: "bloom_filter_embedded",
embedded: true,
+ range_bitmap: false,
},
FixtureCase {
table: "bloom_filter_sidecar",
embedded: false,
+ range_bitmap: false,
+ },
+ FixtureCase {
+ table: "range_bitmap_embedded",
+ embedded: true,
+ range_bitmap: true,
+ },
+ FixtureCase {
+ table: "range_bitmap_sidecar",
+ embedded: false,
+ range_bitmap: true,
},
];
@@ -198,7 +213,13 @@ async fn
reads_java_written_file_indexes_and_prunes_data_files() {
let predicates = PredicateBuilder::new(table.schema().fields());
let id_one = predicates.equal("id", Datum::Int(1)).unwrap();
let null_id = predicates.is_null("id").unwrap();
- let missing_id = predicates.equal("id", Datum::Int(2)).unwrap();
+ let missing = if case.range_bitmap {
+ predicates
+ .between("id", Datum::Int(3), Datum::Int(7))
+ .unwrap()
+ } else {
+ predicates.equal("id", Datum::Int(2)).unwrap()
+ };
let residual = Predicate::and(vec![
id_one.clone(),
predicates
@@ -207,7 +228,7 @@ async fn
reads_java_written_file_indexes_and_prunes_data_files() {
]);
let mut planning_builder = table.new_read_builder();
- planning_builder.with_filter(missing_id.clone());
+ planning_builder.with_filter(missing.clone());
let (plan, trace) = planning_builder
.new_scan()
.plan_with_trace()
@@ -253,15 +274,26 @@ async fn
reads_java_written_file_indexes_and_prunes_data_files() {
"{} must retain row-level residual filtering with FileIndex
enabled={enabled}",
case.table
);
+ if case.range_bitmap {
+ let range_hit = predicates
+ .between("id", Datum::Int(1), Datum::Int(3))
+ .unwrap();
+ assert_eq!(
+ query(&table, enabled, range_hit).await,
+ vec![(Some(1), "drop".to_string()), (Some(1),
"keep".to_string())],
+ "{} range query with FileIndex enabled={enabled}",
+ case.table
+ );
+ }
assert!(
- query(&table, enabled, missing_id.clone()).await.is_empty(),
+ query(&table, enabled, missing.clone()).await.is_empty(),
"{} with FileIndex enabled={enabled}",
case.table
);
}
probe.reset();
- assert!(query(&table, true, missing_id.clone()).await.is_empty());
+ assert!(query(&table, true, missing.clone()).await.is_empty());
assert_eq!(
probe.data_file_opens(),
0,
@@ -270,7 +302,7 @@ async fn
reads_java_written_file_indexes_and_prunes_data_files() {
);
probe.reset();
- assert!(query(&table, false, missing_id).await.is_empty());
+ assert!(query(&table, false, missing).await.is_empty());
assert!(
probe.data_file_opens() > 0,
"{} must open the data file when FileIndex reads are disabled",