This is an automated email from the ASF dual-hosted git repository.
JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git
The following commit(s) were added to refs/heads/master by this push:
new 2488a5ed33 [core] Fix readAllDeletionVectors not seeking to correct
offset (#8211)
2488a5ed33 is described below
commit 2488a5ed33a97cca95fedd286405ec1fe412936f
Author: yugan <[email protected]>
AuthorDate: Fri Jun 12 15:43:29 2026 +0800
[core] Fix readAllDeletionVectors not seeking to correct offset (#8211)
---
.../deletionvectors/DeletionVectorsIndexFile.java | 1 +
.../DeletionVectorsIndexFileTest.java | 56 ++++++++++++++++++++++
2 files changed, 57 insertions(+)
diff --git
a/paimon-core/src/main/java/org/apache/paimon/deletionvectors/DeletionVectorsIndexFile.java
b/paimon-core/src/main/java/org/apache/paimon/deletionvectors/DeletionVectorsIndexFile.java
index f643b0d6e9..e4606adf55 100644
---
a/paimon-core/src/main/java/org/apache/paimon/deletionvectors/DeletionVectorsIndexFile.java
+++
b/paimon-core/src/main/java/org/apache/paimon/deletionvectors/DeletionVectorsIndexFile.java
@@ -80,6 +80,7 @@ public class DeletionVectorsIndexFile extends IndexFile {
checkVersion(inputStream);
DataInputStream dataInputStream = new DataInputStream(inputStream);
for (DeletionVectorMeta deletionVectorMeta :
deletionVectorMetas.values()) {
+ inputStream.seek(deletionVectorMeta.offset());
deletionVectors.put(
deletionVectorMeta.dataFileName(),
DeletionVector.read(dataInputStream, (long)
deletionVectorMeta.length()));
diff --git
a/paimon-core/src/test/java/org/apache/paimon/deletionvectors/DeletionVectorsIndexFileTest.java
b/paimon-core/src/test/java/org/apache/paimon/deletionvectors/DeletionVectorsIndexFileTest.java
index ed342c9025..9a243bf8bf 100644
---
a/paimon-core/src/test/java/org/apache/paimon/deletionvectors/DeletionVectorsIndexFileTest.java
+++
b/paimon-core/src/test/java/org/apache/paimon/deletionvectors/DeletionVectorsIndexFileTest.java
@@ -34,7 +34,10 @@ import org.junit.jupiter.params.provider.ValueSource;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
@@ -260,6 +263,59 @@ public class DeletionVectorsIndexFileTest {
assertThat(dvs2.size()).isEqualTo(100000);
}
+ @ParameterizedTest
+ @ValueSource(booleans = {false, true})
+ public void testReadAllDeletionVectorsWithOutOfOrderDvRanges(boolean
bitmap64) {
+ IndexPathFactory pathFactory = getPathFactory();
+ DeletionVectorsIndexFile deletionVectorsIndexFile =
+ deletionVectorsIndexFile(pathFactory, bitmap64);
+
+ // write multiple DVs so they are stored sequentially in the index file
+ HashMap<String, DeletionVector> deleteMap = new HashMap<>();
+ Map<String, Integer> expected = new HashMap<>();
+ for (int i = 0; i < 10; i++) {
+ DeletionVector dv = createEmptyDV(bitmap64);
+ dv.delete(i * 100);
+ dv.delete(i * 100 + 1);
+ deleteMap.put("file" + i + ".parquet", dv);
+ expected.put("file" + i + ".parquet", i * 100);
+ }
+
+ List<IndexFileMeta> indexFiles =
deletionVectorsIndexFile.writeWithRolling(deleteMap);
+ assertThat(indexFiles.size()).isEqualTo(1);
+ IndexFileMeta original = indexFiles.get(0);
+
+ // build a new IndexFileMeta with dvRanges in reverse offset order,
+ // simulating compaction merging dvRanges from multiple sources
+ LinkedHashMap<String, DeletionVectorMeta> originalRanges =
original.dvRanges();
+ List<Map.Entry<String, DeletionVectorMeta>> entries =
+ new ArrayList<>(originalRanges.entrySet());
+ Collections.reverse(entries);
+ LinkedHashMap<String, DeletionVectorMeta> reversedRanges = new
LinkedHashMap<>();
+ for (Map.Entry<String, DeletionVectorMeta> entry : entries) {
+ reversedRanges.put(entry.getKey(), entry.getValue());
+ }
+
+ IndexFileMeta reordered =
+ new IndexFileMeta(
+ original.indexType(),
+ original.fileName(),
+ original.fileSize(),
+ original.rowCount(),
+ reversedRanges,
+ original.externalPath());
+
+ // read with out-of-order dvRanges — this would fail without the seek
fix
+ Map<String, DeletionVector> result =
+ deletionVectorsIndexFile.readAllDeletionVectors(reordered);
+ assertThat(result).hasSize(10);
+ for (Map.Entry<String, Integer> e : expected.entrySet()) {
+
assertThat(result.get(e.getKey()).isDeleted(e.getValue())).isTrue();
+ assertThat(result.get(e.getKey()).isDeleted(e.getValue() +
1)).isTrue();
+ assertThat(result.get(e.getKey()).isDeleted(e.getValue() +
2)).isFalse();
+ }
+ }
+
@ParameterizedTest
@ValueSource(booleans = {false, true})
public void testReadDeletionFile(boolean bitmap64) throws IOException {