Skip to content

Commit 7f8447e

Browse files
committed
GH-200: Map transferred children by type id
DenseUnionVector keeps typeFields and childVectors by type id and maps the i-th registered type to its id through typeMapFields, but the transfer pair indexed them by i. With declared type ids such as [5, 10], the target's setValueCount then failed on a null child, and splitAndTransfer indexed per-type arrays of length nextTypeId by type id.
1 parent f41e9a8 commit 7f8447e

2 files changed

Lines changed: 80 additions & 10 deletions

File tree

‎vector/src/main/codegen/templates/DenseUnionVector.java‎

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,8 @@ public class DenseUnionVector extends AbstractContainerVector implements FieldVe
103103
*/
104104
private Field[] typeFields = new Field[Byte.MAX_VALUE + 1];
105105
/**
106-
* The index is the index into the typeFields array, and the value is the logical field id.
106+
* The index is the order in which the type was registered, and the value is its type id, i.e.
107+
* the index into the typeFields and childVectors arrays.
107108
*/
108109
private byte[] typeMapFields = new byte[Byte.MAX_VALUE + 1];
109110

@@ -623,12 +624,16 @@ public TransferImpl(DenseUnionVector to) {
623624
}
624625
625626
private void createTransferPairs() {
627+
// Expects the i-th registered type to be the i-th child of the internal struct. Type
628+
// fields and child vectors are indexed by its type id, which differs from i when the
629+
// union declares type ids.
626630
for (int i = 0; i < nextTypeId; i++) {
631+
byte typeId = typeMapFields[i];
627632
ValueVector srcVec = internalStruct.getVectorById(i);
628633
ValueVector dstVec = to.internalStruct.getVectorById(i);
629-
to.typeFields[i] = typeFields[i];
630-
to.typeMapFields[i] = typeMapFields[i];
631-
to.childVectors[i] = dstVec;
634+
to.typeFields[typeId] = typeFields[typeId];
635+
to.typeMapFields[i] = typeId;
636+
to.childVectors[typeId] = dstVec;
632637
internalTransferPairs[i] = srcVec.makeTransferPair(dstVec);
633638
}
634639
to.nextTypeId = nextTypeId;
@@ -647,7 +652,7 @@ public void transfer() {
647652
for (int i = 0; i < nextTypeId; i++) {
648653
if (internalTransferPairs[i] != null) {
649654
internalTransferPairs[i].transfer();
650-
to.childVectors[i] = internalTransferPairs[i].getTo();
655+
to.childVectors[typeMapFields[i]] = internalTransferPairs[i].getTo();
651656
}
652657
}
653658
to.valueCount = valueCount;
@@ -670,8 +675,8 @@ public void splitAndTransfer(int startIndex, int length) {
670675
to.reallocOffsetBuffer();
671676
}
672677
673-
int [] typeCounts = new int[nextTypeId];
674-
int [] typeStarts = new int[nextTypeId];
678+
int [] typeCounts = new int[Byte.MAX_VALUE + 1];
679+
int [] typeStarts = new int[Byte.MAX_VALUE + 1];
675680
for (int i = 0; i < typeCounts.length; i++) {
676681
typeCounts[i] = 0;
677682
typeStarts[i] = -1;
@@ -690,9 +695,10 @@ public void splitAndTransfer(int startIndex, int length) {
690695
691696
// transfer vector values
692697
for (int i = 0; i < nextTypeId; i++) {
693-
if (typeCounts[i] > 0 && typeStarts[i] != -1) {
694-
internalTransferPairs[i].splitAndTransfer(typeStarts[i], typeCounts[i]);
695-
to.childVectors[i] = internalTransferPairs[i].getTo();
698+
byte typeId = typeMapFields[i];
699+
if (typeCounts[typeId] > 0 && typeStarts[typeId] != -1) {
700+
internalTransferPairs[i].splitAndTransfer(typeStarts[typeId], typeCounts[typeId]);
701+
to.childVectors[typeId] = internalTransferPairs[i].getTo();
696702
}
697703
}
698704

‎vector/src/test/java/org/apache/arrow/vector/TestDenseUnionVector.java‎

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,48 @@ public void testTransfer() throws Exception {
191191
}
192192
}
193193

194+
@Test
195+
public void testTransferWithDeclaredTypeIds() {
196+
try (DenseUnionVector srcVector = newVectorWithTypeIds5And10()) {
197+
Field srcField = srcVector.getField();
198+
TransferPair pair = srcVector.getTransferPair(allocator);
199+
try (DenseUnionVector destVector = (DenseUnionVector) pair.getTo()) {
200+
pair.transfer();
201+
destVector.setValueCount(3);
202+
203+
assertEquals(srcField, destVector.getField());
204+
assertEquals(5, destVector.getObject(0));
205+
assertEquals(true, destVector.getObject(1));
206+
assertEquals(7, destVector.getObject(2));
207+
208+
TransferPair secondPair = destVector.getTransferPair(allocator);
209+
try (DenseUnionVector secondDestVector = (DenseUnionVector) secondPair.getTo()) {
210+
secondPair.transfer();
211+
212+
assertEquals(srcField, secondDestVector.getField());
213+
assertEquals(3, secondDestVector.getValueCount());
214+
assertEquals(5, secondDestVector.getObject(0));
215+
assertEquals(true, secondDestVector.getObject(1));
216+
assertEquals(7, secondDestVector.getObject(2));
217+
}
218+
}
219+
}
220+
}
221+
222+
@Test
223+
public void testSplitAndTransferWithDeclaredTypeIds() {
224+
try (DenseUnionVector srcVector = newVectorWithTypeIds5And10()) {
225+
TransferPair pair = srcVector.getTransferPair(allocator);
226+
try (DenseUnionVector destVector = (DenseUnionVector) pair.getTo()) {
227+
pair.splitAndTransfer(1, 2);
228+
229+
assertEquals(2, destVector.getValueCount());
230+
assertEquals(true, destVector.getObject(0));
231+
assertEquals(7, destVector.getObject(1));
232+
}
233+
}
234+
}
235+
194236
@Test
195237
public void testSplitAndTransfer() throws Exception {
196238
try (DenseUnionVector sourceVector =
@@ -706,4 +748,26 @@ private static NullableFloat4Holder newFloat4Holder(float value) {
706748
holder.value = value;
707749
return holder;
708750
}
751+
752+
/** Returns a dense union with declared type ids 5 (int) and 10 (bit), as IPC can produce. */
753+
private DenseUnionVector newVectorWithTypeIds5And10() {
754+
Field field =
755+
new Field(
756+
"u",
757+
FieldType.nullable(new ArrowType.Union(UnionMode.Dense, new int[] {5, 10})),
758+
List.of(
759+
Field.nullable("i", MinorType.INT.getType()),
760+
Field.nullable("b", MinorType.BIT.getType())));
761+
DenseUnionVector vector = (DenseUnionVector) field.createVector(allocator);
762+
vector.allocateNew();
763+
vector.setTypeId(0, (byte) 5);
764+
vector.setSafe(0, newIntHolder(5));
765+
vector.setTypeId(1, (byte) 10);
766+
vector.setSafe(1, newBitHolder(true));
767+
vector.setTypeId(2, (byte) 5);
768+
vector.setSafe(2, newIntHolder(7));
769+
vector.setValueCount(3);
770+
return vector;
771+
}
772+
709773
}

0 commit comments

Comments
 (0)