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.git
The following commit(s) were added to refs/heads/main by this push:
new b33f040640 GH-41272: [Java] LargeListViewVector Implementation (#43516)
b33f040640 is described below
commit b33f040640c7ccb3e6a8406e4d3158608c597025
Author: Vibhatha Lakmal Abeykoon <[email protected]>
AuthorDate: Fri Aug 9 08:12:10 2024 +0530
GH-41272: [Java] LargeListViewVector Implementation (#43516)
### Rationale for this change
This PR includes the initial integration of `LargeListViewVector`.
### What changes are included in this PR?
This PR includes the core functions associated with the
`LargeListViewVector`.
### Are these changes tested?
Yes.
### Are there any user-facing changes?
No
* GitHub Issue: #41272
Authored-by: Vibhatha Abeykoon <[email protected]>
Signed-off-by: David Li <[email protected]>
---
.../jdbc/binder/ColumnBinderArrowTypeVisitor.java | 5 +
.../apache/arrow/c/BufferImportTypeVisitor.java | 6 +
.../driver/jdbc/utils/AvaticaParameterBinder.java | 5 +
.../arrow/driver/jdbc/utils/ConvertUtils.java | 6 +
java/vector/src/main/codegen/data/ArrowTypes.tdd | 5 +
.../src/main/codegen/templates/ComplexCopier.java | 1 +
.../codegen/templates/PromotableViewWriter.java | 13 +-
.../main/codegen/templates/PromotableWriter.java | 47 +
.../main/codegen/templates/UnionListWriter.java | 48 +-
.../src/main/codegen/templates/UnionReader.java | 2 +-
.../java/org/apache/arrow/vector/BufferLayout.java | 5 +
.../java/org/apache/arrow/vector/TypeLayout.java | 16 +
.../complex/BaseLargeRepeatedValueViewVector.java | 406 +++++
.../arrow/vector/complex/LargeListViewVector.java | 875 +++++++++++
.../complex/impl/UnionLargeListViewReader.java | 116 ++
.../apache/arrow/vector/extension/OpaqueType.java | 5 +
.../java/org/apache/arrow/vector/types/Types.java | 21 +
.../arrow/vector/TestLargeListViewVector.java | 1649 ++++++++++++++++++++
18 files changed, 3225 insertions(+), 6 deletions(-)
diff --git
a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/binder/ColumnBinderArrowTypeVisitor.java
b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/binder/ColumnBinderArrowTypeVisitor.java
index 30b2305f3f..cb8e43035d 100644
---
a/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/binder/ColumnBinderArrowTypeVisitor.java
+++
b/java/adapter/jdbc/src/main/java/org/apache/arrow/adapter/jdbc/binder/ColumnBinderArrowTypeVisitor.java
@@ -284,4 +284,9 @@ public class ColumnBinderArrowTypeVisitor implements
ArrowType.ArrowTypeVisitor<
public ColumnBinder visit(ArrowType.ListView type) {
throw new UnsupportedOperationException("No column binder implemented for
type " + type);
}
+
+ @Override
+ public ColumnBinder visit(ArrowType.LargeListView type) {
+ throw new UnsupportedOperationException("No column binder implemented for
type " + type);
+ }
}
diff --git
a/java/c/src/main/java/org/apache/arrow/c/BufferImportTypeVisitor.java
b/java/c/src/main/java/org/apache/arrow/c/BufferImportTypeVisitor.java
index 5f262d3dc3..633ecd43bd 100644
--- a/java/c/src/main/java/org/apache/arrow/c/BufferImportTypeVisitor.java
+++ b/java/c/src/main/java/org/apache/arrow/c/BufferImportTypeVisitor.java
@@ -403,4 +403,10 @@ class BufferImportTypeVisitor implements
ArrowType.ArrowTypeVisitor<List<ArrowBu
throw new UnsupportedOperationException(
"Importing buffers for view type: " + type + " not supported");
}
+
+ @Override
+ public List<ArrowBuf> visit(ArrowType.LargeListView type) {
+ throw new UnsupportedOperationException(
+ "Importing buffers for view type: " + type + " not supported");
+ }
}
diff --git
a/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/AvaticaParameterBinder.java
b/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/AvaticaParameterBinder.java
index 7acffb4bc9..232fa15240 100644
---
a/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/AvaticaParameterBinder.java
+++
b/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/AvaticaParameterBinder.java
@@ -276,5 +276,10 @@ public class AvaticaParameterBinder {
public Boolean visit(ArrowType.ListView type) {
throw new UnsupportedOperationException("Binding is not yet supported
for type " + type);
}
+
+ @Override
+ public Boolean visit(ArrowType.LargeListView type) {
+ throw new UnsupportedOperationException("Binding is not yet supported
for type " + type);
+ }
}
}
diff --git
a/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ConvertUtils.java
b/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ConvertUtils.java
index 77b7a88536..ea57aeb774 100644
---
a/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ConvertUtils.java
+++
b/java/flight/flight-sql-jdbc-core/src/main/java/org/apache/arrow/driver/jdbc/utils/ConvertUtils.java
@@ -278,5 +278,11 @@ public final class ConvertUtils {
throw new UnsupportedOperationException(
"AvaticaParameter not yet supported for type " + type);
}
+
+ @Override
+ public AvaticaParameter visit(ArrowType.LargeListView type) {
+ throw new UnsupportedOperationException(
+ "AvaticaParameter not yet supported for type " + type);
+ }
}
}
diff --git a/java/vector/src/main/codegen/data/ArrowTypes.tdd
b/java/vector/src/main/codegen/data/ArrowTypes.tdd
index 72df477979..d0e8ef1e35 100644
--- a/java/vector/src/main/codegen/data/ArrowTypes.tdd
+++ b/java/vector/src/main/codegen/data/ArrowTypes.tdd
@@ -134,6 +134,11 @@
name: "ListView",
fields: [],
complex: true
+ },
+ {
+ name: "LargeListView",
+ fields: [],
+ complex: true
}
]
}
diff --git a/java/vector/src/main/codegen/templates/ComplexCopier.java
b/java/vector/src/main/codegen/templates/ComplexCopier.java
index 1eebba018b..5adad52312 100644
--- a/java/vector/src/main/codegen/templates/ComplexCopier.java
+++ b/java/vector/src/main/codegen/templates/ComplexCopier.java
@@ -53,6 +53,7 @@ public class ComplexCopier {
case LIST:
case LISTVIEW:
case LARGELIST:
+ case LARGELISTVIEW:
case FIXED_SIZE_LIST:
if (reader.isSet()) {
writer.startList();
diff --git a/java/vector/src/main/codegen/templates/PromotableViewWriter.java
b/java/vector/src/main/codegen/templates/PromotableViewWriter.java
index 373abbe4b9..a40901e295 100644
--- a/java/vector/src/main/codegen/templates/PromotableViewWriter.java
+++ b/java/vector/src/main/codegen/templates/PromotableViewWriter.java
@@ -68,6 +68,15 @@ public class PromotableViewWriter extends PromotableWriter {
super(v, listViewVector, nullableStructWriterFactory);
}
+ public PromotableViewWriter(ValueVector v, LargeListViewVector
largeListViewVector) {
+ super(v, largeListViewVector);
+ }
+
+ public PromotableViewWriter(ValueVector v, LargeListViewVector
largeListViewVector,
+ NullableStructWriterFactory nullableStructWriterFactory) {
+ super(v, largeListViewVector, nullableStructWriterFactory);
+ }
+
public PromotableViewWriter(ValueVector v, AbstractStructVector
parentContainer) {
super(v, parentContainer);
}
@@ -103,8 +112,10 @@ public class PromotableViewWriter extends PromotableWriter
{
v = fixedListVector.addOrGetVector(fieldType).getVector();
} else if (listViewVector != null) {
v = listViewVector.addOrGetVector(fieldType).getVector();
- } else {
+ } else if (largeListVector != null) {
v = largeListVector.addOrGetVector(fieldType).getVector();
+ } else {
+ v = largeListViewVector.addOrGetVector(fieldType).getVector();
}
v.allocateNew();
setWriter(v);
diff --git a/java/vector/src/main/codegen/templates/PromotableWriter.java
b/java/vector/src/main/codegen/templates/PromotableWriter.java
index 82bd3c5345..c0e686f317 100644
--- a/java/vector/src/main/codegen/templates/PromotableWriter.java
+++ b/java/vector/src/main/codegen/templates/PromotableWriter.java
@@ -41,6 +41,7 @@ public class PromotableWriter extends
AbstractPromotableFieldWriter {
protected final ListViewVector listViewVector;
protected final FixedSizeListVector fixedListVector;
protected final LargeListVector largeListVector;
+ protected final LargeListViewVector largeListViewVector;
protected final NullableStructWriterFactory nullableStructWriterFactory;
protected int position;
protected static final int MAX_DECIMAL_PRECISION = 38;
@@ -84,6 +85,7 @@ public class PromotableWriter extends
AbstractPromotableFieldWriter {
this.listViewVector = null;
this.fixedListVector = null;
this.largeListVector = null;
+ this.largeListViewVector = null;
this.nullableStructWriterFactory = nullableStructWriterFactory;
init(v);
}
@@ -118,6 +120,26 @@ public class PromotableWriter extends
AbstractPromotableFieldWriter {
this(v, largeListVector,
NullableStructWriterFactory.getNullableStructWriterFactoryInstance());
}
+ /**
+ * Constructs a new instance.
+ *
+ * @param v The vector to initialize the writer with.
+ * @param listViewVector The vector that serves as a parent of v.
+ */
+ public PromotableWriter(ValueVector v, ListViewVector listViewVector) {
+ this(v, listViewVector,
NullableStructWriterFactory.getNullableStructWriterFactoryInstance());
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param v The vector to initialize the writer with.
+ * @param largeListViewVector The vector that serves as a parent of v.
+ */
+ public PromotableWriter(ValueVector v, LargeListViewVector
largeListViewVector) {
+ this(v, largeListViewVector,
NullableStructWriterFactory.getNullableStructWriterFactoryInstance());
+ }
+
/**
* Constructs a new instance.
*
@@ -134,6 +156,7 @@ public class PromotableWriter extends
AbstractPromotableFieldWriter {
this.parentContainer = null;
this.fixedListVector = null;
this.largeListVector = null;
+ this.largeListViewVector = null;
this.nullableStructWriterFactory = nullableStructWriterFactory;
init(v);
}
@@ -154,6 +177,7 @@ public class PromotableWriter extends
AbstractPromotableFieldWriter {
this.parentContainer = null;
this.fixedListVector = null;
this.largeListVector = null;
+ this.largeListViewVector = null;
this.nullableStructWriterFactory = nullableStructWriterFactory;
init(v);
}
@@ -174,6 +198,7 @@ public class PromotableWriter extends
AbstractPromotableFieldWriter {
this.listVector = null;
this.listViewVector = null;
this.largeListVector = null;
+ this.largeListViewVector = null;
this.nullableStructWriterFactory = nullableStructWriterFactory;
init(v);
}
@@ -194,6 +219,28 @@ public class PromotableWriter extends
AbstractPromotableFieldWriter {
this.parentContainer = null;
this.listVector = null;
this.listViewVector = null;
+ this.largeListViewVector = null;
+ this.nullableStructWriterFactory = nullableStructWriterFactory;
+ init(v);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param v The vector to initialize the writer with.
+ * @param largeListViewVector The vector that serves as a parent of v.
+ * @param nullableStructWriterFactory The factory to create the delegate
writer.
+ */
+ public PromotableWriter(
+ ValueVector v,
+ LargeListViewVector largeListViewVector,
+ NullableStructWriterFactory nullableStructWriterFactory) {
+ this.largeListViewVector = largeListViewVector;
+ this.fixedListVector = null;
+ this.parentContainer = null;
+ this.listVector = null;
+ this.listViewVector = null;
+ this.largeListVector = null;
this.nullableStructWriterFactory = nullableStructWriterFactory;
init(v);
}
diff --git a/java/vector/src/main/codegen/templates/UnionListWriter.java
b/java/vector/src/main/codegen/templates/UnionListWriter.java
index e40c70eaff..3962e1d073 100644
--- a/java/vector/src/main/codegen/templates/UnionListWriter.java
+++ b/java/vector/src/main/codegen/templates/UnionListWriter.java
@@ -26,7 +26,7 @@ import java.lang.UnsupportedOperationException;
import java.math.BigDecimal;
<@pp.dropOutputFile />
-<#list ["List", "ListView", "LargeList"] as listName>
+<#list ["List", "ListView", "LargeList", "LargeListView"] as listName>
<@pp.changeOutputFile
name="/org/apache/arrow/vector/complex/impl/Union${listName}Writer.java" />
@@ -53,15 +53,18 @@ public class Union${listName}Writer extends
AbstractFieldWriter {
private boolean inStruct = false;
private boolean listStarted = false;
private String structName;
- <#if listName == "LargeList">
+ <#if listName == "LargeList" || listName == "LargeListView">
private static final long OFFSET_WIDTH = 8;
<#else>
private static final int OFFSET_WIDTH = 4;
</#if>
- <#if listName = "ListView">
+ <#if listName == "ListView">
private static final long SIZE_WIDTH = 4;
</#if>
+ <#if listName == "LargeListView">
+ private static final long SIZE_WIDTH = 8;
+ </#if>
public Union${listName}Writer(${listName}Vector vector) {
this(vector,
NullableStructWriterFactory.getNullableStructWriterFactoryInstance());
@@ -69,7 +72,7 @@ public class Union${listName}Writer extends
AbstractFieldWriter {
public Union${listName}Writer(${listName}Vector vector,
NullableStructWriterFactory nullableStructWriterFactory) {
this.vector = vector;
- <#if listName = "ListView">
+ <#if listName = "ListView" || listName = "LargeListView">
this.writer = new PromotableViewWriter(vector.getDataVector(), vector,
nullableStructWriterFactory);
<#else>
this.writer = new PromotableWriter(vector.getDataVector(), vector,
nullableStructWriterFactory);
@@ -231,12 +234,49 @@ public class Union${listName}Writer extends
AbstractFieldWriter {
listStarted = false;
}
+ @Override
public void startListView() {
vector.startNewValue(idx());
writer.setPosition(vector.getOffsetBuffer().getInt((idx()) *
OFFSET_WIDTH));
listStarted = true;
}
+ @Override
+ public void endListView() {
+ int sizeUptoIdx = 0;
+ for (int i = 0; i < idx(); i++) {
+ sizeUptoIdx += vector.getSizeBuffer().getInt(i * SIZE_WIDTH);
+ }
+ vector.getSizeBuffer().setInt(idx() * SIZE_WIDTH, writer.idx() -
sizeUptoIdx);
+ setPosition(idx() + 1);
+ listStarted = false;
+ }
+ <#elseif listName == "LargeListView">
+ @Override
+ public void startList() {
+ vector.startNewValue(idx());
+ writer.setPosition(vector.getOffsetBuffer().getInt((idx()) *
OFFSET_WIDTH));
+ listStarted = true;
+ }
+
+ @Override
+ public void endList() {
+ int sizeUptoIdx = 0;
+ for (int i = 0; i < idx(); i++) {
+ sizeUptoIdx += vector.getSizeBuffer().getInt(i * SIZE_WIDTH);
+ }
+ vector.getSizeBuffer().setInt(idx() * SIZE_WIDTH, writer.idx() -
sizeUptoIdx);
+ setPosition(idx() + 1);
+ listStarted = false;
+ }
+
+ @Override
+ public void startListView() {
+ vector.startNewValue(idx());
+
writer.setPosition(checkedCastToInt(vector.getOffsetBuffer().getInt((idx()) *
OFFSET_WIDTH)));
+ listStarted = true;
+ }
+
@Override
public void endListView() {
int sizeUptoIdx = 0;
diff --git a/java/vector/src/main/codegen/templates/UnionReader.java
b/java/vector/src/main/codegen/templates/UnionReader.java
index 615ea3a536..d2b2f4bb70 100644
--- a/java/vector/src/main/codegen/templates/UnionReader.java
+++ b/java/vector/src/main/codegen/templates/UnionReader.java
@@ -39,7 +39,7 @@ package org.apache.arrow.vector.complex.impl;
@SuppressWarnings("unused")
public class UnionReader extends AbstractFieldReader {
- private static final int NUM_SUPPORTED_TYPES = 49;
+ private static final int NUM_SUPPORTED_TYPES = 50;
private BaseReader[] readers = new BaseReader[NUM_SUPPORTED_TYPES];
public UnionVector data;
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/BufferLayout.java
b/java/vector/src/main/java/org/apache/arrow/vector/BufferLayout.java
index d4248c4ef9..6c6fd919ab 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/BufferLayout.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/BufferLayout.java
@@ -61,6 +61,7 @@ public class BufferLayout {
private static final BufferLayout VALUES_32 = new
BufferLayout(BufferType.DATA, 32);
private static final BufferLayout VALUES_16 = new
BufferLayout(BufferType.DATA, 16);
private static final BufferLayout VALUES_8 = new
BufferLayout(BufferType.DATA, 8);
+ private static final BufferLayout LARGE_SIZE_BUFFER = new
BufferLayout(BufferType.SIZE, 64);
private static final BufferLayout SIZE_BUFFER = new
BufferLayout(BufferType.SIZE, 32);
private static final BufferLayout VIEW_BUFFER = new
BufferLayout(BufferType.VIEWS, 16);
@@ -80,6 +81,10 @@ public class BufferLayout {
return SIZE_BUFFER;
}
+ public static BufferLayout largeSizeBuffer() {
+ return LARGE_SIZE_BUFFER;
+ }
+
/**
* Returns a databuffer for the given bitwidth. Only supports powers of two
between 8 and 128
* inclusive.
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/TypeLayout.java
b/java/vector/src/main/java/org/apache/arrow/vector/TypeLayout.java
index b8535532ea..78a3cac020 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/TypeLayout.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/TypeLayout.java
@@ -116,6 +116,16 @@ public class TypeLayout {
return new TypeLayout(vectors);
}
+ @Override
+ public TypeLayout visit(ArrowType.LargeListView type) {
+ List<BufferLayout> vectors =
+ asList(
+ BufferLayout.validityVector(),
+ BufferLayout.largeOffsetBuffer(),
+ BufferLayout.largeSizeBuffer());
+ return new TypeLayout(vectors);
+ }
+
@Override
public TypeLayout visit(ArrowType.LargeList type) {
List<BufferLayout> vectors =
@@ -340,6 +350,12 @@ public class TypeLayout {
return 2;
}
+ @Override
+ public Integer visit(ArrowType.LargeListView type) {
+ // validity buffer + offset buffer + size buffer
+ return 3;
+ }
+
@Override
public Integer visit(FixedSizeList type) {
// validity buffer
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/complex/BaseLargeRepeatedValueViewVector.java
b/java/vector/src/main/java/org/apache/arrow/vector/complex/BaseLargeRepeatedValueViewVector.java
new file mode 100644
index 0000000000..26079cbee9
--- /dev/null
+++
b/java/vector/src/main/java/org/apache/arrow/vector/complex/BaseLargeRepeatedValueViewVector.java
@@ -0,0 +1,406 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.arrow.vector.complex;
+
+import static org.apache.arrow.memory.util.LargeMemoryUtil.capAtMaxInt;
+import static org.apache.arrow.memory.util.LargeMemoryUtil.checkedCastToInt;
+
+import java.util.Collections;
+import java.util.Iterator;
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.memory.util.CommonUtil;
+import org.apache.arrow.util.Preconditions;
+import org.apache.arrow.vector.AddOrGetResult;
+import org.apache.arrow.vector.BaseFixedWidthVector;
+import org.apache.arrow.vector.BaseValueVector;
+import org.apache.arrow.vector.BaseVariableWidthVector;
+import org.apache.arrow.vector.DensityAwareVector;
+import org.apache.arrow.vector.FieldVector;
+import org.apache.arrow.vector.NullVector;
+import org.apache.arrow.vector.UInt4Vector;
+import org.apache.arrow.vector.ValueVector;
+import org.apache.arrow.vector.ZeroVector;
+import org.apache.arrow.vector.types.pojo.ArrowType;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.CallBack;
+import org.apache.arrow.vector.util.OversizedAllocationException;
+import org.apache.arrow.vector.util.SchemaChangeRuntimeException;
+
+public abstract class BaseLargeRepeatedValueViewVector extends BaseValueVector
+ implements RepeatedValueVector, FieldVector {
+ public static final FieldVector DEFAULT_DATA_VECTOR = ZeroVector.INSTANCE;
+ public static final String DATA_VECTOR_NAME = "$data$";
+
+ public static final byte OFFSET_WIDTH = 8;
+ public static final byte SIZE_WIDTH = 8;
+ protected ArrowBuf offsetBuffer;
+ protected ArrowBuf sizeBuffer;
+ protected FieldVector vector;
+ protected final CallBack repeatedCallBack;
+ protected int valueCount;
+ protected long offsetAllocationSizeInBytes = INITIAL_VALUE_ALLOCATION *
OFFSET_WIDTH;
+ protected long sizeAllocationSizeInBytes = INITIAL_VALUE_ALLOCATION *
SIZE_WIDTH;
+ private final String name;
+
+ protected String defaultDataVectorName = DATA_VECTOR_NAME;
+
+ protected BaseLargeRepeatedValueViewVector(
+ String name, BufferAllocator allocator, CallBack callBack) {
+ this(name, allocator, DEFAULT_DATA_VECTOR, callBack);
+ }
+
+ protected BaseLargeRepeatedValueViewVector(
+ String name, BufferAllocator allocator, FieldVector vector, CallBack
callBack) {
+ super(allocator);
+ this.name = name;
+ this.offsetBuffer = allocator.getEmpty();
+ this.sizeBuffer = allocator.getEmpty();
+ this.vector = Preconditions.checkNotNull(vector, "data vector cannot be
null");
+ this.repeatedCallBack = callBack;
+ this.valueCount = 0;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean allocateNewSafe() {
+ boolean dataAlloc = false;
+ try {
+ allocateBuffers();
+ dataAlloc = vector.allocateNewSafe();
+ } catch (Exception e) {
+ clear();
+ return false;
+ } finally {
+ if (!dataAlloc) {
+ clear();
+ }
+ }
+ return dataAlloc;
+ }
+
+ private void allocateBuffers() {
+ offsetBuffer = allocateBuffers(offsetAllocationSizeInBytes);
+ sizeBuffer = allocateBuffers(sizeAllocationSizeInBytes);
+ }
+
+ private ArrowBuf allocateBuffers(final long size) {
+ final int curSize = (int) size;
+ ArrowBuf buffer = allocator.buffer(curSize);
+ buffer.readerIndex(0);
+ buffer.setZero(0, buffer.capacity());
+ return buffer;
+ }
+
+ @Override
+ public void reAlloc() {
+ reallocateBuffers();
+ vector.reAlloc();
+ }
+
+ protected void reallocateBuffers() {
+ reallocOffsetBuffer();
+ reallocSizeBuffer();
+ }
+
+ private void reallocOffsetBuffer() {
+ final long currentBufferCapacity = offsetBuffer.capacity();
+ long newAllocationSize = currentBufferCapacity * 2;
+ if (newAllocationSize == 0) {
+ if (offsetAllocationSizeInBytes > 0) {
+ newAllocationSize = offsetAllocationSizeInBytes;
+ } else {
+ newAllocationSize = INITIAL_VALUE_ALLOCATION * OFFSET_WIDTH * 2;
+ }
+ }
+
+ newAllocationSize = CommonUtil.nextPowerOfTwo(newAllocationSize);
+ newAllocationSize = Math.min(newAllocationSize, (long) OFFSET_WIDTH *
Integer.MAX_VALUE);
+ assert newAllocationSize >= 1;
+
+ if (newAllocationSize > MAX_ALLOCATION_SIZE || newAllocationSize <=
offsetBuffer.capacity()) {
+ throw new OversizedAllocationException("Unable to expand the buffer");
+ }
+
+ final ArrowBuf newBuf = allocator.buffer(newAllocationSize);
+ newBuf.setBytes(0, offsetBuffer, 0, currentBufferCapacity);
+ newBuf.setZero(currentBufferCapacity, newBuf.capacity() -
currentBufferCapacity);
+ offsetBuffer.getReferenceManager().release(1);
+ offsetBuffer = newBuf;
+ offsetAllocationSizeInBytes = newAllocationSize;
+ }
+
+ private void reallocSizeBuffer() {
+ final long currentBufferCapacity = sizeBuffer.capacity();
+ long newAllocationSize = currentBufferCapacity * 2;
+ if (newAllocationSize == 0) {
+ if (sizeAllocationSizeInBytes > 0) {
+ newAllocationSize = sizeAllocationSizeInBytes;
+ } else {
+ newAllocationSize = INITIAL_VALUE_ALLOCATION * SIZE_WIDTH * 2;
+ }
+ }
+
+ newAllocationSize = CommonUtil.nextPowerOfTwo(newAllocationSize);
+ newAllocationSize = Math.min(newAllocationSize, (long) SIZE_WIDTH *
Integer.MAX_VALUE);
+ assert newAllocationSize >= 1;
+
+ if (newAllocationSize > MAX_ALLOCATION_SIZE || newAllocationSize <=
sizeBuffer.capacity()) {
+ throw new OversizedAllocationException("Unable to expand the buffer");
+ }
+
+ final ArrowBuf newBuf = allocator.buffer(newAllocationSize);
+ newBuf.setBytes(0, sizeBuffer, 0, currentBufferCapacity);
+ newBuf.setZero(currentBufferCapacity, newBuf.capacity() -
currentBufferCapacity);
+ sizeBuffer.getReferenceManager().release(1);
+ sizeBuffer = newBuf;
+ sizeAllocationSizeInBytes = newAllocationSize;
+ }
+
+ @Override
+ public FieldVector getDataVector() {
+ return vector;
+ }
+
+ @Override
+ public void setInitialCapacity(int numRecords) {
+ offsetAllocationSizeInBytes = (long) (numRecords) * OFFSET_WIDTH;
+ sizeAllocationSizeInBytes = (long) (numRecords) * SIZE_WIDTH;
+ if (vector instanceof BaseFixedWidthVector || vector instanceof
BaseVariableWidthVector) {
+ vector.setInitialCapacity(numRecords *
RepeatedValueVector.DEFAULT_REPEAT_PER_RECORD);
+ } else {
+ vector.setInitialCapacity(numRecords);
+ }
+ }
+
+ @Override
+ public void setInitialCapacity(int numRecords, double density) {
+ if ((numRecords * density) >= Integer.MAX_VALUE) {
+ throw new OversizedAllocationException("Requested amount of memory is
more than max allowed");
+ }
+
+ offsetAllocationSizeInBytes = (long) numRecords * OFFSET_WIDTH;
+ sizeAllocationSizeInBytes = (long) numRecords * SIZE_WIDTH;
+
+ int innerValueCapacity = Math.max((int) (numRecords * density), 1);
+
+ if (vector instanceof DensityAwareVector) {
+ ((DensityAwareVector) vector).setInitialCapacity(innerValueCapacity,
density);
+ } else {
+ vector.setInitialCapacity(innerValueCapacity);
+ }
+ }
+
+ /**
+ * Specialized version of setInitialTotalCapacity() for LargeListViewVector.
This is used by some
+ * callers when they want to explicitly control and be conservative about
memory allocated for
+ * inner data vector. This is very useful when we are working with memory
constraints for a query
+ * and have a fixed amount of memory reserved for the record batch. In such
cases, we are likely
+ * to face OOM or related problems when we reserve memory for a record batch
with value count x
+ * and do setInitialCapacity(x) such that each vector allocates only what is
necessary and not the
+ * default amount, but the multiplier forces the memory requirement to go
beyond what was needed.
+ *
+ * @param numRecords value count
+ * @param totalNumberOfElements the total number of elements to allow for in
this vector across
+ * all records.
+ */
+ public void setInitialTotalCapacity(int numRecords, int
totalNumberOfElements) {
+ offsetAllocationSizeInBytes = (long) numRecords * OFFSET_WIDTH;
+ sizeAllocationSizeInBytes = (long) numRecords * SIZE_WIDTH;
+ vector.setInitialCapacity(totalNumberOfElements);
+ }
+
+ @Override
+ public int getValueCapacity() {
+ throw new UnsupportedOperationException(
+ "Get value capacity is not supported in RepeatedValueVector");
+ }
+
+ protected int getOffsetBufferValueCapacity() {
+ return checkedCastToInt(offsetBuffer.capacity() / OFFSET_WIDTH);
+ }
+
+ protected int getSizeBufferValueCapacity() {
+ return capAtMaxInt(sizeBuffer.capacity() / SIZE_WIDTH);
+ }
+
+ @Override
+ public int getBufferSize() {
+ if (valueCount == 0) {
+ return 0;
+ }
+ return (valueCount * OFFSET_WIDTH) + (valueCount * SIZE_WIDTH) +
vector.getBufferSize();
+ }
+
+ @Override
+ public int getBufferSizeFor(int valueCount) {
+ if (valueCount == 0) {
+ return 0;
+ }
+
+ int innerVectorValueCount = 0;
+
+ for (int i = 0; i < valueCount; i++) {
+ innerVectorValueCount += sizeBuffer.getInt(i * SIZE_WIDTH);
+ }
+
+ return (valueCount * OFFSET_WIDTH)
+ + (valueCount * SIZE_WIDTH)
+ + vector.getBufferSizeFor(checkedCastToInt(innerVectorValueCount));
+ }
+
+ @Override
+ public Iterator<ValueVector> iterator() {
+ return Collections.<ValueVector>singleton(getDataVector()).iterator();
+ }
+
+ @Override
+ public void clear() {
+ offsetBuffer = releaseBuffer(offsetBuffer);
+ sizeBuffer = releaseBuffer(sizeBuffer);
+ vector.clear();
+ valueCount = 0;
+ super.clear();
+ }
+
+ @Override
+ public void reset() {
+ offsetBuffer.setZero(0, offsetBuffer.capacity());
+ sizeBuffer.setZero(0, sizeBuffer.capacity());
+ vector.reset();
+ valueCount = 0;
+ }
+
+ @Override
+ public ArrowBuf[] getBuffers(boolean clear) {
+ return new ArrowBuf[0];
+ }
+
+ @Override
+ public int getValueCount() {
+ return valueCount;
+ }
+
+ @Override
+ public void setValueCount(int valueCount) {
+ this.valueCount = valueCount;
+ while (valueCount > getOffsetBufferValueCapacity()) {
+ reallocateBuffers();
+ }
+ final int childValueCount = valueCount == 0 ? 0 : getLengthOfChildVector();
+ vector.setValueCount(childValueCount);
+ }
+
+ protected int getLengthOfChildVector() {
+ int maxOffsetSizeSum = offsetBuffer.getInt(0) + sizeBuffer.getInt(0);
+ int minOffset = offsetBuffer.getInt(0);
+ for (int i = 0; i < valueCount; i++) {
+ int currentOffset = offsetBuffer.getInt((long) i * OFFSET_WIDTH);
+ int currentSize = sizeBuffer.getInt((long) i * SIZE_WIDTH);
+ int currentSum = currentOffset + currentSize;
+
+ maxOffsetSizeSum = Math.max(maxOffsetSizeSum, currentSum);
+ minOffset = Math.min(minOffset, currentOffset);
+ }
+
+ return maxOffsetSizeSum - minOffset;
+ }
+
+ protected int getLengthOfChildVectorByIndex(int index) {
+ int maxOffsetSizeSum = offsetBuffer.getInt(0) + sizeBuffer.getInt(0);
+ int minOffset = offsetBuffer.getInt(0);
+ for (int i = 0; i < index; i++) {
+ int currentOffset = offsetBuffer.getInt((long) i * OFFSET_WIDTH);
+ int currentSize = sizeBuffer.getInt((long) i * SIZE_WIDTH);
+ int currentSum = currentOffset + currentSize;
+
+ maxOffsetSizeSum = Math.max(maxOffsetSizeSum, currentSum);
+ minOffset = Math.min(minOffset, currentOffset);
+ }
+
+ return maxOffsetSizeSum - minOffset;
+ }
+
+ /**
+ * Initialize the data vector (and execute callback) if it hasn't already
been done, returns the
+ * data vector.
+ */
+ public <T extends ValueVector> AddOrGetResult<T> addOrGetVector(FieldType
fieldType) {
+ boolean created = false;
+ if (vector instanceof NullVector) {
+ vector = fieldType.createNewSingleVector(defaultDataVectorName,
allocator, repeatedCallBack);
+ // returned vector must have the same field
+ created = true;
+ if (repeatedCallBack != null
+ &&
+ // not a schema change if changing from ZeroVector to ZeroVector
+ (fieldType.getType().getTypeID() != ArrowType.ArrowTypeID.Null)) {
+ repeatedCallBack.doWork();
+ }
+ }
+
+ if (vector.getField().getType().getTypeID() !=
fieldType.getType().getTypeID()) {
+ final String msg =
+ String.format(
+ "Inner vector type mismatch. Requested type: [%s], actual type:
[%s]",
+ fieldType.getType().getTypeID(),
vector.getField().getType().getTypeID());
+ throw new SchemaChangeRuntimeException(msg);
+ }
+
+ return new AddOrGetResult<>((T) vector, created);
+ }
+
+ protected void replaceDataVector(FieldVector v) {
+ vector.clear();
+ vector = v;
+ }
+
+ public abstract boolean isEmpty(int index);
+
+ /**
+ * Start a new value at the given index.
+ *
+ * @param index the index to start the new value at
+ * @return the offset in the data vector where the new value starts
+ */
+ public int startNewValue(int index) {
+ while (index >= getOffsetBufferValueCapacity()) {
+ reallocOffsetBuffer();
+ }
+ while (index >= getSizeBufferValueCapacity()) {
+ reallocSizeBuffer();
+ }
+
+ if (index > 0) {
+ final int prevOffset = getLengthOfChildVectorByIndex(index);
+ offsetBuffer.setInt((long) index * OFFSET_WIDTH, prevOffset);
+ }
+
+ setValueCount(index + 1);
+ return offsetBuffer.getInt((long) index * OFFSET_WIDTH);
+ }
+
+ @Override
+ @Deprecated
+ public UInt4Vector getOffsetVector() {
+ throw new UnsupportedOperationException("There is no inner offset vector");
+ }
+}
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/complex/LargeListViewVector.java
b/java/vector/src/main/java/org/apache/arrow/vector/complex/LargeListViewVector.java
new file mode 100644
index 0000000000..1bb24a53fc
--- /dev/null
+++
b/java/vector/src/main/java/org/apache/arrow/vector/complex/LargeListViewVector.java
@@ -0,0 +1,875 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.arrow.vector.complex;
+
+import static java.util.Collections.singletonList;
+import static org.apache.arrow.memory.util.LargeMemoryUtil.capAtMaxInt;
+import static org.apache.arrow.memory.util.LargeMemoryUtil.checkedCastToInt;
+import static org.apache.arrow.util.Preconditions.checkArgument;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.memory.OutOfMemoryException;
+import org.apache.arrow.memory.util.ArrowBufPointer;
+import org.apache.arrow.memory.util.ByteFunctionHelpers;
+import org.apache.arrow.memory.util.CommonUtil;
+import org.apache.arrow.memory.util.hash.ArrowBufHasher;
+import org.apache.arrow.util.Preconditions;
+import org.apache.arrow.vector.AddOrGetResult;
+import org.apache.arrow.vector.BitVectorHelper;
+import org.apache.arrow.vector.BufferBacked;
+import org.apache.arrow.vector.FieldVector;
+import org.apache.arrow.vector.ValueIterableVector;
+import org.apache.arrow.vector.ValueVector;
+import org.apache.arrow.vector.compare.VectorVisitor;
+import org.apache.arrow.vector.complex.impl.UnionLargeListViewReader;
+import org.apache.arrow.vector.complex.impl.UnionLargeListViewWriter;
+import org.apache.arrow.vector.complex.impl.UnionListReader;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.ipc.message.ArrowFieldNode;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.ArrowType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.CallBack;
+import org.apache.arrow.vector.util.JsonStringArrayList;
+import org.apache.arrow.vector.util.OversizedAllocationException;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * A large list view vector contains lists of a specific type of elements. Its
structure contains 3
+ * elements.
+ *
+ * <ol>
+ * <li>A validity buffer.
+ * <li>An offset buffer, that denotes lists starting positions.
+ * <li>A size buffer, that denotes sizes of the lists.
+ * <li>A child data vector that contains the elements of lists.
+ * </ol>
+ *
+ * This is the LargeListView variant of listview, it has a 64-bit wide offset
+ *
+ * <p>WARNING: Currently Arrow in Java doesn't support 64-bit vectors. This
class follows the
+ * expected behaviour of a LargeList but doesn't actually support allocating a
64-bit vector. It has
+ * little use until 64-bit vectors are supported and should be used with
caution. todo review
+ * checkedCastToInt usage in this class. Once int64 indexed vectors are
supported these checks
+ * aren't needed.
+ */
+public class LargeListViewVector extends BaseLargeRepeatedValueViewVector
+ implements PromotableVector, ValueIterableVector<List<?>> {
+
+ protected ArrowBuf validityBuffer;
+ protected UnionLargeListViewReader reader;
+ private CallBack callBack;
+ protected Field field;
+ protected int validityAllocationSizeInBytes;
+
+ public static LargeListViewVector empty(String name, BufferAllocator
allocator) {
+ return new LargeListViewVector(
+ name, allocator, FieldType.nullable(ArrowType.LargeListView.INSTANCE),
null);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param name The name of the instance.
+ * @param allocator The allocator to use for allocating/reallocating buffers.
+ * @param fieldType The type of this list.
+ * @param callBack A schema change callback.
+ */
+ public LargeListViewVector(
+ String name, BufferAllocator allocator, FieldType fieldType, CallBack
callBack) {
+ this(new Field(name, fieldType, null), allocator, callBack);
+ }
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param field The field materialized by this vector.
+ * @param allocator The allocator to use for allocating/reallocating buffers.
+ * @param callBack A schema change callback.
+ */
+ public LargeListViewVector(Field field, BufferAllocator allocator, CallBack
callBack) {
+ super(field.getName(), allocator, callBack);
+ this.validityBuffer = allocator.getEmpty();
+ this.field = field;
+ this.callBack = callBack;
+ this.validityAllocationSizeInBytes =
getValidityBufferSizeFromCount(INITIAL_VALUE_ALLOCATION);
+ }
+
+ @Override
+ public void initializeChildrenFromFields(List<Field> children) {
+ checkArgument(
+ children.size() == 1,
+ "ListViews have one child Field. Found: %s",
+ children.isEmpty() ? "none" : children);
+
+ Field field = children.get(0);
+ AddOrGetResult<FieldVector> addOrGetVector =
addOrGetVector(field.getFieldType());
+ checkArgument(
+ addOrGetVector.isCreated(), "Child vector already existed: %s",
addOrGetVector.getVector());
+
+
addOrGetVector.getVector().initializeChildrenFromFields(field.getChildren());
+ this.field = new Field(this.field.getName(), this.field.getFieldType(),
children);
+ }
+
+ @Override
+ public void setInitialCapacity(int numRecords) {
+ validityAllocationSizeInBytes = getValidityBufferSizeFromCount(numRecords);
+ super.setInitialCapacity(numRecords);
+ }
+
+ /**
+ * Specialized version of setInitialCapacity() for LargeListViewVector. This
is used by some
+ * callers when they want to explicitly control and be conservative about
memory allocated for
+ * inner data vector. This is very useful when we are working with memory
constraints for a query
+ * and have a fixed amount of memory reserved for the record batch. In such
cases, we are likely
+ * to face OOM or related problems when we reserve memory for a record batch
with value count x
+ * and do setInitialCapacity(x) such that each vector allocates only what is
necessary and not the
+ * default amount, but the multiplier forces the memory requirement to go
beyond what was needed.
+ *
+ * @param numRecords value count
+ * @param density density of LargeListViewVector. Density is the average
size of a list per
+ * position in the LargeListViewVector. For example, a density value of
10 implies each
+ * position in the list vector has a list of 10 values. A density value
of 0.1 implies out of
+ * 10 positions in the list vector, 1 position has a list of size 1, and
the remaining
+ * positions are null (no lists) or empty lists. This helps in tightly
controlling the memory
+ * we provision for inner data vector.
+ */
+ @Override
+ public void setInitialCapacity(int numRecords, double density) {
+ validityAllocationSizeInBytes = getValidityBufferSizeFromCount(numRecords);
+ super.setInitialCapacity(numRecords, density);
+ }
+
+ /**
+ * Specialized version of setInitialTotalCapacity() for LargeListViewVector.
This is used by some
+ * callers when they want to explicitly control and be conservative about
memory allocated for
+ * inner data vector. This is very useful when we are working with memory
constraints for a query
+ * and have a fixed amount of memory reserved for the record batch. In such
cases, we are likely
+ * to face OOM or related problems when we reserve memory for a record batch
with value count x
+ * and do setInitialCapacity(x) such that each vector allocates only what is
necessary and not the
+ * default amount, but the multiplier forces the memory requirement to go
beyond what was needed.
+ *
+ * @param numRecords value count
+ * @param totalNumberOfElements the total number of elements to allow for in
this vector across
+ * all records.
+ */
+ @Override
+ public void setInitialTotalCapacity(int numRecords, int
totalNumberOfElements) {
+ validityAllocationSizeInBytes = getValidityBufferSizeFromCount(numRecords);
+ super.setInitialTotalCapacity(numRecords, totalNumberOfElements);
+ }
+
+ @Override
+ public List<FieldVector> getChildrenFromFields() {
+ return singletonList(getDataVector());
+ }
+
+ /**
+ * Load the buffers associated with this Field.
+ *
+ * @param fieldNode the fieldNode
+ * @param ownBuffers the buffers for this Field (own buffers only, children
not included)
+ */
+ @Override
+ public void loadFieldBuffers(ArrowFieldNode fieldNode, List<ArrowBuf>
ownBuffers) {
+ if (ownBuffers.size() != 3) {
+ throw new IllegalArgumentException(
+ "Illegal buffer count, expected " + 3 + ", got: " +
ownBuffers.size());
+ }
+
+ ArrowBuf bitBuffer = ownBuffers.get(0);
+ ArrowBuf offBuffer = ownBuffers.get(1);
+ ArrowBuf szBuffer = ownBuffers.get(2);
+
+ validityBuffer.getReferenceManager().release();
+ validityBuffer = BitVectorHelper.loadValidityBuffer(fieldNode, bitBuffer,
allocator);
+ offsetBuffer.getReferenceManager().release();
+ offsetBuffer = offBuffer.getReferenceManager().retain(offBuffer,
allocator);
+ sizeBuffer.getReferenceManager().release();
+ sizeBuffer = szBuffer.getReferenceManager().retain(szBuffer, allocator);
+
+ validityAllocationSizeInBytes =
checkedCastToInt(validityBuffer.capacity());
+ offsetAllocationSizeInBytes = offsetBuffer.capacity();
+ sizeAllocationSizeInBytes = sizeBuffer.capacity();
+
+ valueCount = fieldNode.getLength();
+ }
+
+ /** Set the reader and writer indexes for the inner buffers. */
+ private void setReaderAndWriterIndex() {
+ validityBuffer.readerIndex(0);
+ offsetBuffer.readerIndex(0);
+ sizeBuffer.readerIndex(0);
+ if (valueCount == 0) {
+ validityBuffer.writerIndex(0);
+ offsetBuffer.writerIndex(0);
+ sizeBuffer.writerIndex(0);
+ } else {
+ validityBuffer.writerIndex(getValidityBufferSizeFromCount(valueCount));
+ offsetBuffer.writerIndex((long) valueCount * OFFSET_WIDTH);
+ sizeBuffer.writerIndex((long) valueCount * SIZE_WIDTH);
+ }
+ }
+
+ @Override
+ public List<ArrowBuf> getFieldBuffers() {
+ List<ArrowBuf> result = new ArrayList<>(2);
+ setReaderAndWriterIndex();
+ result.add(validityBuffer);
+ result.add(offsetBuffer);
+ result.add(sizeBuffer);
+
+ return result;
+ }
+
+ /**
+ * Export the buffers of the fields for C Data Interface. This method
traverses the buffers and
+ * export buffer and buffer's memory address into a list of buffers and a
pointer to the list of
+ * buffers.
+ */
+ @Override
+ public void exportCDataBuffers(List<ArrowBuf> buffers, ArrowBuf buffersPtr,
long nullValue) {
+ throw new UnsupportedOperationException("exportCDataBuffers Not
implemented yet");
+ }
+
+ @Override
+ public void allocateNew() throws OutOfMemoryException {
+ if (!allocateNewSafe()) {
+ throw new OutOfMemoryException("Failure while allocating memory");
+ }
+ }
+
+ @Override
+ public boolean allocateNewSafe() {
+ boolean success = false;
+ try {
+ /* release the current buffers, hence this is a new allocation
+ * Note that, the `clear` method call below is releasing validityBuffer
+ * calling the superclass clear method which is releasing the associated
buffers
+ * (sizeBuffer and offsetBuffer).
+ */
+ clear();
+ /* allocate validity buffer */
+ allocateValidityBuffer(validityAllocationSizeInBytes);
+ /* allocate offset, data and sizes buffer */
+ success = super.allocateNewSafe();
+ } finally {
+ if (!success) {
+ clear();
+ }
+ }
+ return success;
+ }
+
+ protected void allocateValidityBuffer(final long size) {
+ final int curSize = (int) size;
+ validityBuffer = allocator.buffer(curSize);
+ validityBuffer.readerIndex(0);
+ validityAllocationSizeInBytes = curSize;
+ validityBuffer.setZero(0, validityBuffer.capacity());
+ }
+
+ @Override
+ public void reAlloc() {
+ /* reallocate the validity buffer */
+ reallocValidityBuffer();
+ /* reallocate the offset, size, and data */
+ super.reAlloc();
+ }
+
+ protected void reallocValidityAndSizeAndOffsetBuffers() {
+ reallocateBuffers();
+ reallocValidityBuffer();
+ }
+
+ private void reallocValidityBuffer() {
+ final int currentBufferCapacity =
checkedCastToInt(validityBuffer.capacity());
+ long newAllocationSize = getNewAllocationSize(currentBufferCapacity);
+
+ final ArrowBuf newBuf = allocator.buffer(newAllocationSize);
+ newBuf.setBytes(0, validityBuffer, 0, currentBufferCapacity);
+ newBuf.setZero(currentBufferCapacity, newBuf.capacity() -
currentBufferCapacity);
+ validityBuffer.getReferenceManager().release(1);
+ validityBuffer = newBuf;
+ validityAllocationSizeInBytes = (int) newAllocationSize;
+ }
+
+ private long getNewAllocationSize(int currentBufferCapacity) {
+ long newAllocationSize = currentBufferCapacity * 2L;
+ if (newAllocationSize == 0) {
+ if (validityAllocationSizeInBytes > 0) {
+ newAllocationSize = validityAllocationSizeInBytes;
+ } else {
+ newAllocationSize =
getValidityBufferSizeFromCount(INITIAL_VALUE_ALLOCATION) * 2L;
+ }
+ }
+ newAllocationSize = CommonUtil.nextPowerOfTwo(newAllocationSize);
+ assert newAllocationSize >= 1;
+
+ if (newAllocationSize > MAX_ALLOCATION_SIZE) {
+ throw new OversizedAllocationException("Unable to expand the buffer");
+ }
+ return newAllocationSize;
+ }
+
+ @Override
+ public void copyFromSafe(int inIndex, int outIndex, ValueVector from) {
+ throw new UnsupportedOperationException(
+ "LargeListViewVector does not support copyFromSafe operation yet.");
+ }
+
+ @Override
+ public void copyFrom(int inIndex, int outIndex, ValueVector from) {
+ throw new UnsupportedOperationException(
+ "LargeListViewVector does not support copyFrom operation yet.");
+ }
+
+ @Override
+ public FieldVector getDataVector() {
+ return vector;
+ }
+
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return getTransferPair(ref, allocator, null);
+ }
+
+ @Override
+ public TransferPair getTransferPair(Field field, BufferAllocator allocator) {
+ return getTransferPair(field, allocator, null);
+ }
+
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator,
CallBack callBack) {
+ throw new UnsupportedOperationException(
+ "LargeListViewVector does not support getTransferPair(String,
BufferAllocator, CallBack) yet");
+ }
+
+ @Override
+ public TransferPair getTransferPair(Field field, BufferAllocator allocator,
CallBack callBack) {
+ throw new UnsupportedOperationException(
+ "LargeListViewVector does not support getTransferPair(Field,
BufferAllocator, CallBack) yet");
+ }
+
+ @Override
+ public TransferPair makeTransferPair(ValueVector target) {
+ throw new UnsupportedOperationException(
+ "LargeListViewVector does not support makeTransferPair(ValueVector)
yet");
+ }
+
+ @Override
+ public long getValidityBufferAddress() {
+ return validityBuffer.memoryAddress();
+ }
+
+ @Override
+ public long getDataBufferAddress() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public long getOffsetBufferAddress() {
+ return offsetBuffer.memoryAddress();
+ }
+
+ @Override
+ public ArrowBuf getValidityBuffer() {
+ return validityBuffer;
+ }
+
+ @Override
+ public ArrowBuf getDataBuffer() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ArrowBuf getOffsetBuffer() {
+ return offsetBuffer;
+ }
+
+ public ArrowBuf getSizeBuffer() {
+ return sizeBuffer;
+ }
+
+ public long getSizeBufferAddress() {
+ return sizeBuffer.memoryAddress();
+ }
+
+ /**
+ * Get the hash code for the element at the given index.
+ *
+ * @param index position of the element
+ * @return hash code for the element at the given index
+ */
+ @Override
+ public int hashCode(int index) {
+ return hashCode(index, null);
+ }
+
+ /**
+ * Get the hash code for the element at the given index.
+ *
+ * @param index position of the element
+ * @param hasher hasher to use
+ * @return hash code for the element at the given index
+ */
+ @Override
+ public int hashCode(int index, ArrowBufHasher hasher) {
+ if (isSet(index) == 0) {
+ return ArrowBufPointer.NULL_HASH_CODE;
+ }
+ int hash = 0;
+ final int start = offsetBuffer.getInt((long) index * OFFSET_WIDTH);
+ final int end = sizeBuffer.getInt((long) index * OFFSET_WIDTH);
+ for (int i = start; i < end; i++) {
+ hash = ByteFunctionHelpers.combineHash(hash,
vector.hashCode(checkedCastToInt(i), hasher));
+ }
+ return hash;
+ }
+
+ @Override
+ public <OUT, IN> OUT accept(VectorVisitor<OUT, IN> visitor, IN value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected FieldReader getReaderImpl() {
+ throw new UnsupportedOperationException(
+ "LargeListViewVector does not support getReaderImpl operation yet.");
+ }
+
+ @Override
+ public UnionListReader getReader() {
+ throw new UnsupportedOperationException(
+ "LargeListViewVector does not support getReader operation yet.");
+ }
+
+ /**
+ * Get the size (number of bytes) of underlying buffers used by this vector.
+ *
+ * @return size of underlying buffers.
+ */
+ @Override
+ public int getBufferSize() {
+ if (valueCount == 0) {
+ return 0;
+ }
+ final int offsetBufferSize = valueCount * OFFSET_WIDTH;
+ final int sizeBufferSize = valueCount * SIZE_WIDTH;
+ final int validityBufferSize = getValidityBufferSizeFromCount(valueCount);
+ return offsetBufferSize + sizeBufferSize + validityBufferSize +
vector.getBufferSize();
+ }
+
+ /**
+ * Get the size (number of bytes) of underlying buffers used by this.
+ *
+ * @param valueCount the number of values to assume this vector contains
+ * @return size of underlying buffers.
+ */
+ @Override
+ public int getBufferSizeFor(int valueCount) {
+ if (valueCount == 0) {
+ return 0;
+ }
+ final int validityBufferSize = getValidityBufferSizeFromCount(valueCount);
+
+ return super.getBufferSizeFor(valueCount) + validityBufferSize;
+ }
+
+ /**
+ * Get the field associated with the list view vector.
+ *
+ * @return the field
+ */
+ @Override
+ public Field getField() {
+ if (field.getChildren().contains(getDataVector().getField())) {
+ return field;
+ }
+ field =
+ new Field(
+ field.getName(),
+ field.getFieldType(),
+ Collections.singletonList(getDataVector().getField()));
+ return field;
+ }
+
+ /**
+ * Get the minor type for the vector.
+ *
+ * @return the minor type
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.LARGELISTVIEW;
+ }
+
+ /** Clear the vector data. */
+ @Override
+ public void clear() {
+ // calling superclass clear method which is releasing the sizeBufer and
offsetBuffer
+ super.clear();
+ validityBuffer = releaseBuffer(validityBuffer);
+ }
+
+ /** Release the buffers associated with this vector. */
+ @Override
+ public void reset() {
+ super.reset();
+ validityBuffer.setZero(0, validityBuffer.capacity());
+ }
+
+ /**
+ * Return the underlying buffers associated with this vector. Note that this
doesn't impact the
+ * reference counts for this buffer, so it only should be used for
in-context access. Also note
+ * that this buffer changes regularly, thus external classes shouldn't hold
a reference to it
+ * (unless they change it).
+ *
+ * @param clear Whether to clear vector before returning, the buffers will
still be refcounted but
+ * the returned array will be the only reference to them
+ * @return The underlying {@link ArrowBuf buffers} that is used by this
vector instance.
+ */
+ @Override
+ public ArrowBuf[] getBuffers(boolean clear) {
+ setReaderAndWriterIndex();
+ final ArrowBuf[] buffers;
+ if (getBufferSize() == 0) {
+ buffers = new ArrowBuf[0];
+ } else {
+ List<ArrowBuf> list = new ArrayList<>();
+ // the order must be validity, offset and size buffers
+ list.add(validityBuffer);
+ list.add(offsetBuffer);
+ list.add(sizeBuffer);
+ list.addAll(Arrays.asList(vector.getBuffers(clear)));
+ buffers = list.toArray(new ArrowBuf[list.size()]);
+ }
+ if (clear) {
+ for (ArrowBuf buffer : buffers) {
+ buffer.getReferenceManager().retain();
+ }
+ clear();
+ }
+ return buffers;
+ }
+
+ /**
+ * Get the element in the list view vector at a particular index.
+ *
+ * @param index position of the element
+ * @return Object at given position
+ */
+ @Override
+ public List<?> getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ }
+ final List<Object> vals = new JsonStringArrayList<>();
+ final int start = offsetBuffer.getInt(index * OFFSET_WIDTH);
+ final int end = start + sizeBuffer.getInt((index) * SIZE_WIDTH);
+ final ValueVector vv = getDataVector();
+ for (int i = start; i < end; i++) {
+ vals.add(vv.getObject(checkedCastToInt(i)));
+ }
+
+ return vals;
+ }
+
+ /**
+ * Check if an element at given index is null.
+ *
+ * @param index position of an element
+ * @return true if an element at given index is null, false otherwise
+ */
+ @Override
+ public boolean isNull(int index) {
+ return (isSet(index) == 0);
+ }
+
+ /**
+ * Check if an element at given index is an empty list.
+ *
+ * @param index position of an element
+ * @return true if an element at given index is an empty list or NULL, false
otherwise
+ */
+ @Override
+ public boolean isEmpty(int index) {
+ if (isNull(index)) {
+ return true;
+ } else {
+ return sizeBuffer.getInt(index * SIZE_WIDTH) == 0;
+ }
+ }
+
+ /**
+ * Same as {@link #isNull(int)}.
+ *
+ * @param index position of the element
+ * @return 1 if element at given index is not null, 0 otherwise
+ */
+ public int isSet(int index) {
+ final int byteIndex = index >> 3;
+ final byte b = validityBuffer.getByte(byteIndex);
+ final int bitIndex = index & 7;
+ return (b >> bitIndex) & 0x01;
+ }
+
+ /**
+ * Get the number of elements that are null in the vector.
+ *
+ * @return the number of null elements.
+ */
+ @Override
+ public int getNullCount() {
+ return BitVectorHelper.getNullCount(validityBuffer, valueCount);
+ }
+
+ /**
+ * Get the value capacity by considering validity and offset capacity. Note
that the size buffer
+ * capacity is not considered here since it has the same capacity as the
offset buffer.
+ *
+ * @return the value capacity
+ */
+ @Override
+ public int getValueCapacity() {
+ return getValidityAndOffsetValueCapacity();
+ }
+
+ private int getValidityAndSizeValueCapacity() {
+ final int offsetValueCapacity = Math.max(getOffsetBufferValueCapacity(),
0);
+ final int sizeValueCapacity = Math.max(getSizeBufferValueCapacity(), 0);
+ return Math.min(offsetValueCapacity, sizeValueCapacity);
+ }
+
+ private int getValidityAndOffsetValueCapacity() {
+ final int offsetValueCapacity = Math.max(getOffsetBufferValueCapacity(),
0);
+ return Math.min(offsetValueCapacity, getValidityBufferValueCapacity());
+ }
+
+ private int getValidityBufferValueCapacity() {
+ return capAtMaxInt(validityBuffer.capacity() * 8);
+ }
+
+ /**
+ * Set the element at the given index to null.
+ *
+ * @param index the value to change
+ */
+ @Override
+ public void setNull(int index) {
+ while (index >= getValidityAndSizeValueCapacity()) {
+ reallocValidityAndSizeAndOffsetBuffers();
+ }
+
+ offsetBuffer.setInt(index * OFFSET_WIDTH, 0);
+ sizeBuffer.setInt(index * SIZE_WIDTH, 0);
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+
+ /**
+ * Start new value in the ListView vector.
+ *
+ * @param index index of the value to start
+ * @return offset of the new value
+ */
+ @Override
+ public int startNewValue(int index) {
+ while (index >= getValidityAndSizeValueCapacity()) {
+ reallocValidityAndSizeAndOffsetBuffers();
+ }
+
+ if (index > 0) {
+ final int prevOffset = getLengthOfChildVectorByIndex(index);
+ offsetBuffer.setInt(index * OFFSET_WIDTH, prevOffset);
+ }
+
+ BitVectorHelper.setBit(validityBuffer, index);
+ return offsetBuffer.getInt(index * OFFSET_WIDTH);
+ }
+
+ /**
+ * Validate the invariants of the offset and size buffers. 0 <= offsets[i]
<= length of the child
+ * array 0 <= offsets[i] + size[i] <= length of the child array
+ *
+ * @param offset the offset at a given index
+ * @param size the size at a given index
+ */
+ private void validateInvariants(int offset, int size) {
+ if (offset < 0) {
+ throw new IllegalArgumentException("Offset cannot be negative");
+ }
+
+ if (size < 0) {
+ throw new IllegalArgumentException("Size cannot be negative");
+ }
+
+ // 0 <= offsets[i] <= length of the child array
+ if (offset > this.vector.getValueCount()) {
+ throw new IllegalArgumentException("Offset is out of bounds.");
+ }
+
+ // 0 <= offsets[i] + size[i] <= length of the child array
+ if (offset + size > this.vector.getValueCount()) {
+ throw new IllegalArgumentException("Offset + size <= length of the child
array.");
+ }
+ }
+
+ /**
+ * Set the offset at the given index. Make sure to use this function after
updating `field` vector
+ * and using `setValidity`
+ *
+ * @param index index of the value to set
+ * @param value value to set
+ */
+ public void setOffset(int index, int value) {
+ validateInvariants(value, sizeBuffer.getInt(index * SIZE_WIDTH));
+
+ offsetBuffer.setInt(index * OFFSET_WIDTH, value);
+ }
+
+ /**
+ * Set the size at the given index. Make sure to use this function after
using `setOffset`.
+ *
+ * @param index index of the value to set
+ * @param value value to set
+ */
+ public void setSize(int index, int value) {
+ validateInvariants(offsetBuffer.getInt(index * SIZE_WIDTH), value);
+
+ sizeBuffer.setInt(index * SIZE_WIDTH, value);
+ }
+
+ /**
+ * Set the validity at the given index.
+ *
+ * @param index index of the value to set
+ * @param value value to set (0 for unset and 1 for a set)
+ */
+ public void setValidity(int index, int value) {
+ if (value == 0) {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ } else {
+ BitVectorHelper.setBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Sets the value count for the vector.
+ *
+ * <p>Important note: The underlying vector does not support 64-bit
allocations yet. This may
+ * throw if attempting to hold larger than what a 32-bit vector can store.
+ *
+ * @param valueCount value count
+ */
+ @Override
+ public void setValueCount(int valueCount) {
+ this.valueCount = valueCount;
+ if (valueCount > 0) {
+ while (valueCount > getValidityAndSizeValueCapacity()) {
+ /* check if validity and offset buffers need to be re-allocated */
+ reallocValidityAndSizeAndOffsetBuffers();
+ }
+ }
+ /* valueCount for the data vector is the current end offset */
+ final long childValueCount = (valueCount == 0) ? 0 :
getLengthOfChildVector();
+ /* set the value count of data vector and this will take care of
+ * checking whether data buffer needs to be reallocated.
+ * TODO: revisit when 64-bit vectors are supported
+ */
+ Preconditions.checkArgument(
+ childValueCount <= Integer.MAX_VALUE && childValueCount >= 0,
+ "LargeListViewVector doesn't yet support 64-bit allocations: %s",
+ childValueCount);
+ vector.setValueCount((int) childValueCount);
+ }
+
+ @Override
+ public <T extends ValueVector> AddOrGetResult<T> addOrGetVector(FieldType
fieldType) {
+ AddOrGetResult<T> result = super.addOrGetVector(fieldType);
+ invalidateReader();
+ return result;
+ }
+
+ @Override
+ public UnionVector promoteToUnion() {
+ UnionVector vector = new UnionVector("$data$", allocator, /* field type*/
null, callBack);
+ replaceDataVector(vector);
+ invalidateReader();
+ if (callBack != null) {
+ callBack.doWork();
+ }
+ return vector;
+ }
+
+ private void invalidateReader() {
+ reader = null;
+ }
+
+ @Deprecated
+ @Override
+ public List<BufferBacked> getFieldInnerVectors() {
+ throw new UnsupportedOperationException("There are no inner vectors. Use
getFieldBuffers");
+ }
+
+ public UnionLargeListViewWriter getWriter() {
+ return new UnionLargeListViewWriter(this);
+ }
+
+ @Override
+ public int getValueCount() {
+ return valueCount;
+ }
+
+ /**
+ * Get the density of this LargeListViewVector.
+ *
+ * @return density
+ */
+ public double getDensity() {
+ if (valueCount == 0) {
+ return 0.0D;
+ }
+ final double totalListSize = getLengthOfChildVector();
+ return totalListSize / valueCount;
+ }
+
+ /** Validating LargeListViewVector creation based on the specification
guideline. */
+ @Override
+ public void validate() {
+ for (int i = 0; i < valueCount; i++) {
+ final int offset = offsetBuffer.getInt((long) i * OFFSET_WIDTH);
+ final int size = sizeBuffer.getInt((long) i * SIZE_WIDTH);
+ validateInvariants(offset, size);
+ }
+ }
+
+ /**
+ * End the current value.
+ *
+ * @param index index of the value to end
+ * @param size number of elements in the list that was written
+ */
+ public void endValue(int index, int size) {
+ sizeBuffer.setInt((long) index * SIZE_WIDTH, size);
+ }
+}
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/complex/impl/UnionLargeListViewReader.java
b/java/vector/src/main/java/org/apache/arrow/vector/complex/impl/UnionLargeListViewReader.java
new file mode 100644
index 0000000000..4bcd028de3
--- /dev/null
+++
b/java/vector/src/main/java/org/apache/arrow/vector/complex/impl/UnionLargeListViewReader.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.arrow.vector.complex.impl;
+
+import static org.apache.arrow.memory.util.LargeMemoryUtil.checkedCastToInt;
+
+import org.apache.arrow.vector.ValueVector;
+import org.apache.arrow.vector.complex.BaseLargeRepeatedValueViewVector;
+import org.apache.arrow.vector.complex.LargeListViewVector;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.UnionHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+
+/** {@link FieldReader} for largeListView of union types. */
+public class UnionLargeListViewReader extends AbstractFieldReader {
+
+ private final LargeListViewVector vector;
+ private final ValueVector data;
+ private int currentOffset;
+ private int size;
+
+ /**
+ * Constructor for UnionLargeListViewReader.
+ *
+ * @param vector the vector to read from
+ */
+ public UnionLargeListViewReader(LargeListViewVector vector) {
+ this.vector = vector;
+ this.data = vector.getDataVector();
+ }
+
+ @Override
+ public Field getField() {
+ return vector.getField();
+ }
+
+ @Override
+ public boolean isSet() {
+ return !vector.isNull(idx());
+ }
+
+ @Override
+ public void setPosition(int index) {
+ super.setPosition(index);
+ if (vector.getOffsetBuffer().capacity() == 0) {
+ currentOffset = 0;
+ size = 0;
+ } else {
+ currentOffset =
+ vector
+ .getOffsetBuffer()
+ .getInt(index * (long)
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH);
+ size =
+ vector.getSizeBuffer().getInt(index * (long)
BaseLargeRepeatedValueViewVector.SIZE_WIDTH);
+ }
+ }
+
+ @Override
+ public FieldReader reader() {
+ return data.getReader();
+ }
+
+ @Override
+ public Object readObject() {
+ return vector.getObject(idx());
+ }
+
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.LISTVIEW;
+ }
+
+ @Override
+ public void read(int index, UnionHolder holder) {
+ setPosition(idx());
+ for (int i = -1; i < index; i++) {
+ next();
+ }
+ holder.reader = data.getReader();
+ holder.isSet = data.getReader().isSet() ? 1 : 0;
+ }
+
+ @Override
+ public int size() {
+ return Math.max(size, 0);
+ }
+
+ @Override
+ public boolean next() {
+ // Here, the currentOffSet keeps track of the current position in the
vector inside the list at
+ // set position.
+ // And, size keeps track of the elements count in the list, so to make
sure we traverse
+ // the full list, we need to check if the currentOffset is less than the
currentOffset + size
+ if (currentOffset < currentOffset + size) {
+ data.getReader().setPosition(checkedCastToInt(currentOffset++));
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git
a/java/vector/src/main/java/org/apache/arrow/vector/extension/OpaqueType.java
b/java/vector/src/main/java/org/apache/arrow/vector/extension/OpaqueType.java
index a0e898a543..f4f06dad2a 100644
---
a/java/vector/src/main/java/org/apache/arrow/vector/extension/OpaqueType.java
+++
b/java/vector/src/main/java/org/apache/arrow/vector/extension/OpaqueType.java
@@ -389,5 +389,10 @@ public class OpaqueType extends ArrowType.ExtensionType {
public FieldVector visit(ListView type) {
throw unsupported(type);
}
+
+ @Override
+ public FieldVector visit(LargeListView type) {
+ throw unsupported(type);
+ }
}
}
diff --git a/java/vector/src/main/java/org/apache/arrow/vector/types/Types.java
b/java/vector/src/main/java/org/apache/arrow/vector/types/Types.java
index ed099890e1..6b2c56de01 100644
--- a/java/vector/src/main/java/org/apache/arrow/vector/types/Types.java
+++ b/java/vector/src/main/java/org/apache/arrow/vector/types/Types.java
@@ -69,6 +69,7 @@ import org.apache.arrow.vector.ViewVarCharVector;
import org.apache.arrow.vector.complex.DenseUnionVector;
import org.apache.arrow.vector.complex.FixedSizeListVector;
import org.apache.arrow.vector.complex.LargeListVector;
+import org.apache.arrow.vector.complex.LargeListViewVector;
import org.apache.arrow.vector.complex.ListVector;
import org.apache.arrow.vector.complex.ListViewVector;
import org.apache.arrow.vector.complex.MapVector;
@@ -111,6 +112,7 @@ import org.apache.arrow.vector.complex.impl.UInt1WriterImpl;
import org.apache.arrow.vector.complex.impl.UInt2WriterImpl;
import org.apache.arrow.vector.complex.impl.UInt4WriterImpl;
import org.apache.arrow.vector.complex.impl.UInt8WriterImpl;
+import org.apache.arrow.vector.complex.impl.UnionLargeListViewWriter;
import org.apache.arrow.vector.complex.impl.UnionLargeListWriter;
import org.apache.arrow.vector.complex.impl.UnionListWriter;
import org.apache.arrow.vector.complex.impl.UnionWriter;
@@ -134,6 +136,7 @@ import
org.apache.arrow.vector.types.pojo.ArrowType.FloatingPoint;
import org.apache.arrow.vector.types.pojo.ArrowType.Int;
import org.apache.arrow.vector.types.pojo.ArrowType.Interval;
import org.apache.arrow.vector.types.pojo.ArrowType.LargeBinary;
+import org.apache.arrow.vector.types.pojo.ArrowType.LargeListView;
import org.apache.arrow.vector.types.pojo.ArrowType.LargeUtf8;
import org.apache.arrow.vector.types.pojo.ArrowType.List;
import org.apache.arrow.vector.types.pojo.ArrowType.ListView;
@@ -645,6 +648,19 @@ public class Types {
return new UnionLargeListWriter((LargeListVector) vector);
}
},
+ LARGELISTVIEW(ArrowType.LargeListView.INSTANCE) {
+ @Override
+ public FieldVector getNewVector(
+ Field field, BufferAllocator allocator, CallBack
schemaChangeCallback) {
+ return new LargeListViewVector(
+ field.getName(), allocator, field.getFieldType(),
schemaChangeCallback);
+ }
+
+ @Override
+ public FieldWriter getNewFieldWriter(ValueVector vector) {
+ return new UnionLargeListViewWriter((LargeListViewVector) vector);
+ }
+ },
FIXED_SIZE_LIST(null) {
@Override
public FieldVector getNewVector(
@@ -996,6 +1012,11 @@ public class Types {
return MinorType.LISTVIEW;
}
+ @Override
+ public MinorType visit(LargeListView type) {
+ return MinorType.LARGELISTVIEW;
+ }
+
@Override
public MinorType visit(ExtensionType type) {
return MinorType.EXTENSIONTYPE;
diff --git
a/java/vector/src/test/java/org/apache/arrow/vector/TestLargeListViewVector.java
b/java/vector/src/test/java/org/apache/arrow/vector/TestLargeListViewVector.java
new file mode 100644
index 0000000000..563ac811c4
--- /dev/null
+++
b/java/vector/src/test/java/org/apache/arrow/vector/TestLargeListViewVector.java
@@ -0,0 +1,1649 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.arrow.vector;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.BaseLargeRepeatedValueViewVector;
+import org.apache.arrow.vector.complex.LargeListViewVector;
+import org.apache.arrow.vector.complex.impl.UnionLargeListViewWriter;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.ArrowType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+public class TestLargeListViewVector {
+
+ private BufferAllocator allocator;
+
+ @BeforeEach
+ public void init() {
+ allocator = new DirtyRootAllocator(Long.MAX_VALUE, (byte) 100);
+ }
+
+ @AfterEach
+ public void terminate() throws Exception {
+ allocator.close();
+ }
+
+ @Test
+ public void testBasicLargeListViewVector() {
+ try (LargeListViewVector largeListViewVector =
+ LargeListViewVector.empty("sourceVector", allocator)) {
+ UnionLargeListViewWriter largeListViewWriter =
largeListViewVector.getWriter();
+
+ /* allocate memory */
+ largeListViewWriter.allocate();
+
+ /* write the first list at index 0 */
+ largeListViewWriter.setPosition(0);
+ largeListViewWriter.startListView();
+
+ largeListViewWriter.bigInt().writeBigInt(12);
+ largeListViewWriter.bigInt().writeBigInt(-7);
+ largeListViewWriter.bigInt().writeBigInt(25);
+ largeListViewWriter.endListView();
+
+ /* the second list at index 1 is null (we are not setting any)*/
+
+ /* write the third list at index 2 */
+ largeListViewWriter.setPosition(2);
+ largeListViewWriter.startListView();
+
+ largeListViewWriter.bigInt().writeBigInt(0);
+ largeListViewWriter.bigInt().writeBigInt(-127);
+ largeListViewWriter.bigInt().writeBigInt(127);
+ largeListViewWriter.bigInt().writeBigInt(50);
+ largeListViewWriter.endListView();
+
+ /* write the fourth list at index 3 (empty list) */
+ largeListViewWriter.setPosition(3);
+ largeListViewWriter.startListView();
+ largeListViewWriter.endListView();
+
+ /* write the fifth list at index 4 */
+ largeListViewWriter.setPosition(4);
+ largeListViewWriter.startListView();
+ largeListViewWriter.bigInt().writeBigInt(1);
+ largeListViewWriter.bigInt().writeBigInt(2);
+ largeListViewWriter.bigInt().writeBigInt(3);
+ largeListViewWriter.bigInt().writeBigInt(4);
+ largeListViewWriter.endListView();
+
+ largeListViewWriter.setValueCount(5);
+ // check value count
+ assertEquals(5, largeListViewVector.getValueCount());
+
+ /* get vector at index 0 -- the value is a BigIntVector*/
+ final ArrowBuf offSetBuffer = largeListViewVector.getOffsetBuffer();
+ final ArrowBuf sizeBuffer = largeListViewVector.getSizeBuffer();
+ final FieldVector dataVec = largeListViewVector.getDataVector();
+
+ // check offset buffer
+ assertEquals(0, offSetBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(0, offSetBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(3, offSetBuffer.getInt(2 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(7, offSetBuffer.getInt(3 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(7, offSetBuffer.getInt(4 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+
+ // check size buffer
+ assertEquals(3, sizeBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(4, sizeBuffer.getInt(2 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(3 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(4, sizeBuffer.getInt(4 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+
+ // check data vector
+ assertEquals(12, ((BigIntVector) dataVec).get(0));
+ assertEquals(-7, ((BigIntVector) dataVec).get(1));
+ assertEquals(25, ((BigIntVector) dataVec).get(2));
+ assertEquals(0, ((BigIntVector) dataVec).get(3));
+ assertEquals(-127, ((BigIntVector) dataVec).get(4));
+ assertEquals(127, ((BigIntVector) dataVec).get(5));
+ assertEquals(50, ((BigIntVector) dataVec).get(6));
+ assertEquals(1, ((BigIntVector) dataVec).get(7));
+ assertEquals(2, ((BigIntVector) dataVec).get(8));
+ assertEquals(3, ((BigIntVector) dataVec).get(9));
+ assertEquals(4, ((BigIntVector) dataVec).get(10));
+
+ largeListViewVector.validate();
+ }
+ }
+
+ @Test
+ public void testImplicitNullVectors() {
+ try (LargeListViewVector largeListViewVector =
+ LargeListViewVector.empty("sourceVector", allocator)) {
+ UnionLargeListViewWriter largeListViewWriter =
largeListViewVector.getWriter();
+ /* allocate memory */
+ largeListViewWriter.allocate();
+
+ final ArrowBuf offSetBuffer = largeListViewVector.getOffsetBuffer();
+ final ArrowBuf sizeBuffer = largeListViewVector.getSizeBuffer();
+
+ /* write the first list at index 0 */
+ largeListViewWriter.setPosition(0);
+ largeListViewWriter.startListView();
+
+ largeListViewWriter.bigInt().writeBigInt(12);
+ largeListViewWriter.bigInt().writeBigInt(-7);
+ largeListViewWriter.bigInt().writeBigInt(25);
+ largeListViewWriter.endListView();
+
+ int offSet0 = offSetBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH);
+ int size0 = sizeBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH);
+
+ // after the first list is written,
+ // the initial offset must be 0,
+ // the size must be 3 (as there are 3 elements in the array),
+ // the lastSet must be 0 since, the first list is written at index 0.
+
+ assertEquals(0, offSet0);
+ assertEquals(3, size0);
+
+ largeListViewWriter.setPosition(5);
+ largeListViewWriter.startListView();
+
+ // writing the 6th list at index 5,
+ // and the list items from index 1 through 4 are not populated.
+ // but since there is a gap between the 0th and 5th list, in terms
+ // of buffer allocation, the offset and size buffers must be updated
+ // to reflect the implicit null vectors.
+
+ for (int i = 1; i < 5; i++) {
+ int offSet = offSetBuffer.getInt(i *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH);
+ int size = sizeBuffer.getInt(i *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH);
+ // Since the list is not written, the offset and size must equal to
child vector's size
+ // i.e., 3, and size should be 0 as the list is not written.
+ // And the last set value is the value currently being written, which
is 5.
+ assertEquals(0, offSet);
+ assertEquals(0, size);
+ }
+
+ largeListViewWriter.bigInt().writeBigInt(12);
+ largeListViewWriter.bigInt().writeBigInt(25);
+ largeListViewWriter.endListView();
+
+ int offSet5 = offSetBuffer.getInt(5 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH);
+ int size5 = sizeBuffer.getInt(5 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH);
+
+ assertEquals(3, offSet5);
+ assertEquals(2, size5);
+
+ largeListViewWriter.setPosition(10);
+ largeListViewWriter.startListView();
+
+ // writing the 11th list at index 10,
+ // and the list items from index 6 through 10 are not populated.
+ // but since there is a gap between the 5th and 11th list, in terms
+ // of buffer allocation, the offset and size buffers must be updated
+ // to reflect the implicit null vectors.
+ for (int i = 6; i < 10; i++) {
+ int offSet = offSetBuffer.getInt(i *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH);
+ int size = sizeBuffer.getInt(i *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH);
+ // Since the list is not written, the offset and size must equal to 0
+ // and size should be 0 as the list is not written.
+ // And the last set value is the value currently being written, which
is 10.
+ assertEquals(0, offSet);
+ assertEquals(0, size);
+ }
+
+ largeListViewWriter.bigInt().writeBigInt(12);
+ largeListViewWriter.endListView();
+
+ int offSet11 = offSetBuffer.getInt(10 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH);
+ int size11 = sizeBuffer.getInt(10 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH);
+
+ assertEquals(5, offSet11);
+ assertEquals(1, size11);
+
+ largeListViewVector.setValueCount(11);
+
+ largeListViewVector.validate();
+ }
+ }
+
+ @Test
+ public void testNestedLargeListViewVector() throws Exception {
+ try (LargeListViewVector largeListViewVector =
+ LargeListViewVector.empty("sourceVector", allocator)) {
+
+ UnionLargeListViewWriter largeListViewWriter =
largeListViewVector.getWriter();
+
+ /* allocate memory */
+ largeListViewWriter.allocate();
+
+ /* the dataVector that backs a largeListViewVector will also be a
+ * largeListViewVector for this test.
+ */
+
+ /* write one or more inner lists at index 0 */
+ largeListViewWriter.setPosition(0);
+ largeListViewWriter.startListView();
+
+ largeListViewWriter.listView().startListView();
+ largeListViewWriter.listView().bigInt().writeBigInt(50);
+ largeListViewWriter.listView().bigInt().writeBigInt(100);
+ largeListViewWriter.listView().bigInt().writeBigInt(200);
+ largeListViewWriter.listView().endListView();
+
+ largeListViewWriter.listView().startListView();
+ largeListViewWriter.listView().bigInt().writeBigInt(75);
+ largeListViewWriter.listView().bigInt().writeBigInt(125);
+ largeListViewWriter.listView().bigInt().writeBigInt(150);
+ largeListViewWriter.listView().bigInt().writeBigInt(175);
+ largeListViewWriter.listView().endListView();
+
+ largeListViewWriter.endListView();
+
+ /* write one or more inner lists at index 1 */
+ largeListViewWriter.setPosition(1);
+ largeListViewWriter.startListView();
+
+ largeListViewWriter.listView().startListView();
+ largeListViewWriter.listView().bigInt().writeBigInt(10);
+ largeListViewWriter.listView().endListView();
+
+ largeListViewWriter.listView().startListView();
+ largeListViewWriter.listView().bigInt().writeBigInt(15);
+ largeListViewWriter.listView().bigInt().writeBigInt(20);
+ largeListViewWriter.listView().endListView();
+
+ largeListViewWriter.listView().startListView();
+ largeListViewWriter.listView().bigInt().writeBigInt(25);
+ largeListViewWriter.listView().bigInt().writeBigInt(30);
+ largeListViewWriter.listView().bigInt().writeBigInt(35);
+ largeListViewWriter.listView().endListView();
+
+ largeListViewWriter.endListView();
+
+ largeListViewVector.setValueCount(2);
+
+ assertEquals(2, largeListViewVector.getValueCount());
+
+ /* get largeListViewVector value at index 0 -- the value itself is a
largeListViewVector */
+ Object result = largeListViewVector.getObject(0);
+ ArrayList<ArrayList<Long>> resultSet = (ArrayList<ArrayList<Long>>)
result;
+ ArrayList<Long> list;
+
+ assertEquals(2, resultSet.size()); /* 2 inner lists at index 0 */
+ assertEquals(3, resultSet.get(0).size()); /* size of first inner list */
+ assertEquals(4, resultSet.get(1).size()); /* size of second inner list */
+
+ list = resultSet.get(0);
+ assertEquals(Long.valueOf(50), list.get(0));
+ assertEquals(Long.valueOf(100), list.get(1));
+ assertEquals(Long.valueOf(200), list.get(2));
+
+ list = resultSet.get(1);
+ assertEquals(Long.valueOf(75), list.get(0));
+ assertEquals(Long.valueOf(125), list.get(1));
+ assertEquals(Long.valueOf(150), list.get(2));
+ assertEquals(Long.valueOf(175), list.get(3));
+
+ /* get largeListViewVector value at index 1 -- the value itself is a
largeListViewVector */
+ result = largeListViewVector.getObject(1);
+ resultSet = (ArrayList<ArrayList<Long>>) result;
+
+ assertEquals(3, resultSet.size()); /* 3 inner lists at index 1 */
+ assertEquals(1, resultSet.get(0).size()); /* size of first inner list */
+ assertEquals(2, resultSet.get(1).size()); /* size of second inner list */
+ assertEquals(3, resultSet.get(2).size()); /* size of third inner list */
+
+ list = resultSet.get(0);
+ assertEquals(Long.valueOf(10), list.get(0));
+
+ list = resultSet.get(1);
+ assertEquals(Long.valueOf(15), list.get(0));
+ assertEquals(Long.valueOf(20), list.get(1));
+
+ list = resultSet.get(2);
+ assertEquals(Long.valueOf(25), list.get(0));
+ assertEquals(Long.valueOf(30), list.get(1));
+ assertEquals(Long.valueOf(35), list.get(2));
+
+ /* check underlying bitVector */
+ assertFalse(largeListViewVector.isNull(0));
+ assertFalse(largeListViewVector.isNull(1));
+
+ /* check underlying offsets */
+ final ArrowBuf offsetBuffer = largeListViewVector.getOffsetBuffer();
+
+ /* largeListViewVector has 2 lists at index 0 and 3 lists at index 1 */
+ assertEquals(0, offsetBuffer.getLong(0 *
LargeListViewVector.OFFSET_WIDTH));
+ assertEquals(2, offsetBuffer.getLong(1 *
LargeListViewVector.OFFSET_WIDTH));
+ }
+ }
+
+ @Test
+ public void testNestedLargeListViewVector1() {
+ try (LargeListViewVector largeListViewVector =
+ LargeListViewVector.empty("sourceVector", allocator)) {
+
+ MinorType listViewType = MinorType.LARGELISTVIEW;
+ MinorType scalarType = MinorType.BIGINT;
+
+
largeListViewVector.addOrGetVector(FieldType.nullable(listViewType.getType()));
+
+ LargeListViewVector innerList1 = (LargeListViewVector)
largeListViewVector.getDataVector();
+ innerList1.addOrGetVector(FieldType.nullable(listViewType.getType()));
+
+ LargeListViewVector innerList2 = (LargeListViewVector)
innerList1.getDataVector();
+ innerList2.addOrGetVector(FieldType.nullable(listViewType.getType()));
+
+ LargeListViewVector innerList3 = (LargeListViewVector)
innerList2.getDataVector();
+ innerList3.addOrGetVector(FieldType.nullable(listViewType.getType()));
+
+ LargeListViewVector innerList4 = (LargeListViewVector)
innerList3.getDataVector();
+ innerList4.addOrGetVector(FieldType.nullable(listViewType.getType()));
+
+ LargeListViewVector innerList5 = (LargeListViewVector)
innerList4.getDataVector();
+ innerList5.addOrGetVector(FieldType.nullable(listViewType.getType()));
+
+ LargeListViewVector innerList6 = (LargeListViewVector)
innerList5.getDataVector();
+ innerList6.addOrGetVector(FieldType.nullable(scalarType.getType()));
+
+ largeListViewVector.setInitialCapacity(128);
+ }
+ }
+
+ @Test
+ public void testNestedLargeListViewVector2() throws Exception {
+ try (LargeListViewVector largeListViewVector =
+ LargeListViewVector.empty("sourceVector", allocator)) {
+ largeListViewVector.setInitialCapacity(1);
+ UnionLargeListViewWriter largeListViewWriter =
largeListViewVector.getWriter();
+ /* allocate memory */
+ largeListViewWriter.allocate();
+
+ /* write one or more inner lists at index 0 */
+ largeListViewWriter.setPosition(0);
+ largeListViewWriter.startListView();
+
+ largeListViewWriter.listView().startListView();
+ largeListViewWriter.listView().bigInt().writeBigInt(50);
+ largeListViewWriter.listView().bigInt().writeBigInt(100);
+ largeListViewWriter.listView().bigInt().writeBigInt(200);
+ largeListViewWriter.listView().endListView();
+
+ largeListViewWriter.listView().startListView();
+ largeListViewWriter.listView().bigInt().writeBigInt(75);
+ largeListViewWriter.listView().bigInt().writeBigInt(125);
+ largeListViewWriter.listView().endListView();
+
+ largeListViewWriter.endListView();
+
+ /* write one or more inner lists at index 1 */
+ largeListViewWriter.setPosition(1);
+ largeListViewWriter.startListView();
+
+ largeListViewWriter.listView().startListView();
+ largeListViewWriter.listView().bigInt().writeBigInt(15);
+ largeListViewWriter.listView().bigInt().writeBigInt(20);
+ largeListViewWriter.listView().endListView();
+
+ largeListViewWriter.listView().startListView();
+ largeListViewWriter.listView().bigInt().writeBigInt(25);
+ largeListViewWriter.listView().bigInt().writeBigInt(30);
+ largeListViewWriter.listView().bigInt().writeBigInt(35);
+ largeListViewWriter.listView().endListView();
+
+ largeListViewWriter.endListView();
+
+ largeListViewVector.setValueCount(2);
+
+ assertEquals(2, largeListViewVector.getValueCount());
+
+ /* get largeListViewVector value at index 0 -- the value itself is a
largeListViewVector */
+ Object result = largeListViewVector.getObject(0);
+ ArrayList<ArrayList<Long>> resultSet = (ArrayList<ArrayList<Long>>)
result;
+ ArrayList<Long> list;
+
+ assertEquals(2, resultSet.size()); /* 2 inner lists at index 0 */
+ assertEquals(3, resultSet.get(0).size()); /* size of first inner list */
+ assertEquals(2, resultSet.get(1).size()); /* size of second inner list */
+
+ list = resultSet.get(0);
+ assertEquals(Long.valueOf(50), list.get(0));
+ assertEquals(Long.valueOf(100), list.get(1));
+ assertEquals(Long.valueOf(200), list.get(2));
+
+ list = resultSet.get(1);
+ assertEquals(Long.valueOf(75), list.get(0));
+ assertEquals(Long.valueOf(125), list.get(1));
+
+ /* get largeListViewVector value at index 1 -- the value itself is a
largeListViewVector */
+ result = largeListViewVector.getObject(1);
+ resultSet = (ArrayList<ArrayList<Long>>) result;
+
+ assertEquals(2, resultSet.size()); /* 3 inner lists at index 1 */
+ assertEquals(2, resultSet.get(0).size()); /* size of first inner list */
+ assertEquals(3, resultSet.get(1).size()); /* size of second inner list */
+
+ list = resultSet.get(0);
+ assertEquals(Long.valueOf(15), list.get(0));
+ assertEquals(Long.valueOf(20), list.get(1));
+
+ list = resultSet.get(1);
+ assertEquals(Long.valueOf(25), list.get(0));
+ assertEquals(Long.valueOf(30), list.get(1));
+ assertEquals(Long.valueOf(35), list.get(2));
+
+ /* check underlying bitVector */
+ assertFalse(largeListViewVector.isNull(0));
+ assertFalse(largeListViewVector.isNull(1));
+
+ /* check underlying offsets */
+ final ArrowBuf offsetBuffer = largeListViewVector.getOffsetBuffer();
+
+ /* largeListViewVector has 2 lists at index 0 and 3 lists at index 1 */
+ assertEquals(0, offsetBuffer.getLong(0 *
LargeListViewVector.OFFSET_WIDTH));
+ assertEquals(2, offsetBuffer.getLong(1 *
LargeListViewVector.OFFSET_WIDTH));
+ }
+ }
+
+ @Test
+ public void testGetBufferAddress() throws Exception {
+ try (LargeListViewVector largeListViewVector =
LargeListViewVector.empty("vector", allocator)) {
+
+ UnionLargeListViewWriter largeListViewWriter =
largeListViewVector.getWriter();
+ boolean error = false;
+
+ largeListViewWriter.allocate();
+
+ largeListViewWriter.setPosition(0);
+ largeListViewWriter.startListView();
+ largeListViewWriter.bigInt().writeBigInt(50);
+ largeListViewWriter.bigInt().writeBigInt(100);
+ largeListViewWriter.bigInt().writeBigInt(200);
+ largeListViewWriter.endListView();
+
+ largeListViewWriter.setPosition(1);
+ largeListViewWriter.startListView();
+ largeListViewWriter.bigInt().writeBigInt(250);
+ largeListViewWriter.bigInt().writeBigInt(300);
+ largeListViewWriter.endListView();
+
+ largeListViewVector.setValueCount(2);
+
+ /* check largeListViewVector contents */
+ Object result = largeListViewVector.getObject(0);
+ ArrayList<Long> resultSet = (ArrayList<Long>) result;
+ assertEquals(3, resultSet.size());
+ assertEquals(Long.valueOf(50), resultSet.get(0));
+ assertEquals(Long.valueOf(100), resultSet.get(1));
+ assertEquals(Long.valueOf(200), resultSet.get(2));
+
+ result = largeListViewVector.getObject(1);
+ resultSet = (ArrayList<Long>) result;
+ assertEquals(2, resultSet.size());
+ assertEquals(Long.valueOf(250), resultSet.get(0));
+ assertEquals(Long.valueOf(300), resultSet.get(1));
+
+ List<ArrowBuf> buffers = largeListViewVector.getFieldBuffers();
+
+ long bitAddress = largeListViewVector.getValidityBufferAddress();
+ long offsetAddress = largeListViewVector.getOffsetBufferAddress();
+ long sizeAddress = largeListViewVector.getSizeBufferAddress();
+
+ try {
+ largeListViewVector.getDataBufferAddress();
+ } catch (UnsupportedOperationException ue) {
+ error = true;
+ } finally {
+ assertTrue(error);
+ }
+
+ assertEquals(3, buffers.size());
+ assertEquals(bitAddress, buffers.get(0).memoryAddress());
+ assertEquals(offsetAddress, buffers.get(1).memoryAddress());
+ assertEquals(sizeAddress, buffers.get(2).memoryAddress());
+
+ /* (3+2)/2 */
+ assertEquals(2.5, largeListViewVector.getDensity(), 0);
+ }
+ }
+
+ /*
+ * Setting up the buffers directly needs to be validated with the base
method used in
+ * the LargeListViewVector class where we use the approach of
startListView(),
+ * write to the child vector and endListView().
+ * <p>
+ * To support this, we have to consider the following scenarios;
+ * <p>
+ * 1. Only using directly buffer-based inserts.
+ * 2. Default list insertion followed by buffer-based inserts.
+ * 3. Buffer-based inserts followed by default list insertion.
+ */
+
+ /* Setting up buffers directly would require the following steps to be taken
+ * 0. Allocate buffers in largeListViewVector by calling `allocateNew`
method.
+ * 1. Initialize the child vector using `initializeChildrenFromFields`
method.
+ * 2. Set values in the child vector.
+ * 3. Set validity, offset and size buffers using `setValidity`,
+ * `setOffset` and `setSize` methods.
+ * 4. Set value count using `setValueCount` method.
+ */
+ @Test
+ public void testBasicLargeListViewSet() {
+
+ try (LargeListViewVector largeListViewVector =
+ LargeListViewVector.empty("sourceVector", allocator)) {
+ // Allocate buffers in largeListViewVector by calling `allocateNew`
method.
+ largeListViewVector.allocateNew();
+
+ // Initialize the child vector using `initializeChildrenFromFields`
method.
+ FieldType fieldType = new FieldType(true, new ArrowType.Int(64, true),
null, null);
+ Field field = new Field("child-vector", fieldType, null);
+
largeListViewVector.initializeChildrenFromFields(Collections.singletonList(field));
+
+ // Set values in the child vector.
+ FieldVector fieldVector = largeListViewVector.getDataVector();
+ fieldVector.clear();
+
+ BigIntVector childVector = (BigIntVector) fieldVector;
+ childVector.allocateNew(7);
+
+ childVector.set(0, 12);
+ childVector.set(1, -7);
+ childVector.set(2, 25);
+ childVector.set(3, 0);
+ childVector.set(4, -127);
+ childVector.set(5, 127);
+ childVector.set(6, 50);
+
+ childVector.setValueCount(7);
+
+ // Set validity, offset and size buffers using `setValidity`,
+ // `setOffset` and `setSize` methods.
+ largeListViewVector.setOffset(0, 0);
+ largeListViewVector.setOffset(1, 3);
+ largeListViewVector.setOffset(2, 3);
+ largeListViewVector.setOffset(3, 7);
+
+ largeListViewVector.setSize(0, 3);
+ largeListViewVector.setSize(1, 0);
+ largeListViewVector.setSize(2, 4);
+ largeListViewVector.setSize(3, 0);
+
+ largeListViewVector.setValidity(0, 1);
+ largeListViewVector.setValidity(1, 0);
+ largeListViewVector.setValidity(2, 1);
+ largeListViewVector.setValidity(3, 1);
+
+ // Set value count using `setValueCount` method.
+ largeListViewVector.setValueCount(4);
+
+ final ArrowBuf offSetBuffer = largeListViewVector.getOffsetBuffer();
+ final ArrowBuf sizeBuffer = largeListViewVector.getSizeBuffer();
+
+ // check offset buffer
+ assertEquals(0, offSetBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(3, offSetBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(3, offSetBuffer.getInt(2 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(7, offSetBuffer.getInt(3 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+
+ // check size buffer
+ assertEquals(3, sizeBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(4, sizeBuffer.getInt(2 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(3 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+
+ // check values
+ assertEquals(12, ((BigIntVector)
largeListViewVector.getDataVector()).get(0));
+ assertEquals(-7, ((BigIntVector)
largeListViewVector.getDataVector()).get(1));
+ assertEquals(25, ((BigIntVector)
largeListViewVector.getDataVector()).get(2));
+ assertEquals(0, ((BigIntVector)
largeListViewVector.getDataVector()).get(3));
+ assertEquals(-127, ((BigIntVector)
largeListViewVector.getDataVector()).get(4));
+ assertEquals(127, ((BigIntVector)
largeListViewVector.getDataVector()).get(5));
+ assertEquals(50, ((BigIntVector)
largeListViewVector.getDataVector()).get(6));
+
+ largeListViewVector.validate();
+ }
+ }
+
+ @Test
+ public void testBasicLargeListViewSetNested() {
+ // Expected largeListViewVector
+ // [[[50,100,200],[75,125,150,175]],[[10],[15,20],[25,30,35]]]
+
+ // Setting child vector
+ // [[50,100,200],[75,125,150,175],[10],[15,20],[25,30,35]]
+ try (LargeListViewVector largeListViewVector =
+ LargeListViewVector.empty("sourceVector", allocator)) {
+ // Allocate buffers in largeListViewVector by calling `allocateNew`
method.
+ largeListViewVector.allocateNew();
+
+ // Initialize the child vector using `initializeChildrenFromFields`
method.
+ FieldType fieldType = new FieldType(true, new ArrowType.LargeListView(),
null, null);
+ FieldType childFieldType = new FieldType(true, new ArrowType.Int(64,
true), null, null);
+ Field childField = new Field("child-vector", childFieldType, null);
+ List<Field> children = new ArrayList<>();
+ children.add(childField);
+ Field field = new Field("child-vector", fieldType, children);
+
largeListViewVector.initializeChildrenFromFields(Collections.singletonList(field));
+
+ // Set values in the child vector.
+ FieldVector fieldVector = largeListViewVector.getDataVector();
+ fieldVector.clear();
+
+ LargeListViewVector childVector = (LargeListViewVector) fieldVector;
+ UnionLargeListViewWriter largeListViewWriter = childVector.getWriter();
+ largeListViewWriter.allocate();
+
+ largeListViewWriter.setPosition(0);
+ largeListViewWriter.startListView();
+
+ largeListViewWriter.bigInt().writeBigInt(50);
+ largeListViewWriter.bigInt().writeBigInt(100);
+ largeListViewWriter.bigInt().writeBigInt(200);
+
+ largeListViewWriter.endListView();
+
+ largeListViewWriter.setPosition(1);
+ largeListViewWriter.startListView();
+
+ largeListViewWriter.bigInt().writeBigInt(75);
+ largeListViewWriter.bigInt().writeBigInt(125);
+ largeListViewWriter.bigInt().writeBigInt(150);
+ largeListViewWriter.bigInt().writeBigInt(175);
+
+ largeListViewWriter.endListView();
+
+ largeListViewWriter.setPosition(2);
+ largeListViewWriter.startListView();
+
+ largeListViewWriter.bigInt().writeBigInt(10);
+
+ largeListViewWriter.endListView();
+
+ largeListViewWriter.startListView();
+ largeListViewWriter.setPosition(3);
+
+ largeListViewWriter.bigInt().writeBigInt(15);
+ largeListViewWriter.bigInt().writeBigInt(20);
+
+ largeListViewWriter.endListView();
+
+ largeListViewWriter.startListView();
+ largeListViewWriter.setPosition(4);
+
+ largeListViewWriter.bigInt().writeBigInt(25);
+ largeListViewWriter.bigInt().writeBigInt(30);
+ largeListViewWriter.bigInt().writeBigInt(35);
+
+ largeListViewWriter.endListView();
+
+ childVector.setValueCount(5);
+
+ // Set validity, offset and size buffers using `setValidity`,
+ // `setOffset` and `setSize` methods.
+
+ largeListViewVector.setValidity(0, 1);
+ largeListViewVector.setValidity(1, 1);
+
+ largeListViewVector.setOffset(0, 0);
+ largeListViewVector.setOffset(1, 2);
+
+ largeListViewVector.setSize(0, 2);
+ largeListViewVector.setSize(1, 3);
+
+ // Set value count using `setValueCount` method.
+ largeListViewVector.setValueCount(2);
+
+ assertEquals(2, largeListViewVector.getValueCount());
+
+ /* get largeListViewVector value at index 0 -- the value itself is a
largeListViewVector */
+ Object result = largeListViewVector.getObject(0);
+ ArrayList<ArrayList<Long>> resultSet = (ArrayList<ArrayList<Long>>)
result;
+ ArrayList<Long> list;
+
+ assertEquals(2, resultSet.size()); /* 2 inner lists at index 0 */
+ assertEquals(3, resultSet.get(0).size()); /* size of the first inner
list */
+ assertEquals(4, resultSet.get(1).size()); /* size of the second inner
list */
+
+ list = resultSet.get(0);
+ assertEquals(Long.valueOf(50), list.get(0));
+ assertEquals(Long.valueOf(100), list.get(1));
+ assertEquals(Long.valueOf(200), list.get(2));
+
+ list = resultSet.get(1);
+ assertEquals(Long.valueOf(75), list.get(0));
+ assertEquals(Long.valueOf(125), list.get(1));
+ assertEquals(Long.valueOf(150), list.get(2));
+ assertEquals(Long.valueOf(175), list.get(3));
+
+ /* get largeListViewVector value at index 1 -- the value itself is a
largeListViewVector */
+ result = largeListViewVector.getObject(1);
+ resultSet = (ArrayList<ArrayList<Long>>) result;
+
+ assertEquals(3, resultSet.size()); /* 3 inner lists at index 1 */
+ assertEquals(1, resultSet.get(0).size()); /* size of the first inner
list */
+ assertEquals(2, resultSet.get(1).size()); /* size of the second inner
list */
+ assertEquals(3, resultSet.get(2).size()); /* size of the third inner
list */
+
+ list = resultSet.get(0);
+ assertEquals(Long.valueOf(10), list.get(0));
+
+ list = resultSet.get(1);
+ assertEquals(Long.valueOf(15), list.get(0));
+ assertEquals(Long.valueOf(20), list.get(1));
+
+ list = resultSet.get(2);
+ assertEquals(Long.valueOf(25), list.get(0));
+ assertEquals(Long.valueOf(30), list.get(1));
+ assertEquals(Long.valueOf(35), list.get(2));
+
+ /* check underlying bitVector */
+ assertFalse(largeListViewVector.isNull(0));
+ assertFalse(largeListViewVector.isNull(1));
+
+ final ArrowBuf offSetBuffer = largeListViewVector.getOffsetBuffer();
+ final ArrowBuf sizeBuffer = largeListViewVector.getSizeBuffer();
+
+ // check offset buffer
+ assertEquals(0, offSetBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(2, offSetBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+
+ // check size buffer
+ assertEquals(2, sizeBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(3, sizeBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+
+ largeListViewVector.validate();
+ }
+ }
+
+ @Test
+ public void testBasicLargeListViewSetWithListViewWriter() {
+ try (LargeListViewVector largeListViewVector =
+ LargeListViewVector.empty("sourceVector", allocator)) {
+ // Allocate buffers in largeListViewVector by calling `allocateNew`
method.
+ largeListViewVector.allocateNew();
+
+ // Initialize the child vector using `initializeChildrenFromFields`
method.
+ FieldType fieldType = new FieldType(true, new ArrowType.Int(64, true),
null, null);
+ Field field = new Field("child-vector", fieldType, null);
+
largeListViewVector.initializeChildrenFromFields(Collections.singletonList(field));
+
+ // Set values in the child vector.
+ FieldVector fieldVector = largeListViewVector.getDataVector();
+ fieldVector.clear();
+
+ BigIntVector childVector = (BigIntVector) fieldVector;
+ childVector.allocateNew(7);
+
+ childVector.set(0, 12);
+ childVector.set(1, -7);
+ childVector.set(2, 25);
+ childVector.set(3, 0);
+ childVector.set(4, -127);
+ childVector.set(5, 127);
+ childVector.set(6, 50);
+
+ childVector.setValueCount(7);
+
+ // Set validity, offset and size buffers using `setValidity`,
+ // `setOffset` and `setSize` methods.
+
+ largeListViewVector.setValidity(0, 1);
+ largeListViewVector.setValidity(1, 0);
+ largeListViewVector.setValidity(2, 1);
+ largeListViewVector.setValidity(3, 1);
+
+ largeListViewVector.setOffset(0, 0);
+ largeListViewVector.setOffset(1, 3);
+ largeListViewVector.setOffset(2, 3);
+ largeListViewVector.setOffset(3, 7);
+
+ largeListViewVector.setSize(0, 3);
+ largeListViewVector.setSize(1, 0);
+ largeListViewVector.setSize(2, 4);
+ largeListViewVector.setSize(3, 0);
+
+ // Set value count using `setValueCount` method.
+ largeListViewVector.setValueCount(4);
+
+ final ArrowBuf offSetBuffer = largeListViewVector.getOffsetBuffer();
+ final ArrowBuf sizeBuffer = largeListViewVector.getSizeBuffer();
+
+ // check offset buffer
+ assertEquals(0, offSetBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(3, offSetBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(3, offSetBuffer.getInt(2 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(7, offSetBuffer.getInt(3 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+
+ // check size buffer
+ assertEquals(3, sizeBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(4, sizeBuffer.getInt(2 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(3 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+
+ // check values
+ assertEquals(12, ((BigIntVector)
largeListViewVector.getDataVector()).get(0));
+ assertEquals(-7, ((BigIntVector)
largeListViewVector.getDataVector()).get(1));
+ assertEquals(25, ((BigIntVector)
largeListViewVector.getDataVector()).get(2));
+ assertEquals(0, ((BigIntVector)
largeListViewVector.getDataVector()).get(3));
+ assertEquals(-127, ((BigIntVector)
largeListViewVector.getDataVector()).get(4));
+ assertEquals(127, ((BigIntVector)
largeListViewVector.getDataVector()).get(5));
+ assertEquals(50, ((BigIntVector)
largeListViewVector.getDataVector()).get(6));
+
+ UnionLargeListViewWriter listViewWriter =
largeListViewVector.getWriter();
+
+ listViewWriter.setPosition(4);
+ listViewWriter.startListView();
+
+ listViewWriter.bigInt().writeBigInt(121);
+ listViewWriter.bigInt().writeBigInt(-71);
+ listViewWriter.bigInt().writeBigInt(251);
+ listViewWriter.endListView();
+
+ largeListViewVector.setValueCount(5);
+
+ // check offset buffer
+ assertEquals(0, offSetBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(3, offSetBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(3, offSetBuffer.getInt(2 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(7, offSetBuffer.getInt(3 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(7, offSetBuffer.getInt(4 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+
+ // check size buffer
+ assertEquals(3, sizeBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(4, sizeBuffer.getInt(2 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(3 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(3, sizeBuffer.getInt(4 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+
+ // check values
+ assertEquals(12, ((BigIntVector)
largeListViewVector.getDataVector()).get(0));
+ assertEquals(-7, ((BigIntVector)
largeListViewVector.getDataVector()).get(1));
+ assertEquals(25, ((BigIntVector)
largeListViewVector.getDataVector()).get(2));
+ assertEquals(0, ((BigIntVector)
largeListViewVector.getDataVector()).get(3));
+ assertEquals(-127, ((BigIntVector)
largeListViewVector.getDataVector()).get(4));
+ assertEquals(127, ((BigIntVector)
largeListViewVector.getDataVector()).get(5));
+ assertEquals(50, ((BigIntVector)
largeListViewVector.getDataVector()).get(6));
+ assertEquals(121, ((BigIntVector)
largeListViewVector.getDataVector()).get(7));
+ assertEquals(-71, ((BigIntVector)
largeListViewVector.getDataVector()).get(8));
+ assertEquals(251, ((BigIntVector)
largeListViewVector.getDataVector()).get(9));
+
+ largeListViewVector.validate();
+ }
+ }
+
+ @Test
+ public void testConsistentChildName() throws Exception {
+ try (LargeListViewVector largeListViewVector =
+ LargeListViewVector.empty("sourceVector", allocator)) {
+ String emptyListStr = largeListViewVector.getField().toString();
+ assertTrue(emptyListStr.contains(LargeListViewVector.DATA_VECTOR_NAME));
+
+
largeListViewVector.addOrGetVector(FieldType.nullable(MinorType.INT.getType()));
+ String emptyVectorStr = largeListViewVector.getField().toString();
+
assertTrue(emptyVectorStr.contains(LargeListViewVector.DATA_VECTOR_NAME));
+ }
+ }
+
+ @Test
+ public void testSetInitialCapacity() {
+ try (final LargeListViewVector vector = LargeListViewVector.empty("",
allocator)) {
+ vector.addOrGetVector(FieldType.nullable(MinorType.INT.getType()));
+
+ vector.setInitialCapacity(512);
+ vector.allocateNew();
+ assertEquals(512, vector.getValueCapacity());
+ assertTrue(vector.getDataVector().getValueCapacity() >= 512);
+
+ vector.setInitialCapacity(512, 4);
+ vector.allocateNew();
+ assertEquals(512, vector.getValueCapacity());
+ assertTrue(vector.getDataVector().getValueCapacity() >= 512 * 4);
+
+ vector.setInitialCapacity(512, 0.1);
+ vector.allocateNew();
+ assertEquals(512, vector.getValueCapacity());
+ assertTrue(vector.getDataVector().getValueCapacity() >= 51);
+
+ vector.setInitialCapacity(512, 0.01);
+ vector.allocateNew();
+ assertEquals(512, vector.getValueCapacity());
+ assertTrue(vector.getDataVector().getValueCapacity() >= 5);
+
+ vector.setInitialCapacity(5, 0.1);
+ vector.allocateNew();
+ assertEquals(8, vector.getValueCapacity());
+ assertTrue(vector.getDataVector().getValueCapacity() >= 1);
+
+ vector.validate();
+ }
+ }
+
+ @Test
+ public void testClearAndReuse() {
+ try (final LargeListViewVector vector = LargeListViewVector.empty("list",
allocator)) {
+ BigIntVector bigIntVector =
+ (BigIntVector)
+
vector.addOrGetVector(FieldType.nullable(MinorType.BIGINT.getType())).getVector();
+ vector.setInitialCapacity(10);
+ vector.allocateNew();
+
+ vector.startNewValue(0);
+ bigIntVector.setSafe(0, 7);
+ vector.endValue(0, 1);
+ vector.startNewValue(1);
+ bigIntVector.setSafe(1, 8);
+ vector.endValue(1, 1);
+ vector.setValueCount(2);
+
+ Object result = vector.getObject(0);
+ ArrayList<Long> resultSet = (ArrayList<Long>) result;
+ assertEquals(Long.valueOf(7), resultSet.get(0));
+
+ result = vector.getObject(1);
+ resultSet = (ArrayList<Long>) result;
+ assertEquals(Long.valueOf(8), resultSet.get(0));
+
+ // Clear and release the buffers to trigger a realloc when adding next
value
+ vector.clear();
+
+ // The list vector should reuse a buffer when reallocating the offset
buffer
+ vector.startNewValue(0);
+ bigIntVector.setSafe(0, 7);
+ vector.endValue(0, 1);
+ vector.startNewValue(1);
+ bigIntVector.setSafe(1, 8);
+ vector.endValue(1, 1);
+ vector.setValueCount(2);
+
+ result = vector.getObject(0);
+ resultSet = (ArrayList<Long>) result;
+ assertEquals(Long.valueOf(7), resultSet.get(0));
+
+ result = vector.getObject(1);
+ resultSet = (ArrayList<Long>) result;
+ assertEquals(Long.valueOf(8), resultSet.get(0));
+ }
+ }
+
+ @Test
+ public void testWriterGetField() {
+ try (final LargeListViewVector vector = LargeListViewVector.empty("list",
allocator)) {
+
+ UnionLargeListViewWriter writer = vector.getWriter();
+ writer.allocate();
+
+ // set some values
+ writer.startListView();
+ writer.integer().writeInt(1);
+ writer.integer().writeInt(2);
+ writer.endListView();
+ vector.setValueCount(2);
+
+ Field expectedDataField =
+ new Field(
+ BaseLargeRepeatedValueViewVector.DATA_VECTOR_NAME,
+ FieldType.nullable(new ArrowType.Int(32, true)),
+ null);
+ Field expectedField =
+ new Field(
+ vector.getName(),
+ FieldType.nullable(ArrowType.LargeListView.INSTANCE),
+ Collections.singletonList(expectedDataField));
+
+ assertEquals(expectedField, writer.getField());
+ }
+ }
+
+ @Test
+ public void testClose() throws Exception {
+ try (final LargeListViewVector vector =
LargeListViewVector.empty("largelistview", allocator)) {
+
+ UnionLargeListViewWriter writer = vector.getWriter();
+ writer.allocate();
+
+ // set some values
+ writer.startListView();
+ writer.integer().writeInt(1);
+ writer.integer().writeInt(2);
+ writer.endListView();
+ vector.setValueCount(2);
+
+ assertTrue(vector.getBufferSize() > 0);
+ assertTrue(vector.getDataVector().getBufferSize() > 0);
+
+ writer.close();
+ assertEquals(0, vector.getBufferSize());
+ assertEquals(0, vector.getDataVector().getBufferSize());
+
+ vector.validate();
+ }
+ }
+
+ @Test
+ public void testGetBufferSizeFor() {
+ try (final LargeListViewVector vector =
LargeListViewVector.empty("largelistview", allocator)) {
+
+ UnionLargeListViewWriter writer = vector.getWriter();
+ writer.allocate();
+
+ // set some values
+ writeIntValues(writer, new int[] {1, 2});
+ writeIntValues(writer, new int[] {3, 4});
+ writeIntValues(writer, new int[] {5, 6});
+ writeIntValues(writer, new int[] {7, 8, 9, 10});
+ writeIntValues(writer, new int[] {11, 12, 13, 14});
+ writer.setValueCount(5);
+
+ IntVector dataVector = (IntVector) vector.getDataVector();
+ int[] indices = new int[] {0, 2, 4, 6, 10, 14};
+
+ for (int valueCount = 1; valueCount <= 5; valueCount++) {
+ int validityBufferSize =
BitVectorHelper.getValidityBufferSize(valueCount);
+ int offsetBufferSize = valueCount *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH;
+ int sizeBufferSize = valueCount *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH;
+
+ int expectedSize =
+ validityBufferSize
+ + offsetBufferSize
+ + sizeBufferSize
+ + dataVector.getBufferSizeFor(indices[valueCount]);
+ assertEquals(expectedSize, vector.getBufferSizeFor(valueCount));
+ }
+ vector.validate();
+ }
+ }
+
+ @Test
+ public void testIsEmpty() {
+ try (final LargeListViewVector vector =
LargeListViewVector.empty("largelistview", allocator)) {
+ UnionLargeListViewWriter writer = vector.getWriter();
+ writer.allocate();
+
+ // set values [1,2], null, [], [5,6]
+ writeIntValues(writer, new int[] {1, 2});
+ writer.setPosition(2);
+ writeIntValues(writer, new int[] {});
+ writeIntValues(writer, new int[] {5, 6});
+ writer.setValueCount(4);
+
+ assertFalse(vector.isEmpty(0));
+ assertTrue(vector.isNull(1));
+ assertTrue(vector.isEmpty(1));
+ assertFalse(vector.isNull(2));
+ assertTrue(vector.isEmpty(2));
+ assertFalse(vector.isEmpty(3));
+
+ vector.validate();
+ }
+ }
+
+ @Test
+ public void testTotalCapacity() {
+ final FieldType type = FieldType.nullable(MinorType.INT.getType());
+ try (final LargeListViewVector vector =
+ new LargeListViewVector("largelistview", allocator, type, null)) {
+ // Force the child vector to be allocated based on the type
+ // (this is a bad API: we have to track and repeat the type twice)
+ vector.addOrGetVector(type);
+
+ // Specify the allocation size but do not actually allocate
+ vector.setInitialTotalCapacity(10, 100);
+
+ // Finally, actually do the allocation
+ vector.allocateNewSafe();
+
+ // Note: allocator rounds up and can be greater than the requested
allocation.
+ assertTrue(vector.getValueCapacity() >= 10);
+ assertTrue(vector.getDataVector().getValueCapacity() >= 100);
+ }
+ }
+
+ @Test
+ public void testSetNull1() {
+ try (LargeListViewVector vector =
LargeListViewVector.empty("largelistview", allocator)) {
+ UnionLargeListViewWriter writer = vector.getWriter();
+ writer.allocate();
+
+ writer.setPosition(0);
+ writer.startListView();
+ writer.bigInt().writeBigInt(10);
+ writer.bigInt().writeBigInt(20);
+ writer.endListView();
+
+ vector.setNull(1);
+
+ writer.setPosition(2);
+ writer.startListView();
+ writer.bigInt().writeBigInt(30);
+ writer.bigInt().writeBigInt(40);
+ writer.endListView();
+
+ vector.setNull(3);
+ vector.setNull(4);
+
+ writer.setPosition(5);
+ writer.startListView();
+ writer.bigInt().writeBigInt(50);
+ writer.bigInt().writeBigInt(60);
+ writer.endListView();
+
+ vector.setValueCount(6);
+
+ assertFalse(vector.isNull(0));
+ assertTrue(vector.isNull(1));
+ assertFalse(vector.isNull(2));
+ assertTrue(vector.isNull(3));
+ assertTrue(vector.isNull(4));
+ assertFalse(vector.isNull(5));
+
+ // validate buffers
+
+ final ArrowBuf validityBuffer = vector.getValidityBuffer();
+ final ArrowBuf offsetBuffer = vector.getOffsetBuffer();
+ final ArrowBuf sizeBuffer = vector.getSizeBuffer();
+
+ assertEquals(1, BitVectorHelper.get(validityBuffer, 0));
+ assertEquals(0, BitVectorHelper.get(validityBuffer, 1));
+ assertEquals(1, BitVectorHelper.get(validityBuffer, 2));
+ assertEquals(0, BitVectorHelper.get(validityBuffer, 3));
+ assertEquals(0, BitVectorHelper.get(validityBuffer, 4));
+ assertEquals(1, BitVectorHelper.get(validityBuffer, 5));
+
+ assertEquals(0, offsetBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(0, offsetBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(2, offsetBuffer.getInt(2 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(0, offsetBuffer.getInt(3 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(0, offsetBuffer.getInt(4 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(4, offsetBuffer.getInt(5 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+
+ assertEquals(2, sizeBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(2, sizeBuffer.getInt(2 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(3 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(4 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(2, sizeBuffer.getInt(5 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+
+ // validate values
+
+ Object result = vector.getObject(0);
+ ArrayList<Long> resultSet = (ArrayList<Long>) result;
+ assertEquals(2, resultSet.size());
+ assertEquals(Long.valueOf(10), resultSet.get(0));
+ assertEquals(Long.valueOf(20), resultSet.get(1));
+
+ result = vector.getObject(2);
+ resultSet = (ArrayList<Long>) result;
+ assertEquals(2, resultSet.size());
+ assertEquals(Long.valueOf(30), resultSet.get(0));
+ assertEquals(Long.valueOf(40), resultSet.get(1));
+
+ result = vector.getObject(5);
+ resultSet = (ArrayList<Long>) result;
+ assertEquals(2, resultSet.size());
+ assertEquals(Long.valueOf(50), resultSet.get(0));
+ assertEquals(Long.valueOf(60), resultSet.get(1));
+
+ vector.validate();
+ }
+ }
+
+ @Test
+ public void testSetNull2() {
+ try (LargeListViewVector vector =
LargeListViewVector.empty("largelistview", allocator)) {
+ // validate setting nulls first and then writing values
+ UnionLargeListViewWriter writer = vector.getWriter();
+ writer.allocate();
+
+ vector.setNull(0);
+ vector.setNull(2);
+ vector.setNull(4);
+
+ writer.setPosition(1);
+ writer.startListView();
+ writer.bigInt().writeBigInt(10);
+ writer.bigInt().writeBigInt(20);
+ writer.bigInt().writeBigInt(30);
+ writer.endListView();
+
+ writer.setPosition(3);
+ writer.startListView();
+ writer.bigInt().writeBigInt(40);
+ writer.bigInt().writeBigInt(50);
+ writer.endListView();
+
+ writer.setPosition(5);
+ writer.startListView();
+ writer.bigInt().writeBigInt(60);
+ writer.bigInt().writeBigInt(70);
+ writer.bigInt().writeBigInt(80);
+ writer.endListView();
+
+ vector.setValueCount(6);
+
+ assertTrue(vector.isNull(0));
+ assertFalse(vector.isNull(1));
+ assertTrue(vector.isNull(2));
+ assertFalse(vector.isNull(3));
+ assertTrue(vector.isNull(4));
+ assertFalse(vector.isNull(5));
+
+ // validate buffers
+
+ final ArrowBuf validityBuffer = vector.getValidityBuffer();
+ final ArrowBuf offsetBuffer = vector.getOffsetBuffer();
+ final ArrowBuf sizeBuffer = vector.getSizeBuffer();
+
+ assertEquals(0, BitVectorHelper.get(validityBuffer, 0));
+ assertEquals(1, BitVectorHelper.get(validityBuffer, 1));
+ assertEquals(0, BitVectorHelper.get(validityBuffer, 2));
+ assertEquals(1, BitVectorHelper.get(validityBuffer, 3));
+ assertEquals(0, BitVectorHelper.get(validityBuffer, 4));
+ assertEquals(1, BitVectorHelper.get(validityBuffer, 5));
+
+ assertEquals(0, offsetBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(0, offsetBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(0, offsetBuffer.getInt(2 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(3, offsetBuffer.getInt(3 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(0, offsetBuffer.getInt(4 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(5, offsetBuffer.getInt(5 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+
+ assertEquals(0, sizeBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(3, sizeBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(2 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(2, sizeBuffer.getInt(3 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(4 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(3, sizeBuffer.getInt(5 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+
+ // validate values
+
+ Object result = vector.getObject(1);
+ ArrayList<Long> resultSet = (ArrayList<Long>) result;
+ assertEquals(3, resultSet.size());
+ assertEquals(Long.valueOf(10), resultSet.get(0));
+ assertEquals(Long.valueOf(20), resultSet.get(1));
+ assertEquals(Long.valueOf(30), resultSet.get(2));
+
+ result = vector.getObject(3);
+ resultSet = (ArrayList<Long>) result;
+ assertEquals(2, resultSet.size());
+ assertEquals(Long.valueOf(40), resultSet.get(0));
+ assertEquals(Long.valueOf(50), resultSet.get(1));
+
+ result = vector.getObject(5);
+ resultSet = (ArrayList<Long>) result;
+ assertEquals(3, resultSet.size());
+ assertEquals(Long.valueOf(60), resultSet.get(0));
+ assertEquals(Long.valueOf(70), resultSet.get(1));
+ assertEquals(Long.valueOf(80), resultSet.get(2));
+
+ vector.validate();
+ }
+ }
+
+ @Test
+ public void testSetNull3() {
+ try (LargeListViewVector vector =
LargeListViewVector.empty("largelistview", allocator)) {
+ // validate setting values first and then writing nulls
+ UnionLargeListViewWriter writer = vector.getWriter();
+ writer.allocate();
+
+ writer.setPosition(1);
+ writer.startListView();
+ writer.bigInt().writeBigInt(10);
+ writer.bigInt().writeBigInt(20);
+ writer.bigInt().writeBigInt(30);
+ writer.endListView();
+
+ writer.setPosition(3);
+ writer.startListView();
+ writer.bigInt().writeBigInt(40);
+ writer.bigInt().writeBigInt(50);
+ writer.endListView();
+
+ writer.setPosition(5);
+ writer.startListView();
+ writer.bigInt().writeBigInt(60);
+ writer.bigInt().writeBigInt(70);
+ writer.bigInt().writeBigInt(80);
+ writer.endListView();
+
+ vector.setNull(0);
+ vector.setNull(2);
+ vector.setNull(4);
+
+ vector.setValueCount(6);
+
+ assertTrue(vector.isNull(0));
+ assertFalse(vector.isNull(1));
+ assertTrue(vector.isNull(2));
+ assertFalse(vector.isNull(3));
+ assertTrue(vector.isNull(4));
+ assertFalse(vector.isNull(5));
+
+ // validate buffers
+
+ final ArrowBuf validityBuffer = vector.getValidityBuffer();
+ final ArrowBuf offsetBuffer = vector.getOffsetBuffer();
+ final ArrowBuf sizeBuffer = vector.getSizeBuffer();
+
+ assertEquals(0, BitVectorHelper.get(validityBuffer, 0));
+ assertEquals(1, BitVectorHelper.get(validityBuffer, 1));
+ assertEquals(0, BitVectorHelper.get(validityBuffer, 2));
+ assertEquals(1, BitVectorHelper.get(validityBuffer, 3));
+ assertEquals(0, BitVectorHelper.get(validityBuffer, 4));
+ assertEquals(1, BitVectorHelper.get(validityBuffer, 5));
+
+ assertEquals(0, offsetBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(0, offsetBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(0, offsetBuffer.getInt(2 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(3, offsetBuffer.getInt(3 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(0, offsetBuffer.getInt(4 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(5, offsetBuffer.getInt(5 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+
+ assertEquals(0, sizeBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(3, sizeBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(2 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(2, sizeBuffer.getInt(3 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(4 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(3, sizeBuffer.getInt(5 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+
+ // validate values
+
+ Object result = vector.getObject(1);
+ ArrayList<Long> resultSet = (ArrayList<Long>) result;
+ assertEquals(3, resultSet.size());
+ assertEquals(Long.valueOf(10), resultSet.get(0));
+ assertEquals(Long.valueOf(20), resultSet.get(1));
+ assertEquals(Long.valueOf(30), resultSet.get(2));
+
+ result = vector.getObject(3);
+ resultSet = (ArrayList<Long>) result;
+ assertEquals(2, resultSet.size());
+ assertEquals(Long.valueOf(40), resultSet.get(0));
+ assertEquals(Long.valueOf(50), resultSet.get(1));
+
+ result = vector.getObject(5);
+ resultSet = (ArrayList<Long>) result;
+ assertEquals(3, resultSet.size());
+ assertEquals(Long.valueOf(60), resultSet.get(0));
+ assertEquals(Long.valueOf(70), resultSet.get(1));
+ assertEquals(Long.valueOf(80), resultSet.get(2));
+
+ vector.validate();
+ }
+ }
+
+ @Test
+ public void testOverWrite1() {
+ try (LargeListViewVector vector =
LargeListViewVector.empty("largelistview", allocator)) {
+ UnionLargeListViewWriter writer = vector.getWriter();
+ writer.allocate();
+
+ writer.setPosition(0);
+ writer.startListView();
+ writer.bigInt().writeBigInt(10);
+ writer.bigInt().writeBigInt(20);
+ writer.bigInt().writeBigInt(30);
+ writer.endListView();
+
+ writer.setPosition(1);
+ writer.startListView();
+ writer.bigInt().writeBigInt(40);
+ writer.bigInt().writeBigInt(50);
+ writer.endListView();
+
+ vector.setValueCount(2);
+
+ writer.setPosition(0);
+ writer.startListView();
+ writer.bigInt().writeBigInt(60);
+ writer.bigInt().writeBigInt(70);
+ writer.endListView();
+
+ writer.setPosition(1);
+ writer.startListView();
+ writer.bigInt().writeBigInt(80);
+ writer.bigInt().writeBigInt(90);
+ writer.endListView();
+
+ vector.setValueCount(2);
+
+ Object result = vector.getObject(0);
+ ArrayList<Long> resultSet = (ArrayList<Long>) result;
+ assertEquals(2, resultSet.size());
+ assertEquals(Long.valueOf(60), resultSet.get(0));
+ assertEquals(Long.valueOf(70), resultSet.get(1));
+
+ result = vector.getObject(1);
+ resultSet = (ArrayList<Long>) result;
+ assertEquals(2, resultSet.size());
+ assertEquals(Long.valueOf(80), resultSet.get(0));
+ assertEquals(Long.valueOf(90), resultSet.get(1));
+
+ vector.validate();
+ }
+ }
+
+ @Test
+ public void testOverwriteWithNull() {
+ try (LargeListViewVector vector =
LargeListViewVector.empty("largelistview", allocator)) {
+ UnionLargeListViewWriter writer = vector.getWriter();
+ writer.allocate();
+
+ ArrowBuf offsetBuffer = vector.getOffsetBuffer();
+ ArrowBuf sizeBuffer = vector.getSizeBuffer();
+
+ writer.setPosition(0);
+ writer.startListView();
+ writer.bigInt().writeBigInt(10);
+ writer.bigInt().writeBigInt(20);
+ writer.bigInt().writeBigInt(30);
+ writer.endListView();
+
+ writer.setPosition(1);
+ writer.startListView();
+ writer.bigInt().writeBigInt(40);
+ writer.bigInt().writeBigInt(50);
+ writer.endListView();
+
+ vector.setValueCount(2);
+
+ assertEquals(0, offsetBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(3, offsetBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+
+ assertEquals(3, sizeBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(2, sizeBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+
+ vector.setNull(0);
+
+ assertEquals(0, offsetBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+
+ vector.setNull(1);
+
+ assertEquals(0, offsetBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+
+ assertTrue(vector.isNull(0));
+ assertTrue(vector.isNull(1));
+
+ writer.setPosition(0);
+ writer.startListView();
+ writer.bigInt().writeBigInt(60);
+ writer.bigInt().writeBigInt(70);
+ writer.endListView();
+
+ assertEquals(0, offsetBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(2, sizeBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+
+ writer.setPosition(1);
+ writer.startListView();
+ writer.bigInt().writeBigInt(80);
+ writer.bigInt().writeBigInt(90);
+ writer.endListView();
+
+ assertEquals(2, offsetBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(2, sizeBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+
+ vector.setValueCount(2);
+
+ assertFalse(vector.isNull(0));
+ assertFalse(vector.isNull(1));
+
+ Object result = vector.getObject(0);
+ ArrayList<Long> resultSet = (ArrayList<Long>) result;
+ assertEquals(2, resultSet.size());
+ assertEquals(Long.valueOf(60), resultSet.get(0));
+ assertEquals(Long.valueOf(70), resultSet.get(1));
+
+ result = vector.getObject(1);
+ resultSet = (ArrayList<Long>) result;
+ assertEquals(2, resultSet.size());
+ assertEquals(Long.valueOf(80), resultSet.get(0));
+ assertEquals(Long.valueOf(90), resultSet.get(1));
+
+ vector.validate();
+ }
+ }
+
+ @Test
+ public void testOutOfOrderOffset1() {
+ // [[12, -7, 25], null, [0, -127, 127, 50], [], [50, 12]]
+ try (LargeListViewVector largeListViewVector =
+ LargeListViewVector.empty("largelistview", allocator)) {
+ // Allocate buffers in largeListViewVector by calling `allocateNew`
method.
+ largeListViewVector.allocateNew();
+
+ // Initialize the child vector using `initializeChildrenFromFields`
method.
+
+ FieldType fieldType = new FieldType(true, new ArrowType.Int(16, true),
null, null);
+ Field field = new Field("child-vector", fieldType, null);
+
largeListViewVector.initializeChildrenFromFields(Collections.singletonList(field));
+
+ // Set values in the child vector.
+ FieldVector fieldVector = largeListViewVector.getDataVector();
+ fieldVector.clear();
+
+ SmallIntVector childVector = (SmallIntVector) fieldVector;
+
+ childVector.allocateNew(7);
+
+ childVector.set(0, 0);
+ childVector.set(1, -127);
+ childVector.set(2, 127);
+ childVector.set(3, 50);
+ childVector.set(4, 12);
+ childVector.set(5, -7);
+ childVector.set(6, 25);
+
+ childVector.setValueCount(7);
+
+ // Set validity, offset and size buffers using `setValidity`,
+ // `setOffset` and `setSize` methods.
+ largeListViewVector.setValidity(0, 1);
+ largeListViewVector.setValidity(1, 0);
+ largeListViewVector.setValidity(2, 1);
+ largeListViewVector.setValidity(3, 1);
+ largeListViewVector.setValidity(4, 1);
+
+ largeListViewVector.setOffset(0, 4);
+ largeListViewVector.setOffset(1, 7);
+ largeListViewVector.setOffset(2, 0);
+ largeListViewVector.setOffset(3, 0);
+ largeListViewVector.setOffset(4, 3);
+
+ largeListViewVector.setSize(0, 3);
+ largeListViewVector.setSize(1, 0);
+ largeListViewVector.setSize(2, 4);
+ largeListViewVector.setSize(3, 0);
+ largeListViewVector.setSize(4, 2);
+
+ // Set value count using `setValueCount` method.
+ largeListViewVector.setValueCount(5);
+
+ final ArrowBuf offSetBuffer = largeListViewVector.getOffsetBuffer();
+ final ArrowBuf sizeBuffer = largeListViewVector.getSizeBuffer();
+
+ // check offset buffer
+ assertEquals(4, offSetBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(7, offSetBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(0, offSetBuffer.getInt(2 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(0, offSetBuffer.getInt(3 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+ assertEquals(3, offSetBuffer.getInt(4 *
BaseLargeRepeatedValueViewVector.OFFSET_WIDTH));
+
+ // check size buffer
+ assertEquals(3, sizeBuffer.getInt(0 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(1 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(4, sizeBuffer.getInt(2 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(0, sizeBuffer.getInt(3 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+ assertEquals(2, sizeBuffer.getInt(4 *
BaseLargeRepeatedValueViewVector.SIZE_WIDTH));
+
+ // check child vector
+ assertEquals(0, ((SmallIntVector)
largeListViewVector.getDataVector()).get(0));
+ assertEquals(-127, ((SmallIntVector)
largeListViewVector.getDataVector()).get(1));
+ assertEquals(127, ((SmallIntVector)
largeListViewVector.getDataVector()).get(2));
+ assertEquals(50, ((SmallIntVector)
largeListViewVector.getDataVector()).get(3));
+ assertEquals(12, ((SmallIntVector)
largeListViewVector.getDataVector()).get(4));
+ assertEquals(-7, ((SmallIntVector)
largeListViewVector.getDataVector()).get(5));
+ assertEquals(25, ((SmallIntVector)
largeListViewVector.getDataVector()).get(6));
+
+ // check values
+ Object result = largeListViewVector.getObject(0);
+ ArrayList<Integer> resultSet = (ArrayList<Integer>) result;
+ assertEquals(3, resultSet.size());
+ assertEquals(Short.valueOf("12"), resultSet.get(0));
+ assertEquals(Short.valueOf("-7"), resultSet.get(1));
+ assertEquals(Short.valueOf("25"), resultSet.get(2));
+
+ assertTrue(largeListViewVector.isNull(1));
+
+ result = largeListViewVector.getObject(2);
+ resultSet = (ArrayList<Integer>) result;
+ assertEquals(4, resultSet.size());
+ assertEquals(Short.valueOf("0"), resultSet.get(0));
+ assertEquals(Short.valueOf("-127"), resultSet.get(1));
+ assertEquals(Short.valueOf("127"), resultSet.get(2));
+ assertEquals(Short.valueOf("50"), resultSet.get(3));
+
+ assertTrue(largeListViewVector.isEmpty(3));
+
+ result = largeListViewVector.getObject(4);
+ resultSet = (ArrayList<Integer>) result;
+ assertEquals(2, resultSet.size());
+ assertEquals(Short.valueOf("50"), resultSet.get(0));
+ assertEquals(Short.valueOf("12"), resultSet.get(1));
+
+ largeListViewVector.validate();
+ }
+ }
+
+ private void writeIntValues(UnionLargeListViewWriter writer, int[] values) {
+ writer.startListView();
+ for (int v : values) {
+ writer.integer().writeInt(v);
+ }
+ writer.endListView();
+ }
+}