Skip to content

Commit a758cad

Browse files
committed
GH-470: [Vector] Fix ListViewVector.getElementEndIndex(index) method
1 parent 60a1a42 commit a758cad

File tree

2 files changed

+167
-50
lines changed

2 files changed

+167
-50
lines changed

vector/src/main/java/org/apache/arrow/vector/complex/ListViewVector.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -891,7 +891,7 @@ public int getElementStartIndex(int index) {
891891

892892
@Override
893893
public int getElementEndIndex(int index) {
894-
return sizeBuffer.getInt(index * OFFSET_WIDTH);
894+
return offsetBuffer.getInt(index * OFFSET_WIDTH) + sizeBuffer.getInt(index * SIZE_WIDTH);
895895
}
896896

897897
@Override

vector/src/test/java/org/apache/arrow/vector/TestListViewVector.java

Lines changed: 166 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,55 +1550,7 @@ public void testOverwriteWithNull() {
15501550
public void testOutOfOrderOffset1() {
15511551
// [[12, -7, 25], null, [0, -127, 127, 50], [], [50, 12]]
15521552
try (ListViewVector listViewVector = ListViewVector.empty("listview", allocator)) {
1553-
// Allocate buffers in listViewVector by calling `allocateNew` method.
1554-
listViewVector.allocateNew();
1555-
1556-
// Initialize the child vector using `initializeChildrenFromFields` method.
1557-
1558-
FieldType fieldType = new FieldType(true, new ArrowType.Int(16, true), null, null);
1559-
Field field = new Field("child-vector", fieldType, null);
1560-
listViewVector.initializeChildrenFromFields(Collections.singletonList(field));
1561-
1562-
// Set values in the child vector.
1563-
FieldVector fieldVector = listViewVector.getDataVector();
1564-
fieldVector.clear();
1565-
1566-
SmallIntVector childVector = (SmallIntVector) fieldVector;
1567-
1568-
childVector.allocateNew(7);
1569-
1570-
childVector.set(0, 0);
1571-
childVector.set(1, -127);
1572-
childVector.set(2, 127);
1573-
childVector.set(3, 50);
1574-
childVector.set(4, 12);
1575-
childVector.set(5, -7);
1576-
childVector.set(6, 25);
1577-
1578-
childVector.setValueCount(7);
1579-
1580-
// Set validity, offset and size buffers using `setValidity`,
1581-
// `setOffset` and `setSize` methods.
1582-
listViewVector.setValidity(0, 1);
1583-
listViewVector.setValidity(1, 0);
1584-
listViewVector.setValidity(2, 1);
1585-
listViewVector.setValidity(3, 1);
1586-
listViewVector.setValidity(4, 1);
1587-
1588-
listViewVector.setOffset(0, 4);
1589-
listViewVector.setOffset(1, 7);
1590-
listViewVector.setOffset(2, 0);
1591-
listViewVector.setOffset(3, 0);
1592-
listViewVector.setOffset(4, 3);
1593-
1594-
listViewVector.setSize(0, 3);
1595-
listViewVector.setSize(1, 0);
1596-
listViewVector.setSize(2, 4);
1597-
listViewVector.setSize(3, 0);
1598-
listViewVector.setSize(4, 2);
1599-
1600-
// Set value count using `setValueCount` method.
1601-
listViewVector.setValueCount(5);
1553+
initializeListViewVectorAsInSpecification(listViewVector);
16021554

16031555
final ArrowBuf offSetBuffer = listViewVector.getOffsetBuffer();
16041556
final ArrowBuf sizeBuffer = listViewVector.getSizeBuffer();
@@ -2217,11 +2169,176 @@ public void testRangeChildVector2() {
22172169
}
22182170
}
22192171

2172+
@Test
2173+
public void testGetElementStartIndexAndEndIndexOrderedOffsetsNoIntersection() {
2174+
/*
2175+
values = [10, 20, 30, 40, 50]
2176+
offsets = [0, 3]
2177+
sizes = [3, 2]
2178+
vector: [[10, 20, 30], [40, 50]]
2179+
*/
2180+
try (ListViewVector listViewVector = ListViewVector.empty("sourceVector", allocator)) {
2181+
initializeListViewVector(
2182+
listViewVector, List.of(10, 20, 30, 40, 50), List.of(1, 1), List.of(0, 3), List.of(3, 2));
2183+
2184+
assertEquals(0, listViewVector.getElementStartIndex(0));
2185+
assertEquals(3, listViewVector.getElementEndIndex(0));
2186+
assertEquals(3, listViewVector.getElementStartIndex(1));
2187+
assertEquals(5, listViewVector.getElementEndIndex(1));
2188+
2189+
final FieldVector dataVec = listViewVector.getDataVector();
2190+
int elemIndex = 0;
2191+
int start = listViewVector.getElementStartIndex(elemIndex);
2192+
int end = listViewVector.getElementEndIndex(elemIndex);
2193+
List<?> list = listViewVector.getObject(elemIndex);
2194+
assertEquals(end - start, list.size());
2195+
for (int j = 0; j < list.size(); j++) {
2196+
assertEquals(((SmallIntVector) dataVec).get(start + j), list.get(j));
2197+
}
2198+
}
2199+
}
2200+
2201+
@Test
2202+
public void testGetElementStartIndexAndEndIndexNotOrderedOffsetsNoIntersection() {
2203+
/*
2204+
values = [1, 2, 3, 4, 5, 6]
2205+
validity = [1, 1, 1]
2206+
offsets = [4, 2, 0]
2207+
sizes = [2, 2, 2]
2208+
vector: [[5, 6], [3, 4], [1, 2]]
2209+
*/
2210+
try (ListViewVector listViewVector = ListViewVector.empty("sourceVector", allocator)) {
2211+
initializeListViewVector(
2212+
listViewVector,
2213+
List.of(1, 2, 3, 4, 5, 6),
2214+
List.of(1, 1, 1),
2215+
List.of(4, 2, 0),
2216+
List.of(2, 2, 2));
2217+
2218+
assertEquals(4, listViewVector.getElementStartIndex(0));
2219+
assertEquals(6, listViewVector.getElementEndIndex(0));
2220+
assertEquals(2, listViewVector.getElementStartIndex(1));
2221+
assertEquals(4, listViewVector.getElementEndIndex(1));
2222+
assertEquals(0, listViewVector.getElementStartIndex(2));
2223+
assertEquals(2, listViewVector.getElementEndIndex(2));
2224+
}
2225+
}
2226+
2227+
@Test
2228+
public void testGetElementStartIndexAndEndIndexOrderedOffsetsWithIntersection() {
2229+
/*
2230+
values = [1, 2, 3, 4, 5]
2231+
validity = [1, 1, 1]
2232+
offsets = [0, 1, 4]
2233+
sizes = [2, 3, 1]
2234+
vector: [[1, 2], [2, 3, 4], [5]]
2235+
*/
2236+
try (ListViewVector listViewVector = ListViewVector.empty("sourceVector", allocator)) {
2237+
initializeListViewVector(
2238+
listViewVector,
2239+
List.of(1, 2, 3, 4, 5),
2240+
List.of(1, 1, 1),
2241+
List.of(0, 1, 4),
2242+
List.of(2, 3, 1));
2243+
2244+
assertEquals(0, listViewVector.getElementStartIndex(0));
2245+
assertEquals(2, listViewVector.getElementEndIndex(0));
2246+
assertEquals(1, listViewVector.getElementStartIndex(1));
2247+
assertEquals(4, listViewVector.getElementEndIndex(1));
2248+
assertEquals(4, listViewVector.getElementStartIndex(2));
2249+
assertEquals(5, listViewVector.getElementEndIndex(2));
2250+
}
2251+
}
2252+
2253+
@Test
2254+
public void testGetElementStartIndexAndEndIndexOrderedOffsetsAsInSpecification() {
2255+
try (ListViewVector listViewVector = ListViewVector.empty("sourceVector", allocator)) {
2256+
initializeListViewVectorAsInSpecification(listViewVector);
2257+
2258+
assertEquals(4, listViewVector.getElementStartIndex(0));
2259+
assertEquals(7, listViewVector.getElementEndIndex(0));
2260+
assertEquals(7, listViewVector.getElementStartIndex(1));
2261+
assertEquals(7, listViewVector.getElementEndIndex(1));
2262+
assertEquals(0, listViewVector.getElementStartIndex(2));
2263+
assertEquals(4, listViewVector.getElementEndIndex(2));
2264+
assertEquals(0, listViewVector.getElementStartIndex(3));
2265+
assertEquals(0, listViewVector.getElementEndIndex(3));
2266+
assertEquals(3, listViewVector.getElementStartIndex(4));
2267+
assertEquals(5, listViewVector.getElementEndIndex(4));
2268+
}
2269+
}
2270+
22202271
private void writeIntValues(UnionListViewWriter writer, int[] values) {
22212272
writer.startListView();
22222273
for (int v : values) {
22232274
writer.integer().writeInt(v);
22242275
}
22252276
writer.endListView();
22262277
}
2278+
2279+
/**
2280+
* ListViewVector from the <a
2281+
* href="https://arrow.apache.org/docs/format/Intro.html#list-view">specification</a>.
2282+
*/
2283+
private void initializeListViewVectorAsInSpecification(ListViewVector listViewVector) {
2284+
/*
2285+
values = [0, -127, 127, 50, 12, -7, 25]
2286+
validity = [1, 1, 1, 0, 1] (reversed)
2287+
offsets = [4, 7, 0, 0, 3]
2288+
sizes = [3, 0, 4, 0, 2]
2289+
vector: [[12, -7, 25], null, [0, -127, 127, 50], [], [50, 12]]
2290+
*/
2291+
initializeListViewVector(
2292+
listViewVector,
2293+
List.of(0, -127, 127, 50, 12, -7, 25),
2294+
List.of(1, 1, 1, 0, 1),
2295+
List.of(4, 7, 0, 0, 3),
2296+
List.of(3, 0, 4, 0, 2));
2297+
}
2298+
2299+
private void initializeListViewVector(
2300+
ListViewVector listViewVector,
2301+
List<Integer> values,
2302+
List<Integer> validity,
2303+
List<Integer> offsets,
2304+
List<Integer> sizes) {
2305+
// Allocate buffers in listViewVector by calling `allocateNew` method.
2306+
assert offsets.size() == sizes.size();
2307+
listViewVector.allocateNew();
2308+
2309+
// Initialize the child vector using `initializeChildrenFromFields` method.
2310+
FieldType fieldType = new FieldType(true, new ArrowType.Int(16, true), null, null);
2311+
Field field = new Field("child-vector", fieldType, null);
2312+
listViewVector.initializeChildrenFromFields(Collections.singletonList(field));
2313+
2314+
// Set values in the child vector.
2315+
FieldVector fieldVector = listViewVector.getDataVector();
2316+
fieldVector.clear();
2317+
2318+
SmallIntVector childVector = (SmallIntVector) fieldVector;
2319+
childVector.allocateNew(values.size());
2320+
for (int i = 0; i < values.size(); i++) {
2321+
childVector.set(i, values.get(i));
2322+
}
2323+
childVector.setValueCount(values.size());
2324+
2325+
// Set validity, offset and size buffers using `setValidity`,
2326+
// `setOffset` and `setSize` methods.
2327+
List<Integer> reversedValidity = new ArrayList<>(validity);
2328+
Collections.reverse(reversedValidity);
2329+
for (int i = 0; i < reversedValidity.size(); i++) {
2330+
listViewVector.setValidity(i, reversedValidity.get(i));
2331+
}
2332+
2333+
for (int i = 0; i < offsets.size(); i++) {
2334+
listViewVector.setOffset(i, offsets.get(i));
2335+
}
2336+
2337+
for (int i = 0; i < sizes.size(); i++) {
2338+
listViewVector.setSize(i, sizes.get(i));
2339+
}
2340+
2341+
// Set value count using `setValueCount` method.
2342+
listViewVector.setValueCount(offsets.size());
2343+
}
22272344
}

0 commit comments

Comments
 (0)