From 3815f20da207c02852b443bccfad945305319a3b Mon Sep 17 00:00:00 2001 From: hutiefang76 <137664623+hutiefang76@users.noreply.github.com> Date: Thu, 10 Sep 2026 16:08:11 +0800 Subject: [PATCH 1/2] GH-812: Fix appending to an empty UnionVector --- .../arrow/vector/util/VectorAppender.java | 4 ++-- .../arrow/vector/util/TestVectorAppender.java | 20 +++++++++++++++++++ 2 files changed, 22 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 2cfeb0a04d..465d010bff 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,8 @@ public ValueVector visit(UnionVector deltaVector, Void value) { UnionVector targetUnionVector = (UnionVector) targetVector; int newValueCount = targetVector.getValueCount() + deltaVector.getValueCount(); - // make sure there is enough capacity - while (targetUnionVector.getValueCapacity() < newValueCount) { + // Child vectors are created and expanded below; an empty union has zero value capacity. + 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 9a8143f51b..57dd852e31 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 void testAppendEmptyStructVector() { } } + @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; From ea411ff7f7aa7cf1ddb8354d14633b38ebd5c6ea Mon Sep 17 00:00:00 2001 From: hutiefang76 <137664623+hutiefang76@users.noreply.github.com> Date: Tue, 15 Sep 2026 00:47:19 +0800 Subject: [PATCH 2/2] GH-812: Remove redundant union capacity comment --- .../main/java/org/apache/arrow/vector/util/VectorAppender.java | 1 - 1 file changed, 1 deletion(-) 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 465d010bff..7176e86c71 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,7 +601,6 @@ public ValueVector visit(UnionVector deltaVector, Void value) { UnionVector targetUnionVector = (UnionVector) targetVector; int newValueCount = targetVector.getValueCount() + deltaVector.getValueCount(); - // Child vectors are created and expanded below; an empty union has zero value capacity. while (targetUnionVector.getTypeBuffer().capacity() / UnionVector.TYPE_WIDTH < newValueCount) { targetUnionVector.reAlloc(); }