From e6918187568dbd01842d8d1d2c808ce16a894239 Mon Sep 17 00:00:00 2001
From: Daniel Baumann
+ * Must be overridden by struct writers.
+ *
+ * Intended only for use in determining whether to add dummy vector to
+ * avoid empty (zero-column) schema, as in JsonReader.
+ * Writer for MapVectors. This extends UnionListWriter to simplify writing map entries to a list
+ * of struct elements, with "key" and "value" fields. The procedure for writing a map begin with
+ * {@link #startMap()} followed by {@link #startEntry()}. An entry is written by using the
+ * {@link #key()} writer to write the key, then the {@link #value()} writer to write a value. After
+ * writing the value, call {@link #endEntry()} to complete the entry. Each map can have 1 or more
+ * entries. When done writing entries, call {@link #endMap()} to complete the map.
+ *
+ * NOTE: the MapVector can have NULL values by not writing to position. If a map is started with
+ * {@link #startMap()}, then it must have a key written. The value of a map entry can be NULL by
+ * not using the {@link #value()} writer.
+ *
+ * Example to write the following map to position 5 of a vector
+ *
+ * type.accept(new ArrowTypeVisitor<Type>() {
+ * ...
+ * });
+ *
+ */
+ public static interface ArrowTypeVisitor{@code
+ * // {
+ * // 1 -> 3,
+ * // 2 -> 4,
+ * // 3 -> NULL
+ * // }
+ *
+ * UnionMapWriter writer = ...
+ *
+ * writer.setPosition(5);
+ * writer.startMap();
+ * writer.startEntry();
+ * writer.key().integer().writeInt(1);
+ * writer.value().integer().writeInt(3);
+ * writer.endEntry();
+ * writer.startEntry();
+ * writer.key().integer().writeInt(2);
+ * writer.value().integer().writeInt(4);
+ * writer.endEntry();
+ * writer.startEntry();
+ * writer.key().integer().writeInt(3);
+ * writer.endEntry();
+ * writer.endMap();
+ *
+ *
v
is a repeated vector, this is number of child elements to allocate.
+ * @throws org.apache.arrow.memory.OutOfMemoryException if it can't allocate the memory.
+ */
+ public static void allocatePrecomputedChildCount(
+ ValueVector v,
+ int valueCount,
+ int bytesPerValue,
+ int childValCount) {
+ if (v instanceof FixedWidthVector) {
+ ((FixedWidthVector) v).allocateNew(valueCount);
+ } else if (v instanceof VariableWidthVector) {
+ ((VariableWidthVector) v).allocateNew(valueCount * bytesPerValue, valueCount);
+ } else if (v instanceof RepeatedFixedWidthVectorLike) {
+ ((RepeatedFixedWidthVectorLike) v).allocateNew(valueCount, childValCount);
+ } else if (v instanceof RepeatedVariableWidthVectorLike) {
+ ((RepeatedVariableWidthVectorLike) v).allocateNew(childValCount * bytesPerValue, valueCount, childValCount);
+ } else {
+ v.allocateNew();
+ }
+ }
+
+ /**
+ * Allocates memory for a vector assuming given number of values and their width.
+ *
+ * @param v The vector the allocate.
+ * @param valueCount The number of elements to allocate.
+ * @param bytesPerValue The bytes per value to use for allocating underlying storage
+ * @param repeatedPerTop If v
is a repeated vector, this is assumed number of elements per child.
+ * @throws org.apache.arrow.memory.OutOfMemoryException if it can't allocate the memory
+ */
+ public static void allocate(ValueVector v, int valueCount, int bytesPerValue, int repeatedPerTop) {
+ allocatePrecomputedChildCount(v, valueCount, bytesPerValue, repeatedPerTop * valueCount);
+ }
+
+ /**
+ * Allocates the exact amount if v is fixed width, otherwise falls back to dynamic allocation.
+ *
+ * @param v value vector we are trying to allocate
+ * @param valueCount size we are trying to allocate
+ * @throws org.apache.arrow.memory.OutOfMemoryException if it can't allocate the memory
+ */
+ public static void allocateNew(ValueVector v, int valueCount) {
+ if (v instanceof FixedWidthVector) {
+ ((FixedWidthVector) v).allocateNew(valueCount);
+ } else if (v instanceof VariableWidthVector) {
+ ((VariableWidthVector) v).allocateNew(valueCount);
+ } else {
+ v.allocateNew();
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BaseFixedWidthVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BaseFixedWidthVector.java
new file mode 100644
index 000000000..ded58b22b
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BaseFixedWidthVector.java
@@ -0,0 +1,930 @@
+/*
+ * 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.apache.arrow.memory.util.LargeMemoryUtil.capAtMaxInt;
+
+import java.nio.ByteBuffer;
+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.memory.util.ArrowBufPointer;
+import org.apache.arrow.memory.util.ByteFunctionHelpers;
+import org.apache.arrow.memory.util.hash.ArrowBufHasher;
+import org.apache.arrow.util.Preconditions;
+import org.apache.arrow.vector.compare.VectorVisitor;
+import org.apache.arrow.vector.ipc.message.ArrowFieldNode;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.util.CallBack;
+import org.apache.arrow.vector.util.OversizedAllocationException;
+import org.apache.arrow.vector.util.TransferPair;
+
+import io.netty.util.internal.PlatformDependent;
+
+/**
+ * BaseFixedWidthVector provides an abstract interface for
+ * implementing vectors of fixed width values. The vectors are nullable
+ * implying that zero or more elements in the vector could be NULL.
+ */
+public abstract class BaseFixedWidthVector extends BaseValueVector
+ implements FixedWidthVector, FieldVector, VectorDefinitionSetter {
+ private final int typeWidth;
+
+ protected int lastValueCapacity;
+ protected int actualValueCapacity;
+
+ protected final Field field;
+ private int allocationMonitor;
+ protected ArrowBuf validityBuffer;
+ protected ArrowBuf valueBuffer;
+ protected int valueCount;
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param field field materialized by this vector
+ * @param allocator The allocator to use for allocating memory for the vector.
+ * @param typeWidth The width in bytes of the type.
+ */
+ public BaseFixedWidthVector(Field field, final BufferAllocator allocator, final int typeWidth) {
+ super(allocator);
+ this.typeWidth = typeWidth;
+ this.field = field;
+ valueCount = 0;
+ allocationMonitor = 0;
+ validityBuffer = allocator.getEmpty();
+ valueBuffer = allocator.getEmpty();
+ lastValueCapacity = INITIAL_VALUE_ALLOCATION;
+ refreshValueCapacity();
+ }
+
+
+ public int getTypeWidth() {
+ return typeWidth;
+ }
+
+ @Override
+ public String getName() {
+ return field.getName();
+ }
+
+ /* TODO:
+ * see if getNullCount() can be made faster -- O(1)
+ */
+
+ /* TODO:
+ * Once the entire hierarchy has been refactored, move common functions
+ * like getNullCount(), splitAndTransferValidityBuffer to top level
+ * base class BaseValueVector.
+ *
+ * Along with this, some class members (validityBuffer) can also be
+ * abstracted out to top level base class.
+ *
+ * Right now BaseValueVector is the top level base class for other
+ * vector types in ValueVector hierarchy (non-nullable) and those
+ * vectors have not yet been refactored/removed so moving things to
+ * the top class as of now is not a good idea.
+ */
+
+ /**
+ * Get the memory address of buffer that manages the validity
+ * (NULL or NON-NULL nature) of elements in the vector.
+ * @return starting address of the buffer
+ */
+ @Override
+ public long getValidityBufferAddress() {
+ return (validityBuffer.memoryAddress());
+ }
+
+ /**
+ * Get the memory address of buffer that stores the data for elements
+ * in the vector.
+ * @return starting address of the buffer
+ */
+ @Override
+ public long getDataBufferAddress() {
+ return (valueBuffer.memoryAddress());
+ }
+
+ /**
+ * Get the memory address of buffer that stores the offsets for elements
+ * in the vector. This operation is not supported for fixed-width vectors.
+ * @return starting address of the buffer
+ * @throws UnsupportedOperationException for fixed width vectors
+ */
+ @Override
+ public long getOffsetBufferAddress() {
+ throw new UnsupportedOperationException("not supported for fixed-width vectors");
+ }
+
+ /**
+ * Get buffer that manages the validity (NULL or NON-NULL nature) of
+ * elements in the vector. Consider it as a buffer for internal bit vector
+ * data structure.
+ * @return buffer
+ */
+ @Override
+ public ArrowBuf getValidityBuffer() {
+ return validityBuffer;
+ }
+
+ /**
+ * Get the buffer that stores the data for elements in the vector.
+ * @return buffer
+ */
+ @Override
+ public ArrowBuf getDataBuffer() {
+ return valueBuffer;
+ }
+
+ /**
+ * buffer that stores the offsets for elements
+ * in the vector. This operation is not supported for fixed-width vectors.
+ * @return buffer
+ * @throws UnsupportedOperationException for fixed width vectors
+ */
+ @Override
+ public ArrowBuf getOffsetBuffer() {
+ throw new UnsupportedOperationException("not supported for fixed-width vectors");
+ }
+
+ /**
+ * Sets the desired value capacity for the vector. This function doesn't
+ * allocate any memory for the vector.
+ * @param valueCount desired number of elements in the vector
+ */
+ @Override
+ public void setInitialCapacity(int valueCount) {
+ computeAndCheckBufferSize(valueCount);
+ lastValueCapacity = valueCount;
+ }
+
+ /**
+ * Get the current value capacity for the vector.
+ *
+ * @return number of elements that vector can hold.
+ */
+ @Override
+ public int getValueCapacity() {
+ return actualValueCapacity;
+ }
+
+ /**
+ * Call this if you change the capacity of valueBuffer or validityBuffer.
+ */
+ protected void refreshValueCapacity() {
+ actualValueCapacity = Math.min(getValueBufferValueCapacity(), getValidityBufferValueCapacity());
+ }
+
+ protected int getValueBufferValueCapacity() {
+ return capAtMaxInt(valueBuffer.capacity() / typeWidth);
+ }
+
+ protected int getValidityBufferValueCapacity() {
+ return capAtMaxInt(validityBuffer.capacity() * 8);
+ }
+
+ /**
+ * zero out the vector and the data in associated buffers.
+ */
+ @Override
+ public void zeroVector() {
+ initValidityBuffer();
+ initValueBuffer();
+ }
+
+ /* zero out the validity buffer */
+ private void initValidityBuffer() {
+ validityBuffer.setZero(0, validityBuffer.capacity());
+ }
+
+ /* zero out the data buffer */
+ private void initValueBuffer() {
+ valueBuffer.setZero(0, valueBuffer.capacity());
+ }
+
+ /**
+ * Reset the vector to initial state. Same as {@link #zeroVector()}.
+ * Note that this method doesn't release any memory.
+ */
+ @Override
+ public void reset() {
+ valueCount = 0;
+ zeroVector();
+ }
+
+ /**
+ * Close the vector and release the associated buffers.
+ */
+ @Override
+ public void close() {
+ clear();
+ }
+
+ /**
+ * Same as {@link #close()}.
+ */
+ @Override
+ public void clear() {
+ valueCount = 0;
+ validityBuffer = releaseBuffer(validityBuffer);
+ valueBuffer = releaseBuffer(valueBuffer);
+ refreshValueCapacity();
+ }
+
+ /* used to step down the memory allocation */
+ protected void incrementAllocationMonitor() {
+ if (allocationMonitor < 0) {
+ allocationMonitor = 0;
+ }
+ allocationMonitor++;
+ }
+
+ /* used to step up the memory allocation */
+ protected void decrementAllocationMonitor() {
+ if (allocationMonitor > 0) {
+ allocationMonitor = 0;
+ }
+ allocationMonitor--;
+ }
+
+ /**
+ * Same as {@link #allocateNewSafe()}.
+ */
+ @Override
+ public void allocateNew() {
+ allocateNew(lastValueCapacity);
+ }
+
+ /**
+ * Allocate memory for the vector. We internally use a default value count
+ * of 4096 to allocate memory for at least these many elements in the
+ * vector. See {@link #allocateNew(int)} for allocating memory for specific
+ * number of elements in the vector.
+ *
+ * @return false if memory allocation fails, true otherwise.
+ */
+ @Override
+ public boolean allocateNewSafe() {
+ try {
+ allocateNew(lastValueCapacity);
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ /**
+ * Allocate memory for the vector to support storing at least the provided number of
+ * elements in the vector. This method must be called prior to using the ValueVector.
+ *
+ * @param valueCount the desired number of elements in the vector
+ * @throws org.apache.arrow.memory.OutOfMemoryException on error
+ */
+ public void allocateNew(int valueCount) {
+ computeAndCheckBufferSize(valueCount);
+
+ /* we are doing a new allocation -- release the current buffers */
+ clear();
+
+ try {
+ allocateBytes(valueCount);
+ } catch (Exception e) {
+ clear();
+ throw e;
+ }
+ }
+
+ /*
+ * Compute the buffer size required for 'valueCount', and check if it's within bounds.
+ */
+ private long computeAndCheckBufferSize(int valueCount) {
+ final long size = computeCombinedBufferSize(valueCount, typeWidth);
+ if (size > MAX_ALLOCATION_SIZE) {
+ throw new OversizedAllocationException("Memory required for vector capacity " +
+ valueCount +
+ " is (" + size + "), which is more than max allowed (" + MAX_ALLOCATION_SIZE + ")");
+ }
+ return size;
+ }
+
+ /**
+ * Actual memory allocation is done by this function. All the calculations
+ * and knowledge about what size to allocate is upto the callers of this
+ * method.
+ * Callers appropriately handle errors if memory allocation fails here.
+ * Callers should also take care of determining that desired size is
+ * within the bounds of max allocation allowed and any other error
+ * conditions.
+ */
+ private void allocateBytes(int valueCount) {
+ DataAndValidityBuffers buffers = allocFixedDataAndValidityBufs(valueCount, typeWidth);
+ valueBuffer = buffers.getDataBuf();
+ validityBuffer = buffers.getValidityBuf();
+ zeroVector();
+
+ refreshValueCapacity();
+ lastValueCapacity = getValueCapacity();
+ }
+
+ /**
+ * During splitAndTransfer, if we splitting from a random position within a byte,
+ * we can't just slice the source buffer so we have to explicitly allocate the
+ * validityBuffer of the target vector. This is unlike the databuffer which we can
+ * always slice for the target vector.
+ */
+ private void allocateValidityBuffer(final int validityBufferSize) {
+ validityBuffer = allocator.buffer(validityBufferSize);
+ validityBuffer.readerIndex(0);
+ refreshValueCapacity();
+ }
+
+ /**
+ * Get the potential buffer size for a particular number of records.
+ * @param count desired number of elements in the vector
+ * @return estimated size of underlying buffers if the vector holds
+ * a given number of elements
+ */
+ @Override
+ public int getBufferSizeFor(final int count) {
+ if (count == 0) {
+ return 0;
+ }
+ return (count * typeWidth) + getValidityBufferSizeFromCount(count);
+ }
+
+ /**
+ * 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;
+ }
+ return (valueCount * typeWidth) + getValidityBufferSizeFromCount(valueCount);
+ }
+
+ /**
+ * Get information about how this field is materialized.
+ * @return the field corresponding to this vector
+ */
+ @Override
+ public Field getField() {
+ return field;
+ }
+
+ /**
+ * 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) {
+ final ArrowBuf[] buffers;
+ setReaderAndWriterIndex();
+ if (getBufferSize() == 0) {
+ buffers = new ArrowBuf[0];
+ } else {
+ buffers = new ArrowBuf[2];
+ buffers[0] = validityBuffer;
+ buffers[1] = valueBuffer;
+ }
+ if (clear) {
+ for (final ArrowBuf buffer : buffers) {
+ buffer.getReferenceManager().retain(1);
+ }
+ clear();
+ }
+ return buffers;
+ }
+
+ /**
+ * Resize the vector to increase the capacity. The internal behavior is to
+ * double the current value capacity.
+ */
+ @Override
+ public void reAlloc() {
+ int targetValueCount = getValueCapacity() * 2;
+ if (targetValueCount == 0) {
+ if (lastValueCapacity > 0) {
+ targetValueCount = lastValueCapacity;
+ } else {
+ targetValueCount = INITIAL_VALUE_ALLOCATION * 2;
+ }
+ }
+ computeAndCheckBufferSize(targetValueCount);
+
+ DataAndValidityBuffers buffers = allocFixedDataAndValidityBufs(targetValueCount, typeWidth);
+ final ArrowBuf newValueBuffer = buffers.getDataBuf();
+ newValueBuffer.setBytes(0, valueBuffer, 0, valueBuffer.capacity());
+ newValueBuffer.setZero(valueBuffer.capacity(), newValueBuffer.capacity() - valueBuffer.capacity());
+ valueBuffer.getReferenceManager().release();
+ valueBuffer = newValueBuffer;
+
+ final ArrowBuf newValidityBuffer = buffers.getValidityBuf();
+ newValidityBuffer.setBytes(0, validityBuffer, 0, validityBuffer.capacity());
+ newValidityBuffer.setZero(validityBuffer.capacity(), newValidityBuffer.capacity() - validityBuffer.capacity());
+ validityBuffer.getReferenceManager().release();
+ validityBuffer = newValidityBuffer;
+
+ refreshValueCapacity();
+ lastValueCapacity = getValueCapacity();
+ }
+
+ /**
+ * Get the inner vectors.
+ *
+ * @deprecated This API will be removed as the current implementations no longer support inner vectors.
+ *
+ * @return the inner vectors for this field as defined by the TypeLayout
+ */
+ @Deprecated
+ @Override
+ public ListNote that data buffer for variable length vectors moves independent + * of the companion validity and offset buffers. This is in + * contrast to what we have for fixed width vectors. + * + *
So even though we may have setup an initial capacity of 1024 + * elements in the vector, it is quite possible + * that we need to reAlloc() the data buffer when we are setting + * the 5th element in the vector simply because previous + * variable length elements have exhausted the buffer capacity. + * However, we really don't need to reAlloc() validity and + * offset buffers until we try to set the 1025th element + * This is why we do a separate check for safe methods to + * determine which buffer needs reallocation. + * @throws OversizedAllocationException if the desired new size is more than + * max allowed + * @throws OutOfMemoryException if the internal memory allocation fails + */ + public void reallocValidityAndOffsetBuffers() { + int targetOffsetCount = capAtMaxInt((offsetBuffer.capacity() / OFFSET_WIDTH) * 2); + if (targetOffsetCount == 0) { + if (lastValueCapacity > 0) { + targetOffsetCount = (lastValueCapacity + 1); + } else { + targetOffsetCount = 2 * (INITIAL_VALUE_ALLOCATION + 1); + } + } + computeAndCheckOffsetsBufferSize(targetOffsetCount); + + DataAndValidityBuffers buffers = allocFixedDataAndValidityBufs(targetOffsetCount, OFFSET_WIDTH); + final ArrowBuf newOffsetBuffer = buffers.getDataBuf(); + newOffsetBuffer.setBytes(0, offsetBuffer, 0, offsetBuffer.capacity()); + newOffsetBuffer.setZero(offsetBuffer.capacity(), newOffsetBuffer.capacity() - offsetBuffer.capacity()); + offsetBuffer.getReferenceManager().release(); + offsetBuffer = newOffsetBuffer; + + final ArrowBuf newValidityBuffer = buffers.getValidityBuf(); + newValidityBuffer.setBytes(0, validityBuffer, 0, validityBuffer.capacity()); + newValidityBuffer.setZero(validityBuffer.capacity(), newValidityBuffer.capacity() - validityBuffer.capacity()); + validityBuffer.getReferenceManager().release(); + validityBuffer = newValidityBuffer; + + lastValueCapacity = getValueCapacity(); + } + + /** + * Get the size (number of bytes) of underlying data buffer. + * @return number of bytes in the data buffer + */ + @Override + public int getByteCapacity() { + return capAtMaxInt(valueBuffer.capacity()); + } + + @Override + public int sizeOfValueBuffer() { + if (valueCount == 0) { + return 0; + } + return capAtMaxInt(offsetBuffer.getLong((long) valueCount * OFFSET_WIDTH)); + } + + /** + * Get the size (number of bytes) of underlying buffers used by this + * vector. + * @return size of underlying buffers. + */ + @Override + public int getBufferSize() { + return getBufferSizeFor(this.valueCount); + } + + /** + * Get the potential buffer size for a particular number of records. + * @param valueCount desired number of elements in the vector + * @return estimated size of underlying buffers if the vector holds + * a given number of elements + */ + @Override + public int getBufferSizeFor(final int valueCount) { + if (valueCount == 0) { + return 0; + } + + final long validityBufferSize = getValidityBufferSizeFromCount(valueCount); + final long offsetBufferSize = (long) (valueCount + 1) * OFFSET_WIDTH; + /* get the end offset for this valueCount */ + final long dataBufferSize = offsetBuffer.getLong((long) valueCount * OFFSET_WIDTH); + return capAtMaxInt(validityBufferSize + offsetBufferSize + dataBufferSize); + } + + /** + * Get information about how this field is materialized. + * @return the field corresponding to this vector + */ + @Override + public Field getField() { + return field; + } + + /** + * 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 io.netty.buffer.ArrowBuf buffers} that is used by this + * vector instance. + */ + @Override + public ArrowBuf[] getBuffers(boolean clear) { + final ArrowBuf[] buffers; + setReaderAndWriterIndex(); + if (getBufferSize() == 0) { + buffers = new ArrowBuf[0]; + } else { + buffers = new ArrowBuf[3]; + buffers[0] = validityBuffer; + buffers[1] = offsetBuffer; + buffers[2] = valueBuffer; + } + if (clear) { + for (final ArrowBuf buffer : buffers) { + buffer.getReferenceManager().retain(); + } + clear(); + } + return buffers; + } + + /** + * Construct a transfer pair of this vector and another vector of same type. + * @param ref name of the target vector + * @param allocator allocator for the target vector + * @param callBack not used + * @return TransferPair + */ + @Override + public TransferPair getTransferPair(String ref, BufferAllocator allocator, CallBack callBack) { + return getTransferPair(ref, allocator); + } + + /** + * Construct a transfer pair of this vector and another vector of same type. + * @param allocator allocator for the target vector + * @return TransferPair + */ + @Override + public TransferPair getTransferPair(BufferAllocator allocator) { + return getTransferPair(getName(), allocator); + } + + /** + * Construct a transfer pair of this vector and another vector of same type. + * @param ref name of the target vector + * @param allocator allocator for the target vector + * @return TransferPair + */ + public abstract TransferPair getTransferPair(String ref, BufferAllocator allocator); + + /** + * Transfer this vector'data to another vector. The memory associated + * with this vector is transferred to the allocator of target vector + * for accounting and management purposes. + * @param target destination vector for transfer + */ + public void transferTo(BaseLargeVariableWidthVector target) { + compareTypes(target, "transferTo"); + target.clear(); + target.validityBuffer = transferBuffer(validityBuffer, target.allocator); + target.valueBuffer = transferBuffer(valueBuffer, target.allocator); + target.offsetBuffer = transferBuffer(offsetBuffer, target.allocator); + target.setLastSet(this.lastSet); + if (this.valueCount > 0) { + target.setValueCount(this.valueCount); + } + clear(); + } + + /** + * Slice this vector at desired index and length and transfer the + * corresponding data to the target vector. + * @param startIndex start position of the split in source vector. + * @param length length of the split. + * @param target destination vector + */ + public void splitAndTransferTo(int startIndex, int length, + BaseLargeVariableWidthVector target) { + Preconditions.checkArgument(startIndex >= 0 && startIndex < valueCount, + "Invalid startIndex: %s", startIndex); + Preconditions.checkArgument(startIndex + length <= valueCount, + "Invalid length: %s", length); + compareTypes(target, "splitAndTransferTo"); + target.clear(); + splitAndTransferValidityBuffer(startIndex, length, target); + splitAndTransferOffsetBuffer(startIndex, length, target); + target.setLastSet(length - 1); + if (length > 0) { + target.setValueCount(length); + } + } + + /** + * Transfer the offsets along with data. Unlike the data buffer, we cannot simply + * slice the offset buffer for split and transfer. The reason is that offsets + * in the target vector have to be adjusted and made relative to the staring + * offset in source vector from the start index of split. This is why, we + * need to explicitly allocate the offset buffer and set the adjusted offsets + * in the target vector. + */ + private void splitAndTransferOffsetBuffer(int startIndex, int length, BaseLargeVariableWidthVector target) { + final long start = offsetBuffer.getLong((long) startIndex * OFFSET_WIDTH); + final long end = offsetBuffer.getLong((long) (startIndex + length) * OFFSET_WIDTH); + final long dataLength = end - start; + target.allocateOffsetBuffer((long) (length + 1) * OFFSET_WIDTH); + for (int i = 0; i < length + 1; i++) { + final long relativeSourceOffset = offsetBuffer.getLong((long) (startIndex + i) * OFFSET_WIDTH) - start; + target.offsetBuffer.setLong((long) i * OFFSET_WIDTH, relativeSourceOffset); + } + final ArrowBuf slicedBuffer = valueBuffer.slice(start, dataLength); + target.valueBuffer = transferBuffer(slicedBuffer, target.allocator); + } + + /* + * Transfer the validity. + */ + private void splitAndTransferValidityBuffer(int startIndex, int length, + BaseLargeVariableWidthVector target) { + int firstByteSource = BitVectorHelper.byteIndex(startIndex); + int lastByteSource = BitVectorHelper.byteIndex(valueCount - 1); + int byteSizeTarget = getValidityBufferSizeFromCount(length); + int offset = startIndex % 8; + + if (length > 0) { + if (offset == 0) { + // slice + if (target.validityBuffer != null) { + target.validityBuffer.getReferenceManager().release(); + } + target.validityBuffer = validityBuffer.slice(firstByteSource, byteSizeTarget); + target.validityBuffer.getReferenceManager().retain(); + } else { + /* Copy data + * When the first bit starts from the middle of a byte (offset != 0), + * copy data from src BitVector. + * Each byte in the target is composed by a part in i-th byte, + * another part in (i+1)-th byte. + */ + target.allocateValidityBuffer(byteSizeTarget); + + for (int i = 0; i < byteSizeTarget - 1; i++) { + byte b1 = BitVectorHelper.getBitsFromCurrentByte(this.validityBuffer, firstByteSource + i, offset); + byte b2 = BitVectorHelper.getBitsFromNextByte(this.validityBuffer, firstByteSource + i + 1, offset); + + target.validityBuffer.setByte(i, (b1 + b2)); + } + /* Copying the last piece is done in the following manner: + * if the source vector has 1 or more bytes remaining, we copy + * the last piece as a byte formed by shifting data + * from the current byte and the next byte. + * + * if the source vector has no more bytes remaining + * (we are at the last byte), we copy the last piece as a byte + * by shifting data from the current byte. + */ + if ((firstByteSource + byteSizeTarget - 1) < lastByteSource) { + byte b1 = BitVectorHelper.getBitsFromCurrentByte(this.validityBuffer, + firstByteSource + byteSizeTarget - 1, offset); + byte b2 = BitVectorHelper.getBitsFromNextByte(this.validityBuffer, + firstByteSource + byteSizeTarget, offset); + + target.validityBuffer.setByte(byteSizeTarget - 1, b1 + b2); + } else { + byte b1 = BitVectorHelper.getBitsFromCurrentByte(this.validityBuffer, + firstByteSource + byteSizeTarget - 1, offset); + target.validityBuffer.setByte(byteSizeTarget - 1, b1); + } + } + } + } + + + /*----------------------------------------------------------------* + | | + | common getters and setters | + | | + *----------------------------------------------------------------*/ + + + /** + * Get the number of elements that are null in the vector. + * + * @return the number of null elements. + */ + public int getNullCount() { + return BitVectorHelper.getNullCount(validityBuffer, valueCount); + } + + /** + * Check if the given index is within the current value capacity + * of the vector. + * + * @param index position to check + * @return true if index is within the current value capacity + */ + public boolean isSafe(int index) { + return index < getValueCapacity(); + } + + /** + * Check if element at given index is null. + * + * @param index position of element + * @return true if element at given index is null + */ + public boolean isNull(int index) { + return (isSet(index) == 0); + } + + /** + * Same as {@link #isNull(int)}. + * + * @param index position of 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 value count of vector. This will always be zero unless + * setValueCount(int) has been called prior to calling this. + * + * @return valueCount for the vector + */ + public int getValueCount() { + return valueCount; + } + + /** + * Sets the value count for the vector. + * + * @param valueCount value count + */ + public void setValueCount(int valueCount) { + assert valueCount >= 0; + this.valueCount = valueCount; + while (valueCount > getValueCapacity()) { + reallocValidityAndOffsetBuffers(); + } + fillHoles(valueCount); + lastSet = valueCount - 1; + setReaderAndWriterIndex(); + } + + /** + * Create holes in the vector upto the given index (exclusive). + * Holes will be created from the current last set position in + * the vector. + * + * @param index target index + */ + public void fillEmpties(int index) { + handleSafe(index, emptyByteArray.length); + fillHoles(index); + lastSet = index - 1; + } + + /** + * Set the index of last non-null element in the vector. + * It is important to call this method with appropriate value + * before calling {@link #setValueCount(int)}. + * + * @param value desired index of last non-null element. + */ + public void setLastSet(int value) { + lastSet = value; + } + + /** + * Get the index of last non-null element in the vector. + * + * @return index of the last non-null element + */ + public int getLastSet() { + return lastSet; + } + + /** + * Mark the particular position in the vector as non-null. + * + * @param index position of the element. + */ + @Override + public void setIndexDefined(int index) { + // We need to check and realloc both validity and offset buffer + while (index >= getValueCapacity()) { + reallocValidityAndOffsetBuffers(); + } + BitVectorHelper.setBit(validityBuffer, index); + } + + /** + * Sets the value length for an element. + * + * @param index position of the element to set + * @param length length of the element + */ + public void setValueLengthSafe(int index, int length) { + assert index >= 0; + handleSafe(index, length); + fillHoles(index); + final long startOffset = getStartOffset(index); + offsetBuffer.setLong((long) (index + 1) * OFFSET_WIDTH, startOffset + length); + lastSet = index; + } + + /** + * Get the variable length element at specified index as Text. + * + * @param index position of element to get + * @return greater than 0 length for non-null element, 0 otherwise + */ + public int getValueLength(int index) { + assert index >= 0; + if (isSet(index) == 0) { + return 0; + } + final long startOffset = getStartOffset(index); + final int dataLength = + (int) (offsetBuffer.getLong((long) (index + 1) * OFFSET_WIDTH) - startOffset); + return dataLength; + } + + /** + * Set the variable length element at the specified index to the supplied + * byte array. This is same as using {@link #set(int, byte[], int, int)} + * with start as 0 and length as value.length + * + * @param index position of the element to set + * @param value array of bytes to write + */ + public void set(int index, byte[] value) { + assert index >= 0; + fillHoles(index); + BitVectorHelper.setBit(validityBuffer, index); + setBytes(index, value, 0, value.length); + lastSet = index; + } + + /** + * Same as {@link #set(int, byte[])} except that it handles the + * case where index and length of new element are beyond the existing + * capacity of the vector. + * + * @param index position of the element to set + * @param value array of bytes to write + */ + public void setSafe(int index, byte[] value) { + assert index >= 0; + handleSafe(index, value.length); + fillHoles(index); + BitVectorHelper.setBit(validityBuffer, index); + setBytes(index, value, 0, value.length); + lastSet = index; + } + + /** + * Set the variable length element at the specified index to the supplied + * byte array. + * + * @param index position of the element to set + * @param value array of bytes to write + * @param start start index in array of bytes + * @param length length of data in array of bytes + */ + public void set(int index, byte[] value, int start, int length) { + assert index >= 0; + fillHoles(index); + BitVectorHelper.setBit(validityBuffer, index); + setBytes(index, value, start, length); + lastSet = index; + } + + /** + * Same as {@link #set(int, byte[], int, int)} except that it handles the + * case where index and length of new element are beyond the existing + * capacity of the vector. + * + * @param index position of the element to set + * @param value array of bytes to write + * @param start start index in array of bytes + * @param length length of data in array of bytes + */ + public void setSafe(int index, byte[] value, int start, int length) { + assert index >= 0; + handleSafe(index, length); + fillHoles(index); + BitVectorHelper.setBit(validityBuffer, index); + setBytes(index, value, start, length); + lastSet = index; + } + + /** + * Set the variable length element at the specified index to the + * content in supplied ByteBuffer. + * + * @param index position of the element to set + * @param value ByteBuffer with data + * @param start start index in ByteBuffer + * @param length length of data in ByteBuffer + */ + public void set(int index, ByteBuffer value, int start, int length) { + assert index >= 0; + fillHoles(index); + BitVectorHelper.setBit(validityBuffer, index); + final long startOffset = getStartOffset(index); + offsetBuffer.setLong((long) (index + 1) * OFFSET_WIDTH, startOffset + length); + valueBuffer.setBytes(startOffset, value, start, length); + lastSet = index; + } + + /** + * Same as {@link #set(int, ByteBuffer, int, int)} except that it handles the + * case where index and length of new element are beyond the existing + * capacity of the vector. + * + * @param index position of the element to set + * @param value ByteBuffer with data + * @param start start index in ByteBuffer + * @param length length of data in ByteBuffer + */ + public void setSafe(int index, ByteBuffer value, int start, int length) { + assert index >= 0; + handleSafe(index, length); + fillHoles(index); + BitVectorHelper.setBit(validityBuffer, index); + final long startOffset = getStartOffset(index); + offsetBuffer.setLong((long) (index + 1) * OFFSET_WIDTH, startOffset + length); + valueBuffer.setBytes(startOffset, value, start, length); + lastSet = index; + } + + /** + * Set the element at the given index to null. + * + * @param index position of element + */ + public void setNull(int index) { + // We need to check and realloc both validity and offset buffer + while (index >= getValueCapacity()) { + reallocValidityAndOffsetBuffers(); + } + BitVectorHelper.unsetBit(validityBuffer, index); + } + + /** + * Store the given value at a particular position in the vector. isSet indicates + * whether the value is NULL or not. + * @param index position of the new value + * @param isSet 0 for NULL value, 1 otherwise + * @param start start position of data in buffer + * @param end end position of data in buffer + * @param buffer data buffer containing the variable width element to be stored + * in the vector + */ + public void set(int index, int isSet, long start, long end, ArrowBuf buffer) { + assert index >= 0; + final long dataLength = end - start; + fillHoles(index); + BitVectorHelper.setValidityBit(validityBuffer, index, isSet); + final long startOffset = offsetBuffer.getLong((long) index * OFFSET_WIDTH); + offsetBuffer.setLong((long) (index + 1) * OFFSET_WIDTH, end); + valueBuffer.setBytes(startOffset, buffer, start, dataLength); + lastSet = index; + } + + /** + * Same as {@link #set(int, int, long, long, ArrowBuf)} except that it handles the case + * when index is greater than or equal to current value capacity of the + * vector. + * @param index position of the new value + * @param isSet 0 for NULL value, 1 otherwise + * @param start start position of data in buffer + * @param end end position of data in buffer + * @param buffer data buffer containing the variable width element to be stored + * in the vector + */ + public void setSafe(int index, int isSet, long start, long end, ArrowBuf buffer) { + assert index >= 0; + final long dataLength = end - start; + handleSafe(index, (int) dataLength); + fillHoles(index); + BitVectorHelper.setValidityBit(validityBuffer, index, isSet); + final long startOffset = offsetBuffer.getLong((long) index * OFFSET_WIDTH); + offsetBuffer.setLong((long) (index + 1) * OFFSET_WIDTH, startOffset + dataLength); + valueBuffer.setBytes(startOffset, buffer, start, dataLength); + lastSet = index; + } + + /** + * Store the given value at a particular position in the vector. isSet indicates + * whether the value is NULL or not. + * @param index position of the new value + * @param start start position of data in buffer + * @param length length of data in buffer + * @param buffer data buffer containing the variable width element to be stored + * in the vector + */ + public void set(int index, long start, int length, ArrowBuf buffer) { + assert index >= 0; + fillHoles(index); + BitVectorHelper.setBit(validityBuffer, index); + final long startOffset = offsetBuffer.getLong((long) index * OFFSET_WIDTH); + offsetBuffer.setLong((long) (index + 1) * OFFSET_WIDTH, startOffset + length); + final ArrowBuf bb = buffer.slice(start, length); + valueBuffer.setBytes(startOffset, bb); + lastSet = index; + } + + /** + * Same as {@link #set(int, int, long, long, ArrowBuf)} except that it handles the case + * when index is greater than or equal to current value capacity of the + * vector. + * @param index position of the new value + * @param start start position of data in buffer + * @param length length of data in buffer + * @param buffer data buffer containing the variable width element to be stored + * in the vector + */ + public void setSafe(int index, long start, int length, ArrowBuf buffer) { + assert index >= 0; + handleSafe(index, length); + fillHoles(index); + BitVectorHelper.setBit(validityBuffer, index); + final long startOffset = offsetBuffer.getLong((long) index * OFFSET_WIDTH); + offsetBuffer.setLong((long) (index + 1) * OFFSET_WIDTH, startOffset + length); + final ArrowBuf bb = buffer.slice(start, length); + valueBuffer.setBytes(startOffset, bb); + lastSet = index; + } + + + /*----------------------------------------------------------------* + | | + | helper methods for setters | + | | + *----------------------------------------------------------------*/ + + + protected final void fillHoles(int index) { + for (int i = lastSet + 1; i < index; i++) { + setBytes(i, emptyByteArray, 0, emptyByteArray.length); + } + lastSet = index - 1; + } + + protected final void setBytes(int index, byte[] value, int start, int length) { + /* end offset of current last element in the vector. this will + * be the start offset of new element we are trying to store. + */ + final long startOffset = getStartOffset(index); + /* set new end offset */ + offsetBuffer.setLong((long) (index + 1) * OFFSET_WIDTH, startOffset + length); + /* store the var length data in value buffer */ + valueBuffer.setBytes(startOffset, value, start, length); + } + + /** + * Gets the starting offset of a record, given its index. + * @param index index of the record. + * @return the starting offset of the record. + */ + protected final long getStartOffset(int index) { + return offsetBuffer.getLong((long) index * OFFSET_WIDTH); + } + + protected final void handleSafe(int index, int dataLength) { + /* + * IMPORTANT: + * value buffer for variable length vectors moves independent + * of the companion validity and offset buffers. This is in + * contrast to what we have for fixed width vectors. + * + * Here there is no concept of getValueCapacity() in the + * data stream. getValueCapacity() is applicable only to validity + * and offset buffers. + * + * So even though we may have setup an initial capacity of 1024 + * elements in the vector, it is quite possible + * that we need to reAlloc() the data buffer when we are setting + * the 5th element in the vector simply because previous + * variable length elements have exhausted the buffer capacity. + * However, we really don't need to reAlloc() validity and + * offset buffers until we try to set the 1025th element + * This is why we do a separate check for safe methods to + * determine which buffer needs reallocation. + */ + while (index >= getValueCapacity()) { + reallocValidityAndOffsetBuffers(); + } + final long startOffset = lastSet < 0 ? 0L : getStartOffset(lastSet + 1); + while (valueBuffer.capacity() < (startOffset + dataLength)) { + reallocDataBuffer(); + } + } + + /** + * Method used by Json Writer to read a variable width element from + * the variable width vector and write to Json. + * + *
This method should not be used externally. + * + * @param data buffer storing the variable width vector elements + * @param offset buffer storing the offsets of variable width vector elements + * @param index position of the element in the vector + * @return array of bytes + */ + public static byte[] get(final ArrowBuf data, final ArrowBuf offset, int index) { + final long currentStartOffset = offset.getLong((long) index * OFFSET_WIDTH); + final int dataLength = + (int) (offset.getLong((long) (index + 1) * OFFSET_WIDTH) - currentStartOffset); + final byte[] result = new byte[dataLength]; + data.getBytes(currentStartOffset, result, 0, dataLength); + return result; + } + + /** + * Method used by Json Reader to explicitly set the offsets of the variable + * width vector data. The method takes care of allocating the memory for + * offsets if the caller hasn't done so. + * + *
This method should not be used externally.
+ *
+ * @param buffer ArrowBuf to store offsets for variable width elements
+ * @param allocator memory allocator
+ * @param valueCount number of elements
+ * @param index position of the element
+ * @param value offset of the element
+ * @return buffer holding the offsets
+ */
+ public static ArrowBuf set(ArrowBuf buffer, BufferAllocator allocator,
+ int valueCount, int index, long value) {
+ if (buffer == null) {
+ buffer = allocator.buffer((long) valueCount * OFFSET_WIDTH);
+ }
+ buffer.setLong((long) index * OFFSET_WIDTH, value);
+ if (index == (valueCount - 1)) {
+ buffer.writerIndex((long) valueCount * OFFSET_WIDTH);
+ }
+
+ return buffer;
+ }
+
+ /**
+ * Copy a cell value from a particular index in source vector to a particular
+ * position in this vector.
+ *
+ * @param fromIndex position to copy from in source vector
+ * @param thisIndex position to copy to in this vector
+ * @param from source vector
+ */
+ @Override
+ public void copyFrom(int fromIndex, int thisIndex, ValueVector from) {
+ Preconditions.checkArgument(this.getMinorType() == from.getMinorType());
+ if (from.isNull(fromIndex)) {
+ fillHoles(thisIndex);
+ BitVectorHelper.unsetBit(this.validityBuffer, thisIndex);
+ final long copyStart = offsetBuffer.getLong((long) thisIndex * OFFSET_WIDTH);
+ offsetBuffer.setLong((long) (thisIndex + 1) * OFFSET_WIDTH, copyStart);
+ } else {
+ final long start = from.getOffsetBuffer().getLong((long) fromIndex * OFFSET_WIDTH);
+ final long end = from.getOffsetBuffer().getLong((long) (fromIndex + 1) * OFFSET_WIDTH);
+ final long length = end - start;
+ fillHoles(thisIndex);
+ BitVectorHelper.setBit(this.validityBuffer, thisIndex);
+ final long copyStart = offsetBuffer.getLong((long) thisIndex * OFFSET_WIDTH);
+ from.getDataBuffer().getBytes(start, this.valueBuffer, copyStart, (int) length);
+ offsetBuffer.setLong((long) (thisIndex + 1) * OFFSET_WIDTH, copyStart + length);
+ }
+ lastSet = thisIndex;
+ }
+
+ /**
+ * Same as {@link #copyFrom(int, int, ValueVector)} except that
+ * it handles the case when the capacity of the vector needs to be expanded
+ * before copy.
+ *
+ * @param fromIndex position to copy from in source vector
+ * @param thisIndex position to copy to in this vector
+ * @param from source vector
+ */
+ @Override
+ public void copyFromSafe(int fromIndex, int thisIndex, ValueVector from) {
+ Preconditions.checkArgument(this.getMinorType() == from.getMinorType());
+ if (from.isNull(fromIndex)) {
+ handleSafe(thisIndex, 0);
+ fillHoles(thisIndex);
+ BitVectorHelper.unsetBit(this.validityBuffer, thisIndex);
+ final long copyStart = offsetBuffer.getLong((long) thisIndex * OFFSET_WIDTH);
+ offsetBuffer.setLong((long) (thisIndex + 1) * OFFSET_WIDTH, copyStart);
+ } else {
+ final long start = from.getOffsetBuffer().getLong((long) fromIndex * OFFSET_WIDTH);
+ final long end = from.getOffsetBuffer().getLong((long) (fromIndex + 1) * OFFSET_WIDTH);
+ final int length = (int) (end - start);
+ handleSafe(thisIndex, length);
+ fillHoles(thisIndex);
+ BitVectorHelper.setBit(this.validityBuffer, thisIndex);
+ final long copyStart = offsetBuffer.getLong((long) thisIndex * OFFSET_WIDTH);
+ from.getDataBuffer().getBytes(start, this.valueBuffer, copyStart, length);
+ offsetBuffer.setLong((long) (thisIndex + 1) * OFFSET_WIDTH, copyStart + length);
+ }
+ lastSet = thisIndex;
+ }
+
+ @Override
+ public ArrowBufPointer getDataPointer(int index) {
+ return getDataPointer(index, new ArrowBufPointer());
+ }
+
+ @Override
+ public ArrowBufPointer getDataPointer(int index, ArrowBufPointer reuse) {
+ if (isNull(index)) {
+ reuse.set(null, 0, 0);
+ } else {
+ long offset = offsetBuffer.getLong((long) index * OFFSET_WIDTH);
+ int length = (int) (offsetBuffer.getLong((long) (index + 1) * OFFSET_WIDTH) - offset);
+ reuse.set(valueBuffer, offset, length);
+ }
+ return reuse;
+ }
+
+ @Override
+ public int hashCode(int index) {
+ return hashCode(index, null);
+ }
+
+ @Override
+ public int hashCode(int index, ArrowBufHasher hasher) {
+ if (isNull(index)) {
+ return ArrowBufPointer.NULL_HASH_CODE;
+ }
+ final long start = getStartOffset(index);
+ final long end = getStartOffset(index + 1);
+ return ByteFunctionHelpers.hash(hasher, this.getDataBuffer(), start, end);
+ }
+
+ @Override
+ public Note that data buffer for variable length vectors moves independent
+ * of the companion validity and offset buffers. This is in
+ * contrast to what we have for fixed width vectors.
+ *
+ * So even though we may have setup an initial capacity of 1024
+ * elements in the vector, it is quite possible
+ * that we need to reAlloc() the data buffer when we are setting
+ * the 5th element in the vector simply because previous
+ * variable length elements have exhausted the buffer capacity.
+ * However, we really don't need to reAlloc() validity and
+ * offset buffers until we try to set the 1025th element
+ * This is why we do a separate check for safe methods to
+ * determine which buffer needs reallocation.
+ * @throws OversizedAllocationException if the desired new size is more than
+ * max allowed
+ * @throws OutOfMemoryException if the internal memory allocation fails
+ */
+ public void reallocValidityAndOffsetBuffers() {
+ int targetOffsetCount = capAtMaxInt((offsetBuffer.capacity() / OFFSET_WIDTH) * 2);
+ if (targetOffsetCount == 0) {
+ if (lastValueCapacity > 0) {
+ targetOffsetCount = (lastValueCapacity + 1);
+ } else {
+ targetOffsetCount = 2 * (INITIAL_VALUE_ALLOCATION + 1);
+ }
+ }
+ computeAndCheckOffsetsBufferSize(targetOffsetCount);
+
+ DataAndValidityBuffers buffers = allocFixedDataAndValidityBufs(targetOffsetCount, OFFSET_WIDTH);
+ final ArrowBuf newOffsetBuffer = buffers.getDataBuf();
+ newOffsetBuffer.setBytes(0, offsetBuffer, 0, offsetBuffer.capacity());
+ newOffsetBuffer.setZero(offsetBuffer.capacity(), newOffsetBuffer.capacity() - offsetBuffer.capacity());
+ offsetBuffer.getReferenceManager().release();
+ offsetBuffer = newOffsetBuffer;
+
+ final ArrowBuf newValidityBuffer = buffers.getValidityBuf();
+ newValidityBuffer.setBytes(0, validityBuffer, 0, validityBuffer.capacity());
+ newValidityBuffer.setZero(validityBuffer.capacity(), newValidityBuffer.capacity() - validityBuffer.capacity());
+ validityBuffer.getReferenceManager().release();
+ validityBuffer = newValidityBuffer;
+
+ lastValueCapacity = getValueCapacity();
+ }
+
+ /**
+ * Get the size (number of bytes) of underlying data buffer.
+ * @return number of bytes in the data buffer
+ */
+ @Override
+ public int getByteCapacity() {
+ return capAtMaxInt(valueBuffer.capacity());
+ }
+
+ @Override
+ public int sizeOfValueBuffer() {
+ if (valueCount == 0) {
+ return 0;
+ }
+ return offsetBuffer.getInt((long) valueCount * OFFSET_WIDTH);
+ }
+
+ /**
+ * Get the size (number of bytes) of underlying buffers used by this
+ * vector.
+ * @return size of underlying buffers.
+ */
+ @Override
+ public int getBufferSize() {
+ return getBufferSizeFor(this.valueCount);
+ }
+
+ /**
+ * Get the potential buffer size for a particular number of records.
+ * @param valueCount desired number of elements in the vector
+ * @return estimated size of underlying buffers if the vector holds
+ * a given number of elements
+ */
+ @Override
+ public int getBufferSizeFor(final int valueCount) {
+ if (valueCount == 0) {
+ return 0;
+ }
+
+ final int validityBufferSize = getValidityBufferSizeFromCount(valueCount);
+ final int offsetBufferSize = (valueCount + 1) * OFFSET_WIDTH;
+ /* get the end offset for this valueCount */
+ final int dataBufferSize = offsetBuffer.getInt((long) valueCount * OFFSET_WIDTH);
+ return validityBufferSize + offsetBufferSize + dataBufferSize;
+ }
+
+ /**
+ * Get information about how this field is materialized.
+ * @return the field corresponding to this vector
+ */
+ @Override
+ public Field getField() {
+ return field;
+ }
+
+ /**
+ * 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) {
+ final ArrowBuf[] buffers;
+ setReaderAndWriterIndex();
+ if (getBufferSize() == 0) {
+ buffers = new ArrowBuf[0];
+ } else {
+ buffers = new ArrowBuf[3];
+ buffers[0] = validityBuffer;
+ buffers[1] = offsetBuffer;
+ buffers[2] = valueBuffer;
+ }
+ if (clear) {
+ for (final ArrowBuf buffer : buffers) {
+ buffer.getReferenceManager().retain();
+ }
+ clear();
+ }
+ return buffers;
+ }
+
+ /**
+ * Construct a transfer pair of this vector and another vector of same type.
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @param callBack not used
+ * @return TransferPair
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator, CallBack callBack) {
+ return getTransferPair(ref, allocator);
+ }
+
+ /**
+ * Construct a transfer pair of this vector and another vector of same type.
+ * @param allocator allocator for the target vector
+ * @return TransferPair
+ */
+ @Override
+ public TransferPair getTransferPair(BufferAllocator allocator) {
+ return getTransferPair(getName(), allocator);
+ }
+
+ /**
+ * Construct a transfer pair of this vector and another vector of same type.
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return TransferPair
+ */
+ public abstract TransferPair getTransferPair(String ref, BufferAllocator allocator);
+
+ /**
+ * Transfer this vector'data to another vector. The memory associated
+ * with this vector is transferred to the allocator of target vector
+ * for accounting and management purposes.
+ * @param target destination vector for transfer
+ */
+ public void transferTo(BaseVariableWidthVector target) {
+ compareTypes(target, "transferTo");
+ target.clear();
+ target.validityBuffer = transferBuffer(validityBuffer, target.allocator);
+ target.valueBuffer = transferBuffer(valueBuffer, target.allocator);
+ target.offsetBuffer = transferBuffer(offsetBuffer, target.allocator);
+ target.setLastSet(this.lastSet);
+ if (this.valueCount > 0) {
+ target.setValueCount(this.valueCount);
+ }
+ clear();
+ }
+
+ /**
+ * Slice this vector at desired index and length and transfer the
+ * corresponding data to the target vector.
+ * @param startIndex start position of the split in source vector.
+ * @param length length of the split.
+ * @param target destination vector
+ */
+ public void splitAndTransferTo(int startIndex, int length,
+ BaseVariableWidthVector target) {
+ Preconditions.checkArgument(startIndex >= 0 && length >= 0 && startIndex + length <= valueCount,
+ "Invalid parameters startIndex: %s, length: %s for valueCount: %s", startIndex, length, valueCount);
+ compareTypes(target, "splitAndTransferTo");
+ target.clear();
+ splitAndTransferValidityBuffer(startIndex, length, target);
+ splitAndTransferOffsetBuffer(startIndex, length, target);
+ target.setLastSet(length - 1);
+ if (length > 0) {
+ target.setValueCount(length);
+ }
+ }
+
+ /**
+ * Transfer the offsets along with data. Unlike the data buffer, we cannot simply
+ * slice the offset buffer for split and transfer. The reason is that offsets
+ * in the target vector have to be adjusted and made relative to the staring
+ * offset in source vector from the start index of split. This is why, we
+ * need to explicitly allocate the offset buffer and set the adjusted offsets
+ * in the target vector.
+ */
+ private void splitAndTransferOffsetBuffer(int startIndex, int length, BaseVariableWidthVector target) {
+ final int start = offsetBuffer.getInt((long) startIndex * OFFSET_WIDTH);
+ final int end = offsetBuffer.getInt((long) (startIndex + length) * OFFSET_WIDTH);
+ final int dataLength = end - start;
+
+ if (start == 0) {
+ final ArrowBuf slicedOffsetBuffer = offsetBuffer.slice(startIndex * OFFSET_WIDTH, (1 + length) * OFFSET_WIDTH);
+ target.offsetBuffer = transferBuffer(slicedOffsetBuffer, target.allocator);
+ } else {
+ target.allocateOffsetBuffer((long) (length + 1) * OFFSET_WIDTH);
+ for (int i = 0; i < length + 1; i++) {
+ final int relativeSourceOffset = offsetBuffer.getInt((long) (startIndex + i) * OFFSET_WIDTH) - start;
+ target.offsetBuffer.setInt((long) i * OFFSET_WIDTH, relativeSourceOffset);
+ }
+ }
+ final ArrowBuf slicedBuffer = valueBuffer.slice(start, dataLength);
+ target.valueBuffer = transferBuffer(slicedBuffer, target.allocator);
+ }
+
+ /*
+ * Transfer the validity.
+ */
+ private void splitAndTransferValidityBuffer(int startIndex, int length,
+ BaseVariableWidthVector target) {
+ if (length <= 0) {
+ return;
+ }
+
+ final int firstByteSource = BitVectorHelper.byteIndex(startIndex);
+ final int lastByteSource = BitVectorHelper.byteIndex(valueCount - 1);
+ final int byteSizeTarget = getValidityBufferSizeFromCount(length);
+ final int offset = startIndex % 8;
+
+ if (offset == 0) {
+ // slice
+ if (target.validityBuffer != null) {
+ target.validityBuffer.getReferenceManager().release();
+ }
+ final ArrowBuf slicedValidityBuffer = validityBuffer.slice(firstByteSource, byteSizeTarget);
+ target.validityBuffer = transferBuffer(slicedValidityBuffer, target.allocator);
+ return;
+ }
+
+ /* Copy data
+ * When the first bit starts from the middle of a byte (offset != 0),
+ * copy data from src BitVector.
+ * Each byte in the target is composed by a part in i-th byte,
+ * another part in (i+1)-th byte.
+ */
+ target.allocateValidityBuffer(byteSizeTarget);
+
+ for (int i = 0; i < byteSizeTarget - 1; i++) {
+ byte b1 = BitVectorHelper.getBitsFromCurrentByte(this.validityBuffer, firstByteSource + i, offset);
+ byte b2 = BitVectorHelper.getBitsFromNextByte(this.validityBuffer, firstByteSource + i + 1, offset);
+
+ target.validityBuffer.setByte(i, (b1 + b2));
+ }
+ /* Copying the last piece is done in the following manner:
+ * if the source vector has 1 or more bytes remaining, we copy
+ * the last piece as a byte formed by shifting data
+ * from the current byte and the next byte.
+ *
+ * if the source vector has no more bytes remaining
+ * (we are at the last byte), we copy the last piece as a byte
+ * by shifting data from the current byte.
+ */
+ if ((firstByteSource + byteSizeTarget - 1) < lastByteSource) {
+ byte b1 = BitVectorHelper.getBitsFromCurrentByte(this.validityBuffer,
+ firstByteSource + byteSizeTarget - 1, offset);
+ byte b2 = BitVectorHelper.getBitsFromNextByte(this.validityBuffer,
+ firstByteSource + byteSizeTarget, offset);
+
+ target.validityBuffer.setByte(byteSizeTarget - 1, b1 + b2);
+ } else {
+ byte b1 = BitVectorHelper.getBitsFromCurrentByte(this.validityBuffer,
+ firstByteSource + byteSizeTarget - 1, offset);
+ target.validityBuffer.setByte(byteSizeTarget - 1, b1);
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | common getters and setters |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the number of elements that are null in the vector.
+ *
+ * @return the number of null elements.
+ */
+ public int getNullCount() {
+ return BitVectorHelper.getNullCount(validityBuffer, valueCount);
+ }
+
+ /**
+ * Check if the given index is within the current value capacity
+ * of the vector.
+ *
+ * @param index position to check
+ * @return true if index is within the current value capacity
+ */
+ public boolean isSafe(int index) {
+ return index < getValueCapacity();
+ }
+
+ /**
+ * Check if element at given index is null.
+ *
+ * @param index position of element
+ * @return true if element at given index is null
+ */
+ public boolean isNull(int index) {
+ return (isSet(index) == 0);
+ }
+
+ /**
+ * Same as {@link #isNull(int)}.
+ *
+ * @param index position of 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 value count of vector. This will always be zero unless
+ * setValueCount(int) has been called prior to calling this.
+ *
+ * @return valueCount for the vector
+ */
+ public int getValueCount() {
+ return valueCount;
+ }
+
+ /**
+ * Sets the value count for the vector.
+ *
+ * @param valueCount value count
+ */
+ public void setValueCount(int valueCount) {
+ assert valueCount >= 0;
+ this.valueCount = valueCount;
+ while (valueCount > getValueCapacity()) {
+ reallocValidityAndOffsetBuffers();
+ }
+ fillHoles(valueCount);
+ lastSet = valueCount - 1;
+ setReaderAndWriterIndex();
+ }
+
+ /**
+ * Create holes in the vector upto the given index (exclusive).
+ * Holes will be created from the current last set position in
+ * the vector.
+ *
+ * @param index target index
+ */
+ public void fillEmpties(int index) {
+ handleSafe(index, emptyByteArray.length);
+ fillHoles(index);
+ lastSet = index - 1;
+ }
+
+ /**
+ * Set the index of last non-null element in the vector.
+ * It is important to call this method with appropriate value
+ * before calling {@link #setValueCount(int)}.
+ *
+ * @param value desired index of last non-null element.
+ */
+ public void setLastSet(int value) {
+ lastSet = value;
+ }
+
+ /**
+ * Get the index of last non-null element in the vector.
+ *
+ * @return index of the last non-null element
+ */
+ public int getLastSet() {
+ return lastSet;
+ }
+
+ /**
+ * Get the starting position (offset) in the data stream for a given
+ * element in the vector.
+ *
+ * @param index position of the element in the vector
+ * @return starting offset for the element
+ */
+ public long getStartEnd(int index) {
+ return offsetBuffer.getLong((long) index * OFFSET_WIDTH);
+ }
+
+ /**
+ * Mark the particular position in the vector as non-null.
+ *
+ * @param index position of the element.
+ */
+ @Override
+ public void setIndexDefined(int index) {
+ // We need to check and realloc both validity and offset buffer
+ while (index >= getValueCapacity()) {
+ reallocValidityAndOffsetBuffers();
+ }
+ BitVectorHelper.setBit(validityBuffer, index);
+ }
+
+ /**
+ * Sets the value length for an element.
+ *
+ * @param index position of the element to set
+ * @param length length of the element
+ */
+ public void setValueLengthSafe(int index, int length) {
+ assert index >= 0;
+ handleSafe(index, length);
+ fillHoles(index);
+ final int startOffset = getStartOffset(index);
+ offsetBuffer.setInt((index + 1) * OFFSET_WIDTH, startOffset + length);
+ lastSet = index;
+ }
+
+ /**
+ * Get the variable length element at specified index as Text.
+ *
+ * @param index position of element to get
+ * @return greater than 0 length for non-null element, 0 otherwise
+ */
+ public int getValueLength(int index) {
+ assert index >= 0;
+ if (isSet(index) == 0) {
+ return 0;
+ }
+ final int startOffset = getStartOffset(index);
+ final int dataLength =
+ offsetBuffer.getInt((index + 1) * OFFSET_WIDTH) - startOffset;
+ return dataLength;
+ }
+
+ /**
+ * Set the variable length element at the specified index to the supplied
+ * byte array. This is same as using {@link #set(int, byte[], int, int)}
+ * with start as 0 and length as value.length
+ *
+ * @param index position of the element to set
+ * @param value array of bytes to write
+ */
+ public void set(int index, byte[] value) {
+ assert index >= 0;
+ fillHoles(index);
+ BitVectorHelper.setBit(validityBuffer, index);
+ setBytes(index, value, 0, value.length);
+ lastSet = index;
+ }
+
+ /**
+ * Same as {@link #set(int, byte[])} except that it handles the
+ * case where index and length of new element are beyond the existing
+ * capacity of the vector.
+ *
+ * @param index position of the element to set
+ * @param value array of bytes to write
+ */
+ public void setSafe(int index, byte[] value) {
+ assert index >= 0;
+ handleSafe(index, value.length);
+ fillHoles(index);
+ BitVectorHelper.setBit(validityBuffer, index);
+ setBytes(index, value, 0, value.length);
+ lastSet = index;
+ }
+
+ /**
+ * Set the variable length element at the specified index to the supplied
+ * byte array.
+ *
+ * @param index position of the element to set
+ * @param value array of bytes to write
+ * @param start start index in array of bytes
+ * @param length length of data in array of bytes
+ */
+ public void set(int index, byte[] value, int start, int length) {
+ assert index >= 0;
+ fillHoles(index);
+ BitVectorHelper.setBit(validityBuffer, index);
+ setBytes(index, value, start, length);
+ lastSet = index;
+ }
+
+ /**
+ * Same as {@link #set(int, byte[], int, int)} except that it handles the
+ * case where index and length of new element are beyond the existing
+ * capacity of the vector.
+ *
+ * @param index position of the element to set
+ * @param value array of bytes to write
+ * @param start start index in array of bytes
+ * @param length length of data in array of bytes
+ */
+ public void setSafe(int index, byte[] value, int start, int length) {
+ assert index >= 0;
+ handleSafe(index, length);
+ fillHoles(index);
+ BitVectorHelper.setBit(validityBuffer, index);
+ setBytes(index, value, start, length);
+ lastSet = index;
+ }
+
+ /**
+ * Set the variable length element at the specified index to the
+ * content in supplied ByteBuffer.
+ *
+ * @param index position of the element to set
+ * @param value ByteBuffer with data
+ * @param start start index in ByteBuffer
+ * @param length length of data in ByteBuffer
+ */
+ public void set(int index, ByteBuffer value, int start, int length) {
+ assert index >= 0;
+ fillHoles(index);
+ BitVectorHelper.setBit(validityBuffer, index);
+ final int startOffset = getStartOffset(index);
+ offsetBuffer.setInt((index + 1) * OFFSET_WIDTH, startOffset + length);
+ valueBuffer.setBytes(startOffset, value, start, length);
+ lastSet = index;
+ }
+
+ /**
+ * Same as {@link #set(int, ByteBuffer, int, int)} except that it handles the
+ * case where index and length of new element are beyond the existing
+ * capacity of the vector.
+ *
+ * @param index position of the element to set
+ * @param value ByteBuffer with data
+ * @param start start index in ByteBuffer
+ * @param length length of data in ByteBuffer
+ */
+ public void setSafe(int index, ByteBuffer value, int start, int length) {
+ assert index >= 0;
+ handleSafe(index, length);
+ fillHoles(index);
+ BitVectorHelper.setBit(validityBuffer, index);
+ final int startOffset = getStartOffset(index);
+ offsetBuffer.setInt((index + 1) * OFFSET_WIDTH, startOffset + length);
+ valueBuffer.setBytes(startOffset, value, start, length);
+ lastSet = index;
+ }
+
+ /**
+ * Set the element at the given index to null.
+ *
+ * @param index position of element
+ */
+ public void setNull(int index) {
+ // We need to check and realloc both validity and offset buffer
+ while (index >= getValueCapacity()) {
+ reallocValidityAndOffsetBuffers();
+ }
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param start start position of data in buffer
+ * @param end end position of data in buffer
+ * @param buffer data buffer containing the variable width element to be stored
+ * in the vector
+ */
+ public void set(int index, int isSet, int start, int end, ArrowBuf buffer) {
+ assert index >= 0;
+ final int dataLength = end - start;
+ fillHoles(index);
+ BitVectorHelper.setValidityBit(validityBuffer, index, isSet);
+ final int startOffset = offsetBuffer.getInt((long) index * OFFSET_WIDTH);
+ offsetBuffer.setInt((index + 1) * OFFSET_WIDTH, startOffset + dataLength);
+ valueBuffer.setBytes(startOffset, buffer, start, dataLength);
+ lastSet = index;
+ }
+
+ /**
+ * Same as {@link #set(int, int, int, int, ArrowBuf)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param start start position of data in buffer
+ * @param end end position of data in buffer
+ * @param buffer data buffer containing the variable width element to be stored
+ * in the vector
+ */
+ public void setSafe(int index, int isSet, int start, int end, ArrowBuf buffer) {
+ assert index >= 0;
+ final int dataLength = end - start;
+ handleSafe(index, dataLength);
+ fillHoles(index);
+ BitVectorHelper.setValidityBit(validityBuffer, index, isSet);
+ final int startOffset = offsetBuffer.getInt((long) index * OFFSET_WIDTH);
+ offsetBuffer.setInt((long) (index + 1) * OFFSET_WIDTH, startOffset + dataLength);
+ valueBuffer.setBytes(startOffset, buffer, start, dataLength);
+ lastSet = index;
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ * @param index position of the new value
+ * @param start start position of data in buffer
+ * @param length length of data in buffer
+ * @param buffer data buffer containing the variable width element to be stored
+ * in the vector
+ */
+ public void set(int index, int start, int length, ArrowBuf buffer) {
+ assert index >= 0;
+ fillHoles(index);
+ BitVectorHelper.setBit(validityBuffer, index);
+ final int startOffset = offsetBuffer.getInt((long) index * OFFSET_WIDTH);
+ offsetBuffer.setInt((long) (index + 1) * OFFSET_WIDTH, startOffset + length);
+ final ArrowBuf bb = buffer.slice(start, length);
+ valueBuffer.setBytes(startOffset, bb);
+ lastSet = index;
+ }
+
+ /**
+ * Same as {@link #set(int, int, int, int, ArrowBuf)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ * @param index position of the new value
+ * @param start start position of data in buffer
+ * @param length length of data in buffer
+ * @param buffer data buffer containing the variable width element to be stored
+ * in the vector
+ */
+ public void setSafe(int index, int start, int length, ArrowBuf buffer) {
+ assert index >= 0;
+ handleSafe(index, length);
+ fillHoles(index);
+ BitVectorHelper.setBit(validityBuffer, index);
+ final int startOffset = offsetBuffer.getInt((long) index * OFFSET_WIDTH);
+ offsetBuffer.setInt((long) (index + 1) * OFFSET_WIDTH, startOffset + length);
+ final ArrowBuf bb = buffer.slice(start, length);
+ valueBuffer.setBytes(startOffset, bb);
+ lastSet = index;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | helper methods for setters |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ protected final void fillHoles(int index) {
+ for (int i = lastSet + 1; i < index; i++) {
+ setBytes(i, emptyByteArray, 0, emptyByteArray.length);
+ }
+ lastSet = index - 1;
+ }
+
+ protected final void setBytes(int index, byte[] value, int start, int length) {
+ /* end offset of current last element in the vector. this will
+ * be the start offset of new element we are trying to store.
+ */
+ final int startOffset = getStartOffset(index);
+ /* set new end offset */
+ offsetBuffer.setInt((long) (index + 1) * OFFSET_WIDTH, startOffset + length);
+ /* store the var length data in value buffer */
+ valueBuffer.setBytes(startOffset, value, start, length);
+ }
+
+ public final int getStartOffset(int index) {
+ return offsetBuffer.getInt((long) index * OFFSET_WIDTH);
+ }
+
+ protected final void handleSafe(int index, int dataLength) {
+ /*
+ * IMPORTANT:
+ * value buffer for variable length vectors moves independent
+ * of the companion validity and offset buffers. This is in
+ * contrast to what we have for fixed width vectors.
+ *
+ * Here there is no concept of getValueCapacity() in the
+ * data stream. getValueCapacity() is applicable only to validity
+ * and offset buffers.
+ *
+ * So even though we may have setup an initial capacity of 1024
+ * elements in the vector, it is quite possible
+ * that we need to reAlloc() the data buffer when we are setting
+ * the 5th element in the vector simply because previous
+ * variable length elements have exhausted the buffer capacity.
+ * However, we really don't need to reAlloc() validity and
+ * offset buffers until we try to set the 1025th element
+ * This is why we do a separate check for safe methods to
+ * determine which buffer needs reallocation.
+ */
+ while (index >= getValueCapacity()) {
+ reallocValidityAndOffsetBuffers();
+ }
+ final int startOffset = lastSet < 0 ? 0 : getStartOffset(lastSet + 1);
+ while (valueBuffer.capacity() < (startOffset + dataLength)) {
+ reallocDataBuffer();
+ }
+ }
+
+ /**
+ * Method used by Json Writer to read a variable width element from
+ * the variable width vector and write to Json.
+ *
+ * This method should not be used externally.
+ *
+ * @param data buffer storing the variable width vector elements
+ * @param offset buffer storing the offsets of variable width vector elements
+ * @param index position of the element in the vector
+ * @return array of bytes
+ */
+ public static byte[] get(final ArrowBuf data, final ArrowBuf offset, int index) {
+ final int currentStartOffset = offset.getInt((long) index * OFFSET_WIDTH);
+ final int dataLength =
+ offset.getInt((long) (index + 1) * OFFSET_WIDTH) - currentStartOffset;
+ final byte[] result = new byte[dataLength];
+ data.getBytes(currentStartOffset, result, 0, dataLength);
+ return result;
+ }
+
+ /**
+ * Method used by Json Reader to explicitly set the offsets of the variable
+ * width vector data. The method takes care of allocating the memory for
+ * offsets if the caller hasn't done so.
+ *
+ * This method should not be used externally.
+ *
+ * @param buffer ArrowBuf to store offsets for variable width elements
+ * @param allocator memory allocator
+ * @param valueCount number of elements
+ * @param index position of the element
+ * @param value offset of the element
+ * @return buffer holding the offsets
+ */
+ public static ArrowBuf set(ArrowBuf buffer, BufferAllocator allocator,
+ int valueCount, int index, int value) {
+ if (buffer == null) {
+ buffer = allocator.buffer((long) valueCount * OFFSET_WIDTH);
+ }
+ buffer.setInt((long) index * OFFSET_WIDTH, value);
+ if (index == (valueCount - 1)) {
+ buffer.writerIndex((long) valueCount * OFFSET_WIDTH);
+ }
+
+ return buffer;
+ }
+
+ /**
+ * Copy a cell value from a particular index in source vector to a particular
+ * position in this vector.
+ *
+ * @param fromIndex position to copy from in source vector
+ * @param thisIndex position to copy to in this vector
+ * @param from source vector
+ */
+ @Override
+ public void copyFrom(int fromIndex, int thisIndex, ValueVector from) {
+ Preconditions.checkArgument(this.getMinorType() == from.getMinorType());
+ if (from.isNull(fromIndex)) {
+ fillHoles(thisIndex);
+ BitVectorHelper.unsetBit(this.validityBuffer, thisIndex);
+ final int copyStart = offsetBuffer.getInt((long) thisIndex * OFFSET_WIDTH);
+ offsetBuffer.setInt((long) (thisIndex + 1) * OFFSET_WIDTH, copyStart);
+ } else {
+ final int start = from.getOffsetBuffer().getInt((long) fromIndex * OFFSET_WIDTH);
+ final int end = from.getOffsetBuffer().getInt((long) (fromIndex + 1) * OFFSET_WIDTH);
+ final int length = end - start;
+ fillHoles(thisIndex);
+ BitVectorHelper.setBit(this.validityBuffer, thisIndex);
+ final int copyStart = offsetBuffer.getInt((long) thisIndex * OFFSET_WIDTH);
+ from.getDataBuffer().getBytes(start, this.valueBuffer, copyStart, length);
+ offsetBuffer.setInt((long) (thisIndex + 1) * OFFSET_WIDTH, copyStart + length);
+ }
+ lastSet = thisIndex;
+ }
+
+ /**
+ * Same as {@link #copyFrom(int, int, ValueVector)} except that
+ * it handles the case when the capacity of the vector needs to be expanded
+ * before copy.
+ *
+ * @param fromIndex position to copy from in source vector
+ * @param thisIndex position to copy to in this vector
+ * @param from source vector
+ */
+ @Override
+ public void copyFromSafe(int fromIndex, int thisIndex, ValueVector from) {
+ Preconditions.checkArgument(this.getMinorType() == from.getMinorType());
+ if (from.isNull(fromIndex)) {
+ handleSafe(thisIndex, 0);
+ fillHoles(thisIndex);
+ BitVectorHelper.unsetBit(this.validityBuffer, thisIndex);
+ final int copyStart = offsetBuffer.getInt(thisIndex * OFFSET_WIDTH);
+ offsetBuffer.setInt((long) (thisIndex + 1) * OFFSET_WIDTH, copyStart);
+ } else {
+ final int start = from.getOffsetBuffer().getInt((long) fromIndex * OFFSET_WIDTH);
+ final int end = from.getOffsetBuffer().getInt((long) (fromIndex + 1) * OFFSET_WIDTH);
+ final int length = end - start;
+ handleSafe(thisIndex, length);
+ fillHoles(thisIndex);
+ BitVectorHelper.setBit(this.validityBuffer, thisIndex);
+ final int copyStart = offsetBuffer.getInt((long) thisIndex * OFFSET_WIDTH);
+ from.getDataBuffer().getBytes(start, this.valueBuffer, copyStart, length);
+ offsetBuffer.setInt((long) (thisIndex + 1) * OFFSET_WIDTH, copyStart + length);
+ }
+ lastSet = thisIndex;
+ }
+
+ @Override
+ public ArrowBufPointer getDataPointer(int index) {
+ return getDataPointer(index, new ArrowBufPointer());
+ }
+
+ @Override
+ public ArrowBufPointer getDataPointer(int index, ArrowBufPointer reuse) {
+ if (isNull(index)) {
+ reuse.set(null, 0, 0);
+ } else {
+ int offset = offsetBuffer.getInt((long) index * OFFSET_WIDTH);
+ int length = offsetBuffer.getInt((long) (index + 1) * OFFSET_WIDTH) - offset;
+ reuse.set(valueBuffer, offset, length);
+ }
+ return reuse;
+ }
+
+ @Override
+ public int hashCode(int index) {
+ return hashCode(index, null);
+ }
+
+ @Override
+ public int hashCode(int index, ArrowBufHasher hasher) {
+ if (isNull(index)) {
+ return ArrowBufPointer.NULL_HASH_CODE;
+ }
+ final int start = getStartOffset(index);
+ final int end = getStartOffset(index + 1);
+ return ByteFunctionHelpers.hash(hasher, this.getDataBuffer(), start, end);
+ }
+
+ @Override
+ public This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static long get(final ArrowBuf buffer, final int index) {
+ return buffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((BigIntVector) to);
+ }
+
+ @Override
+ public void setWithPossibleTruncate(int index, long value) {
+ this.setSafe(index, value);
+ }
+
+ @Override
+ public void setUnsafeWithPossibleTruncate(int index, long value) {
+ this.set(index, value);
+ }
+
+ @Override
+ public long getValueAsLong(int index) {
+ return this.get(index);
+ }
+
+ private class TransferImpl implements TransferPair {
+ BigIntVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new BigIntVector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(BigIntVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public BigIntVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, BigIntVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BitVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BitVector.java
new file mode 100644
index 000000000..3bcfd983e
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BitVector.java
@@ -0,0 +1,599 @@
+/*
+ * 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.apache.arrow.memory.util.LargeMemoryUtil.capAtMaxInt;
+import static org.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.memory.util.ArrowBufPointer;
+import org.apache.arrow.memory.util.hash.ArrowBufHasher;
+import org.apache.arrow.util.Preconditions;
+import org.apache.arrow.vector.complex.impl.BitReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.BitHolder;
+import org.apache.arrow.vector.holders.NullableBitHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.OversizedAllocationException;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * BitVector implements a fixed width (1 bit) vector of
+ * boolean values which could be null. Each value in the vector corresponds
+ * to a single bit in the underlying data stream backing the vector.
+ */
+public final class BitVector extends BaseFixedWidthVector {
+
+ private static final int HASH_CODE_FOR_ZERO = 17;
+
+ private static final int HASH_CODE_FOR_ONE = 19;
+
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a BitVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public BitVector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.BIT.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a BitVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public BitVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a BitVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field the Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public BitVector(Field field, BufferAllocator allocator) {
+ super(field, allocator, 0);
+ reader = new BitReaderImpl(BitVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.BIT;
+ }
+
+ /**
+ * Sets the desired value capacity for the vector. This function doesn't
+ * allocate any memory for the vector.
+ *
+ * @param valueCount desired number of elements in the vector
+ */
+ @Override
+ public void setInitialCapacity(int valueCount) {
+ final int size = getValidityBufferSizeFromCount(valueCount);
+ if (size * 2 > MAX_ALLOCATION_SIZE) {
+ throw new OversizedAllocationException("Requested amount of memory is more than max allowed");
+ }
+ lastValueCapacity = valueCount;
+ }
+
+ @Override
+ protected int getValueBufferValueCapacity() {
+ return capAtMaxInt(valueBuffer.capacity() * 8);
+ }
+
+ /**
+ * Get the potential buffer size for a particular number of records.
+ *
+ * @param count desired number of elements in the vector
+ * @return estimated size of underlying buffers if the vector holds
+ * a given number of elements
+ */
+ @Override
+ public int getBufferSizeFor(final int count) {
+ if (count == 0) {
+ return 0;
+ }
+ return 2 * getValidityBufferSizeFromCount(count);
+ }
+
+ /**
+ * Get the size (number of bytes) of underlying buffers used by this vector.
+ *
+ * @return size of underlying buffers.
+ */
+ @Override
+ public int getBufferSize() {
+ return getBufferSizeFor(valueCount);
+ }
+
+ /**
+ * Slice this vector at desired index and length and transfer the
+ * corresponding data to the target vector.
+ *
+ * @param startIndex start position of the split in source vector.
+ * @param length length of the split.
+ * @param target destination vector
+ */
+ public void splitAndTransferTo(int startIndex, int length, BaseFixedWidthVector target) {
+ Preconditions.checkArgument(startIndex >= 0 && length >= 0 && startIndex + length <= valueCount,
+ "Invalid parameters startIndex: %s, length: %s for valueCount: %s", startIndex, length, valueCount);
+ compareTypes(target, "splitAndTransferTo");
+ target.clear();
+ target.validityBuffer = splitAndTransferBuffer(startIndex, length, target,
+ validityBuffer, target.validityBuffer);
+ target.valueBuffer = splitAndTransferBuffer(startIndex, length, target,
+ valueBuffer, target.valueBuffer);
+ target.refreshValueCapacity();
+
+ target.setValueCount(length);
+ }
+
+ private ArrowBuf splitAndTransferBuffer(
+ int startIndex,
+ int length,
+ BaseFixedWidthVector target,
+ ArrowBuf sourceBuffer,
+ ArrowBuf destBuffer) {
+ int firstByteSource = BitVectorHelper.byteIndex(startIndex);
+ int lastByteSource = BitVectorHelper.byteIndex(valueCount - 1);
+ int byteSizeTarget = getValidityBufferSizeFromCount(length);
+ int offset = startIndex % 8;
+
+ if (length > 0) {
+ if (offset == 0) {
+ /* slice */
+ if (destBuffer != null) {
+ destBuffer.getReferenceManager().release();
+ }
+ destBuffer = sourceBuffer.slice(firstByteSource, byteSizeTarget);
+ destBuffer.getReferenceManager().retain(1);
+ } else {
+ /* Copy data
+ * When the first bit starts from the middle of a byte (offset != 0),
+ * copy data from src BitVector.
+ * Each byte in the target is composed by a part in i-th byte,
+ * another part in (i+1)-th byte.
+ */
+ destBuffer = allocator.buffer(byteSizeTarget);
+ destBuffer.readerIndex(0);
+ destBuffer.setZero(0, destBuffer.capacity());
+
+ for (int i = 0; i < byteSizeTarget - 1; i++) {
+ byte b1 = BitVectorHelper.getBitsFromCurrentByte(sourceBuffer, firstByteSource + i, offset);
+ byte b2 = BitVectorHelper.getBitsFromNextByte(sourceBuffer, firstByteSource + i + 1, offset);
+
+ destBuffer.setByte(i, (b1 + b2));
+ }
+
+ /* Copying the last piece is done in the following manner:
+ * if the source vector has 1 or more bytes remaining, we copy
+ * the last piece as a byte formed by shifting data
+ * from the current byte and the next byte.
+ *
+ * if the source vector has no more bytes remaining
+ * (we are at the last byte), we copy the last piece as a byte
+ * by shifting data from the current byte.
+ */
+ if ((firstByteSource + byteSizeTarget - 1) < lastByteSource) {
+ byte b1 = BitVectorHelper.getBitsFromCurrentByte(sourceBuffer,
+ firstByteSource + byteSizeTarget - 1, offset);
+ byte b2 = BitVectorHelper.getBitsFromNextByte(sourceBuffer,
+ firstByteSource + byteSizeTarget, offset);
+
+ destBuffer.setByte(byteSizeTarget - 1, b1 + b2);
+ } else {
+ byte b1 = BitVectorHelper.getBitsFromCurrentByte(sourceBuffer,
+ firstByteSource + byteSizeTarget - 1, offset);
+ destBuffer.setByte(byteSizeTarget - 1, b1);
+ }
+ }
+ }
+
+ return destBuffer;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+ private int getBit(int index) {
+ final int byteIndex = index >> 3;
+ final byte b = valueBuffer.getByte(byteIndex);
+ final int bitIndex = index & 7;
+ return (b >> bitIndex) & 0x01;
+ }
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public int get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return getBit(index);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableBitHolder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = getBit(index);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Boolean getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return new Boolean(getBit(index) != 0);
+ }
+ }
+
+ /**
+ * Copy a cell value from a particular index in source vector to a particular
+ * position in this vector.
+ *
+ * @param fromIndex position to copy from in source vector
+ * @param thisIndex position to copy to in this vector
+ * @param from source vector
+ */
+ @Override
+ public void copyFrom(int fromIndex, int thisIndex, ValueVector from) {
+ Preconditions.checkArgument(this.getMinorType() == from.getMinorType());
+ boolean fromIsSet = BitVectorHelper.get(from.getValidityBuffer(), fromIndex) != 0;
+ if (fromIsSet) {
+ BitVectorHelper.setBit(validityBuffer, thisIndex);
+ BitVectorHelper.setValidityBit(valueBuffer, thisIndex, ((BitVector) from).getBit(fromIndex));
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, thisIndex);
+ }
+ }
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, int value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ if (value != 0) {
+ BitVectorHelper.setBit(valueBuffer, index);
+ } else {
+ BitVectorHelper.unsetBit(valueBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableBitHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ if (holder.value != 0) {
+ BitVectorHelper.setBit(valueBuffer, index);
+ } else {
+ BitVectorHelper.unsetBit(valueBuffer, index);
+ }
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, BitHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ if (holder.value != 0) {
+ BitVectorHelper.setBit(valueBuffer, index);
+ } else {
+ BitVectorHelper.unsetBit(valueBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, int value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableBitHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableBitHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, BitHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, BitHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void set(int index, int isSet, int value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, int)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void setSafe(int index, int isSet, int value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+ /**
+ * Set the element at the given index to one.
+ *
+ * @param index position of element
+ */
+ public void setToOne(int index) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ BitVectorHelper.setBit(valueBuffer, index);
+ }
+
+ /**
+ * Same as {@link #setToOne(int)} except that it handles the case when
+ * index is greater than or equal to current value capacity of the vector.
+ *
+ * @param index position of the element
+ */
+ public void setSafeToOne(int index) {
+ handleSafe(index);
+ setToOne(index);
+ }
+
+ @Override
+ public ArrowBufPointer getDataPointer(int index) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public ArrowBufPointer getDataPointer(int index, ArrowBufPointer reuse) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int hashCode(int index) {
+ if (isNull(index)) {
+ return ArrowBufPointer.NULL_HASH_CODE;
+ } else {
+ if (get(index) == 0) {
+ return HASH_CODE_FOR_ZERO;
+ } else {
+ return HASH_CODE_FOR_ONE;
+ }
+ }
+ }
+
+ @Override
+ public int hashCode(int index, ArrowBufHasher hasher) {
+ return hashCode(index);
+ }
+
+ /**
+ * Set count bits to 1 in data starting at firstBitIndex.
+ *
+ * @param firstBitIndex the index of the first bit to set
+ * @param count the number of bits to set
+ */
+ public void setRangeToOne(int firstBitIndex, int count) {
+ int startByteIndex = BitVectorHelper.byteIndex(firstBitIndex);
+ final int lastBitIndex = firstBitIndex + count;
+ final int endByteIndex = BitVectorHelper.byteIndex(lastBitIndex);
+ final int startByteBitIndex = BitVectorHelper.bitIndex(firstBitIndex);
+ final int endBytebitIndex = BitVectorHelper.bitIndex(lastBitIndex);
+ if (count < 8 && startByteIndex == endByteIndex) {
+ // handles the case where we don't have a first and a last byte
+ byte bitMask = 0;
+ for (int i = startByteBitIndex; i < endBytebitIndex; ++i) {
+ bitMask |= (byte) (1L << i);
+ }
+ BitVectorHelper.setBitMaskedByte(validityBuffer, startByteIndex, bitMask);
+ BitVectorHelper.setBitMaskedByte(valueBuffer, startByteIndex, bitMask);
+ } else {
+ // fill in first byte (if it's not full)
+ if (startByteBitIndex != 0) {
+ final byte bitMask = (byte) (0xFFL << startByteBitIndex);
+ BitVectorHelper.setBitMaskedByte(validityBuffer, startByteIndex, bitMask);
+ BitVectorHelper.setBitMaskedByte(valueBuffer, startByteIndex, bitMask);
+ ++startByteIndex;
+ }
+
+ // fill in one full byte at a time
+ validityBuffer.setOne(startByteIndex, endByteIndex - startByteIndex);
+ valueBuffer.setOne(startByteIndex, endByteIndex - startByteIndex);
+
+ // fill in the last byte (if it's not full)
+ if (endBytebitIndex != 0) {
+ final int byteIndex = BitVectorHelper.byteIndex(lastBitIndex - endBytebitIndex);
+ final byte bitMask = (byte) (0xFFL >>> ((8 - endBytebitIndex) & 7));
+ BitVectorHelper.setBitMaskedByte(validityBuffer, byteIndex, bitMask);
+ BitVectorHelper.setBitMaskedByte(valueBuffer, byteIndex, bitMask);
+ }
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((BitVector) to);
+ }
+
+ private class TransferImpl implements TransferPair {
+ BitVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new BitVector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(BitVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public BitVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, BitVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BitVectorHelper.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BitVectorHelper.java
new file mode 100644
index 000000000..3745c5a75
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BitVectorHelper.java
@@ -0,0 +1,449 @@
+/*
+ * 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 io.netty.util.internal.PlatformDependent.getByte;
+import static io.netty.util.internal.PlatformDependent.getInt;
+import static io.netty.util.internal.PlatformDependent.getLong;
+import static org.apache.arrow.memory.util.LargeMemoryUtil.checkedCastToInt;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BoundsChecking;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.ipc.message.ArrowFieldNode;
+import org.apache.arrow.vector.util.DataSizeRoundingUtil;
+
+import io.netty.util.internal.PlatformDependent;
+
+/**
+ * Helper class for performing generic operations on a bit vector buffer.
+ * External use of this class is not recommended.
+ */
+public class BitVectorHelper {
+
+ private BitVectorHelper() {}
+
+ /**
+ * Get the index of byte corresponding to bit index in validity buffer.
+ */
+ public static long byteIndex(long absoluteBitIndex) {
+ return absoluteBitIndex >> 3;
+ }
+
+ /**
+ * Get the relative index of bit within the byte in validity buffer.
+ */
+ public static int bitIndex(long absoluteBitIndex) {
+ return checkedCastToInt(absoluteBitIndex & 7);
+ }
+
+ /**
+ * Get the index of byte corresponding to bit index in validity buffer.
+ */
+ public static int byteIndex(int absoluteBitIndex) {
+ return absoluteBitIndex >> 3;
+ }
+
+ /**
+ * Get the relative index of bit within the byte in validity buffer.
+ */
+ public static int bitIndex(int absoluteBitIndex) {
+ return absoluteBitIndex & 7;
+ }
+
+ /**
+ * Set the bit at provided index to 1.
+ *
+ * @param validityBuffer validity buffer of the vector
+ * @param index index to be set
+ */
+ public static void setBit(ArrowBuf validityBuffer, long index) {
+ // it can be observed that some logic is duplicate of the logic in setValidityBit.
+ // this is because JIT cannot always remove the if branch in setValidityBit,
+ // so we give a dedicated implementation for setting bits.
+ final long byteIndex = byteIndex(index);
+ final int bitIndex = bitIndex(index);
+
+ // the byte is promoted to an int, because according to Java specification,
+ // bytes will be promoted to ints automatically, upon expression evaluation.
+ // by promoting it manually, we avoid the unnecessary conversions.
+ int currentByte = validityBuffer.getByte(byteIndex);
+ final int bitMask = 1 << bitIndex;
+ currentByte |= bitMask;
+ validityBuffer.setByte(byteIndex, currentByte);
+ }
+
+ /**
+ * Set the bit at provided index to 0.
+ *
+ * @param validityBuffer validity buffer of the vector
+ * @param index index to be set
+ */
+ public static void unsetBit(ArrowBuf validityBuffer, int index) {
+ // it can be observed that some logic is duplicate of the logic in setValidityBit.
+ // this is because JIT cannot always remove the if branch in setValidityBit,
+ // so we give a dedicated implementation for unsetting bits.
+ final int byteIndex = byteIndex(index);
+ final int bitIndex = bitIndex(index);
+
+ // the byte is promoted to an int, because according to Java specification,
+ // bytes will be promoted to ints automatically, upon expression evaluation.
+ // by promoting it manually, we avoid the unnecessary conversions.
+ int currentByte = validityBuffer.getByte(byteIndex);
+ final int bitMask = 1 << bitIndex;
+ currentByte &= ~bitMask;
+ validityBuffer.setByte(byteIndex, currentByte);
+ }
+
+ /**
+ * Set the bit at a given index to provided value (1 or 0).
+ *
+ * @param validityBuffer validity buffer of the vector
+ * @param index index to be set
+ * @param value value to set
+ */
+ public static void setValidityBit(ArrowBuf validityBuffer, int index, int value) {
+ final int byteIndex = byteIndex(index);
+ final int bitIndex = bitIndex(index);
+
+ // the byte is promoted to an int, because according to Java specification,
+ // bytes will be promoted to ints automatically, upon expression evaluation.
+ // by promoting it manually, we avoid the unnecessary conversions.
+ int currentByte = validityBuffer.getByte(byteIndex);
+ final int bitMask = 1 << bitIndex;
+ if (value != 0) {
+ currentByte |= bitMask;
+ } else {
+ currentByte &= ~bitMask;
+ }
+ validityBuffer.setByte(byteIndex, currentByte);
+ }
+
+ /**
+ * Set the bit at a given index to provided value (1 or 0). Internally
+ * takes care of allocating the buffer if the caller didn't do so.
+ *
+ * @param validityBuffer validity buffer of the vector
+ * @param allocator allocator for the buffer
+ * @param valueCount number of values to allocate/set
+ * @param index index to be set
+ * @param value value to set
+ * @return ArrowBuf
+ */
+ public static ArrowBuf setValidityBit(ArrowBuf validityBuffer, BufferAllocator allocator,
+ int valueCount, int index, int value) {
+ if (validityBuffer == null) {
+ validityBuffer = allocator.buffer(getValidityBufferSize(valueCount));
+ }
+ setValidityBit(validityBuffer, index, value);
+ if (index == (valueCount - 1)) {
+ validityBuffer.writerIndex(getValidityBufferSize(valueCount));
+ }
+
+ return validityBuffer;
+ }
+
+ /**
+ * Check if a bit at a given index is set or not.
+ *
+ * @param buffer buffer to check
+ * @param index index of the buffer
+ * @return 1 if bit is set, 0 otherwise.
+ */
+ public static int get(final ArrowBuf buffer, int index) {
+ final int byteIndex = index >> 3;
+ final byte b = buffer.getByte(byteIndex);
+ final int bitIndex = index & 7;
+ return (b >> bitIndex) & 0x01;
+ }
+
+ /**
+ * Compute the size of validity buffer required to manage a given number
+ * of elements in a vector.
+ *
+ * @param valueCount number of elements in the vector
+ * @return buffer size
+ */
+ public static int getValidityBufferSize(int valueCount) {
+ return DataSizeRoundingUtil.divideBy8Ceil(valueCount);
+ }
+
+ /**
+ * Given a validity buffer, find the number of bits that are not set.
+ * This is used to compute the number of null elements in a nullable vector.
+ *
+ * @param validityBuffer validity buffer of the vector
+ * @param valueCount number of values in the vector
+ * @return number of bits not set.
+ */
+ public static int getNullCount(final ArrowBuf validityBuffer, final int valueCount) {
+ if (valueCount == 0) {
+ return 0;
+ }
+ int count = 0;
+ final int sizeInBytes = getValidityBufferSize(valueCount);
+ // If value count is not a multiple of 8, then calculate number of used bits in the last byte
+ final int remainder = valueCount % 8;
+ final int fullBytesCount = remainder == 0 ? sizeInBytes : sizeInBytes - 1;
+
+ int index = 0;
+ while (index + 8 <= fullBytesCount) {
+ long longValue = validityBuffer.getLong(index);
+ count += Long.bitCount(longValue);
+ index += 8;
+ }
+
+ if (index + 4 <= fullBytesCount) {
+ int intValue = validityBuffer.getInt(index);
+ count += Integer.bitCount(intValue);
+ index += 4;
+ }
+
+ while (index < fullBytesCount) {
+ byte byteValue = validityBuffer.getByte(index);
+ count += Integer.bitCount(byteValue & 0xFF);
+ index += 1;
+ }
+
+ // handling with the last bits
+ if (remainder != 0) {
+ byte byteValue = validityBuffer.getByte(sizeInBytes - 1);
+
+ // making the remaining bits all 1s if it is not fully filled
+ byte mask = (byte) (0xFF << remainder);
+ byteValue = (byte) (byteValue | mask);
+ count += Integer.bitCount(byteValue & 0xFF);
+ }
+
+ return 8 * sizeInBytes - count;
+ }
+
+ /**
+ * Tests if all bits in a validity buffer are equal 0 or 1, according to the specified parameter.
+ * @param validityBuffer the validity buffer.
+ * @param valueCount the bit count.
+ * @param checkOneBits if set to true, the method checks if all bits are equal to 1;
+ * otherwise, it checks if all bits are equal to 0.
+ * @return true if all bits are 0 or 1 according to the parameter, and false otherwise.
+ */
+ public static boolean checkAllBitsEqualTo(
+ final ArrowBuf validityBuffer, final int valueCount, final boolean checkOneBits) {
+ if (valueCount == 0) {
+ return true;
+ }
+ final int sizeInBytes = getValidityBufferSize(valueCount);
+
+ // boundary check
+ validityBuffer.checkBytes(0, sizeInBytes);
+
+ // If value count is not a multiple of 8, then calculate number of used bits in the last byte
+ final int remainder = valueCount % 8;
+ final int fullBytesCount = remainder == 0 ? sizeInBytes : sizeInBytes - 1;
+
+ // the integer number to compare against
+ final int intToCompare = checkOneBits ? -1 : 0;
+
+ int index = 0;
+ while (index + 8 <= fullBytesCount) {
+ long longValue = getLong(validityBuffer.memoryAddress() + index);
+ if (longValue != (long) intToCompare) {
+ return false;
+ }
+ index += 8;
+ }
+
+ if (index + 4 <= fullBytesCount) {
+ int intValue = getInt(validityBuffer.memoryAddress() + index);
+ if (intValue != intToCompare) {
+ return false;
+ }
+ index += 4;
+ }
+
+ while (index < fullBytesCount) {
+ byte byteValue = getByte(validityBuffer.memoryAddress() + index);
+ if (byteValue != (byte) intToCompare) {
+ return false;
+ }
+ index += 1;
+ }
+
+ // handling with the last bits
+ if (remainder != 0) {
+ byte byteValue = getByte(validityBuffer.memoryAddress() + sizeInBytes - 1);
+ byte mask = (byte) ((1 << remainder) - 1);
+ byteValue = (byte) (byteValue & mask);
+ if (checkOneBits) {
+ if ((mask & byteValue) != mask) {
+ return false;
+ }
+ } else {
+ if (byteValue != (byte) 0) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /** Returns the byte at index from data right-shifted by offset. */
+ public static byte getBitsFromCurrentByte(final ArrowBuf data, final int index, final int offset) {
+ return (byte) ((data.getByte(index) & 0xFF) >>> offset);
+ }
+
+ /**
+ * Returns the byte at This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static int get(final ArrowBuf buffer, final int index) {
+ return buffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((DateDayVector) to);
+ }
+
+ private class TransferImpl implements TransferPair {
+ DateDayVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new DateDayVector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(DateDayVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public DateDayVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, DateDayVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/DateMilliVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/DateMilliVector.java
new file mode 100644
index 000000000..73738d771
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/DateMilliVector.java
@@ -0,0 +1,350 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import java.time.LocalDateTime;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.DateMilliReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.DateMilliHolder;
+import org.apache.arrow.vector.holders.NullableDateMilliHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.DateUtility;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * DateMilliVector implements a fixed width vector (8 bytes) of
+ * date values which could be null. A validity buffer (bit vector) is
+ * maintained to track which elements in the vector are null.
+ */
+public final class DateMilliVector extends BaseFixedWidthVector {
+ public static final byte TYPE_WIDTH = 8;
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a DateMilliVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public DateMilliVector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.DATEMILLI.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a DateMilliVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public DateMilliVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a DateMilliVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public DateMilliVector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ reader = new DateMilliReaderImpl(DateMilliVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.DATEMILLI;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public long get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableDateMilliHolder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public LocalDateTime getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ final long millis = valueBuffer.getLong((long) index * TYPE_WIDTH);
+ return DateUtility.getLocalDateTimeFromEpochMilli(millis);
+ }
+ }
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ private void setValue(int index, long value) {
+ valueBuffer.setLong((long) index * TYPE_WIDTH, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, long value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableDateMilliHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, DateMilliHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, long)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, long value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableDateMilliHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableDateMilliHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, DateMilliHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, DateMilliHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void set(int index, int isSet, long value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, long)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void setSafe(int index, int isSet, long value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+ /**
+ * Given a data buffer, get the value stored at a particular position
+ * in the vector.
+ *
+ * This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static long get(final ArrowBuf buffer, final int index) {
+ return buffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((DateMilliVector) to);
+ }
+
+ private class TransferImpl implements TransferPair {
+ DateMilliVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new DateMilliVector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(DateMilliVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public DateMilliVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, DateMilliVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java
new file mode 100644
index 000000000..c5fef82d0
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/Decimal256Vector.java
@@ -0,0 +1,584 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import java.math.BigDecimal;
+import java.nio.ByteOrder;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.Decimal256ReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.Decimal256Holder;
+import org.apache.arrow.vector.holders.NullableDecimal256Holder;
+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.DecimalUtility;
+import org.apache.arrow.vector.util.TransferPair;
+
+import io.netty.util.internal.PlatformDependent;
+
+/**
+ * Decimal256Vector implements a fixed width vector (32 bytes) of
+ * decimal values which could be null. A validity buffer (bit vector) is
+ * maintained to track which elements in the vector are null.
+ */
+public final class Decimal256Vector extends BaseFixedWidthVector {
+ public static final byte TYPE_WIDTH = 32;
+ private static final boolean LITTLE_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN;
+ private final FieldReader reader;
+
+ private final int precision;
+ private final int scale;
+
+ /**
+ * Instantiate a Decimal256Vector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public Decimal256Vector(String name, BufferAllocator allocator,
+ int precision, int scale) {
+ this(name, FieldType.nullable(new ArrowType.Decimal(precision, scale, /*bitWidth=*/TYPE_WIDTH * 8)), allocator);
+ }
+
+ /**
+ * Instantiate a Decimal256Vector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public Decimal256Vector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a Decimal256Vector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public Decimal256Vector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ ArrowType.Decimal arrowType = (ArrowType.Decimal) field.getFieldType().getType();
+ reader = new Decimal256ReaderImpl(Decimal256Vector.this);
+ this.precision = arrowType.getPrecision();
+ this.scale = arrowType.getScale();
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.DECIMAL256;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public ArrowBuf get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.slice((long) index * TYPE_WIDTH, TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableDecimal256Holder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.buffer = valueBuffer;
+ holder.precision = precision;
+ holder.scale = scale;
+ holder.start = ((long) index) * TYPE_WIDTH;
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public BigDecimal getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return DecimalUtility.getBigDecimalFromArrowBuf(valueBuffer, index, scale, TYPE_WIDTH);
+ }
+ }
+
+ /**
+ * Return precision for the decimal value.
+ */
+ public int getPrecision() {
+ return precision;
+ }
+
+ /**
+ * Return scale for the decimal value.
+ */
+ public int getScale() {
+ return scale;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param buffer ArrowBuf containing decimal value.
+ */
+ public void set(int index, ArrowBuf buffer) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ valueBuffer.setBytes((long) index * TYPE_WIDTH, buffer, 0, TYPE_WIDTH);
+ }
+
+ /**
+ * Set the decimal element at given index to the provided array of bytes.
+ * Decimal256 is now implemented as Native Endian. This API allows the user
+ * to pass a decimal value in the form of byte array in BE byte order.
+ *
+ * Consumers of Arrow code can use this API instead of first swapping
+ * the source bytes (doing a write and read) and then finally writing to
+ * ArrowBuf of decimal vector.
+ *
+ * This method takes care of adding the necessary padding if the length
+ * of byte array is less then 32 (length of decimal type).
+ *
+ * @param index position of element
+ * @param value array of bytes containing decimal in big endian byte order.
+ */
+ public void setBigEndian(int index, byte[] value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ final int length = value.length;
+
+ // do the bound check.
+ valueBuffer.checkBytes((long) index * TYPE_WIDTH, (long) (index + 1) * TYPE_WIDTH);
+
+ long outAddress = valueBuffer.memoryAddress() + (long) index * TYPE_WIDTH;
+ if (length == 0) {
+ PlatformDependent.setMemory(outAddress, Decimal256Vector.TYPE_WIDTH, (byte) 0);
+ return;
+ }
+ if (LITTLE_ENDIAN) {
+ // swap bytes to convert BE to LE
+ for (int byteIdx = 0; byteIdx < length; ++byteIdx) {
+ PlatformDependent.putByte(outAddress + byteIdx, value[length - 1 - byteIdx]);
+ }
+
+ if (length == TYPE_WIDTH) {
+ return;
+ }
+
+ if (length < TYPE_WIDTH) {
+ // sign extend
+ final byte pad = (byte) (value[0] < 0 ? 0xFF : 0x00);
+ PlatformDependent.setMemory(outAddress + length, Decimal256Vector.TYPE_WIDTH - length, pad);
+ return;
+ }
+ } else {
+ if (length <= TYPE_WIDTH) {
+ // copy data from value to outAddress
+ PlatformDependent.copyMemory(value, 0, outAddress + Decimal256Vector.TYPE_WIDTH - length, length);
+ // sign extend
+ final byte pad = (byte) (value[0] < 0 ? 0xFF : 0x00);
+ PlatformDependent.setMemory(outAddress, Decimal256Vector.TYPE_WIDTH - length, pad);
+ return;
+ }
+ }
+ throw new IllegalArgumentException(
+ "Invalid decimal value length. Valid length in [1 - 32], got " + length);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param start start index of data in the buffer
+ * @param buffer ArrowBuf containing decimal value.
+ */
+ public void set(int index, long start, ArrowBuf buffer) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ valueBuffer.setBytes((long) index * TYPE_WIDTH, buffer, start, TYPE_WIDTH);
+ }
+
+ /**
+ * Sets the element at given index using the buffer whose size maybe <= 32 bytes.
+ * @param index index to write the decimal to
+ * @param start start of value in the buffer
+ * @param buffer contains the decimal in native endian bytes
+ * @param length length of the value in the buffer
+ */
+ public void setSafe(int index, long start, ArrowBuf buffer, int length) {
+ handleSafe(index);
+ BitVectorHelper.setBit(validityBuffer, index);
+
+ // do the bound checks.
+ buffer.checkBytes(start, start + length);
+ valueBuffer.checkBytes((long) index * TYPE_WIDTH, (long) (index + 1) * TYPE_WIDTH);
+
+ long inAddress = buffer.memoryAddress() + start;
+ long outAddress = valueBuffer.memoryAddress() + (long) index * TYPE_WIDTH;
+ if (LITTLE_ENDIAN) {
+ PlatformDependent.copyMemory(inAddress, outAddress, length);
+ // sign extend
+ if (length < TYPE_WIDTH) {
+ byte msb = PlatformDependent.getByte(inAddress + length - 1);
+ final byte pad = (byte) (msb < 0 ? 0xFF : 0x00);
+ PlatformDependent.setMemory(outAddress + length, Decimal256Vector.TYPE_WIDTH - length, pad);
+ }
+ } else {
+ PlatformDependent.copyMemory(inAddress, outAddress + Decimal256Vector.TYPE_WIDTH - length, length);
+ // sign extend
+ if (length < TYPE_WIDTH) {
+ byte msb = PlatformDependent.getByte(inAddress);
+ final byte pad = (byte) (msb < 0 ? 0xFF : 0x00);
+ PlatformDependent.setMemory(outAddress, Decimal256Vector.TYPE_WIDTH - length, pad);
+ }
+ }
+ }
+
+
+ /**
+ * Sets the element at given index using the buffer whose size maybe <= 32 bytes.
+ * @param index index to write the decimal to
+ * @param start start of value in the buffer
+ * @param buffer contains the decimal in big endian bytes
+ * @param length length of the value in the buffer
+ */
+ public void setBigEndianSafe(int index, long start, ArrowBuf buffer, int length) {
+ handleSafe(index);
+ BitVectorHelper.setBit(validityBuffer, index);
+
+ // do the bound checks.
+ buffer.checkBytes(start, start + length);
+ valueBuffer.checkBytes((long) index * TYPE_WIDTH, (long) (index + 1) * TYPE_WIDTH);
+
+ // not using buffer.getByte() to avoid boundary checks for every byte.
+ long inAddress = buffer.memoryAddress() + start;
+ long outAddress = valueBuffer.memoryAddress() + (long) index * TYPE_WIDTH;
+ if (LITTLE_ENDIAN) {
+ // swap bytes to convert BE to LE
+ for (int byteIdx = 0; byteIdx < length; ++byteIdx) {
+ byte val = PlatformDependent.getByte((inAddress + length - 1) - byteIdx);
+ PlatformDependent.putByte(outAddress + byteIdx, val);
+ }
+ // sign extend
+ if (length < 32) {
+ byte msb = PlatformDependent.getByte(inAddress);
+ final byte pad = (byte) (msb < 0 ? 0xFF : 0x00);
+ PlatformDependent.setMemory(outAddress + length, Decimal256Vector.TYPE_WIDTH - length, pad);
+ }
+ } else {
+ PlatformDependent.copyMemory(inAddress, outAddress + Decimal256Vector.TYPE_WIDTH - length, length);
+ // sign extend
+ if (length < TYPE_WIDTH) {
+ byte msb = PlatformDependent.getByte(inAddress);
+ final byte pad = (byte) (msb < 0 ? 0xFF : 0x00);
+ PlatformDependent.setMemory(outAddress, Decimal256Vector.TYPE_WIDTH - length, pad);
+ }
+ }
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value BigDecimal containing decimal value.
+ */
+ public void set(int index, BigDecimal value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ DecimalUtility.checkPrecisionAndScale(value, precision, scale);
+ DecimalUtility.writeBigDecimalToArrowBuf(value, valueBuffer, index, TYPE_WIDTH);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value long value.
+ */
+ public void set(int index, long value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ DecimalUtility.writeLongToArrowBuf(value, valueBuffer, index, TYPE_WIDTH);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableDecimal256Holder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ valueBuffer.setBytes((long) index * TYPE_WIDTH, holder.buffer, holder.start, TYPE_WIDTH);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, Decimal256Holder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ valueBuffer.setBytes((long) index * TYPE_WIDTH, holder.buffer, holder.start, TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #set(int, ArrowBuf)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param buffer ArrowBuf containing decimal value.
+ */
+ public void setSafe(int index, ArrowBuf buffer) {
+ handleSafe(index);
+ set(index, buffer);
+ }
+
+ /**
+ * Same as {@link #setBigEndian(int, byte[])} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ */
+ public void setBigEndianSafe(int index, byte[] value) {
+ handleSafe(index);
+ setBigEndian(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, int, ArrowBuf)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param start start index of data in the buffer
+ * @param buffer ArrowBuf containing decimal value.
+ */
+ public void setSafe(int index, long start, ArrowBuf buffer) {
+ handleSafe(index);
+ set(index, start, buffer);
+ }
+
+ /**
+ * Same as {@link #set(int, BigDecimal)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value BigDecimal containing decimal value.
+ */
+ public void setSafe(int index, BigDecimal value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, long)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value long value.
+ */
+ public void setSafe(int index, long value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableDecimalHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableDecimal256Holder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, Decimal256Holder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, Decimal256Holder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param start start position of the value in the buffer
+ * @param buffer buffer containing the value to be stored in the vector
+ */
+ public void set(int index, int isSet, long start, ArrowBuf buffer) {
+ if (isSet > 0) {
+ set(index, start, buffer);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #setSafe(int, int, int, ArrowBuf)} except that it handles
+ * the case when the position of new value is beyond the current value
+ * capacity of the vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param start start position of the value in the buffer
+ * @param buffer buffer containing the value to be stored in the vector
+ */
+ public void setSafe(int index, int isSet, long start, ArrowBuf buffer) {
+ handleSafe(index);
+ set(index, isSet, start, buffer);
+ }
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((Decimal256Vector) to);
+ }
+
+ private class TransferImpl implements TransferPair {
+ Decimal256Vector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new Decimal256Vector(ref, allocator, Decimal256Vector.this.precision,
+ Decimal256Vector.this.scale);
+ }
+
+ public TransferImpl(Decimal256Vector to) {
+ this.to = to;
+ }
+
+ @Override
+ public Decimal256Vector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, Decimal256Vector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java
new file mode 100644
index 000000000..f988f4f94
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/DecimalVector.java
@@ -0,0 +1,584 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import java.math.BigDecimal;
+import java.nio.ByteOrder;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.DecimalReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.DecimalHolder;
+import org.apache.arrow.vector.holders.NullableDecimalHolder;
+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.DecimalUtility;
+import org.apache.arrow.vector.util.TransferPair;
+
+import io.netty.util.internal.PlatformDependent;
+
+/**
+ * DecimalVector implements a fixed width vector (16 bytes) of
+ * decimal values which could be null. A validity buffer (bit vector) is
+ * maintained to track which elements in the vector are null.
+ */
+public final class DecimalVector extends BaseFixedWidthVector {
+ public static final byte TYPE_WIDTH = 16;
+ private static final boolean LITTLE_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN;
+ private final FieldReader reader;
+
+ private final int precision;
+ private final int scale;
+
+ /**
+ * Instantiate a DecimalVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public DecimalVector(String name, BufferAllocator allocator,
+ int precision, int scale) {
+ this(name, FieldType.nullable(new ArrowType.Decimal(precision, scale, TYPE_WIDTH * 8)), allocator);
+ }
+
+ /**
+ * Instantiate a DecimalVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public DecimalVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a DecimalVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public DecimalVector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ ArrowType.Decimal arrowType = (ArrowType.Decimal) field.getFieldType().getType();
+ reader = new DecimalReaderImpl(DecimalVector.this);
+ this.precision = arrowType.getPrecision();
+ this.scale = arrowType.getScale();
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.DECIMAL;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public ArrowBuf get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.slice((long) index * TYPE_WIDTH, TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableDecimalHolder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.buffer = valueBuffer;
+ holder.precision = precision;
+ holder.scale = scale;
+ holder.start = (long) index * TYPE_WIDTH;
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public BigDecimal getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return DecimalUtility.getBigDecimalFromArrowBuf(valueBuffer, index, scale, TYPE_WIDTH);
+ }
+ }
+
+ /**
+ * Return precision for the decimal value.
+ */
+ public int getPrecision() {
+ return precision;
+ }
+
+ /**
+ * Return scale for the decimal value.
+ */
+ public int getScale() {
+ return scale;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param buffer ArrowBuf containing decimal value.
+ */
+ public void set(int index, ArrowBuf buffer) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ valueBuffer.setBytes((long) index * TYPE_WIDTH, buffer, 0, TYPE_WIDTH);
+ }
+
+ /**
+ * Set the decimal element at given index to the provided array of bytes.
+ * Decimal is now implemented as Native Endian. This API allows the user
+ * to pass a decimal value in the form of byte array in BE byte order.
+ *
+ * Consumers of Arrow code can use this API instead of first swapping
+ * the source bytes (doing a write and read) and then finally writing to
+ * ArrowBuf of decimal vector.
+ *
+ * This method takes care of adding the necessary padding if the length
+ * of byte array is less then 16 (length of decimal type).
+ *
+ * @param index position of element
+ * @param value array of bytes containing decimal in big endian byte order.
+ */
+ public void setBigEndian(int index, byte[] value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ final int length = value.length;
+
+ // do the bound check.
+ valueBuffer.checkBytes((long) index * TYPE_WIDTH, (long) (index + 1) * TYPE_WIDTH);
+
+ long outAddress = valueBuffer.memoryAddress() + (long) index * TYPE_WIDTH;
+ if (length == 0) {
+ PlatformDependent.setMemory(outAddress, DecimalVector.TYPE_WIDTH, (byte) 0);
+ return;
+ }
+ if (LITTLE_ENDIAN) {
+ // swap bytes to convert BE to LE
+ for (int byteIdx = 0; byteIdx < length; ++byteIdx) {
+ PlatformDependent.putByte(outAddress + byteIdx, value[length - 1 - byteIdx]);
+ }
+
+ if (length == TYPE_WIDTH) {
+ return;
+ }
+
+ if (length < TYPE_WIDTH) {
+ // sign extend
+ final byte pad = (byte) (value[0] < 0 ? 0xFF : 0x00);
+ PlatformDependent.setMemory(outAddress + length, DecimalVector.TYPE_WIDTH - length, pad);
+ return;
+ }
+ } else {
+ if (length <= TYPE_WIDTH) {
+ // copy data from value to outAddress
+ PlatformDependent.copyMemory(value, 0, outAddress + DecimalVector.TYPE_WIDTH - length, length);
+ // sign extend
+ final byte pad = (byte) (value[0] < 0 ? 0xFF : 0x00);
+ PlatformDependent.setMemory(outAddress, DecimalVector.TYPE_WIDTH - length, pad);
+ return;
+ }
+ }
+ throw new IllegalArgumentException(
+ "Invalid decimal value length. Valid length in [1 - 16], got " + length);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param start start index of data in the buffer
+ * @param buffer ArrowBuf containing decimal value.
+ */
+ public void set(int index, long start, ArrowBuf buffer) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ valueBuffer.setBytes((long) index * TYPE_WIDTH, buffer, start, TYPE_WIDTH);
+ }
+
+ /**
+ * Sets the element at given index using the buffer whose size maybe <= 16 bytes.
+ * @param index index to write the decimal to
+ * @param start start of value in the buffer
+ * @param buffer contains the decimal in native endian bytes
+ * @param length length of the value in the buffer
+ */
+ public void setSafe(int index, long start, ArrowBuf buffer, int length) {
+ handleSafe(index);
+ BitVectorHelper.setBit(validityBuffer, index);
+
+ // do the bound checks.
+ buffer.checkBytes(start, start + length);
+ valueBuffer.checkBytes((long) index * TYPE_WIDTH, (long) (index + 1) * TYPE_WIDTH);
+
+ long inAddress = buffer.memoryAddress() + start;
+ long outAddress = valueBuffer.memoryAddress() + (long) index * TYPE_WIDTH;
+ if (LITTLE_ENDIAN) {
+ PlatformDependent.copyMemory(inAddress, outAddress, length);
+ // sign extend
+ if (length < TYPE_WIDTH) {
+ byte msb = PlatformDependent.getByte(inAddress + length - 1);
+ final byte pad = (byte) (msb < 0 ? 0xFF : 0x00);
+ PlatformDependent.setMemory(outAddress + length, DecimalVector.TYPE_WIDTH - length, pad);
+ }
+ } else {
+ PlatformDependent.copyMemory(inAddress, outAddress + DecimalVector.TYPE_WIDTH - length, length);
+ // sign extend
+ if (length < TYPE_WIDTH) {
+ byte msb = PlatformDependent.getByte(inAddress);
+ final byte pad = (byte) (msb < 0 ? 0xFF : 0x00);
+ PlatformDependent.setMemory(outAddress, DecimalVector.TYPE_WIDTH - length, pad);
+ }
+ }
+ }
+
+
+ /**
+ * Sets the element at given index using the buffer whose size maybe <= 16 bytes.
+ * @param index index to write the decimal to
+ * @param start start of value in the buffer
+ * @param buffer contains the decimal in big endian bytes
+ * @param length length of the value in the buffer
+ */
+ public void setBigEndianSafe(int index, long start, ArrowBuf buffer, int length) {
+ handleSafe(index);
+ BitVectorHelper.setBit(validityBuffer, index);
+
+ // do the bound checks.
+ buffer.checkBytes(start, start + length);
+ valueBuffer.checkBytes((long) index * TYPE_WIDTH, (long) (index + 1) * TYPE_WIDTH);
+
+ // not using buffer.getByte() to avoid boundary checks for every byte.
+ long inAddress = buffer.memoryAddress() + start;
+ long outAddress = valueBuffer.memoryAddress() + (long) index * TYPE_WIDTH;
+ if (LITTLE_ENDIAN) {
+ // swap bytes to convert BE to LE
+ for (int byteIdx = 0; byteIdx < length; ++byteIdx) {
+ byte val = PlatformDependent.getByte((inAddress + length - 1) - byteIdx);
+ PlatformDependent.putByte(outAddress + byteIdx, val);
+ }
+ // sign extend
+ if (length < TYPE_WIDTH) {
+ byte msb = PlatformDependent.getByte(inAddress);
+ final byte pad = (byte) (msb < 0 ? 0xFF : 0x00);
+ PlatformDependent.setMemory(outAddress + length, DecimalVector.TYPE_WIDTH - length, pad);
+ }
+ } else {
+ PlatformDependent.copyMemory(inAddress, outAddress + DecimalVector.TYPE_WIDTH - length, length);
+ // sign extend
+ if (length < TYPE_WIDTH) {
+ byte msb = PlatformDependent.getByte(inAddress);
+ final byte pad = (byte) (msb < 0 ? 0xFF : 0x00);
+ PlatformDependent.setMemory(outAddress, DecimalVector.TYPE_WIDTH - length, pad);
+ }
+ }
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value BigDecimal containing decimal value.
+ */
+ public void set(int index, BigDecimal value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ DecimalUtility.checkPrecisionAndScale(value, precision, scale);
+ DecimalUtility.writeBigDecimalToArrowBuf(value, valueBuffer, index, TYPE_WIDTH);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value long value.
+ */
+ public void set(int index, long value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ DecimalUtility.writeLongToArrowBuf(value, valueBuffer, index, TYPE_WIDTH);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableDecimalHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ valueBuffer.setBytes((long) index * TYPE_WIDTH, holder.buffer, holder.start, TYPE_WIDTH);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, DecimalHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ valueBuffer.setBytes((long) index * TYPE_WIDTH, holder.buffer, holder.start, TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #set(int, ArrowBuf)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param buffer ArrowBuf containing decimal value.
+ */
+ public void setSafe(int index, ArrowBuf buffer) {
+ handleSafe(index);
+ set(index, buffer);
+ }
+
+ /**
+ * Same as {@link #setBigEndian(int, byte[])} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ */
+ public void setBigEndianSafe(int index, byte[] value) {
+ handleSafe(index);
+ setBigEndian(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, long, ArrowBuf)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param start start index of data in the buffer
+ * @param buffer ArrowBuf containing decimal value.
+ */
+ public void setSafe(int index, long start, ArrowBuf buffer) {
+ handleSafe(index);
+ set(index, start, buffer);
+ }
+
+ /**
+ * Same as {@link #set(int, BigDecimal)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value BigDecimal containing decimal value.
+ */
+ public void setSafe(int index, BigDecimal value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, long)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value long value.
+ */
+ public void setSafe(int index, long value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableDecimalHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableDecimalHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, DecimalHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, DecimalHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param start start position of the value in the buffer
+ * @param buffer buffer containing the value to be stored in the vector
+ */
+ public void set(int index, int isSet, long start, ArrowBuf buffer) {
+ if (isSet > 0) {
+ set(index, start, buffer);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, long, ArrowBuf)} except that it handles
+ * the case when the position of new value is beyond the current value
+ * capacity of the vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param start start position of the value in the buffer
+ * @param buffer buffer containing the value to be stored in the vector
+ */
+ public void setSafe(int index, int isSet, long start, ArrowBuf buffer) {
+ handleSafe(index);
+ set(index, isSet, start, buffer);
+ }
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((DecimalVector) to);
+ }
+
+ private class TransferImpl implements TransferPair {
+ DecimalVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new DecimalVector(ref, allocator, DecimalVector.this.precision,
+ DecimalVector.this.scale);
+ }
+
+ public TransferImpl(DecimalVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public DecimalVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, DecimalVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/DensityAwareVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/DensityAwareVector.java
new file mode 100644
index 000000000..c16db40f7
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/DensityAwareVector.java
@@ -0,0 +1,57 @@
+/*
+ * 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;
+
+/**
+ * Vector that support density aware initial capacity settings.
+ * We use this for ListVector and VarCharVector as of now to
+ * control the memory allocated.
+ *
+ * For ListVector, we have been using a multiplier of 5
+ * to compute the initial capacity of the inner data vector.
+ * For deeply nested lists and lists with lots of NULL values,
+ * this is over-allocation upfront. So density helps to be
+ * conservative when computing the value capacity of the
+ * inner vector.
+ *
+ * For example, a density value of 10 implies each position in the
+ * list vector has a list of 10 values. So we will provision
+ * an initial capacity of (valuecount * 10) for the inner vector.
+ * A density value of 0.1 implies out of 10 positions in the list vector,
+ * 1 position has a list of size 1 and remaining positions are
+ * null (no lists) or empty lists. This helps in tightly controlling
+ * the memory we provision for inner data vector.
+ *
+ * Similar analogy is applicable for VarCharVector where the capacity
+ * of the data buffer can be controlled using density multiplier
+ * instead of default multiplier of 8 (default size of average
+ * varchar length).
+ *
+ * Also from container vectors, we propagate the density down
+ * the inner vectors so that they can use it appropriately.
+ */
+public interface DensityAwareVector {
+
+ /**
+ * Set value with density.
+ *
+ * @param valueCount the number of values in this vector
+ * @param density the density of the vector
+ */
+ void setInitialCapacity(int valueCount, double density);
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/DurationVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/DurationVector.java
new file mode 100644
index 000000000..9671b34e0
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/DurationVector.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;
+
+import static java.util.concurrent.TimeUnit.MICROSECONDS;
+import static org.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import java.time.Duration;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.DurationReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.DurationHolder;
+import org.apache.arrow.vector.holders.NullableDurationHolder;
+import org.apache.arrow.vector.types.TimeUnit;
+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.TransferPair;
+
+/**
+ * DurationVector implements a fixed width vector (8 bytes) of
+ * a configurable TimeUnit granularity duration values which could be null.
+ * A validity buffer (bit vector) is maintained to track which elements in the
+ * vector are null.
+ */
+public final class DurationVector extends BaseFixedWidthVector {
+ public static final byte TYPE_WIDTH = 8;
+ private final FieldReader reader;
+
+ private final TimeUnit unit;
+
+ /**
+ * Instantiate a DurationVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public DurationVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a DurationVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public DurationVector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ reader = new DurationReaderImpl(DurationVector.this);
+ this.unit = ((ArrowType.Duration) field.getFieldType().getType()).getUnit();
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.DURATION;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+ /**
+ * Given a data buffer, get the value stored at a particular position
+ * in the vector.
+ *
+ * This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static long get(final ArrowBuf buffer, final int index) {
+ return buffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public ArrowBuf get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ return null;
+ }
+ return valueBuffer.slice((long) index * TYPE_WIDTH, TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableDurationHolder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = get(valueBuffer, index);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Duration getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ final long value = get(valueBuffer, index);
+ return toDuration(value, unit);
+ }
+ }
+
+ /**
+ * Converts the given value and unit to the appropriate {@link Duration}.
+ */
+ public static Duration toDuration(long value, TimeUnit unit) {
+ switch (unit) {
+ case SECOND:
+ return Duration.ofSeconds(value);
+ case MILLISECOND:
+ return Duration.ofMillis(value);
+ case NANOSECOND:
+ return Duration.ofNanos(value);
+ case MICROSECOND:
+ return Duration.ofNanos(MICROSECONDS.toNanos(value));
+ default:
+ throw new IllegalArgumentException("Unknown timeunit: " + unit);
+ }
+ }
+
+ /**
+ * Get the Interval value at a given index as a {@link StringBuilder} object.
+ *
+ * @param index position of the element
+ * @return String Builder object with Interval in java.time.Duration format.
+ */
+ public StringBuilder getAsStringBuilder(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return getAsStringBuilderHelper(index);
+ }
+ }
+
+ private StringBuilder getAsStringBuilderHelper(int index) {
+ return new StringBuilder(getObject(index).toString());
+ }
+
+ /**
+ * Gets the time unit of the duration.
+ */
+ public TimeUnit getUnit() {
+ return unit;
+ }
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, ArrowBuf value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ valueBuffer.setBytes((long) index * TYPE_WIDTH, value, 0, TYPE_WIDTH);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value The duration value (in the timeunit associated with this vector)
+ */
+ public void set(int index, long value) {
+ final long offsetIndex = (long) index * TYPE_WIDTH;
+ BitVectorHelper.setBit(validityBuffer, index);
+ valueBuffer.setLong(offsetIndex, value);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableDurationHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ set(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, DurationHolder holder) {
+ set(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, ArrowBuf)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, ArrowBuf value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, long)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value duration in the time unit this vector was constructed with
+ */
+ public void setSafe(int index, long value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableDurationHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableDurationHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, DurationHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, DurationHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value The duration value (in the TimeUnit associated with this vector).
+ */
+ public void set(int index, int isSet, long value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, long)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value The duration value (in the timeunit associated with this vector)
+ */
+ public void setSafe(int index, int isSet, long value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((DurationVector) to);
+ }
+
+ private class TransferImpl implements TransferPair {
+ DurationVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new DurationVector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(DurationVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public DurationVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, DurationVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/ElementAddressableVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/ElementAddressableVector.java
new file mode 100644
index 000000000..f37a50100
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/ElementAddressableVector.java
@@ -0,0 +1,42 @@
+/*
+ * 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 org.apache.arrow.memory.util.ArrowBufPointer;
+
+/**
+ * Vector for which each data element resides in a continuous memory region,
+ * so it can be pointed to by an {@link org.apache.arrow.memory.util.ArrowBufPointer}.
+ */
+public interface ElementAddressableVector extends ValueVector {
+
+ /**
+ * Gets the pointer for the data at the given index.
+ * @param index the index for the data.
+ * @return the pointer to the data.
+ */
+ ArrowBufPointer getDataPointer(int index);
+
+ /**
+ * Gets the pointer for the data at the given index.
+ * @param index the index for the data.
+ * @param reuse the data pointer to fill, this avoids creating a new pointer object.
+ * @return the pointer to the data, it should be the same one as the input parameter
+ */
+ ArrowBufPointer getDataPointer(int index, ArrowBufPointer reuse);
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/ExtensionTypeVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/ExtensionTypeVector.java
new file mode 100644
index 000000000..2041227fc
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/ExtensionTypeVector.java
@@ -0,0 +1,274 @@
+/*
+ * 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 java.util.Iterator;
+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.util.Preconditions;
+import org.apache.arrow.vector.compare.VectorVisitor;
+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.Field;
+import org.apache.arrow.vector.util.CallBack;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * A vector that wraps an underlying vector, used to help implement extension types.
+ * @param Generally, this should access the underlying vector and construct the corresponding Java object from the raw
+ * data.
+ */
+ @Override
+ public abstract Object getObject(int index);
+
+ @Override
+ public int getNullCount() {
+ return underlyingVector.getNullCount();
+ }
+
+ @Override
+ public boolean isNull(int index) {
+ return underlyingVector.isNull(index);
+ }
+
+ @Override
+ public void initializeChildrenFromFields(List This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static byte[] get(final ArrowBuf buffer, final int index, final int byteWidth) {
+ final byte[] dst = new byte[byteWidth];
+ buffer.getBytes((long) index * byteWidth, dst, 0, byteWidth);
+ return dst;
+ }
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((FixedSizeBinaryVector) to);
+ }
+
+ private class TransferImpl implements TransferPair {
+ FixedSizeBinaryVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new FixedSizeBinaryVector(ref, allocator, FixedSizeBinaryVector.this.byteWidth);
+ }
+
+ public TransferImpl(FixedSizeBinaryVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public FixedSizeBinaryVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, FixedSizeBinaryVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/FixedWidthVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/FixedWidthVector.java
new file mode 100644
index 000000000..58effeecb
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/FixedWidthVector.java
@@ -0,0 +1,36 @@
+/*
+ * 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;
+
+/**
+ * Interface for all fixed width {@link ElementAddressableVector} (e.g. integer, fixed size binary, etc).
+ */
+public interface FixedWidthVector extends ElementAddressableVector {
+
+ /**
+ * Allocate a new memory space for this vector. Must be called prior to using the ValueVector.
+ *
+ * @param valueCount Number of values in the vector.
+ */
+ void allocateNew(int valueCount);
+
+ /**
+ * Zero out the underlying buffer backing this vector.
+ */
+ void zeroVector();
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/Float4Vector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/Float4Vector.java
new file mode 100644
index 000000000..365a1529b
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/Float4Vector.java
@@ -0,0 +1,361 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.Float4ReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.Float4Holder;
+import org.apache.arrow.vector.holders.NullableFloat4Holder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * Float4Vector implements a fixed width vector (4 bytes) of
+ * float values which could be null. A validity buffer (bit vector) is
+ * maintained to track which elements in the vector are null.
+ */
+public final class Float4Vector extends BaseFixedWidthVector implements FloatingPointVector {
+ public static final byte TYPE_WIDTH = 4;
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a Float4Vector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public Float4Vector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.FLOAT4.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a Float4Vector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public Float4Vector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a Float4Vector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public Float4Vector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ reader = new Float4ReaderImpl(Float4Vector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.FLOAT4;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public float get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.getFloat((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableFloat4Holder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getFloat((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Float getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return valueBuffer.getFloat((long) index * TYPE_WIDTH);
+ }
+ }
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ private void setValue(int index, float value) {
+ valueBuffer.setFloat((long) index * TYPE_WIDTH, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, float value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableFloat4Holder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, Float4Holder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, float)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, float value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableFloat4Holder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableFloat4Holder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, Float4Holder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, Float4Holder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void set(int index, int isSet, float value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, float)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void setSafe(int index, int isSet, float value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+ /**
+ * Given a data buffer, get the value stored at a particular position
+ * in the vector.
+ *
+ * This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static float get(final ArrowBuf buffer, final int index) {
+ return buffer.getFloat((long) index * TYPE_WIDTH);
+ }
+
+ @Override
+ public void setWithPossibleTruncate(int index, double value) {
+ set(index, (float) value);
+ }
+
+ @Override
+ public void setSafeWithPossibleTruncate(int index, double value) {
+ setSafe(index, (float) value);
+ }
+
+ @Override
+ public double getValueAsDouble(int index) {
+ return get(index);
+ }
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((Float4Vector) to);
+ }
+
+ private class TransferImpl implements TransferPair {
+ Float4Vector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new Float4Vector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(Float4Vector to) {
+ this.to = to;
+ }
+
+ @Override
+ public Float4Vector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, Float4Vector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/Float8Vector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/Float8Vector.java
new file mode 100644
index 000000000..948390d46
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/Float8Vector.java
@@ -0,0 +1,362 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.Float8ReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.Float8Holder;
+import org.apache.arrow.vector.holders.NullableFloat8Holder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * Float8Vector implements a fixed width vector (8 bytes) of
+ * double values which could be null. A validity buffer (bit vector) is
+ * maintained to track which elements in the vector are null.
+ */
+public final class Float8Vector extends BaseFixedWidthVector implements FloatingPointVector {
+ public static final byte TYPE_WIDTH = 8;
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a Float8Vector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public Float8Vector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.FLOAT8.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a Float8Vector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public Float8Vector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a Float8Vector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public Float8Vector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ reader = new Float8ReaderImpl(Float8Vector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.FLOAT8;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public double get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.getDouble((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableFloat8Holder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getDouble((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Double getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return valueBuffer.getDouble((long) index * TYPE_WIDTH);
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ private void setValue(int index, double value) {
+ valueBuffer.setDouble((long) index * TYPE_WIDTH, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, double value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableFloat8Holder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, Float8Holder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, double)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, double value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableFloat8Holder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableFloat8Holder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, Float8Holder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, Float8Holder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void set(int index, int isSet, double value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, double)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void setSafe(int index, int isSet, double value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+ /**
+ * Given a data buffer, get the value stored at a particular position
+ * in the vector.
+ *
+ * This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static double get(final ArrowBuf buffer, final int index) {
+ return buffer.getDouble((long) index * TYPE_WIDTH);
+ }
+
+ @Override
+ public void setWithPossibleTruncate(int index, double value) {
+ set(index, value);
+ }
+
+ @Override
+ public void setSafeWithPossibleTruncate(int index, double value) {
+ setSafe(index, value);
+ }
+
+ @Override
+ public double getValueAsDouble(int index) {
+ return get(index);
+ }
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((Float8Vector) to);
+ }
+
+ private class TransferImpl implements TransferPair {
+ Float8Vector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new Float8Vector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(Float8Vector to) {
+ this.to = to;
+ }
+
+ @Override
+ public Float8Vector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, Float8Vector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/FloatingPointVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/FloatingPointVector.java
new file mode 100644
index 000000000..4c5143de6
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/FloatingPointVector.java
@@ -0,0 +1,46 @@
+/*
+ * 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;
+
+/**
+ * The interface for vectors with floating point values.
+ */
+public interface FloatingPointVector extends ValueVector {
+
+ /**
+ * Sets the value at the given index, note this value may be truncated internally.
+ * @param index the index to set.
+ * @param value the value to set.
+ */
+ void setWithPossibleTruncate(int index, double value);
+
+ /**
+ * Sets the value at the given index, note this value may be truncated internally.
+ * Any expansion/reallocation is handled automatically.
+ * @param index the index to set.
+ * @param value the value to set.
+ */
+ void setSafeWithPossibleTruncate(int index, double value);
+
+ /**
+ * Gets the value at the given index.
+ * @param index the index to retrieve the value.
+ * @return the value at the index.
+ */
+ double getValueAsDouble(int index);
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/GenerateSampleData.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/GenerateSampleData.java
new file mode 100644
index 000000000..3da915541
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/GenerateSampleData.java
@@ -0,0 +1,337 @@
+/*
+ * 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 java.math.BigDecimal;
+import java.nio.charset.Charset;
+
+/**
+ * Helper class to generate test data for Nullable fixed and variable
+ * width scalar vectors. Previous implementations of java vector classes
+ * provided generateTestData(now deprecated) API to populate the vector
+ * with sample data. This class should be used for that purpose.
+ */
+public class GenerateSampleData {
+ private GenerateSampleData() {}
+
+ /** Populates This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static int get(final ArrowBuf buffer, final int index) {
+ return buffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((IntVector) to);
+ }
+
+ @Override
+ public void setWithPossibleTruncate(int index, long value) {
+ this.setSafe(index, (int) value);
+ }
+
+ @Override
+ public void setUnsafeWithPossibleTruncate(int index, long value) {
+ this.set(index, (int) value);
+ }
+
+ @Override
+ public long getValueAsLong(int index) {
+ return this.get(index);
+ }
+
+ private class TransferImpl implements TransferPair {
+ IntVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new IntVector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(IntVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public IntVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, IntVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/IntervalDayVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/IntervalDayVector.java
new file mode 100644
index 000000000..0dc860e6b
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/IntervalDayVector.java
@@ -0,0 +1,433 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import java.time.Duration;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.IntervalDayReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.IntervalDayHolder;
+import org.apache.arrow.vector.holders.NullableIntervalDayHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * IntervalDayVector implements a fixed width vector (8 bytes) of
+ * interval (days and milliseconds) values which could be null.
+ * A validity buffer (bit vector) is maintained to track which elements in the
+ * vector are null.
+ */
+public final class IntervalDayVector extends BaseFixedWidthVector {
+ public static final byte TYPE_WIDTH = 8;
+ private static final byte MILLISECOND_OFFSET = 4;
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a IntervalDayVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public IntervalDayVector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.INTERVALDAY.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a IntervalDayVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public IntervalDayVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a IntervalDayVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public IntervalDayVector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ reader = new IntervalDayReaderImpl(IntervalDayVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.INTERVALDAY;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+ /**
+ * Given a data buffer, get the number of days stored at a particular position
+ * in the vector.
+ *
+ * This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return day value stored at the index.
+ */
+ public static int getDays(final ArrowBuf buffer, final int index) {
+ return buffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Given a data buffer, get the get the number of milliseconds stored at a particular position
+ * in the vector.
+ *
+ * This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return milliseconds value stored at the index.
+ */
+ public static int getMilliseconds(final ArrowBuf buffer, final int index) {
+ return buffer.getInt((long) index * TYPE_WIDTH + MILLISECOND_OFFSET);
+ }
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public ArrowBuf get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ return null;
+ }
+ return valueBuffer.slice((long) index * TYPE_WIDTH, TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableIntervalDayHolder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ final long startIndex = (long) index * TYPE_WIDTH;
+ holder.isSet = 1;
+ holder.days = valueBuffer.getInt(startIndex);
+ holder.milliseconds = valueBuffer.getInt(startIndex + MILLISECOND_OFFSET);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Duration getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ final long startIndex = (long) index * TYPE_WIDTH;
+ final int days = valueBuffer.getInt(startIndex);
+ final int milliseconds = valueBuffer.getInt(startIndex + MILLISECOND_OFFSET);
+ return Duration.ofDays(days).plusMillis(milliseconds);
+ }
+ }
+
+ /**
+ * Get the Interval value at a given index as a {@link StringBuilder} object.
+ *
+ * @param index position of the element
+ * @return String Builder object with Interval value as
+ * [days, hours, minutes, seconds, millis]
+ */
+ public StringBuilder getAsStringBuilder(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return getAsStringBuilderHelper(index);
+ }
+ }
+
+ private StringBuilder getAsStringBuilderHelper(int index) {
+ final long startIndex = (long) index * TYPE_WIDTH;
+
+ final int days = valueBuffer.getInt(startIndex);
+ int millis = valueBuffer.getInt(startIndex + MILLISECOND_OFFSET);
+
+ final int hours = millis / (org.apache.arrow.vector.util.DateUtility.hoursToMillis);
+ millis = millis % (org.apache.arrow.vector.util.DateUtility.hoursToMillis);
+
+ final int minutes = millis / (org.apache.arrow.vector.util.DateUtility.minutesToMillis);
+ millis = millis % (org.apache.arrow.vector.util.DateUtility.minutesToMillis);
+
+ final int seconds = millis / (org.apache.arrow.vector.util.DateUtility.secondsToMillis);
+ millis = millis % (org.apache.arrow.vector.util.DateUtility.secondsToMillis);
+
+ final String dayString = (Math.abs(days) == 1) ? " day " : " days ";
+
+ return (new StringBuilder()
+ .append(days).append(dayString)
+ .append(hours).append(":")
+ .append(minutes).append(":")
+ .append(seconds).append(".")
+ .append(millis));
+ }
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, ArrowBuf value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ valueBuffer.setBytes((long) index * TYPE_WIDTH, value, 0, TYPE_WIDTH);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param days days for the interval
+ * @param milliseconds milliseconds for the interval
+ */
+ public void set(int index, int days, int milliseconds) {
+ final long offsetIndex = (long) index * TYPE_WIDTH;
+ BitVectorHelper.setBit(validityBuffer, index);
+ valueBuffer.setInt(offsetIndex, days);
+ valueBuffer.setInt((offsetIndex + MILLISECOND_OFFSET), milliseconds);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableIntervalDayHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ set(index, holder.days, holder.milliseconds);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, IntervalDayHolder holder) {
+ set(index, holder.days, holder.milliseconds);
+ }
+
+ /**
+ * Same as {@link #set(int, ArrowBuf)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, ArrowBuf value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, int, int)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param days days for the interval
+ * @param milliseconds milliseconds for the interval
+ */
+ public void setSafe(int index, int days, int milliseconds) {
+ handleSafe(index);
+ set(index, days, milliseconds);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableIntervalDayHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableIntervalDayHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, IntervalDayHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, IntervalDayHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param days days component of interval
+ * @param milliseconds millisecond component of interval
+ */
+ public void set(int index, int isSet, int days, int milliseconds) {
+ if (isSet > 0) {
+ set(index, days, milliseconds);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, int, int)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param days days component of interval
+ * @param milliseconds millisecond component of interval
+ */
+ public void setSafe(int index, int isSet, int days, int milliseconds) {
+ handleSafe(index);
+ set(index, isSet, days, milliseconds);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((IntervalDayVector) to);
+ }
+
+ private class TransferImpl implements TransferPair {
+ IntervalDayVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new IntervalDayVector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(IntervalDayVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public IntervalDayVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, IntervalDayVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/IntervalMonthDayNanoVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/IntervalMonthDayNanoVector.java
new file mode 100644
index 000000000..ba3a26a89
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/IntervalMonthDayNanoVector.java
@@ -0,0 +1,442 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import java.time.Duration;
+import java.time.Period;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.IntervalMonthDayNanoReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.IntervalMonthDayNanoHolder;
+import org.apache.arrow.vector.holders.NullableIntervalMonthDayNanoHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * IntervalMonthDayNanoVector implements a fixed width vector (16 bytes) of
+ * interval (month, days and nanoseconds) values which could be null.
+ * A validity buffer (bit vector) is maintained to track which elements in the
+ * vector are null.
+ *
+ * Month, day and nanoseconds are indepndent from one another and there
+ * is no specific limits imposed on their values.
+ */
+public final class IntervalMonthDayNanoVector extends BaseFixedWidthVector {
+ public static final byte TYPE_WIDTH = 16;
+ private static final byte DAY_OFFSET = 4;
+ private static final byte NANOSECOND_OFFSET = 8;
+ private final FieldReader reader;
+
+
+ /**
+ * Instantiate a IntervalMonthDayNanoVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public IntervalMonthDayNanoVector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.INTERVALDAY.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a IntervalMonthDayNanoVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public IntervalMonthDayNanoVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a IntervalMonthDayNanoVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public IntervalMonthDayNanoVector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ reader = new IntervalMonthDayNanoReaderImpl(IntervalMonthDayNanoVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.INTERVALMONTHDAYNANO;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+ /**
+ * Given a data buffer, get the number of months stored at a particular position
+ * in the vector.
+ *
+ * This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return day value stored at the index.
+ */
+ public static int getMonths(final ArrowBuf buffer, final int index) {
+ return buffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+
+ /**
+ * Given a data buffer, get the number of days stored at a particular position
+ * in the vector.
+ *
+ * This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return day value stored at the index.
+ */
+ public static int getDays(final ArrowBuf buffer, final int index) {
+ return buffer.getInt((long) index * TYPE_WIDTH + DAY_OFFSET);
+ }
+
+ /**
+ * Given a data buffer, get the get the number of nanoseconds stored at a particular position
+ * in the vector.
+ *
+ * This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return nanoseconds value stored at the index.
+ */
+ public static long getNanoseconds(final ArrowBuf buffer, final int index) {
+ return buffer.getLong((long) index * TYPE_WIDTH + NANOSECOND_OFFSET);
+ }
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public ArrowBuf get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ return null;
+ }
+ return valueBuffer.slice((long) index * TYPE_WIDTH, TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableIntervalMonthDayNanoHolder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ final long startIndex = (long) index * TYPE_WIDTH;
+ holder.isSet = 1;
+ holder.months = valueBuffer.getInt(startIndex);
+ holder.days = valueBuffer.getInt(startIndex + DAY_OFFSET);
+ holder.nanoseconds = valueBuffer.getLong(startIndex + NANOSECOND_OFFSET);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public PeriodDuration getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ final long startIndex = (long) index * TYPE_WIDTH;
+ final int months = valueBuffer.getInt(startIndex);
+ final int days = valueBuffer.getInt(startIndex + DAY_OFFSET);
+ final long nanoseconds = valueBuffer.getLong(startIndex + NANOSECOND_OFFSET);
+
+ return new PeriodDuration(Period.ofMonths(months).plusDays(days),
+ Duration.ofNanos(nanoseconds));
+ }
+ }
+
+ /**
+ * Get the Interval value at a given index as a {@link StringBuilder} object.
+ *
+ * @param index position of the element
+ * @return String Builder object with Interval value as
+ */
+ public StringBuilder getAsStringBuilder(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return getAsStringBuilderHelper(index);
+ }
+ }
+
+ private StringBuilder getAsStringBuilderHelper(int index) {
+ return new StringBuilder().append(getObject(index).toString()).append(" ");
+ }
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, ArrowBuf value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ valueBuffer.setBytes((long) index * TYPE_WIDTH, value, 0, TYPE_WIDTH);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param months months component of interval
+ * @param days days component of interval
+ * @param nanoseconds nanosecond component of interval
+ */
+ public void set(int index, int months, int days, long nanoseconds) {
+ final long offsetIndex = (long) index * TYPE_WIDTH;
+ BitVectorHelper.setBit(validityBuffer, index);
+ valueBuffer.setInt(offsetIndex, months);
+ valueBuffer.setInt(offsetIndex + DAY_OFFSET, days);
+ valueBuffer.setLong((offsetIndex + NANOSECOND_OFFSET), nanoseconds);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableIntervalMonthDayNanoHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ set(index, holder.months, holder.days, holder.nanoseconds);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, IntervalMonthDayNanoHolder holder) {
+ set(index, holder.months, holder.days, holder.nanoseconds);
+ }
+
+ /**
+ * Same as {@link #set(int, ArrowBuf)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, ArrowBuf value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, int, int, long)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param months months for the interval
+ * @param days days for the interval
+ * @param nanoseconds nanoseconds for the interval
+ */
+ public void setSafe(int index, int months, int days, long nanoseconds) {
+ handleSafe(index);
+ set(index, months, days, nanoseconds);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableIntervalMonthDayNanoHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableIntervalMonthDayNanoHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, IntervalMonthDayNanoHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, IntervalMonthDayNanoHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param months months component of interval
+ * @param days days component of interval
+ * @param nanoseconds nanosecond component of interval
+ */
+ public void set(int index, int isSet, int months, int days, long nanoseconds) {
+ if (isSet > 0) {
+ set(index, months, days, nanoseconds);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, int, int, long)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param months months component of interval
+ * @param days days component of interval
+ * @param nanoseconds nanosecond component of interval
+ */
+ public void setSafe(int index, int isSet, int months, int days,
+ long nanoseconds) {
+ handleSafe(index);
+ set(index, isSet, months, days, nanoseconds);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((IntervalMonthDayNanoVector) to);
+ }
+
+ private class TransferImpl implements TransferPair {
+ IntervalMonthDayNanoVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new IntervalMonthDayNanoVector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(IntervalMonthDayNanoVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public IntervalMonthDayNanoVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, IntervalMonthDayNanoVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/IntervalYearVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/IntervalYearVector.java
new file mode 100644
index 000000000..7ddfe6b78
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/IntervalYearVector.java
@@ -0,0 +1,382 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import java.time.Period;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.IntervalYearReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.IntervalYearHolder;
+import org.apache.arrow.vector.holders.NullableIntervalYearHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * IntervalYearVector implements a fixed width (4 bytes) vector of
+ * interval (years and months) values which could be null. A validity buffer
+ * (bit vector) is maintained to track which elements in the vector are null.
+ */
+public final class IntervalYearVector extends BaseFixedWidthVector {
+ public static final byte TYPE_WIDTH = 4;
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a IntervalYearVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public IntervalYearVector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.INTERVALYEAR.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a IntervalYearVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public IntervalYearVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a IntervalYearVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public IntervalYearVector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ reader = new IntervalYearReaderImpl(IntervalYearVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.INTERVALYEAR;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Given a data buffer, get the value stored at a particular position
+ * in the vector.
+ *
+ * This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static int getTotalMonths(final ArrowBuf buffer, final int index) {
+ return buffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public int get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableIntervalYearHolder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Period getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ final int interval = valueBuffer.getInt((long) index * TYPE_WIDTH);
+ // TODO: verify interval is in months
+ return Period.ofMonths(interval);
+ }
+ }
+
+ /**
+ * Get the Interval value at a given index as a {@link StringBuilder} object.
+ *
+ * @param index position of the element
+ * @return String Builder object with Interval value as
+ * [years, months]
+ */
+ public StringBuilder getAsStringBuilder(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return getAsStringBuilderHelper(index);
+ }
+ }
+
+ private StringBuilder getAsStringBuilderHelper(int index) {
+ int value = valueBuffer.getInt((long) index * TYPE_WIDTH);
+
+ final int years = (value / org.apache.arrow.vector.util.DateUtility.yearsToMonths);
+ final int months = (value % org.apache.arrow.vector.util.DateUtility.yearsToMonths);
+
+ final String yearString = (Math.abs(years) == 1) ? " year " : " years ";
+ final String monthString = (Math.abs(months) == 1) ? " month " : " months ";
+
+ return (new StringBuilder()
+ .append(years)
+ .append(yearString)
+ .append(months)
+ .append(monthString));
+ }
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ private void setValue(int index, int value) {
+ valueBuffer.setInt((long) index * TYPE_WIDTH, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, int value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableIntervalYearHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, IntervalYearHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, int)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, int value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableIntervalYearHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableIntervalYearHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, IntervalYearHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, IntervalYearHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void set(int index, int isSet, int value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, int)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void setSafe(int index, int isSet, int value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((IntervalYearVector) to);
+ }
+
+ private class TransferImpl implements TransferPair {
+ IntervalYearVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new IntervalYearVector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(IntervalYearVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public IntervalYearVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, IntervalYearVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/LargeVarBinaryVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/LargeVarBinaryVector.java
new file mode 100644
index 000000000..e9d60b38e
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/LargeVarBinaryVector.java
@@ -0,0 +1,305 @@
+/*
+ * 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 org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.LargeVarBinaryReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.LargeVarBinaryHolder;
+import org.apache.arrow.vector.holders.NullableLargeVarBinaryHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * LargeVarBinaryVector implements a large variable width vector of binary
+ * values which could be NULL. A validity buffer (bit vector) is maintained
+ * to track which elements in the vector are null.
+ * The size of the underlying buffer can be over 2GB.
+ */
+public final class LargeVarBinaryVector extends BaseLargeVariableWidthVector {
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a LargeVarBinaryVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public LargeVarBinaryVector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.LARGEVARBINARY.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a LargeVarBinaryVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public LargeVarBinaryVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a LargeVarBinaryVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public LargeVarBinaryVector(Field field, BufferAllocator allocator) {
+ super(field, allocator);
+ reader = new LargeVarBinaryReaderImpl(LargeVarBinaryVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.LARGEVARBINARY;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the variable length element at specified index as byte array.
+ *
+ * @param index position of element to get
+ * @return array of bytes for non-null element, null otherwise
+ */
+ public byte[] get(int index) {
+ assert index >= 0;
+ if (isSet(index) == 0) {
+ return null;
+ }
+ final long startOffset = getStartOffset(index);
+ final int dataLength =
+ (int) (offsetBuffer.getLong((long) (index + 1) * OFFSET_WIDTH) - startOffset);
+ final byte[] result = new byte[dataLength];
+ valueBuffer.getBytes(startOffset, result, 0, dataLength);
+ return result;
+ }
+
+ /**
+ * Get the variable length element at specified index as Text.
+ *
+ * @param index position of element to get
+ * @return byte array for non-null element, null otherwise
+ */
+ public byte[] getObject(int index) {
+ return get(index);
+ }
+
+ /**
+ * Get the variable length element at specified index and sets the state
+ * in provided holder.
+ *
+ * @param index position of element to get
+ * @param holder data holder to be populated by this function
+ */
+ public void get(int index, NullableLargeVarBinaryHolder holder) {
+ assert index >= 0;
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.start = getStartOffset(index);
+ holder.end = offsetBuffer.getLong((long) (index + 1) * OFFSET_WIDTH);
+ holder.buffer = valueBuffer;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Set the variable length element at the specified index to the data
+ * buffer supplied in the holder.
+ *
+ * @param index position of the element to set
+ * @param holder holder that carries data buffer.
+ */
+ public void set(int index, LargeVarBinaryHolder holder) {
+ assert index >= 0;
+ fillHoles(index);
+ BitVectorHelper.setBit(validityBuffer, index);
+ final int dataLength = (int) (holder.end - holder.start);
+ final long startOffset = getStartOffset(index);
+ offsetBuffer.setLong((long) (index + 1) * OFFSET_WIDTH, startOffset + dataLength);
+ valueBuffer.setBytes(startOffset, holder.buffer, holder.start, dataLength);
+ lastSet = index;
+ }
+
+ /**
+ * Same as {@link #set(int, LargeVarBinaryHolder)} except that it handles the
+ * case where index and length of new element are beyond the existing
+ * capacity of the vector.
+ *
+ * @param index position of the element to set
+ * @param holder holder that carries data buffer.
+ */
+ public void setSafe(int index, LargeVarBinaryHolder holder) {
+ assert index >= 0;
+ final int dataLength = (int) (holder.end - holder.start);
+ handleSafe(index, dataLength);
+ fillHoles(index);
+ BitVectorHelper.setBit(validityBuffer, index);
+ final long startOffset = getStartOffset(index);
+ offsetBuffer.setLong((long) (index + 1) * OFFSET_WIDTH, startOffset + dataLength);
+ valueBuffer.setBytes(startOffset, holder.buffer, holder.start, dataLength);
+ lastSet = index;
+ }
+
+ /**
+ * Set the variable length element at the specified index to the data
+ * buffer supplied in the holder.
+ *
+ * @param index position of the element to set
+ * @param holder holder that carries data buffer.
+ */
+ public void set(int index, NullableLargeVarBinaryHolder holder) {
+ assert index >= 0;
+ fillHoles(index);
+ BitVectorHelper.setValidityBit(validityBuffer, index, holder.isSet);
+ final long startOffset = getStartOffset(index);
+ if (holder.isSet != 0) {
+ final int dataLength = (int) (holder.end - holder.start);
+ offsetBuffer.setLong((long) (index + 1) * OFFSET_WIDTH, startOffset + dataLength);
+ valueBuffer.setBytes(startOffset, holder.buffer, holder.start, dataLength);
+ } else {
+ offsetBuffer.setLong((long) (index + 1) * OFFSET_WIDTH, startOffset);
+ }
+ lastSet = index;
+ }
+
+ /**
+ * Same as {@link #set(int, NullableLargeVarBinaryHolder)} except that it handles the
+ * case where index and length of new element are beyond the existing
+ * capacity of the vector.
+ *
+ * @param index position of the element to set
+ * @param holder holder that carries data buffer.
+ */
+ public void setSafe(int index, NullableLargeVarBinaryHolder holder) {
+ assert index >= 0;
+ if (holder.isSet != 0) {
+ final int dataLength = (int) (holder.end - holder.start);
+ handleSafe(index, dataLength);
+ fillHoles(index);
+ final long startOffset = getStartOffset(index);
+ offsetBuffer.setLong((long) (index + 1) * OFFSET_WIDTH, startOffset + dataLength);
+ valueBuffer.setBytes(startOffset, holder.buffer, holder.start, dataLength);
+ } else {
+ fillEmpties(index + 1);
+ }
+ BitVectorHelper.setValidityBit(validityBuffer, index, holder.isSet);
+ lastSet = index;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((LargeVarBinaryVector) to);
+ }
+
+ private class TransferImpl implements TransferPair {
+ LargeVarBinaryVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new LargeVarBinaryVector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(LargeVarBinaryVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public LargeVarBinaryVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, LargeVarBinaryVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/LargeVarCharVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/LargeVarCharVector.java
new file mode 100644
index 000000000..fd2057260
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/LargeVarCharVector.java
@@ -0,0 +1,331 @@
+/*
+ * 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 org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.LargeVarCharReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.LargeVarCharHolder;
+import org.apache.arrow.vector.holders.NullableLargeVarCharHolder;
+import org.apache.arrow.vector.types.Types;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.Text;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * LargeVarCharVector implements a variable width vector of VARCHAR
+ * values which could be NULL. A validity buffer (bit vector) is maintained
+ * to track which elements in the vector are null.
+ *
+ * The offset width of this vector is 8, so the underlying buffer can be larger than 2GB.
+ * Null checking is on by default. You can disable it by setting either the system property or the
+ * environmental variable to "false". The system property is named "arrow.enable_null_check_for_get" and
+ * the environmental variable is named "ARROW_ENABLE_NULL_CHECK_FOR_GET".
+ * When both the system property and the environmental variable are set, the system property takes precedence.
+ *
+ * Disabling null-checking in the "get" methods may lead to performance improvements.
+ * For example, suppose we have the following micro-benchmark:
+ *
+ *
+ * Performance evaluations of the micro-benchmark with the JMH framework reveal that, disabling null checking
+ * has the following effects:
+ * 1. The amounts of byte code and assembly code generated by JIT are both smaller.
+ * 2. The performance improves by about 30% (2.819 ± 0.005 us/op vs. 4.069 ± 0.004 us/op).
+ *
+ * Therefore, for scenarios where the user can be sure that the null-checking is unnecessary,
+ * it is beneficial to disable it with this configuration.
+ * This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static short get(final ArrowBuf buffer, final int index) {
+ return buffer.getShort((long) index * TYPE_WIDTH);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((SmallIntVector) to);
+ }
+
+ @Override
+ public void setWithPossibleTruncate(int index, long value) {
+ this.setSafe(index, (int) value);
+ }
+
+ @Override
+ public void setUnsafeWithPossibleTruncate(int index, long value) {
+ this.set(index, (int) value);
+ }
+
+ @Override
+ public long getValueAsLong(int index) {
+ return this.get(index);
+ }
+
+ private class TransferImpl implements TransferPair {
+ SmallIntVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new SmallIntVector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(SmallIntVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public SmallIntVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, SmallIntVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeMicroVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeMicroVector.java
new file mode 100644
index 000000000..cf128859e
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeMicroVector.java
@@ -0,0 +1,347 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.TimeMicroReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.NullableTimeMicroHolder;
+import org.apache.arrow.vector.holders.TimeMicroHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * TimeMicroVector implements a fixed width vector (8 bytes) of
+ * time (microsecond resolution) values which could be null.
+ * A validity buffer (bit vector) is maintained to track which elements in the
+ * vector are null.
+ */
+public final class TimeMicroVector extends BaseFixedWidthVector {
+ public static final byte TYPE_WIDTH = 8;
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a TimeMicroVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeMicroVector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.TIMEMICRO.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a TimeMicroVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeMicroVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a TimeMicroVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeMicroVector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ reader = new TimeMicroReaderImpl(TimeMicroVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.TIMEMICRO;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public long get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableTimeMicroHolder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Long getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+ }
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ private void setValue(int index, long value) {
+ valueBuffer.setLong((long) index * TYPE_WIDTH, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, long value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableTimeMicroHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, TimeMicroHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, long)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, long value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableTimeMicroHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableTimeMicroHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, TimeMicroHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, TimeMicroHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void set(int index, int isSet, long value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, long)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void setSafe(int index, int isSet, long value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+ /**
+ * Given a data buffer, get the value stored at a particular position
+ * in the vector.
+ *
+ * This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static long get(final ArrowBuf buffer, int index) {
+ return buffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((TimeMicroVector) to);
+ }
+
+ private class TransferImpl implements TransferPair {
+ TimeMicroVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new TimeMicroVector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(TimeMicroVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public TimeMicroVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, TimeMicroVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeMilliVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeMilliVector.java
new file mode 100644
index 000000000..b96990b10
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeMilliVector.java
@@ -0,0 +1,351 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import java.time.LocalDateTime;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.TimeMilliReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.NullableTimeMilliHolder;
+import org.apache.arrow.vector.holders.TimeMilliHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.DateUtility;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * TimeMilliVector implements a fixed width (4 bytes) vector of
+ * time (millisecond resolution) values which could be null. A validity buffer
+ * (bit vector) is maintained to track which elements in the vector are null.
+ */
+public final class TimeMilliVector extends BaseFixedWidthVector {
+ public static final byte TYPE_WIDTH = 4;
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a TimeMilliVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeMilliVector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.TIMEMILLI.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a TimeMilliVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeMilliVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a TimeMilliVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeMilliVector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ reader = new TimeMilliReaderImpl(TimeMilliVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.TIMEMILLI;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public int get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableTimeMilliHolder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public LocalDateTime getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ }
+ final int millis = valueBuffer.getInt((long) index * TYPE_WIDTH);
+ // TODO: this doesn't seem right, time not from epoch
+ return DateUtility.getLocalDateTimeFromEpochMilli(millis);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ private void setValue(int index, int value) {
+ valueBuffer.setInt((long) index * TYPE_WIDTH, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, int value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableTimeMilliHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, TimeMilliHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, int)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, int value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableTimeMilliHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableTimeMilliHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, TimeMilliHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, TimeMilliHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void set(int index, int isSet, int value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, int)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void setSafe(int index, int isSet, int value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+
+ /**
+ * Given a data buffer, get the value stored at a particular position
+ * in the vector.
+ *
+ * This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static int get(final ArrowBuf buffer, final int index) {
+ return buffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((TimeMilliVector) to);
+ }
+
+ private class TransferImpl implements TransferPair {
+ TimeMilliVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new TimeMilliVector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(TimeMilliVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public TimeMilliVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, TimeMilliVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeNanoVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeNanoVector.java
new file mode 100644
index 000000000..bc78a0264
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeNanoVector.java
@@ -0,0 +1,347 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.TimeNanoReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.NullableTimeNanoHolder;
+import org.apache.arrow.vector.holders.TimeNanoHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * TimeNanoVector implements a fixed width vector (8 bytes) of
+ * time (nanosecond resolution) values which could be null. A validity buffer
+ * (bit vector) is maintained to track which elements in the vector are null.
+ */
+public final class TimeNanoVector extends BaseFixedWidthVector {
+ public static final byte TYPE_WIDTH = 8;
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a TimeNanoVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeNanoVector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.TIMENANO.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a TimeNanoVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeNanoVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a TimeNanoVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeNanoVector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ reader = new TimeNanoReaderImpl(TimeNanoVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.TIMENANO;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public long get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableTimeNanoHolder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Long getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ private void setValue(int index, long value) {
+ valueBuffer.setLong((long) index * TYPE_WIDTH, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, long value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableTimeNanoHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, TimeNanoHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, long)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, long value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableTimeNanoHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableTimeNanoHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, TimeNanoHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, TimeNanoHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void set(int index, int isSet, long value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, long)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void setSafe(int index, int isSet, long value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+ /**
+ * Given a data buffer, get the value stored at a particular position
+ * in the vector.
+ *
+ * This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static long get(final ArrowBuf buffer, final int index) {
+ return buffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((TimeNanoVector) to);
+ }
+
+ private class TransferImpl implements TransferPair {
+ TimeNanoVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new TimeNanoVector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(TimeNanoVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public TimeNanoVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, TimeNanoVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeSecVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeSecVector.java
new file mode 100644
index 000000000..29b7381be
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeSecVector.java
@@ -0,0 +1,348 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.TimeSecReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.NullableTimeSecHolder;
+import org.apache.arrow.vector.holders.TimeSecHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * TimeSecVector implements a fixed width (4 bytes) vector of
+ * time (seconds resolution) values which could be null. A validity buffer (bit vector) is
+ * maintained to track which elements in the vector are null.
+ */
+public final class TimeSecVector extends BaseFixedWidthVector {
+ public static final byte TYPE_WIDTH = 4;
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a TimeSecVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeSecVector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.TIMESEC.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a TimeSecVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeSecVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a TimeSecVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeSecVector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ reader = new TimeSecReaderImpl(TimeSecVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.TIMESEC;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public int get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableTimeSecHolder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Integer getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return valueBuffer.getInt((long) index * TYPE_WIDTH);
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ private void setValue(int index, int value) {
+ valueBuffer.setInt((long) index * TYPE_WIDTH, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, int value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableTimeSecHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, TimeSecHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, int)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, int value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableTimeSecHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableTimeSecHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, TimeSecHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, TimeSecHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void set(int index, int isSet, int value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, int)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void setSafe(int index, int isSet, int value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+ /**
+ * Given a data buffer, get the value stored at a particular position
+ * in the vector.
+ *
+ * This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static int get(final ArrowBuf buffer, final int index) {
+ return buffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((TimeSecVector) to);
+ }
+
+ private class TransferImpl implements TransferPair {
+ TimeSecVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new TimeSecVector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(TimeSecVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public TimeSecVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, TimeSecVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMicroTZVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMicroTZVector.java
new file mode 100644
index 000000000..17715780e
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMicroTZVector.java
@@ -0,0 +1,239 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.TimeStampMicroTZReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.NullableTimeStampMicroTZHolder;
+import org.apache.arrow.vector.holders.TimeStampMicroTZHolder;
+import org.apache.arrow.vector.types.TimeUnit;
+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.TransferPair;
+
+/**
+ * TimeStampMicroTZVector implements a fixed width vector (8 bytes) of
+ * timestamp (microsecond resolution) values which could be null. A validity buffer
+ * (bit vector) is maintained to track which elements in the vector are null.
+ */
+public final class TimeStampMicroTZVector extends TimeStampVector {
+ private final FieldReader reader;
+ private final String timeZone;
+
+ /**
+ * Instantiate a TimeStampMicroTZVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampMicroTZVector(String name, BufferAllocator allocator, String timeZone) {
+ this(name, FieldType.nullable(new ArrowType.Timestamp(TimeUnit.MICROSECOND, timeZone)), allocator);
+ }
+
+ /**
+ * Instantiate a TimeStampMicroTZVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampMicroTZVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ super(name, fieldType, allocator);
+ ArrowType.Timestamp arrowType = (ArrowType.Timestamp) fieldType.getType();
+ timeZone = arrowType.getTimezone();
+ reader = new TimeStampMicroTZReaderImpl(TimeStampMicroTZVector.this);
+ }
+
+ /**
+ * Instantiate a TimeStampMicroTZVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampMicroTZVector(Field field, BufferAllocator allocator) {
+ super(field, allocator);
+ ArrowType.Timestamp arrowType = (ArrowType.Timestamp) field.getFieldType().getType();
+ timeZone = arrowType.getTimezone();
+ reader = new TimeStampMicroTZReaderImpl(TimeStampMicroTZVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.TIMESTAMPMICROTZ;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableTimeStampMicroTZHolder holder) {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Long getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableTimeStampMicroTZHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, TimeStampMicroTZHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableTimeStampMicroTZHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableTimeStampMicroTZHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, TimeStampMicroTZHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, TimeStampMicroTZHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ TimeStampMicroTZVector to = new TimeStampMicroTZVector(ref,
+ field.getFieldType(), allocator);
+ return new TransferImpl(to);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((TimeStampMicroTZVector) to);
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMicroVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMicroVector.java
new file mode 100644
index 000000000..5cbef8962
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMicroVector.java
@@ -0,0 +1,236 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import java.time.LocalDateTime;
+
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.TimeStampMicroReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.NullableTimeStampMicroHolder;
+import org.apache.arrow.vector.holders.TimeStampMicroHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.DateUtility;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * TimeStampMicroVector implements a fixed width vector (8 bytes) of
+ * timestamp (microsecond resolution) values which could be null. A validity buffer
+ * (bit vector) is maintained to track which elements in the vector are null.
+ */
+public final class TimeStampMicroVector extends TimeStampVector {
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a TimeStampMicroVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampMicroVector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.TIMESTAMPMICRO.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a TimeStampMicroVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampMicroVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ super(name, fieldType, allocator);
+ reader = new TimeStampMicroReaderImpl(TimeStampMicroVector.this);
+ }
+
+ /**
+ * Instantiate a TimeStampMicroVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampMicroVector(Field field, BufferAllocator allocator) {
+ super(field, allocator);
+ reader = new TimeStampMicroReaderImpl(TimeStampMicroVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.TIMESTAMPMICRO;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableTimeStampMicroHolder holder) {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public LocalDateTime getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ final long micros = valueBuffer.getLong((long) index * TYPE_WIDTH);
+ return DateUtility.getLocalDateTimeFromEpochMicro(micros);
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableTimeStampMicroHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, TimeStampMicroHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableTimeStampMicroHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableTimeStampMicroHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, TimeStampMicroHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, TimeStampMicroHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ TimeStampMicroVector to = new TimeStampMicroVector(ref,
+ field.getFieldType(), allocator);
+ return new TransferImpl(to);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((TimeStampMicroVector) to);
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMilliTZVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMilliTZVector.java
new file mode 100644
index 000000000..e66bbf450
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMilliTZVector.java
@@ -0,0 +1,238 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.TimeStampMilliTZReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.NullableTimeStampMilliTZHolder;
+import org.apache.arrow.vector.holders.TimeStampMilliTZHolder;
+import org.apache.arrow.vector.types.TimeUnit;
+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.TransferPair;
+
+/**
+ * TimeStampMilliTZVector implements a fixed width vector (8 bytes) of
+ * timestamp (millisecond resolution) values which could be null. A validity buffer
+ * (bit vector) is maintained to track which elements in the vector are null.
+ */
+public final class TimeStampMilliTZVector extends TimeStampVector {
+ private final FieldReader reader;
+ private final String timeZone;
+
+ /**
+ * Instantiate a TimeStampMilliTZVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampMilliTZVector(String name, BufferAllocator allocator, String timeZone) {
+ this(name, FieldType.nullable(new ArrowType.Timestamp(TimeUnit.MILLISECOND, timeZone)), allocator);
+ }
+
+ /**
+ * Instantiate a TimeStampMilliTZVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampMilliTZVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ super(name, fieldType, allocator);
+ ArrowType.Timestamp arrowType = (ArrowType.Timestamp) fieldType.getType();
+ timeZone = arrowType.getTimezone();
+ reader = new TimeStampMilliTZReaderImpl(TimeStampMilliTZVector.this);
+ }
+
+ /**
+ * Instantiate a TimeStampMilliTZVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampMilliTZVector(Field field, BufferAllocator allocator) {
+ super(field, allocator);
+ ArrowType.Timestamp arrowType = (ArrowType.Timestamp) field.getFieldType().getType();
+ timeZone = arrowType.getTimezone();
+ reader = new TimeStampMilliTZReaderImpl(TimeStampMilliTZVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.TIMESTAMPMILLITZ;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableTimeStampMilliTZHolder holder) {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Long getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableTimeStampMilliTZHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, TimeStampMilliTZHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableTimeStampMilliTZHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableTimeStampMilliTZHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, TimeStampMilliTZHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, TimeStampMilliTZHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ TimeStampMilliTZVector to = new TimeStampMilliTZVector(ref,
+ field.getFieldType(), allocator);
+ return new TransferImpl(to);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((TimeStampMilliTZVector) to);
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMilliVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMilliVector.java
new file mode 100644
index 000000000..8f46f5606
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampMilliVector.java
@@ -0,0 +1,236 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import java.time.LocalDateTime;
+
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.TimeStampMilliReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.NullableTimeStampMilliHolder;
+import org.apache.arrow.vector.holders.TimeStampMilliHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.DateUtility;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * TimeStampMilliVector implements a fixed width vector (8 bytes) of
+ * timestamp (millisecond resolution) values which could be null. A validity buffer
+ * (bit vector) is maintained to track which elements in the vector are null.
+ */
+public final class TimeStampMilliVector extends TimeStampVector {
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a TimeStampMilliVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampMilliVector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.TIMESTAMPMILLI.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a TimeStampMilliVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampMilliVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ super(name, fieldType, allocator);
+ reader = new TimeStampMilliReaderImpl(TimeStampMilliVector.this);
+ }
+
+ /**
+ * Instantiate a TimeStampMilliVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampMilliVector(Field field, BufferAllocator allocator) {
+ super(field, allocator);
+ reader = new TimeStampMilliReaderImpl(TimeStampMilliVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.TIMESTAMPMILLI;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableTimeStampMilliHolder holder) {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public LocalDateTime getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ final long millis = valueBuffer.getLong((long) index * TYPE_WIDTH);
+ return DateUtility.getLocalDateTimeFromEpochMilli(millis);
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableTimeStampMilliHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, TimeStampMilliHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableTimeStampMilliHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableTimeStampMilliHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, TimeStampMilliHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, TimeStampMilliHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ TimeStampMilliVector to = new TimeStampMilliVector(ref,
+ field.getFieldType(), allocator);
+ return new TransferImpl(to);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((TimeStampMilliVector) to);
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampNanoTZVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampNanoTZVector.java
new file mode 100644
index 000000000..a3e582a7c
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampNanoTZVector.java
@@ -0,0 +1,241 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.TimeStampNanoTZReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.NullableTimeStampNanoTZHolder;
+import org.apache.arrow.vector.holders.TimeStampNanoTZHolder;
+import org.apache.arrow.vector.types.TimeUnit;
+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.TransferPair;
+
+/**
+ * TimeStampNanoTZVector implements a fixed width vector (8 bytes) of
+ * timestamp (nanosecond resolution) values which could be null. A validity buffer
+ * (bit vector) is maintained to track which elements in the vector are null.
+ */
+public final class TimeStampNanoTZVector extends TimeStampVector {
+ private final FieldReader reader;
+ private final String timeZone;
+
+ /**
+ * Instantiate a TimeStampNanoTZVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampNanoTZVector(String name, BufferAllocator allocator, String timeZone) {
+ this(name, FieldType.nullable(new ArrowType.Timestamp(TimeUnit.NANOSECOND, timeZone)), allocator);
+ }
+
+ /**
+ * Instantiate a TimeStampNanoTZVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampNanoTZVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ super(name, fieldType, allocator);
+ ArrowType.Timestamp arrowType = (ArrowType.Timestamp) fieldType.getType();
+ timeZone = arrowType.getTimezone();
+ reader = new TimeStampNanoTZReaderImpl(TimeStampNanoTZVector.this);
+ }
+
+ /**
+ * Instantiate a TimeStampNanoTZVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampNanoTZVector(Field field, BufferAllocator allocator) {
+ super(field, allocator);
+ ArrowType.Timestamp arrowType = (ArrowType.Timestamp) field.getFieldType().getType();
+ timeZone = arrowType.getTimezone();
+ reader = new TimeStampNanoTZReaderImpl(TimeStampNanoTZVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.TIMESTAMPNANOTZ;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableTimeStampNanoTZHolder holder) {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Long getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableTimeStampNanoTZHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, TimeStampNanoTZHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableTimeStampNanoTZHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(
+ int index,
+ NullableTimeStampNanoTZHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, TimeStampNanoTZHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, TimeStampNanoTZHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ TimeStampNanoTZVector to = new TimeStampNanoTZVector(ref,
+ field.getFieldType(), allocator);
+ return new TransferImpl(to);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((TimeStampNanoTZVector) to);
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampNanoVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampNanoVector.java
new file mode 100644
index 000000000..7b87dac43
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampNanoVector.java
@@ -0,0 +1,236 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import java.time.LocalDateTime;
+
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.TimeStampNanoReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.NullableTimeStampNanoHolder;
+import org.apache.arrow.vector.holders.TimeStampNanoHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.DateUtility;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * TimeStampNanoVector implements a fixed width vector (8 bytes) of
+ * timestamp (nanosecond resolution) values which could be null. A validity buffer
+ * (bit vector) is maintained to track which elements in the vector are null.
+ */
+public final class TimeStampNanoVector extends TimeStampVector {
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a TimeStampNanoVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampNanoVector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.TIMESTAMPNANO.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a TimeStampNanoVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampNanoVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ super(name, fieldType, allocator);
+ reader = new TimeStampNanoReaderImpl(TimeStampNanoVector.this);
+ }
+
+ /**
+ * Instantiate a TimeStampNanoVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampNanoVector(Field field, BufferAllocator allocator) {
+ super(field, allocator);
+ reader = new TimeStampNanoReaderImpl(TimeStampNanoVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.TIMESTAMPNANO;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableTimeStampNanoHolder holder) {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public LocalDateTime getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ final long nanos = valueBuffer.getLong((long) index * TYPE_WIDTH);
+ return DateUtility.getLocalDateTimeFromEpochNano(nanos);
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableTimeStampNanoHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, TimeStampNanoHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableTimeStampNanoHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableTimeStampNanoHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, TimeStampNanoHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, TimeStampNanoHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ TimeStampNanoVector to = new TimeStampNanoVector(ref,
+ field.getFieldType(), allocator);
+ return new TransferImpl(to);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((TimeStampNanoVector) to);
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampSecTZVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampSecTZVector.java
new file mode 100644
index 000000000..f5a0498fe
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampSecTZVector.java
@@ -0,0 +1,238 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.TimeStampSecTZReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.NullableTimeStampSecTZHolder;
+import org.apache.arrow.vector.holders.TimeStampSecTZHolder;
+import org.apache.arrow.vector.types.TimeUnit;
+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.TransferPair;
+
+/**
+ * TimeStampSecTZVector implements a fixed width vector (8 bytes) of
+ * timestamp (seconds resolution) values which could be null. A validity buffer
+ * (bit vector) is maintained to track which elements in the vector are null.
+ */
+public final class TimeStampSecTZVector extends TimeStampVector {
+ private final FieldReader reader;
+ private final String timeZone;
+
+ /**
+ * Instantiate a TimeStampSecTZVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampSecTZVector(String name, BufferAllocator allocator, String timeZone) {
+ this(name, FieldType.nullable(new ArrowType.Timestamp(TimeUnit.SECOND, timeZone)), allocator);
+ }
+
+ /**
+ * Instantiate a TimeStampSecTZVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampSecTZVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ super(name, fieldType, allocator);
+ ArrowType.Timestamp arrowType = (ArrowType.Timestamp) fieldType.getType();
+ timeZone = arrowType.getTimezone();
+ reader = new TimeStampSecTZReaderImpl(TimeStampSecTZVector.this);
+ }
+
+ /**
+ * Instantiate a TimeStampSecTZVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampSecTZVector(Field field, BufferAllocator allocator) {
+ super(field, allocator);
+ ArrowType.Timestamp arrowType = (ArrowType.Timestamp) field.getFieldType().getType();
+ timeZone = arrowType.getTimezone();
+ reader = new TimeStampSecTZReaderImpl(TimeStampSecTZVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.TIMESTAMPSECTZ;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableTimeStampSecTZHolder holder) {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Long getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableTimeStampSecTZHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, TimeStampSecTZHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableTimeStampSecTZHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableTimeStampSecTZHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, TimeStampSecTZHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, TimeStampSecTZHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ TimeStampSecTZVector to = new TimeStampSecTZVector(ref,
+ field.getFieldType(), allocator);
+ return new TransferImpl(to);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((TimeStampSecTZVector) to);
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampSecVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampSecVector.java
new file mode 100644
index 000000000..f12e19684
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampSecVector.java
@@ -0,0 +1,237 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import java.time.LocalDateTime;
+
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.TimeStampSecReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.NullableTimeStampSecHolder;
+import org.apache.arrow.vector.holders.TimeStampSecHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.DateUtility;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * TimeStampSecVector implements a fixed width vector (8 bytes) of
+ * timestamp (seconds resolution) values which could be null. A validity buffer (bit vector) is
+ * maintained to track which elements in the vector are null.
+ */
+public final class TimeStampSecVector extends TimeStampVector {
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a TimeStampSecVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampSecVector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.TIMESTAMPSEC.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a TimeStampSecVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampSecVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ super(name, fieldType, allocator);
+ reader = new TimeStampSecReaderImpl(TimeStampSecVector.this);
+ }
+
+ /**
+ * Instantiate a TimeStampSecVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampSecVector(Field field, BufferAllocator allocator) {
+ super(field, allocator);
+ reader = new TimeStampSecReaderImpl(TimeStampSecVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.TIMESTAMPSEC;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableTimeStampSecHolder holder) {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public LocalDateTime getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ final long secs = valueBuffer.getLong((long) index * TYPE_WIDTH);
+ final long millis = java.util.concurrent.TimeUnit.SECONDS.toMillis(secs);
+ return DateUtility.getLocalDateTimeFromEpochMilli(millis);
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableTimeStampSecHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, TimeStampSecHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableTimeStampSecHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableTimeStampSecHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, TimeStampSecHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, TimeStampSecHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ TimeStampSecVector to = new TimeStampSecVector(ref,
+ field.getFieldType(), allocator);
+ return new TransferImpl(to);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((TimeStampSecVector) to);
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampVector.java
new file mode 100644
index 000000000..d85a793fb
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TimeStampVector.java
@@ -0,0 +1,197 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * TimeStampVector is an abstract interface for fixed width vector (8 bytes)
+ * of timestamp values which could be null. A validity buffer (bit vector) is
+ * maintained to track which elements in the vector are null.
+ */
+public abstract class TimeStampVector extends BaseFixedWidthVector {
+ public static final byte TYPE_WIDTH = 8;
+
+ /**
+ * Instantiate a TimeStampVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a TimeStampVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TimeStampVector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public long get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ protected void setValue(int index, long value) {
+ valueBuffer.setLong((long) index * TYPE_WIDTH, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, long value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, long)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, long value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void set(int index, int isSet, long value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, long)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void setSafe(int index, int isSet, long value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+ /**
+ * Given a data buffer, get the value stored at a particular position
+ * in the vector.
+ *
+ * This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static long get(final ArrowBuf buffer, final int index) {
+ return buffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * {@link TransferPair} for {@link TimeStampVector}.
+ */
+ public class TransferImpl implements TransferPair {
+ TimeStampVector to;
+
+ public TransferImpl(TimeStampVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public TimeStampVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, TimeStampVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TinyIntVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TinyIntVector.java
new file mode 100644
index 000000000..f08b0e02f
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TinyIntVector.java
@@ -0,0 +1,390 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.TinyIntReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.NullableTinyIntHolder;
+import org.apache.arrow.vector.holders.TinyIntHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * TinyIntVector implements a fixed width (1 bytes) vector of
+ * byte values which could be null. A validity buffer (bit vector) is
+ * maintained to track which elements in the vector are null.
+ */
+public final class TinyIntVector extends BaseFixedWidthVector implements BaseIntVector {
+ public static final byte TYPE_WIDTH = 1;
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a TinyIntVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public TinyIntVector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.TINYINT.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a TinyIntVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TinyIntVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a TinyIntVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public TinyIntVector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ reader = new TinyIntReaderImpl(TinyIntVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.TINYINT;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public byte get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.getByte(index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableTinyIntHolder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getByte(index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Byte getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return valueBuffer.getByte(index * TYPE_WIDTH);
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+ private void setValue(int index, int value) {
+ valueBuffer.setByte(index * TYPE_WIDTH, value);
+ }
+
+ private void setValue(int index, byte value) {
+ valueBuffer.setByte(index * TYPE_WIDTH, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, int value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, byte value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableTinyIntHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, TinyIntHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, int)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, int value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, byte)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, byte value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableTinyIntHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableTinyIntHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, TinyIntHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, TinyIntHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void set(int index, int isSet, byte value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, byte)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void setSafe(int index, int isSet, byte value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+ /**
+ * Given a data buffer, get the value stored at a particular position
+ * in the vector.
+ *
+ * This method should not be used externally.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static byte get(final ArrowBuf buffer, final int index) {
+ return buffer.getByte(index * TYPE_WIDTH);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Construct a TransferPair comprising of this and a target vector of
+ * the same type.
+ *
+ * @param ref name of the target vector
+ * @param allocator allocator for the target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ /**
+ * Construct a TransferPair with a desired target vector of the same type.
+ *
+ * @param to target vector
+ * @return {@link TransferPair}
+ */
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((TinyIntVector) to);
+ }
+
+ @Override
+ public void setWithPossibleTruncate(int index, long value) {
+ this.setSafe(index, (int) value);
+ }
+
+ @Override
+ public void setUnsafeWithPossibleTruncate(int index, long value) {
+ this.set(index, (int) value);
+ }
+
+ @Override
+ public long getValueAsLong(int index) {
+ return this.get(index);
+ }
+
+ private class TransferImpl implements TransferPair {
+ TinyIntVector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new TinyIntVector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(TinyIntVector to) {
+ this.to = to;
+ }
+
+ @Override
+ public TinyIntVector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, TinyIntVector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TypeLayout.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TypeLayout.java
new file mode 100644
index 000000000..60fe2a6a6
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/TypeLayout.java
@@ -0,0 +1,448 @@
+/*
+ * 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 java.util.Arrays.asList;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.arrow.util.Preconditions;
+import org.apache.arrow.vector.BufferLayout.BufferType;
+import org.apache.arrow.vector.types.pojo.ArrowType;
+import org.apache.arrow.vector.types.pojo.ArrowType.ArrowTypeVisitor;
+import org.apache.arrow.vector.types.pojo.ArrowType.Binary;
+import org.apache.arrow.vector.types.pojo.ArrowType.Bool;
+import org.apache.arrow.vector.types.pojo.ArrowType.Date;
+import org.apache.arrow.vector.types.pojo.ArrowType.Decimal;
+import org.apache.arrow.vector.types.pojo.ArrowType.Duration;
+import org.apache.arrow.vector.types.pojo.ArrowType.FixedSizeBinary;
+import org.apache.arrow.vector.types.pojo.ArrowType.FixedSizeList;
+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.LargeUtf8;
+import org.apache.arrow.vector.types.pojo.ArrowType.Map;
+import org.apache.arrow.vector.types.pojo.ArrowType.Null;
+import org.apache.arrow.vector.types.pojo.ArrowType.Struct;
+import org.apache.arrow.vector.types.pojo.ArrowType.Time;
+import org.apache.arrow.vector.types.pojo.ArrowType.Timestamp;
+import org.apache.arrow.vector.types.pojo.ArrowType.Union;
+import org.apache.arrow.vector.types.pojo.ArrowType.Utf8;
+
+/**
+ * The buffer layout of vectors for a given type.
+ * It defines its own buffers followed by the buffers for the children
+ * if it is a nested type (Struct_, List, Union)
+ */
+public class TypeLayout {
+
+ /**
+ * Constructs a new {@TypeLayout} for the given To avoid overflow, the returned type is one step up from the signed
+ * type.
+ *
+ * This method is mainly meant for integration tests.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static short getNoOverflow(final ArrowBuf buffer, final int index) {
+ byte b = buffer.getByte(index * TYPE_WIDTH);
+ return (short) (PROMOTION_MASK & b);
+ }
+
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public byte get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.getByte(index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableUInt1Holder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getByte(index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Byte getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return valueBuffer.getByte(index * TYPE_WIDTH);
+ }
+ }
+
+ /**
+ * Returns the value stored at index without the potential for overflow.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Short getObjectNoOverflow(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return getNoOverflow(valueBuffer, index);
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ private void setValue(int index, int value) {
+ valueBuffer.setByte(index * TYPE_WIDTH, value);
+ }
+
+ private void setValue(int index, byte value) {
+ valueBuffer.setByte(index * TYPE_WIDTH, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, int value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, byte value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableUInt1Holder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, UInt1Holder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, int)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, int value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, byte)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, byte value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableUInt1Holder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableUInt1Holder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, UInt1Holder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, UInt1Holder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Sets the value at index to value isSet > 0, otherwise sets the index position
+ * to invalid/null.
+ */
+ public void set(int index, int isSet, byte value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, byte)} but will reallocate the buffer if index
+ * is larger than current capacity.
+ */
+ public void setSafe(int index, int isSet, byte value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((UInt1Vector) to);
+ }
+
+ @Override
+ public void setWithPossibleTruncate(int index, long value) {
+ this.setSafe(index, (int) value);
+ }
+
+ @Override
+ public void setUnsafeWithPossibleTruncate(int index, long value) {
+ this.set(index, (int) value);
+ }
+
+ @Override
+ public long getValueAsLong(int index) {
+ return this.get(index) & PROMOTION_MASK;
+ }
+
+ @Override
+ public String toString() {
+ return ValueVectorUtility.getToString(this, 0, getValueCount(), (v, i) -> v.getObjectNoOverflow(i));
+ }
+
+ private class TransferImpl implements TransferPair {
+ UInt1Vector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new UInt1Vector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(UInt1Vector to) {
+ this.to = to;
+ }
+
+ @Override
+ public UInt1Vector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, UInt1Vector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/UInt2Vector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/UInt2Vector.java
new file mode 100644
index 000000000..5c29ab6b3
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/UInt2Vector.java
@@ -0,0 +1,346 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.UInt2ReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.NullableUInt2Holder;
+import org.apache.arrow.vector.holders.UInt2Holder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.TransferPair;
+import org.apache.arrow.vector.util.ValueVectorUtility;
+
+/**
+ * UInt2Vector implements a fixed width (2 bytes) vector of
+ * integer values which could be null. A validity buffer (bit vector) is
+ * maintained to track which elements in the vector are null.
+ */
+public final class UInt2Vector extends BaseFixedWidthVector implements BaseIntVector {
+
+ /**
+ * The maximum 16-bit unsigned integer.
+ */
+ public static final char MAX_UINT2 = (char) 0XFFFF;
+
+ public static final byte TYPE_WIDTH = 2;
+ private final FieldReader reader;
+
+ public UInt2Vector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.UINT2.getType()), allocator);
+ }
+
+ public UInt2Vector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ public UInt2Vector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ reader = new UInt2ReaderImpl(UInt2Vector.this);
+ }
+
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.UINT2;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+ /**
+ * Given a data buffer, get the value stored at a particular position
+ * in the vector.
+ *
+ * This method is mainly meant for integration tests.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static char get(final ArrowBuf buffer, final int index) {
+ return buffer.getChar((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public char get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.getChar((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableUInt2Holder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getChar((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Character getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return valueBuffer.getChar((long) index * TYPE_WIDTH);
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ private void setValue(int index, int value) {
+ valueBuffer.setChar((long) index * TYPE_WIDTH, value);
+ }
+
+ private void setValue(int index, char value) {
+ valueBuffer.setChar((long) index * TYPE_WIDTH, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, int value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, char value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableUInt2Holder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, UInt2Holder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, int)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, int value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, char)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, char value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableUInt2Holder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableUInt2Holder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, UInt2Holder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, UInt2Holder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Sets the given index to value is isSet is positive, otherwise sets
+ * the position as invalid/null.
+ */
+ public void set(int index, int isSet, char value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, char)} but will reallocate the buffer if index
+ * is larger than current capacity.
+ */
+ public void setSafe(int index, int isSet, char value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((UInt2Vector) to);
+ }
+
+ @Override
+ public void setWithPossibleTruncate(int index, long value) {
+ this.setSafe(index, (int) value);
+ }
+
+ @Override
+ public void setUnsafeWithPossibleTruncate(int index, long value) {
+ this.set(index, (int) value);
+ }
+
+ @Override
+ public long getValueAsLong(int index) {
+ return this.get(index);
+ }
+
+ @Override
+ public String toString() {
+ return ValueVectorUtility.getToString(this, 0, getValueCount(), (v, i) ->
+ v.isNull(i) ? "null" : Integer.toString(v.get(i) & 0x0000ffff));
+ }
+
+ private class TransferImpl implements TransferPair {
+ UInt2Vector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new UInt2Vector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(UInt2Vector to) {
+ this.to = to;
+ }
+
+ @Override
+ public UInt2Vector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, UInt2Vector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/UInt4Vector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/UInt4Vector.java
new file mode 100644
index 000000000..cc954d67d
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/UInt4Vector.java
@@ -0,0 +1,340 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.UInt4ReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.NullableUInt4Holder;
+import org.apache.arrow.vector.holders.UInt4Holder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.TransferPair;
+import org.apache.arrow.vector.util.ValueVectorUtility;
+
+/**
+ * UInt4Vector implements a fixed width (4 bytes) vector of
+ * integer values which could be null. A validity buffer (bit vector) is
+ * maintained to track which elements in the vector are null.
+ */
+public final class UInt4Vector extends BaseFixedWidthVector implements BaseIntVector {
+
+ /**
+ * The mask to use when promoting the unsigned int value to a long int.
+ */
+ public static final long PROMOTION_MASK = 0x00000000FFFFFFFFL;
+
+ /**
+ * The maximum 32-bit unsigned integer.
+ */
+ public static final int MAX_UINT4 = 0XFFFFFFFF;
+
+ public static final byte TYPE_WIDTH = 4;
+ private final FieldReader reader;
+
+ public UInt4Vector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.UINT4.getType()), allocator);
+ }
+
+ public UInt4Vector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ public UInt4Vector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ reader = new UInt4ReaderImpl(UInt4Vector.this);
+ }
+
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.UINT4;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+ /**
+ * Given a data buffer, get the value stored at a particular position
+ * in the vector.
+ *
+ * To avoid overflow, the returned type is one step up from the signed
+ * type.
+ *
+ * This method is mainly meant for integration tests.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static long getNoOverflow(final ArrowBuf buffer, final int index) {
+ long l = buffer.getInt((long) index * TYPE_WIDTH);
+ return PROMOTION_MASK & l;
+ }
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public int get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableUInt4Holder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Integer getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return valueBuffer.getInt((long) index * TYPE_WIDTH);
+ }
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Long getObjectNoOverflow(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return getNoOverflow(valueBuffer, index);
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ private void setValue(int index, int value) {
+ valueBuffer.setInt((long) index * TYPE_WIDTH, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, int value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableUInt4Holder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, UInt4Holder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, int)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, int value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableUInt4Holder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableUInt4Holder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, UInt4Holder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, UInt4Holder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Sets the value at index to value isSet > 0, otherwise sets the index position
+ * to invalid/null.
+ */
+ public void set(int index, int isSet, int value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, int)} but will reallocate if the buffer if index
+ * is larger than the current capacity.
+ */
+ public void setSafe(int index, int isSet, int value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((UInt4Vector) to);
+ }
+
+ @Override
+ public void setWithPossibleTruncate(int index, long value) {
+ this.setSafe(index, (int) value);
+ }
+
+ @Override
+ public void setUnsafeWithPossibleTruncate(int index, long value) {
+ this.set(index, (int) value);
+ }
+
+ @Override
+ public long getValueAsLong(int index) {
+ return this.get(index) & PROMOTION_MASK;
+ }
+
+ @Override
+ public String toString() {
+ return ValueVectorUtility.getToString(this, 0, getValueCount(), (v, i) -> v.getObjectNoOverflow(i));
+ }
+
+ private class TransferImpl implements TransferPair {
+ UInt4Vector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new UInt4Vector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(UInt4Vector to) {
+ this.to = to;
+ }
+
+ @Override
+ public UInt4Vector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, UInt4Vector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/UInt8Vector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/UInt8Vector.java
new file mode 100644
index 000000000..98eaf25a6
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/UInt8Vector.java
@@ -0,0 +1,336 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import java.math.BigInteger;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.UInt8ReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.NullableUInt8Holder;
+import org.apache.arrow.vector.holders.UInt8Holder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.TransferPair;
+import org.apache.arrow.vector.util.ValueVectorUtility;
+
+/**
+ * UInt8Vector implements a fixed width vector (8 bytes) of
+ * integer values which could be null. A validity buffer (bit vector) is
+ * maintained to track which elements in the vector are null.
+ */
+public final class UInt8Vector extends BaseFixedWidthVector implements BaseIntVector {
+
+ /**
+ * The maximum 64-bit unsigned long integer.
+ */
+ public static final long MAX_UINT8 = 0XFFFFFFFFFFFFFFFFL;
+
+ public static final byte TYPE_WIDTH = 8;
+ private final FieldReader reader;
+
+ public UInt8Vector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.UINT8.getType()), allocator);
+ }
+
+ public UInt8Vector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ public UInt8Vector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ reader = new UInt8ReaderImpl(UInt8Vector.this);
+ }
+
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.UINT8;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+ private static final BigInteger SAFE_CONVERSION_MASK = new BigInteger("ffffffffffffffff", 16);
+
+ /**
+ * Given a data buffer, get the value stored at a particular position
+ * in the vector.
+ *
+ * To avoid overflow, the returned type is one step up from the signed
+ * type.
+ *
+ * This method is mainly meant for integration tests.
+ *
+ * @param buffer data buffer
+ * @param index position of the element.
+ * @return value stored at the index.
+ */
+ public static BigInteger getNoOverflow(final ArrowBuf buffer, final int index) {
+ BigInteger l = BigInteger.valueOf(buffer.getLong((long) index * TYPE_WIDTH));
+ return SAFE_CONVERSION_MASK.and(l);
+ }
+
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public long get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableUInt8Holder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Long getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return valueBuffer.getLong((long) index * TYPE_WIDTH);
+ }
+ }
+
+ /**
+ * Returns the value stored at index without the potential for overflow.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public BigInteger getObjectNoOverflow(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return getNoOverflow(valueBuffer, index);
+ }
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ private void setValue(int index, long value) {
+ valueBuffer.setLong((long) index * TYPE_WIDTH, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, long value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableUInt8Holder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, UInt8Holder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, long)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, long value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableUInt8Holder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableUInt8Holder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, UInt8Holder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, UInt8Holder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /** Sets value at index is isSet is positive otherwise sets the index to invalid/null. */
+ public void set(int index, int isSet, long value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, long)} but will reallocate if index is greater than current capacity.
+ */
+ public void setSafe(int index, int isSet, long value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector transfer |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ @Override
+ public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
+ return new TransferImpl(ref, allocator);
+ }
+
+ @Override
+ public TransferPair makeTransferPair(ValueVector to) {
+ return new TransferImpl((UInt8Vector) to);
+ }
+
+ @Override
+ public void setWithPossibleTruncate(int index, long value) {
+ this.setSafe(index, value);
+ }
+
+ @Override
+ public void setUnsafeWithPossibleTruncate(int index, long value) {
+ this.set(index, value);
+ }
+
+ @Override
+ public long getValueAsLong(int index) {
+ return this.get(index);
+ }
+
+ @Override
+ public String toString() {
+ return ValueVectorUtility.getToString(this, 0, getValueCount(), (v, i) -> v.getObjectNoOverflow(i));
+ }
+
+ private class TransferImpl implements TransferPair {
+ UInt8Vector to;
+
+ public TransferImpl(String ref, BufferAllocator allocator) {
+ to = new UInt8Vector(ref, field.getFieldType(), allocator);
+ }
+
+ public TransferImpl(UInt8Vector to) {
+ this.to = to;
+ }
+
+ @Override
+ public UInt8Vector getTo() {
+ return to;
+ }
+
+ @Override
+ public void transfer() {
+ transferTo(to);
+ }
+
+ @Override
+ public void splitAndTransfer(int startIndex, int length) {
+ splitAndTransferTo(startIndex, length, to);
+ }
+
+ @Override
+ public void copyValueSafe(int fromIndex, int toIndex) {
+ to.copyFromSafe(fromIndex, toIndex, UInt8Vector.this);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/ValueVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/ValueVector.java
new file mode 100644
index 000000000..aa29c2931
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/ValueVector.java
@@ -0,0 +1,285 @@
+/*
+ * 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 java.io.Closeable;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.memory.OutOfMemoryException;
+import org.apache.arrow.memory.util.hash.ArrowBufHasher;
+import org.apache.arrow.vector.compare.VectorVisitor;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.util.CallBack;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * An abstraction that is used to store a sequence of values in an individual column.
+ *
+ * A {@link ValueVector value vector} stores underlying data in-memory in a columnar fashion that is compact and
+ * efficient. The column whose data is stored, is referred by {@link #getField()}.
+ *
+ * It is important that vector is allocated before attempting to read or write.
+ *
+ * There are a few "rules" around vectors:
+ *
+ * Please note that the current implementation doesn't enforce those rules, hence we may find few places that
+ * deviate from these rules (e.g. offset vectors in Variable Length and Repeated vector)
+ *
+ * This interface "should" strive to guarantee this order of operation:
+ * vv
uses
+ * has a positive reference count, throws if this precondition
+ * isn't met. Returns true otherwise.
+ */
+ public static boolean checkBufRefs(final ValueVector vv) {
+ for (final ArrowBuf buffer : vv.getBuffers(false)) {
+ if (buffer.refCnt() <= 0) {
+ throw new IllegalStateException("zero refcount");
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public BufferAllocator getAllocator() {
+ return allocator;
+ }
+
+ void compareTypes(BaseValueVector target, String caller) {
+ if (this.getMinorType() != target.getMinorType()) {
+ throw new UnsupportedOperationException(caller + " should have vectors of exact same type");
+ }
+ }
+
+ protected ArrowBuf releaseBuffer(ArrowBuf buffer) {
+ buffer.getReferenceManager().release();
+ buffer = allocator.getEmpty();
+ return buffer;
+ }
+
+ /* number of bytes for the validity buffer for the given valueCount */
+ protected static int getValidityBufferSizeFromCount(final int valueCount) {
+ return DataSizeRoundingUtil.divideBy8Ceil(valueCount);
+ }
+
+ /* round up bytes for the validity buffer for the given valueCount */
+ private static long roundUp8ForValidityBuffer(long valueCount) {
+ return ((valueCount + 63) >> 6) << 3;
+ }
+
+ long computeCombinedBufferSize(int valueCount, int typeWidth) {
+ Preconditions.checkArgument(valueCount >= 0, "valueCount must be >= 0");
+ Preconditions.checkArgument(typeWidth >= 0, "typeWidth must be >= 0");
+
+ // compute size of validity buffer.
+ long bufferSize = roundUp8ForValidityBuffer(valueCount);
+
+ // add the size of the value buffer.
+ if (typeWidth == 0) {
+ // for boolean type, value-buffer and validity-buffer are of same size.
+ bufferSize *= 2;
+ } else {
+ bufferSize += DataSizeRoundingUtil.roundUpTo8Multiple((long) valueCount * typeWidth);
+ }
+ return allocator.getRoundingPolicy().getRoundedSize(bufferSize);
+ }
+
+ /**
+ * Container for primitive vectors (1 for the validity bit-mask and one to hold the values).
+ */
+ class DataAndValidityBuffers {
+ private ArrowBuf dataBuf;
+ private ArrowBuf validityBuf;
+
+ DataAndValidityBuffers(ArrowBuf dataBuf, ArrowBuf validityBuf) {
+ this.dataBuf = dataBuf;
+ this.validityBuf = validityBuf;
+ }
+
+ ArrowBuf getDataBuf() {
+ return dataBuf;
+ }
+
+ ArrowBuf getValidityBuf() {
+ return validityBuf;
+ }
+ }
+
+ DataAndValidityBuffers allocFixedDataAndValidityBufs(int valueCount, int typeWidth) {
+ long bufferSize = computeCombinedBufferSize(valueCount, typeWidth);
+ assert bufferSize <= MAX_ALLOCATION_SIZE;
+
+ long validityBufferSize;
+ long dataBufferSize;
+ if (typeWidth == 0) {
+ validityBufferSize = dataBufferSize = bufferSize / 2;
+ } else {
+ // Due to the rounding policy, the bufferSize could be greater than the
+ // requested size. Utilize the allocated buffer fully.;
+ long actualCount = (long) ((bufferSize * 8.0) / (8 * typeWidth + 1));
+ do {
+ validityBufferSize = roundUp8ForValidityBuffer(actualCount);
+ dataBufferSize = DataSizeRoundingUtil.roundUpTo8Multiple(actualCount * typeWidth);
+ if (validityBufferSize + dataBufferSize <= bufferSize) {
+ break;
+ }
+ --actualCount;
+ }
+ while (true);
+ }
+
+
+ /* allocate combined buffer */
+ ArrowBuf combinedBuffer = allocator.buffer(bufferSize);
+
+ /* slice into requested lengths */
+ ArrowBuf dataBuf = null;
+ ArrowBuf validityBuf = null;
+ long bufferOffset = 0;
+ for (int numBuffers = 0; numBuffers < 2; ++numBuffers) {
+ long len = (numBuffers == 0 ? dataBufferSize : validityBufferSize);
+ ArrowBuf buf = combinedBuffer.slice(bufferOffset, len);
+ buf.getReferenceManager().retain();
+ buf.readerIndex(0);
+ buf.writerIndex(0);
+
+ bufferOffset += len;
+ if (numBuffers == 0) {
+ dataBuf = buf;
+ } else {
+ validityBuf = buf;
+ }
+ }
+ combinedBuffer.getReferenceManager().release();
+ return new DataAndValidityBuffers(dataBuf, validityBuf);
+ }
+
+ public static ArrowBuf transferBuffer(final ArrowBuf srcBuffer, final BufferAllocator targetAllocator) {
+ final ReferenceManager referenceManager = srcBuffer.getReferenceManager();
+ return referenceManager.transferOwnership(srcBuffer, targetAllocator).getTransferredBuffer();
+ }
+
+ @Override
+ public void copyFrom(int fromIndex, int thisIndex, ValueVector from) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void copyFromSafe(int fromIndex, int thisIndex, ValueVector from) {
+ throw new UnsupportedOperationException();
+ }
+}
+
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BaseVariableWidthVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BaseVariableWidthVector.java
new file mode 100644
index 000000000..866dd9e21
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BaseVariableWidthVector.java
@@ -0,0 +1,1410 @@
+/*
+ * 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.apache.arrow.memory.util.LargeMemoryUtil.capAtMaxInt;
+
+import java.nio.ByteBuffer;
+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.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.compare.VectorVisitor;
+import org.apache.arrow.vector.ipc.message.ArrowFieldNode;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.util.CallBack;
+import org.apache.arrow.vector.util.OversizedAllocationException;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * BaseVariableWidthVector is a base class providing functionality for strings/bytes types.
+ */
+public abstract class BaseVariableWidthVector extends BaseValueVector
+ implements VariableWidthVector, FieldVector, VectorDefinitionSetter {
+ private static final int DEFAULT_RECORD_BYTE_COUNT = 8;
+ private static final int INITIAL_BYTE_COUNT = INITIAL_VALUE_ALLOCATION * DEFAULT_RECORD_BYTE_COUNT;
+ private int lastValueCapacity;
+ private long lastValueAllocationSizeInBytes;
+
+ /* protected members */
+ public static final int OFFSET_WIDTH = 4; /* 4 byte unsigned int to track offsets */
+ protected static final byte[] emptyByteArray = new byte[]{};
+ protected ArrowBuf validityBuffer;
+ protected ArrowBuf valueBuffer;
+ protected ArrowBuf offsetBuffer;
+ protected int valueCount;
+ protected int lastSet;
+ protected final Field field;
+
+ /**
+ * Constructs a new instance.
+ *
+ * @param field The field materialized by this vector.
+ * @param allocator The allocator to use for creating/resizing buffers
+ */
+ public BaseVariableWidthVector(Field field, final BufferAllocator allocator) {
+ super(allocator);
+ this.field = field;
+ lastValueAllocationSizeInBytes = INITIAL_BYTE_COUNT;
+ // -1 because we require one extra slot for the offset array.
+ lastValueCapacity = INITIAL_VALUE_ALLOCATION - 1;
+ valueCount = 0;
+ lastSet = -1;
+ offsetBuffer = allocator.getEmpty();
+ validityBuffer = allocator.getEmpty();
+ valueBuffer = allocator.getEmpty();
+ }
+
+ @Override
+ public String getName() {
+ return field.getName();
+ }
+
+ /* TODO:
+ * see if getNullCount() can be made faster -- O(1)
+ */
+
+ /* TODO:
+ * Once the entire hierarchy has been refactored, move common functions
+ * like getNullCount(), splitAndTransferValidityBuffer to top level
+ * base class BaseValueVector.
+ *
+ * Along with this, some class members (validityBuffer) can also be
+ * abstracted out to top level base class.
+ *
+ * Right now BaseValueVector is the top level base class for other
+ * vector types in ValueVector hierarchy (non-nullable) and those
+ * vectors have not yet been refactored/removed so moving things to
+ * the top class as of now is not a good idea.
+ */
+
+ /**
+ * Get buffer that manages the validity (NULL or NON-NULL nature) of
+ * elements in the vector. Consider it as a buffer for internal bit vector
+ * data structure.
+ * @return buffer
+ */
+ @Override
+ public ArrowBuf getValidityBuffer() {
+ return validityBuffer;
+ }
+
+ /**
+ * Get the buffer that stores the data for elements in the vector.
+ * @return buffer
+ */
+ @Override
+ public ArrowBuf getDataBuffer() {
+ return valueBuffer;
+ }
+
+ /**
+ * buffer that stores the offsets for elements
+ * in the vector. This operation is not supported for fixed-width vectors.
+ * @return buffer
+ */
+ @Override
+ public ArrowBuf getOffsetBuffer() {
+ return offsetBuffer;
+ }
+
+ /**
+ * Get the memory address of buffer that stores the offsets for elements
+ * in the vector.
+ * @return starting address of the buffer
+ */
+ @Override
+ public long getOffsetBufferAddress() {
+ return offsetBuffer.memoryAddress();
+ }
+
+ /**
+ * Get the memory address of buffer that manages the validity
+ * (NULL or NON-NULL nature) of elements in the vector.
+ * @return starting address of the buffer
+ */
+ @Override
+ public long getValidityBufferAddress() {
+ return validityBuffer.memoryAddress();
+ }
+
+ /**
+ * Get the memory address of buffer that stores the data for elements
+ * in the vector.
+ * @return starting address of the buffer
+ */
+ @Override
+ public long getDataBufferAddress() {
+ return valueBuffer.memoryAddress();
+ }
+
+ /**
+ * Sets the desired value capacity for the vector. This function doesn't
+ * allocate any memory for the vector.
+ * @param valueCount desired number of elements in the vector
+ */
+ @Override
+ public void setInitialCapacity(int valueCount) {
+ final long size = (long) valueCount * DEFAULT_RECORD_BYTE_COUNT;
+ checkDataBufferSize(size);
+ computeAndCheckOffsetsBufferSize(valueCount);
+ lastValueAllocationSizeInBytes = (int) size;
+ lastValueCapacity = valueCount;
+ }
+
+ /**
+ * Sets the desired value capacity for the vector. This function doesn't
+ * allocate any memory for the vector.
+ * @param valueCount desired number of elements in the vector
+ * @param density average number of bytes per variable width element
+ */
+ @Override
+ public void setInitialCapacity(int valueCount, double density) {
+ long size = Math.max((long) (valueCount * density), 1L);
+ checkDataBufferSize(size);
+ computeAndCheckOffsetsBufferSize(valueCount);
+ lastValueAllocationSizeInBytes = (int) size;
+ lastValueCapacity = valueCount;
+ }
+
+ /**
+ * Get the density of this ListVector.
+ * @return density
+ */
+ public double getDensity() {
+ if (valueCount == 0) {
+ return 0.0D;
+ }
+ final int startOffset = offsetBuffer.getInt(0);
+ final int endOffset = offsetBuffer.getInt((long) valueCount * OFFSET_WIDTH);
+ final double totalListSize = endOffset - startOffset;
+ return totalListSize / valueCount;
+ }
+
+ /**
+ * Get the current capacity which does not exceed either validity buffer or offset buffer.
+ * Note: Here the `getValueCapacity` has no relationship with the value buffer.
+ * @return number of elements that vector can hold.
+ */
+ @Override
+ public int getValueCapacity() {
+ final int offsetValueCapacity = Math.max(getOffsetBufferValueCapacity() - 1, 0);
+ return Math.min(offsetValueCapacity, getValidityBufferValueCapacity());
+ }
+
+ private int getValidityBufferValueCapacity() {
+ return capAtMaxInt(validityBuffer.capacity() * 8);
+ }
+
+ private int getOffsetBufferValueCapacity() {
+ return capAtMaxInt(offsetBuffer.capacity() / OFFSET_WIDTH);
+ }
+
+ /**
+ * zero out the vector and the data in associated buffers.
+ */
+ public void zeroVector() {
+ initValidityBuffer();
+ initOffsetBuffer();
+ valueBuffer.setZero(0, valueBuffer.capacity());
+ }
+
+ /* zero out the validity buffer */
+ private void initValidityBuffer() {
+ validityBuffer.setZero(0, validityBuffer.capacity());
+ }
+
+ /* zero out the offset buffer */
+ private void initOffsetBuffer() {
+ offsetBuffer.setZero(0, offsetBuffer.capacity());
+ }
+
+ /**
+ * Reset the vector to initial state. Same as {@link #zeroVector()}.
+ * Note that this method doesn't release any memory.
+ */
+ public void reset() {
+ zeroVector();
+ lastSet = -1;
+ valueCount = 0;
+ }
+
+ /**
+ * Close the vector and release the associated buffers.
+ */
+ @Override
+ public void close() {
+ clear();
+ }
+
+ /**
+ * Same as {@link #close()}.
+ */
+ @Override
+ public void clear() {
+ validityBuffer = releaseBuffer(validityBuffer);
+ valueBuffer = releaseBuffer(valueBuffer);
+ offsetBuffer = releaseBuffer(offsetBuffer);
+ lastSet = -1;
+ valueCount = 0;
+ }
+
+ /**
+ * Get the inner vectors.
+ *
+ * @deprecated This API will be removed as the current implementations no longer support inner vectors.
+ *
+ * @return the inner vectors for this field as defined by the TypeLayout
+ */
+ @Deprecated
+ @Override
+ public Listindex
from left-shifted by (8 - offset
).
+ */
+ public static byte getBitsFromNextByte(ArrowBuf data, int index, int offset) {
+ return (byte) ((data.getByte(index) << (8 - offset)));
+ }
+
+ /**
+ * Returns a new buffer if the source validity buffer is either all null or all
+ * not-null, otherwise returns a buffer pointing to the same memory as source.
+ *
+ * @param fieldNode The fieldNode containing the null count
+ * @param sourceValidityBuffer The source validity buffer that will have its
+ * position copied if there is a mix of null and non-null values
+ * @param allocator The allocator to use for creating a new buffer if necessary.
+ * @return A new buffer that is either allocated or points to the same memory as sourceValidityBuffer.
+ */
+ public static ArrowBuf loadValidityBuffer(final ArrowFieldNode fieldNode,
+ final ArrowBuf sourceValidityBuffer,
+ final BufferAllocator allocator) {
+ final int valueCount = fieldNode.getLength();
+ ArrowBuf newBuffer = null;
+ /* either all NULLs or all non-NULLs */
+ if (fieldNode.getNullCount() == 0 || fieldNode.getNullCount() == valueCount) {
+ newBuffer = allocator.buffer(getValidityBufferSize(valueCount));
+ newBuffer.setZero(0, newBuffer.capacity());
+ if (fieldNode.getNullCount() != 0) {
+ /* all NULLs */
+ return newBuffer;
+ }
+ /* all non-NULLs */
+ int fullBytesCount = valueCount / 8;
+ newBuffer.setOne(0, fullBytesCount);
+ int remainder = valueCount % 8;
+ if (remainder > 0) {
+ byte bitMask = (byte) (0xFFL >>> ((8 - remainder) & 7));
+ newBuffer.setByte(fullBytesCount, bitMask);
+ }
+ } else {
+ /* mixed byte pattern -- create another ArrowBuf associated with the
+ * target allocator
+ */
+ newBuffer = sourceValidityBuffer.getReferenceManager().retain(sourceValidityBuffer, allocator);
+ }
+
+ return newBuffer;
+ }
+
+ /**
+ * Set the byte of the given index in the data buffer by applying a bit mask to
+ * the current byte at that index.
+ *
+ * @param data buffer to set
+ * @param byteIndex byteIndex within the buffer
+ * @param bitMask bit mask to be set
+ */
+ static void setBitMaskedByte(ArrowBuf data, int byteIndex, byte bitMask) {
+ byte currentByte = data.getByte(byteIndex);
+ currentByte |= bitMask;
+ data.setByte(byteIndex, currentByte);
+ }
+
+ /**
+ * Concat two validity buffers.
+ * @param input1 the first validity buffer.
+ * @param numBits1 the number of bits in the first validity buffer.
+ * @param input2 the second validity buffer.
+ * @param numBits2 the number of bits in the second validity buffer.
+ * @param output the output validity buffer. It can be the same one as the first input.
+ * The caller must make sure the output buffer has enough capacity.
+ */
+ public static void concatBits(ArrowBuf input1, int numBits1, ArrowBuf input2, int numBits2, ArrowBuf output) {
+ int numBytes1 = DataSizeRoundingUtil.divideBy8Ceil(numBits1);
+ int numBytes2 = DataSizeRoundingUtil.divideBy8Ceil(numBits2);
+ int numBytesOut = DataSizeRoundingUtil.divideBy8Ceil(numBits1 + numBits2);
+
+ if (BoundsChecking.BOUNDS_CHECKING_ENABLED) {
+ output.checkBytes(0, numBytesOut);
+ }
+
+ // copy the first bit set
+ if (input1 != output) {
+ PlatformDependent.copyMemory(input1.memoryAddress(), output.memoryAddress(), numBytes1);
+ }
+
+ if (bitIndex(numBits1) == 0) {
+ // The number of bits for the first bit set is a multiple of 8, so the boundary is at byte boundary.
+ // For this case, we have a shortcut to copy all bytes from the second set after the byte boundary.
+ PlatformDependent.copyMemory(input2.memoryAddress(), output.memoryAddress() + numBytes1, numBytes2);
+ return;
+ }
+
+ // the number of bits to fill a full byte after the first input is processed
+ int numBitsToFill = 8 - bitIndex(numBits1);
+
+ // mask to clear high bits
+ int mask = (1 << (8 - numBitsToFill)) - 1;
+
+ int numFullBytes = numBits2 / 8;
+
+ int prevByte = output.getByte(numBytes1 - 1) & mask;
+ for (int i = 0; i < numFullBytes; i++) {
+ int curByte = input2.getByte(i) & 0xff;
+
+ // first fill the bits to a full byte
+ int byteToFill = (curByte << (8 - numBitsToFill)) & 0xff;
+ output.setByte(numBytes1 + i - 1, byteToFill | prevByte);
+
+ // fill remaining bits in the current byte
+ // note that it is also the previous byte for the next iteration
+ prevByte = curByte >>> numBitsToFill;
+ }
+
+ int lastOutputByte = prevByte;
+
+ // the number of extra bits for the second input, relative to full bytes
+ int numTrailingBits = bitIndex(numBits2);
+
+ if (numTrailingBits == 0) {
+ output.setByte(numBytes1 + numFullBytes - 1, lastOutputByte);
+ return;
+ }
+
+ // process remaining bits from input2
+ int remByte = input2.getByte(numBytes2 - 1) & 0xff;
+
+ int byteToFill = remByte << (8 - numBitsToFill);
+ lastOutputByte |= byteToFill;
+
+ output.setByte(numBytes1 + numFullBytes - 1, lastOutputByte);
+
+ if (numTrailingBits > numBitsToFill) {
+ // clear all bits for the last byte before writing
+ output.setByte(numBytes1 + numFullBytes, 0);
+
+ // some remaining bits cannot be filled in the previous byte
+ int leftByte = remByte >>> numBitsToFill;
+ output.setByte(numBytes1 + numFullBytes, leftByte);
+ }
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BufferBacked.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BufferBacked.java
new file mode 100644
index 000000000..ccba5b26c
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BufferBacked.java
@@ -0,0 +1,31 @@
+/*
+ * 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 org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.vector.ipc.message.ArrowFieldNode;
+
+/**
+ * Content is backed by a buffer and can be loaded/unloaded.
+ */
+public interface BufferBacked {
+
+ void load(ArrowFieldNode fieldNode, ArrowBuf data);
+
+ ArrowBuf unLoad();
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BufferLayout.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BufferLayout.java
new file mode 100644
index 000000000..09c874e39
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/BufferLayout.java
@@ -0,0 +1,153 @@
+/*
+ * 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 org.apache.arrow.util.Preconditions;
+
+/**
+ * Metadata class that captures the "type" of an Arrow buffer.
+ * (e.g. data buffers, offset buffers for variable width types and validity
+ * buffers).
+ */
+public class BufferLayout {
+
+ /**
+ * Enumeration of the different logical types a buffer can have.
+ */
+ public enum BufferType {
+ DATA("DATA"),
+ OFFSET("OFFSET"),
+ VALIDITY("VALIDITY"),
+ TYPE("TYPE_ID");
+
+ private final String name;
+
+ BufferType(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+ }
+
+ private static final BufferLayout VALIDITY_BUFFER = new BufferLayout(BufferType.VALIDITY, 1);
+ private static final BufferLayout OFFSET_BUFFER = new BufferLayout(BufferType.OFFSET, 32);
+ private static final BufferLayout LARGE_OFFSET_BUFFER = new BufferLayout(BufferType.OFFSET, 64);
+ private static final BufferLayout TYPE_BUFFER = new BufferLayout(BufferType.TYPE, 32);
+ private static final BufferLayout BIT_BUFFER = new BufferLayout(BufferType.DATA, 1);
+ private static final BufferLayout VALUES_256 = new BufferLayout(BufferType.DATA, 256);
+ private static final BufferLayout VALUES_128 = new BufferLayout(BufferType.DATA, 128);
+ private static final BufferLayout VALUES_64 = new BufferLayout(BufferType.DATA, 64);
+ 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);
+
+ public static BufferLayout typeBuffer() {
+ return TYPE_BUFFER;
+ }
+
+ public static BufferLayout offsetBuffer() {
+ return OFFSET_BUFFER;
+ }
+
+ public static BufferLayout largeOffsetBuffer() {
+ return LARGE_OFFSET_BUFFER;
+ }
+
+ /**
+ * Returns a databuffer for the given bitwidth. Only supports powers of two between 8 and 128
+ * inclusive.
+ */
+ public static BufferLayout dataBuffer(int typeBitWidth) {
+ switch (typeBitWidth) {
+ case 8:
+ return VALUES_8;
+ case 16:
+ return VALUES_16;
+ case 32:
+ return VALUES_32;
+ case 64:
+ return VALUES_64;
+ case 128:
+ return VALUES_128;
+ case 256:
+ return VALUES_256;
+ default:
+ throw new IllegalArgumentException("only 8, 16, 32, 64, 128, or 256 bits supported");
+ }
+ }
+
+ public static BufferLayout booleanVector() {
+ return BIT_BUFFER;
+ }
+
+ public static BufferLayout validityVector() {
+ return VALIDITY_BUFFER;
+ }
+
+ public static BufferLayout byteVector() {
+ return dataBuffer(8);
+ }
+
+ private final short typeBitWidth;
+
+ private final BufferType type;
+
+ BufferLayout(BufferType type, int typeBitWidth) {
+ super();
+ this.type = Preconditions.checkNotNull(type);
+ this.typeBitWidth = (short) typeBitWidth;
+ if (typeBitWidth <= 0) {
+ throw new IllegalArgumentException("bitWidth invalid: " + typeBitWidth);
+ }
+ }
+
+ public int getTypeBitWidth() {
+ return typeBitWidth;
+ }
+
+ public BufferType getType() {
+ return type;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s(%s)", type, typeBitWidth);
+ }
+
+ @Override
+ public int hashCode() {
+ return 31 * (31 + type.hashCode()) + typeBitWidth;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ BufferLayout other = (BufferLayout) obj;
+ return type.equals(other.type) && (typeBitWidth == other.typeBitWidth);
+ }
+}
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/DateDayVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/DateDayVector.java
new file mode 100644
index 000000000..3e8826845
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/DateDayVector.java
@@ -0,0 +1,347 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.DateDayReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.DateDayHolder;
+import org.apache.arrow.vector.holders.NullableDateDayHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * DateDayVector implements a fixed width (4 bytes) vector of
+ * date values which could be null. A validity buffer (bit vector) is
+ * maintained to track which elements in the vector are null.
+ */
+public final class DateDayVector extends BaseFixedWidthVector {
+
+ public static final byte TYPE_WIDTH = 4;
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a DateDayVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public DateDayVector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.DATEDAY.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a DateDayVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public DateDayVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a DateDayVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public DateDayVector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ reader = new DateDayReaderImpl(DateDayVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.DATEDAY;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public int get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableDateDayHolder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Integer getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return valueBuffer.getInt((long) index * TYPE_WIDTH);
+ }
+ }
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ private void setValue(int index, int value) {
+ valueBuffer.setInt((long) index * TYPE_WIDTH, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, int value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableDateDayHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, DateDayHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, int)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, int value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableDateDayHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableDateDayHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, DateDayHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, DateDayHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void set(int index, int isSet, int value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, int)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void setSafe(int index, int isSet, int value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+ /**
+ * Given a data buffer, get the value stored at a particular position
+ * in the vector.
+ *
+ * index
+ * is larger than capacity.
+ */
+ public void setSafe(int index, byte[] value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Sets the value if isSet is positive, otherwise sets the index to null/invalid.
+ */
+ public void set(int index, int isSet, byte[] value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ public void setSafe(int index, int isSet, byte[] value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param buffer ArrowBuf containing binary value.
+ */
+ public void set(int index, ArrowBuf buffer) {
+ assert index >= 0;
+ assert byteWidth <= buffer.capacity();
+ BitVectorHelper.setBit(validityBuffer, index);
+ valueBuffer.setBytes((long) index * byteWidth, buffer, 0, byteWidth);
+ }
+
+ /**
+ * Same as {@link #set(int, ArrowBuf)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param buffer ArrowBuf containing binary value.
+ */
+ public void setSafe(int index, ArrowBuf buffer) {
+ handleSafe(index);
+ set(index, buffer);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param buffer ArrowBuf containing binary value.
+ */
+ public void set(int index, int isSet, ArrowBuf buffer) {
+ if (isSet > 0) {
+ set(index, buffer);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, ArrowBuf)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param buffer ArrowBuf containing binary value.
+ */
+ public void setSafe(int index, int isSet, ArrowBuf buffer) {
+ handleSafe(index);
+ set(index, isSet, buffer);
+ }
+
+ /**
+ * Set the variable length element at the specified index to the data
+ * buffer supplied in the holder.
+ *
+ * @param index position of the element to set
+ * @param holder holder that carries data buffer.
+ */
+ public void set(int index, FixedSizeBinaryHolder holder) {
+ assert holder.byteWidth == byteWidth;
+ set(index, holder.buffer);
+ }
+
+ /**
+ * Same as {@link #set(int, FixedSizeBinaryHolder)} except that it handles the
+ * case where index and length of new element are beyond the existing
+ * capacity of the vector.
+ *
+ * @param index position of the element to set
+ * @param holder holder that carries data buffer.
+ */
+ public void setSafe(int index, FixedSizeBinaryHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Set the variable length element at the specified index to the data
+ * buffer supplied in the holder.
+ *
+ * @param index position of the element to set
+ * @param holder holder that carries data buffer.
+ */
+ public void set(int index, NullableFixedSizeBinaryHolder holder) {
+ assert holder.byteWidth == byteWidth;
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException("holder has a negative isSet value");
+ } else if (holder.isSet > 0) {
+ set(index, holder.buffer);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, NullableFixedSizeBinaryHolder)} except that it handles the
+ * case where index and length of new element are beyond the existing
+ * capacity of the vector.
+ *
+ * @param index position of the element to set
+ * @param holder holder that carries data buffer.
+ */
+ public void setSafe(int index, NullableFixedSizeBinaryHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Given a data buffer, get the value stored at a particular position
+ * in the vector.
+ *
+ * vector
with valueCount
random values. */
+ public static void generateTestData(final ValueVector vector, final int valueCount) {
+ if (vector instanceof IntVector) {
+ writeIntData((IntVector) vector, valueCount);
+ } else if (vector instanceof DecimalVector) {
+ writeDecimalData((DecimalVector) vector, valueCount);
+ } else if (vector instanceof BitVector) {
+ writeBooleanData((BitVector) vector, valueCount);
+ } else if (vector instanceof VarCharVector) {
+ writeVarCharData((VarCharVector) vector, valueCount);
+ } else if (vector instanceof VarBinaryVector) {
+ writeVarBinaryData((VarBinaryVector) vector, valueCount);
+ } else if (vector instanceof BigIntVector) {
+ writeBigIntData((BigIntVector) vector, valueCount);
+ } else if (vector instanceof Float4Vector) {
+ writeFloatData((Float4Vector) vector, valueCount);
+ } else if (vector instanceof Float8Vector) {
+ writeDoubleData((Float8Vector) vector, valueCount);
+ } else if (vector instanceof DateDayVector) {
+ writeDateDayData((DateDayVector) vector, valueCount);
+ } else if (vector instanceof DateMilliVector) {
+ writeDateMilliData((DateMilliVector) vector, valueCount);
+ } else if (vector instanceof IntervalDayVector) {
+ writeIntervalDayData((IntervalDayVector) vector, valueCount);
+ } else if (vector instanceof IntervalYearVector) {
+ writeIntervalYearData((IntervalYearVector) vector, valueCount);
+ } else if (vector instanceof SmallIntVector) {
+ writeSmallIntData((SmallIntVector) vector, valueCount);
+ } else if (vector instanceof TinyIntVector) {
+ writeTinyIntData((TinyIntVector) vector, valueCount);
+ } else if (vector instanceof TimeMicroVector) {
+ writeTimeMicroData((TimeMicroVector) vector, valueCount);
+ } else if (vector instanceof TimeMilliVector) {
+ writeTimeMilliData((TimeMilliVector) vector, valueCount);
+ } else if (vector instanceof TimeNanoVector) {
+ writeTimeNanoData((TimeNanoVector) vector, valueCount);
+ } else if (vector instanceof TimeSecVector) {
+ writeTimeSecData((TimeSecVector) vector, valueCount);
+ } else if (vector instanceof TimeStampSecVector) {
+ writeTimeStampData((TimeStampSecVector) vector, valueCount);
+ } else if (vector instanceof TimeStampMicroVector) {
+ writeTimeStampData((TimeStampMicroVector) vector, valueCount);
+ } else if (vector instanceof TimeStampMilliVector) {
+ writeTimeStampData((TimeStampMilliVector) vector, valueCount);
+ } else if (vector instanceof TimeStampNanoVector) {
+ writeTimeStampData((TimeStampNanoVector) vector, valueCount);
+ } else if (vector instanceof TimeStampSecTZVector) {
+ writeTimeStampData((TimeStampSecTZVector) vector, valueCount);
+ } else if (vector instanceof TimeStampMicroTZVector) {
+ writeTimeStampData((TimeStampMicroTZVector) vector, valueCount);
+ } else if (vector instanceof TimeStampMilliTZVector) {
+ writeTimeStampData((TimeStampMilliTZVector) vector, valueCount);
+ } else if (vector instanceof TimeStampNanoTZVector) {
+ writeTimeStampData((TimeStampNanoTZVector) vector, valueCount);
+ }
+ }
+
+ private static void writeTimeStampData(TimeStampVector vector, int valueCount) {
+ final long even = 100000;
+ final long odd = 200000;
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+
+ private static void writeDecimalData(DecimalVector vector, int valueCount) {
+ final BigDecimal even = new BigDecimal(0.0543278923);
+ final BigDecimal odd = new BigDecimal(2.0543278923);
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+
+ private static void writeIntData(IntVector vector, int valueCount) {
+ final int even = 1000;
+ final int odd = 2000;
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+
+ private static void writeBooleanData(BitVector vector, int valueCount) {
+ final int even = 0;
+ final int odd = 1;
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+
+ private static void writeIntervalYearData(IntervalYearVector vector, int valueCount) {
+ final int even = 1;
+ final int odd = 2;
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+
+ private static void writeIntervalDayData(IntervalDayVector vector, int valueCount) {
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, 1, 50);
+ } else {
+ vector.setSafe(i, 2, 100);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+
+ private static void writeTimeSecData(TimeSecVector vector, int valueCount) {
+ final int even = 500;
+ final int odd = 900;
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+
+ private static void writeTimeMilliData(TimeMilliVector vector, int valueCount) {
+ final int even = 1000;
+ final int odd = 2000;
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+
+ private static void writeTimeMicroData(TimeMicroVector vector, int valueCount) {
+ final long even = 1000000000;
+ final long odd = 2000000000;
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+
+ }
+
+ private static void writeTimeNanoData(TimeNanoVector vector, int valueCount) {
+ final long even = 1000000000;
+ final long odd = 2000000000;
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+
+ private static void writeDateDayData(DateDayVector vector, int valueCount) {
+ final int even = 1000;
+ final int odd = 2000;
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+
+ private static void writeDateMilliData(DateMilliVector vector, int valueCount) {
+ final long even = 1000000000;
+ final long odd = 2000000000;
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+
+ private static void writeSmallIntData(SmallIntVector vector, int valueCount) {
+ final short even = 10;
+ final short odd = 20;
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+
+ private static void writeTinyIntData(TinyIntVector vector, int valueCount) {
+ final byte even = 1;
+ final byte odd = 2;
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+
+ private static void writeBigIntData(BigIntVector vector, int valueCount) {
+ final long even = 1000000000;
+ final long odd = 2000000000;
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+
+ private static void writeFloatData(Float4Vector vector, int valueCount) {
+ final float even = 20.3f;
+ final float odd = 40.2f;
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+
+ private static void writeDoubleData(Float8Vector vector, int valueCount) {
+ final double even = 20.2373;
+ final double odd = 40.2378;
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+
+ private static void writeVarBinaryData(VarBinaryVector vector, int valueCount) {
+ Charset utf8Charset = Charset.forName("UTF-8");
+ final byte[] even = "AAAAA1".getBytes(utf8Charset);
+ final byte[] odd = "BBBBBBBBB2".getBytes(utf8Charset);
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+
+ private static void writeVarCharData(VarCharVector vector, int valueCount) {
+ Charset utf8Charset = Charset.forName("UTF-8");
+ final byte[] even = "AAAAA1".getBytes(utf8Charset);
+ final byte[] odd = "BBBBBBBBB2".getBytes(utf8Charset);
+ for (int i = 0; i < valueCount; i++) {
+ if (i % 2 == 0) {
+ vector.setSafe(i, even);
+ } else {
+ vector.setSafe(i, odd);
+ }
+ }
+ vector.setValueCount(valueCount);
+ }
+}
+
diff --git a/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/IntVector.java b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/IntVector.java
new file mode 100644
index 000000000..e591ec1e8
--- /dev/null
+++ b/src/arrow/java/vector/src/main/java/org/apache/arrow/vector/IntVector.java
@@ -0,0 +1,362 @@
+/*
+ * 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.apache.arrow.vector.NullCheckingForGet.NULL_CHECKING_ENABLED;
+
+import org.apache.arrow.memory.ArrowBuf;
+import org.apache.arrow.memory.BufferAllocator;
+import org.apache.arrow.vector.complex.impl.IntReaderImpl;
+import org.apache.arrow.vector.complex.reader.FieldReader;
+import org.apache.arrow.vector.holders.IntHolder;
+import org.apache.arrow.vector.holders.NullableIntHolder;
+import org.apache.arrow.vector.types.Types.MinorType;
+import org.apache.arrow.vector.types.pojo.Field;
+import org.apache.arrow.vector.types.pojo.FieldType;
+import org.apache.arrow.vector.util.TransferPair;
+
+/**
+ * IntVector implements a fixed width (4 bytes) vector of
+ * integer values which could be null. A validity buffer (bit vector) is
+ * maintained to track which elements in the vector are null.
+ */
+public final class IntVector extends BaseFixedWidthVector implements BaseIntVector {
+ public static final byte TYPE_WIDTH = 4;
+ private final FieldReader reader;
+
+ /**
+ * Instantiate a IntVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param allocator allocator for memory management.
+ */
+ public IntVector(String name, BufferAllocator allocator) {
+ this(name, FieldType.nullable(MinorType.INT.getType()), allocator);
+ }
+
+ /**
+ * Instantiate a IntVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param name name of the vector
+ * @param fieldType type of Field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public IntVector(String name, FieldType fieldType, BufferAllocator allocator) {
+ this(new Field(name, fieldType, null), allocator);
+ }
+
+ /**
+ * Instantiate a IntVector. This doesn't allocate any memory for
+ * the data in vector.
+ *
+ * @param field field materialized by this vector
+ * @param allocator allocator for memory management.
+ */
+ public IntVector(Field field, BufferAllocator allocator) {
+ super(field, allocator, TYPE_WIDTH);
+ reader = new IntReaderImpl(IntVector.this);
+ }
+
+ /**
+ * Get a reader that supports reading values from this vector.
+ *
+ * @return Field Reader for this vector
+ */
+ @Override
+ public FieldReader getReader() {
+ return reader;
+ }
+
+ /**
+ * Get minor type for this vector. The vector holds values belonging
+ * to a particular type.
+ *
+ * @return {@link org.apache.arrow.vector.types.Types.MinorType}
+ */
+ @Override
+ public MinorType getMinorType() {
+ return MinorType.INT;
+ }
+
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value retrieval methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ /**
+ * Get the element at the given index from the vector.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public int get(int index) throws IllegalStateException {
+ if (NULL_CHECKING_ENABLED && isSet(index) == 0) {
+ throw new IllegalStateException("Value at index is null");
+ }
+ return valueBuffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Get the element at the given index from the vector and
+ * sets the state in holder. If element at given index
+ * is null, holder.isSet will be zero.
+ *
+ * @param index position of element
+ */
+ public void get(int index, NullableIntHolder holder) {
+ if (isSet(index) == 0) {
+ holder.isSet = 0;
+ return;
+ }
+ holder.isSet = 1;
+ holder.value = valueBuffer.getInt((long) index * TYPE_WIDTH);
+ }
+
+ /**
+ * Same as {@link #get(int)}.
+ *
+ * @param index position of element
+ * @return element at given index
+ */
+ public Integer getObject(int index) {
+ if (isSet(index) == 0) {
+ return null;
+ } else {
+ return valueBuffer.getInt((long) index * TYPE_WIDTH);
+ }
+ }
+
+ /*----------------------------------------------------------------*
+ | |
+ | vector value setter methods |
+ | |
+ *----------------------------------------------------------------*/
+
+
+ private void setValue(int index, int value) {
+ valueBuffer.setInt((long) index * TYPE_WIDTH, value);
+ }
+
+ /**
+ * Set the element at the given index to the given value.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void set(int index, int value) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, value);
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ * If the value in holder is not indicated as set, element in the
+ * at the given index will be null.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void set(int index, NullableIntHolder holder) throws IllegalArgumentException {
+ if (holder.isSet < 0) {
+ throw new IllegalArgumentException();
+ } else if (holder.isSet > 0) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Set the element at the given index to the value set in data holder.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void set(int index, IntHolder holder) {
+ BitVectorHelper.setBit(validityBuffer, index);
+ setValue(index, holder.value);
+ }
+
+ /**
+ * Same as {@link #set(int, int)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param value value of element
+ */
+ public void setSafe(int index, int value) {
+ handleSafe(index);
+ set(index, value);
+ }
+
+ /**
+ * Same as {@link #set(int, NullableIntHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder nullable data holder for value of element
+ */
+ public void setSafe(int index, NullableIntHolder holder) throws IllegalArgumentException {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Same as {@link #set(int, IntHolder)} except that it handles the
+ * case when index is greater than or equal to existing
+ * value capacity {@link #getValueCapacity()}.
+ *
+ * @param index position of element
+ * @param holder data holder for value of element
+ */
+ public void setSafe(int index, IntHolder holder) {
+ handleSafe(index);
+ set(index, holder);
+ }
+
+ /**
+ * Store the given value at a particular position in the vector. isSet indicates
+ * whether the value is NULL or not.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void set(int index, int isSet, int value) {
+ if (isSet > 0) {
+ set(index, value);
+ } else {
+ BitVectorHelper.unsetBit(validityBuffer, index);
+ }
+ }
+
+ /**
+ * Same as {@link #set(int, int, int)} except that it handles the case
+ * when index is greater than or equal to current value capacity of the
+ * vector.
+ *
+ * @param index position of the new value
+ * @param isSet 0 for NULL value, 1 otherwise
+ * @param value element value
+ */
+ public void setSafe(int index, int isSet, int value) {
+ handleSafe(index);
+ set(index, isSet, value);
+ }
+
+ /**
+ * Given a data buffer, get the value stored at a particular position
+ * in the vector.
+ *
+ * {@code
+ *
+ * Float8Vector vector = ...
+ *
+ * public void test() {
+ * sum = 0;
+ * for (int i = 0; i < 1024; i++) {
+ * vector.set(i, i + 10.0);
+ * safeSum += vector.get(i);
+ * }
+ * }
+ *
+ * }
+ * arrowType
.
+ */
+ public static TypeLayout getTypeLayout(final ArrowType arrowType) {
+ TypeLayout layout = arrowType.accept(new ArrowTypeVisitorarrowType
.
+ */
+ public static int getTypeBufferCount(final ArrowType arrowType) {
+ return arrowType.accept(new ArrowTypeVisitor
+ *
+ *
+ *
+ * allocate > mutate > setvaluecount > access > clear (or allocate to start the process over).
+ *
+ */
+public interface ValueVector extends Closeable, Iterablefields
.
+ */
+ public VectorSchemaRoot(Listfields
.
+ * @param rowCount The number of rows contained.
+ */
+ public VectorSchemaRoot(List