This is an automated email from the ASF dual-hosted git repository.

lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-java.git


The following commit(s) were added to refs/heads/main by this push:
     new c85a554d5 GH-1190: Reserve view slots for empty view vector values 
(#1192)
c85a554d5 is described below

commit c85a554d5b9e4e5c08b4703e5d41de5352bcda7c
Author: Goutam Adwant <[email protected]>
AuthorDate: Tue Aug 25 18:27:11 2026 -0700

    GH-1190: Reserve view slots for empty view vector values (#1192)
    
    ## What's Changed
    
    Fixes `BaseVariableWidthViewVector.handleSafe` so `setSafe` reserves a
    full 16-byte view slot for the target index even when the value length
    is zero.
    
    Closes #1190.
---
 .../arrow/vector/BaseVariableWidthViewVector.java  |  4 +-
 .../arrow/vector/TestVariableWidthViewVector.java  | 54 ++++++++++++++++++++++
 2 files changed, 57 insertions(+), 1 deletion(-)

diff --git 
a/vector/src/main/java/org/apache/arrow/vector/BaseVariableWidthViewVector.java 
b/vector/src/main/java/org/apache/arrow/vector/BaseVariableWidthViewVector.java
index ea9de8320..8d2a2d740 100644
--- 
a/vector/src/main/java/org/apache/arrow/vector/BaseVariableWidthViewVector.java
+++ 
b/vector/src/main/java/org/apache/arrow/vector/BaseVariableWidthViewVector.java
@@ -1405,7 +1405,9 @@ public abstract class BaseVariableWidthViewVector extends 
BaseValueVector
   }
 
   protected final void handleSafe(int index, int dataLength) {
-    final long targetCapacity = roundUpToMultipleOf16((long) index * 
ELEMENT_SIZE + dataLength);
+    // The view buffer stores one fixed-width view per value; payload bytes 
are allocated
+    // separately.
+    final long targetCapacity = roundUpToMultipleOf16(((long) index + 1) * 
ELEMENT_SIZE);
     if (viewBuffer.capacity() < targetCapacity) {
       reallocViewBuffer(targetCapacity);
     }
diff --git 
a/vector/src/test/java/org/apache/arrow/vector/TestVariableWidthViewVector.java 
b/vector/src/test/java/org/apache/arrow/vector/TestVariableWidthViewVector.java
index baf5e672c..c4a1ae9b6 100644
--- 
a/vector/src/test/java/org/apache/arrow/vector/TestVariableWidthViewVector.java
+++ 
b/vector/src/test/java/org/apache/arrow/vector/TestVariableWidthViewVector.java
@@ -540,6 +540,60 @@ public class TestVariableWidthViewVector {
     }
   }
 
+  @ParameterizedTest
+  @MethodSource({"vectorCreatorProvider"})
+  public void testSetSafeEmptyValueAtViewBufferBoundary(
+      Function<BufferAllocator, BaseVariableWidthViewVector> vectorCreator) {
+    try (final BaseVariableWidthViewVector vector = 
vectorCreator.apply(allocator)) {
+      final byte[] emptyValue = new byte[0];
+      vector.allocateNew();
+      final int valueCapacity = vector.getValueCapacity();
+
+      for (int i = 0; i <= valueCapacity; i++) {
+        vector.setSafe(i, emptyValue);
+      }
+
+      vector.setValueCount(valueCapacity + 1);
+      assertTrue(vector.getValueCapacity() > valueCapacity);
+      assertEquals(0, vector.getValueLength(valueCapacity));
+      assertArrayEquals(emptyValue, vector.get(valueCapacity));
+    }
+  }
+
+  @ParameterizedTest
+  @MethodSource({"vectorCreatorProvider"})
+  public void testSetValueCountFillsEmptiesAtViewBufferBoundary(
+      Function<BufferAllocator, BaseVariableWidthViewVector> vectorCreator) {
+    try (final BaseVariableWidthViewVector vector = 
vectorCreator.apply(allocator)) {
+      vector.allocateNew();
+      final int valueCapacity = vector.getValueCapacity();
+
+      vector.setSafe(valueCapacity - 1, "x".getBytes(StandardCharsets.UTF_8));
+      vector.setValueCount(valueCapacity + 1);
+
+      assertTrue(vector.getValueCapacity() > valueCapacity);
+      assertTrue(vector.isNull(valueCapacity));
+    }
+  }
+
+  @ParameterizedTest
+  @MethodSource({"vectorCreatorProvider"})
+  public void testSetNullAtViewBufferBoundary(
+      Function<BufferAllocator, BaseVariableWidthViewVector> vectorCreator) {
+    try (final BaseVariableWidthViewVector vector = 
vectorCreator.apply(allocator)) {
+      vector.allocateNew();
+      final int valueCapacity = vector.getValueCapacity();
+
+      for (int i = 0; i <= valueCapacity; i++) {
+        vector.setNull(i);
+      }
+      vector.setValueCount(valueCapacity + 1);
+
+      assertTrue(vector.getValueCapacity() > valueCapacity);
+      assertTrue(vector.isNull(valueCapacity));
+    }
+  }
+
   @Test
   public void testNullableVarType1() {
 

Reply via email to