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

jbonofre 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 f804f9074 GH-812: Fix appending to an empty UnionVector (#1292)
f804f9074 is described below

commit f804f90748345cb0d19d16c31c81d8c9ac5f21ad
Author: hutiefang76 <[email protected]>
AuthorDate: Sun Oct 4 23:05:53 2026 +0800

    GH-812: Fix appending to an empty UnionVector (#1292)
    
    ## What's Changed
    
    Appending to a newly created `UnionVector` repeatedly reallocates its
    type buffer until allocation fails: its value capacity remains zero
    until it has child vectors. Check the type buffer capacity at this
    stage, since the existing append loop creates and expands the child
    vectors afterward.
    
    The regression appends two floats to an empty union with a bounded
    allocator. It fails before the change with an allocation error and
    passes afterward. All 32 `TestVectorAppender` tests pass with both the
    Netty and Unsafe allocators on JDK 21. Checkstyle and Spotless also
    pass.
    
    Closes #812.
    
    Validation (JDK 21):
    
    ```sh
    mvn -B -pl vector -am test -Dtest=TestVectorAppender 
-Dsurefire.failIfNoSpecifiedTests=false
    mvn -B -pl vector spotless:check
    ```
    
    Developed with AI assistance; the regression was verified to fail before
    the fix and pass afterward.
---
 .../org/apache/arrow/vector/util/VectorAppender.java |  3 +--
 .../apache/arrow/vector/util/TestVectorAppender.java | 20 ++++++++++++++++++++
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git 
a/vector/src/main/java/org/apache/arrow/vector/util/VectorAppender.java 
b/vector/src/main/java/org/apache/arrow/vector/util/VectorAppender.java
index 2cfeb0a04..7176e86c7 100644
--- a/vector/src/main/java/org/apache/arrow/vector/util/VectorAppender.java
+++ b/vector/src/main/java/org/apache/arrow/vector/util/VectorAppender.java
@@ -601,8 +601,7 @@ public class VectorAppender implements 
VectorVisitor<ValueVector, Void> {
     UnionVector targetUnionVector = (UnionVector) targetVector;
     int newValueCount = targetVector.getValueCount() + 
deltaVector.getValueCount();
 
-    // make sure there is enough capacity
-    while (targetUnionVector.getValueCapacity() < newValueCount) {
+    while (targetUnionVector.getTypeBuffer().capacity() / 
UnionVector.TYPE_WIDTH < newValueCount) {
       targetUnionVector.reAlloc();
     }
 
diff --git 
a/vector/src/test/java/org/apache/arrow/vector/util/TestVectorAppender.java 
b/vector/src/test/java/org/apache/arrow/vector/util/TestVectorAppender.java
index 9a8143f51..57dd852e3 100644
--- a/vector/src/test/java/org/apache/arrow/vector/util/TestVectorAppender.java
+++ b/vector/src/test/java/org/apache/arrow/vector/util/TestVectorAppender.java
@@ -804,6 +804,26 @@ public class TestVectorAppender {
     }
   }
 
+  @Test
+  public void testAppendToEmptyUnionVector() {
+    try (BufferAllocator limitedAllocator = allocator.newChildAllocator("empty 
union", 0, 1048576);
+        UnionVector target = UnionVector.empty("target", limitedAllocator);
+        UnionVector delta = UnionVector.empty("delta", limitedAllocator)) {
+      delta.setType(0, Types.MinorType.FLOAT4);
+      delta.setType(1, Types.MinorType.FLOAT4);
+      Float4Vector values = delta.getFloat4Vector();
+      values.allocateNew();
+      ValueVectorDataPopulator.setVector(values, 1f, 2f);
+      delta.setValueCount(2);
+
+      delta.accept(new VectorAppender(target), null);
+
+      assertEquals(2, target.getValueCount());
+      assertEquals(1f, target.getObject(0));
+      assertEquals(2f, target.getObject(1));
+    }
+  }
+
   @Test
   public void testAppendUnionVector() {
     final int length1 = 10;

Reply via email to