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 d47a807ae3 [format] Stop aliasing the output vector when tracking the
previous delta value (#9275)
d47a807ae3 is described below
commit d47a807ae30ba73eae41de12cb98dcfce1a52b97
Author: ZIHAN DAI <[email protected]>
AuthorDate: Thu Aug 20 12:03:01 2026 +1000
[format] Stop aliasing the output vector when tracking the previous delta
value (#9275)
---
.../reader/VectorizedDeltaByteArrayReader.java | 9 +++++--
.../parquet/reader/DeltaByteArrayEncodingTest.java | 28 ++++++++++++++++++++++
2 files changed, 35 insertions(+), 2 deletions(-)
diff --git
a/paimon-format/src/main/java/org/apache/paimon/format/parquet/reader/VectorizedDeltaByteArrayReader.java
b/paimon-format/src/main/java/org/apache/paimon/format/parquet/reader/VectorizedDeltaByteArrayReader.java
index 90031f1336..05ca1bacbb 100644
---
a/paimon-format/src/main/java/org/apache/paimon/format/parquet/reader/VectorizedDeltaByteArrayReader.java
+++
b/paimon-format/src/main/java/org/apache/paimon/format/parquet/reader/VectorizedDeltaByteArrayReader.java
@@ -92,8 +92,13 @@ public class VectorizedDeltaByteArrayReader extends
VectorizedReaderBase
System.arraycopy(suffixArray, suffix.position(), bytes,
prefixLength, suffixLength);
c.putByteArray(rowId + i, bytes, offset, length);
- BytesColumnVector.Bytes b = c.getBytes(rowId + i);
- previous = ByteBuffer.wrap(b.data, b.offset, b.len);
+ // Keep the value we just assembled rather than a view over the
output vector's
+ // buffer. The record reader resets that vector between batches,
and reset() zeroes
+ // the buffer, so a view into it would hand NUL bytes to the next
value's prefix
+ // whenever a page spans more than one batch. skipBinary avoids
the same hazard by
+ // alternating two vectors; here the array is already a fresh
copy, so wrapping it
+ // costs nothing.
+ previous = ByteBuffer.wrap(bytes);
currentRow++;
}
}
diff --git
a/paimon-format/src/test/java/org/apache/paimon/format/parquet/reader/DeltaByteArrayEncodingTest.java
b/paimon-format/src/test/java/org/apache/paimon/format/parquet/reader/DeltaByteArrayEncodingTest.java
index 8e83924d1d..f1330f2f9c 100644
---
a/paimon-format/src/test/java/org/apache/paimon/format/parquet/reader/DeltaByteArrayEncodingTest.java
+++
b/paimon-format/src/test/java/org/apache/paimon/format/parquet/reader/DeltaByteArrayEncodingTest.java
@@ -102,6 +102,34 @@ public class DeltaByteArrayEncodingTest {
Integer.MAX_VALUE - 1));
}
+ /**
+ * The record reader resets the vector between batches, so a page that
spans two batches has to
+ * survive that reset. Every other case here reads a whole page into one
vector without a reset,
+ * which is why none of them exercises this.
+ */
+ @Test
+ public void readingOnePageInTwoBatchesKeepsThePrefix() throws Exception {
+ String[] vals = new String[8];
+ for (int i = 0; i < vals.length; i++) {
+ vals[i] = String.format("shared-prefix-%04d", i);
+ }
+ Utils.writeData(writer, vals);
+ HeapBytesVector vector = new HeapBytesVector(vals.length);
+ reader.initFromPage(vals.length, writer.getBytes().toInputStream());
+
+ int half = vals.length / 2;
+ reader.readBinary(half, vector, 0);
+ for (int i = 0; i < half; i++) {
+ assertArrayEquals(vals[i].getBytes(),
vector.getBytes(i).getBytes());
+ }
+
+ vector.reset();
+ reader.readBinary(vals.length - half, vector, 0);
+ for (int i = 0; i < vals.length - half; i++) {
+ assertArrayEquals(vals[half + i].getBytes(),
vector.getBytes(i).getBytes());
+ }
+ }
+
private void assertReadWrite(
DeltaByteArrayWriter writer, VectorizedDeltaByteArrayReader
reader, String[] vals)
throws Exception {