codegen.templates.UnionVector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of arrow-vector Show documentation
Show all versions of arrow-vector Show documentation
An off-heap reference implementation for Arrow columnar data format.
The newest version!
/*
* 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.
*/
import io.netty.buffer.ArrowBuf;
import org.apache.arrow.memory.BufferAllocator;
import org.apache.arrow.memory.ReferenceManager;
import org.apache.arrow.memory.util.hash.ArrowBufHasher;
import org.apache.arrow.util.Preconditions;
import org.apache.arrow.vector.FieldVector;
import org.apache.arrow.vector.ValueVector;
import org.apache.arrow.vector.complex.StructVector;
import org.apache.arrow.vector.compare.VectorVisitor;
import org.apache.arrow.vector.types.UnionMode;
import org.apache.arrow.vector.compare.RangeEqualsVisitor;
import org.apache.arrow.vector.types.pojo.ArrowType;
import org.apache.arrow.vector.types.pojo.FieldType;
import org.apache.arrow.vector.util.CallBack;
import org.apache.arrow.vector.util.ValueVectorUtility;
<@pp.dropOutputFile />
<@pp.changeOutputFile name="/org/apache/arrow/vector/complex/UnionVector.java" />
<#include "/@includes/license.ftl" />
package org.apache.arrow.vector.complex;
<#include "/@includes/vv_imports.ftl" />
import io.netty.buffer.ArrowBuf;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import org.apache.arrow.vector.compare.VectorVisitor;
import org.apache.arrow.vector.complex.impl.ComplexCopier;
import org.apache.arrow.vector.util.CallBack;
import org.apache.arrow.vector.util.ValueVectorUtility;
import org.apache.arrow.vector.ipc.message.ArrowFieldNode;
import org.apache.arrow.memory.BaseAllocator;
import org.apache.arrow.memory.util.ArrowBufPointer;
import org.apache.arrow.memory.util.hash.ArrowBufHasher;
import org.apache.arrow.vector.BaseValueVector;
import org.apache.arrow.vector.util.OversizedAllocationException;
import org.apache.arrow.util.Preconditions;
import static org.apache.arrow.vector.types.UnionMode.Sparse;
import static org.apache.arrow.memory.util.LargeMemoryUtil.checkedCastToInt;
import static org.apache.arrow.memory.util.LargeMemoryUtil.capAtMaxInt;
/*
* This class is generated using freemarker and the ${.template_name} template.
*/
@SuppressWarnings("unused")
/**
* A vector which can hold values of different types. It does so by using a StructVector which contains a vector for each
* primitive type that is stored. StructVector is used in order to take advantage of its serialization/deserialization methods,
* as well as the addOrGet method.
*
* For performance reasons, UnionVector stores a cached reference to each subtype vector, to avoid having to do the struct lookup
* each time the vector is accessed.
* Source code generated using FreeMarker template ${.template_name}
*/
public class UnionVector implements FieldVector {
private String name;
private BufferAllocator allocator;
int valueCount;
NonNullableStructVector internalStruct;
protected ArrowBuf typeBuffer;
private StructVector structVector;
private ListVector listVector;
private FieldReader reader;
private int singleType = 0;
private ValueVector singleVector;
private final CallBack callBack;
private int typeBufferAllocationSizeInBytes;
private final FieldType fieldType;
private static final byte TYPE_WIDTH = 1;
private static final FieldType INTERNAL_STRUCT_TYPE = new FieldType(false /*nullable*/,
ArrowType.Struct.INSTANCE, null /*dictionary*/, null /*metadata*/);
public static UnionVector empty(String name, BufferAllocator allocator) {
FieldType fieldType = FieldType.nullable(new ArrowType.Union(
UnionMode.Sparse, null));
return new UnionVector(name, allocator, fieldType, null);
}
@Deprecated
public UnionVector(String name, BufferAllocator allocator, CallBack callBack) {
this(name, allocator, null, callBack);
}
public UnionVector(String name, BufferAllocator allocator, FieldType fieldType, CallBack callBack) {
this.name = name;
this.allocator = allocator;
this.fieldType = fieldType;
this.internalStruct = new NonNullableStructVector("internal", allocator, INTERNAL_STRUCT_TYPE,
callBack);
this.typeBuffer = allocator.getEmpty();
this.callBack = callBack;
this.typeBufferAllocationSizeInBytes = BaseValueVector.INITIAL_VALUE_ALLOCATION * TYPE_WIDTH;
}
public BufferAllocator getAllocator() {
return allocator;
}
@Override
public MinorType getMinorType() {
return MinorType.UNION;
}
@Override
public void initializeChildrenFromFields(List children) {
internalStruct.initializeChildrenFromFields(children);
}
@Override
public List getChildrenFromFields() {
return internalStruct.getChildrenFromFields();
}
@Override
public void loadFieldBuffers(ArrowFieldNode fieldNode, List ownBuffers) {
if (ownBuffers.size() != 1) {
throw new IllegalArgumentException("Illegal buffer count, expected " + 1 + ", got: " + ownBuffers.size());
}
ArrowBuf buffer = ownBuffers.get(0);
typeBuffer.getReferenceManager().release();
typeBuffer = buffer.getReferenceManager().retain(buffer, allocator);
typeBufferAllocationSizeInBytes = checkedCastToInt(typeBuffer.capacity());
this.valueCount = fieldNode.getLength();
}
@Override
public List getFieldBuffers() {
List result = new ArrayList<>(1);
setReaderAndWriterIndex();
result.add(typeBuffer);
return result;
}
private void setReaderAndWriterIndex() {
typeBuffer.readerIndex(0);
typeBuffer.writerIndex(valueCount * TYPE_WIDTH);
}
@Override
@Deprecated
public List getFieldInnerVectors() {
throw new UnsupportedOperationException("There are no inner vectors. Use geFieldBuffers");
}
private String fieldName(MinorType type) {
return type.name().toLowerCase();
}
private FieldType fieldType(MinorType type) {
return FieldType.nullable(type.getType());
}
private T addOrGet(MinorType minorType, Class c) {
return internalStruct.addOrGet(fieldName(minorType), fieldType(minorType), c);
}
private T addOrGet(MinorType minorType, ArrowType arrowType, Class c) {
return internalStruct.addOrGet(fieldName(minorType), FieldType.nullable(arrowType), c);
}
@Override
public long getValidityBufferAddress() {
return typeBuffer.memoryAddress();
}
@Override
public long getDataBufferAddress() {
throw new UnsupportedOperationException();
}
@Override
public long getOffsetBufferAddress() {
throw new UnsupportedOperationException();
}
@Override
public ArrowBuf getValidityBuffer() { return typeBuffer; }
@Override
public ArrowBuf getDataBuffer() { throw new UnsupportedOperationException(); }
@Override
public ArrowBuf getOffsetBuffer() { throw new UnsupportedOperationException(); }
public StructVector getStruct() {
if (structVector == null) {
int vectorCount = internalStruct.size();
structVector = addOrGet(MinorType.STRUCT, StructVector.class);
if (internalStruct.size() > vectorCount) {
structVector.allocateNew();
if (callBack != null) {
callBack.doWork();
}
}
}
return structVector;
}
<#list vv.types as type>
<#list type.minor as minor>
<#assign name = minor.class?cap_first />
<#assign fields = minor.fields!type.fields />
<#assign uncappedName = name?uncap_first/>
<#assign lowerCaseName = name?lower_case/>
<#if !minor.typeParams?? || minor.class == "Decimal" >
private ${name}Vector ${uncappedName}Vector;
public ${name}Vector get${name}Vector(<#if minor.class == "Decimal">ArrowType arrowType#if>) {
if (${uncappedName}Vector == null) {
int vectorCount = internalStruct.size();
${uncappedName}Vector = addOrGet(MinorType.${name?upper_case},<#if minor.class == "Decimal"> arrowType,#if> ${name}Vector.class);
if (internalStruct.size() > vectorCount) {
${uncappedName}Vector.allocateNew();
if (callBack != null) {
callBack.doWork();
}
}
}
return ${uncappedName}Vector;
}
<#if minor.class == "Decimal">
public ${name}Vector get${name}Vector() {
if (${uncappedName}Vector == null) {
throw new IllegalArgumentException("No Decimal Vector present. Provide ArrowType argument to create a new vector");
}
return ${uncappedName}Vector;
}
#if>
#if>
#list>
#list>
public ListVector getList() {
if (listVector == null) {
int vectorCount = internalStruct.size();
listVector = addOrGet(MinorType.LIST, ListVector.class);
if (internalStruct.size() > vectorCount) {
listVector.allocateNew();
if (callBack != null) {
callBack.doWork();
}
}
}
return listVector;
}
public int getTypeValue(int index) {
return typeBuffer.getByte(index * TYPE_WIDTH);
}
@Override
public void allocateNew() throws OutOfMemoryException {
/* new allocation -- clear the current buffers */
clear();
internalStruct.allocateNew();
try {
allocateTypeBuffer();
} catch (Exception e) {
clear();
throw e;
}
}
@Override
public boolean allocateNewSafe() {
/* new allocation -- clear the current buffers */
clear();
boolean safe = internalStruct.allocateNewSafe();
if (!safe) { return false; }
try {
allocateTypeBuffer();
} catch (Exception e) {
clear();
return false;
}
return true;
}
private void allocateTypeBuffer() {
typeBuffer = allocator.buffer(typeBufferAllocationSizeInBytes);
typeBuffer.readerIndex(0);
typeBuffer.setZero(0, typeBuffer.capacity());
}
@Override
public void reAlloc() {
internalStruct.reAlloc();
reallocTypeBuffer();
}
private void reallocTypeBuffer() {
final long currentBufferCapacity = typeBuffer.capacity();
long baseSize = typeBufferAllocationSizeInBytes;
if (baseSize < currentBufferCapacity) {
baseSize = currentBufferCapacity;
}
long newAllocationSize = baseSize * 2L;
newAllocationSize = BaseAllocator.nextPowerOfTwo(newAllocationSize);
assert newAllocationSize >= 1;
if (newAllocationSize > BaseValueVector.MAX_ALLOCATION_SIZE) {
throw new OversizedAllocationException("Unable to expand the buffer");
}
final ArrowBuf newBuf = allocator.buffer(checkedCastToInt(newAllocationSize));
newBuf.setBytes(0, typeBuffer, 0, currentBufferCapacity);
newBuf.setZero(currentBufferCapacity, newBuf.capacity() - currentBufferCapacity);
typeBuffer.getReferenceManager().release(1);
typeBuffer = newBuf;
typeBufferAllocationSizeInBytes = (int)newAllocationSize;
}
@Override
public void setInitialCapacity(int numRecords) { }
@Override
public int getValueCapacity() {
return Math.min(getTypeBufferValueCapacity(), internalStruct.getValueCapacity());
}
@Override
public void close() {
clear();
}
@Override
public void clear() {
valueCount = 0;
typeBuffer.getReferenceManager().release();
typeBuffer = allocator.getEmpty();
internalStruct.clear();
}
@Override
public void reset() {
valueCount = 0;
typeBuffer.setZero(0, typeBuffer.capacity());
internalStruct.reset();
}
@Override
public Field getField() {
List childFields = new ArrayList<>();
List children = internalStruct.getChildren();
int[] typeIds = new int[children.size()];
for (ValueVector v : children) {
typeIds[childFields.size()] = v.getMinorType().ordinal();
childFields.add(v.getField());
}
FieldType fieldType;
if (this.fieldType == null) {
fieldType = FieldType.nullable(new ArrowType.Union(Sparse, typeIds));
} else {
final UnionMode mode = ((ArrowType.Union)this.fieldType.getType()).getMode();
fieldType = new FieldType(this.fieldType.isNullable(), new ArrowType.Union(mode, typeIds),
this.fieldType.getDictionary(), this.fieldType.getMetadata());
}
return new Field(name, fieldType, childFields);
}
@Override
public TransferPair getTransferPair(BufferAllocator allocator) {
return getTransferPair(name, allocator);
}
@Override
public TransferPair getTransferPair(String ref, BufferAllocator allocator) {
return getTransferPair(ref, allocator, null);
}
@Override
public TransferPair getTransferPair(String ref, BufferAllocator allocator, CallBack callBack) {
return new org.apache.arrow.vector.complex.UnionVector.TransferImpl(ref, allocator, callBack);
}
@Override
public TransferPair makeTransferPair(ValueVector target) {
return new TransferImpl((UnionVector) target);
}
@Override
public void copyFrom(int inIndex, int outIndex, ValueVector from) {
Preconditions.checkArgument(this.getMinorType() == from.getMinorType());
UnionVector fromCast = (UnionVector) from;
fromCast.getReader().setPosition(inIndex);
getWriter().setPosition(outIndex);
ComplexCopier.copy(fromCast.reader, writer);
}
@Override
public void copyFromSafe(int inIndex, int outIndex, ValueVector from) {
copyFrom(inIndex, outIndex, from);
}
public FieldVector addVector(FieldVector v) {
String name = v.getMinorType().name().toLowerCase();
Preconditions.checkState(internalStruct.getChild(name) == null, String.format("%s vector already exists", name));
final FieldVector newVector = internalStruct.addOrGet(name, v.getField().getFieldType(), v.getClass());
v.makeTransferPair(newVector).transfer();
internalStruct.putChild(name, newVector);
if (callBack != null) {
callBack.doWork();
}
return newVector;
}
/**
* Directly put a vector to internalStruct without creating a new one with same type.
*/
public void directAddVector(FieldVector v) {
String name = v.getMinorType().name().toLowerCase();
Preconditions.checkState(internalStruct.getChild(name) == null, String.format("%s vector already exists", name));
internalStruct.putChild(name, v);
if (callBack != null) {
callBack.doWork();
}
}
private class TransferImpl implements TransferPair {
private final TransferPair internalStructVectorTransferPair;
private final UnionVector to;
public TransferImpl(String name, BufferAllocator allocator, CallBack callBack) {
to = new UnionVector(name, allocator, callBack);
internalStructVectorTransferPair = internalStruct.makeTransferPair(to.internalStruct);
}
public TransferImpl(UnionVector to) {
this.to = to;
internalStructVectorTransferPair = internalStruct.makeTransferPair(to.internalStruct);
}
@Override
public void transfer() {
to.clear();
final ReferenceManager refManager = typeBuffer.getReferenceManager();
to.typeBuffer = refManager.transferOwnership(typeBuffer, to.allocator).getTransferredBuffer();
internalStructVectorTransferPair.transfer();
to.valueCount = valueCount;
clear();
}
@Override
public void splitAndTransfer(int startIndex, int length) {
Preconditions.checkArgument(startIndex >= 0 && length >= 0 && startIndex + length <= valueCount,
"Invalid parameters startIndex: %s, length: %s for valueCount: %s", startIndex, length, valueCount);
to.clear();
internalStructVectorTransferPair.splitAndTransfer(startIndex, length);
final int startPoint = startIndex * TYPE_WIDTH;
final int sliceLength = length * TYPE_WIDTH;
final ArrowBuf slicedBuffer = typeBuffer.slice(startPoint, sliceLength);
final ReferenceManager refManager = slicedBuffer.getReferenceManager();
to.typeBuffer = refManager.transferOwnership(slicedBuffer, to.allocator).getTransferredBuffer();
to.setValueCount(length);
}
@Override
public ValueVector getTo() {
return to;
}
@Override
public void copyValueSafe(int from, int to) {
this.to.copyFrom(from, to, UnionVector.this);
}
}
@Override
public FieldReader getReader() {
if (reader == null) {
reader = new UnionReader(this);
}
return reader;
}
public FieldWriter getWriter() {
if (writer == null) {
writer = new UnionWriter(this);
}
return writer;
}
@Override
public int getBufferSize() {
if (valueCount == 0) { return 0; }
return (valueCount * TYPE_WIDTH) + internalStruct.getBufferSize();
}
@Override
public int getBufferSizeFor(final int valueCount) {
if (valueCount == 0) {
return 0;
}
long bufferSize = 0;
for (final ValueVector v : (Iterable) this) {
bufferSize += v.getBufferSizeFor(valueCount);
}
return (int) bufferSize + (valueCount * TYPE_WIDTH);
}
@Override
public ArrowBuf[] getBuffers(boolean clear) {
List list = new java.util.ArrayList<>();
setReaderAndWriterIndex();
if (getBufferSize() != 0) {
list.add(typeBuffer);
list.addAll(java.util.Arrays.asList(internalStruct.getBuffers(clear)));
}
if (clear) {
valueCount = 0;
typeBuffer.getReferenceManager().retain();
typeBuffer.getReferenceManager().release();
typeBuffer = allocator.getEmpty();
}
return list.toArray(new ArrowBuf[list.size()]);
}
@Override
public Iterator iterator() {
List vectors = org.apache.arrow.util.Collections2.toList(internalStruct.iterator());
return vectors.iterator();
}
public ValueVector getVector(int index) {
return getVector(index, null);
}
public ValueVector getVector(int index, ArrowType arrowType) {
int type = typeBuffer.getByte(index * TYPE_WIDTH);
return getVectorByType(type, arrowType);
}
public ValueVector getVectorByType(int typeId) {
return getVectorByType(typeId, null);
}
public ValueVector getVectorByType(int typeId, ArrowType arrowType) {
switch (MinorType.values()[typeId]) {
case NULL:
return null;
<#list vv.types as type>
<#list type.minor as minor>
<#assign name = minor.class?cap_first />
<#assign fields = minor.fields!type.fields />
<#assign uncappedName = name?uncap_first/>
<#if !minor.typeParams?? || minor.class == "Decimal" >
case ${name?upper_case}:
return get${name}Vector(<#if minor.class == "Decimal">arrowType#if>);
#if>
#list>
#list>
case STRUCT:
return getStruct();
case LIST:
return getList();
default:
throw new UnsupportedOperationException("Cannot support type: " + MinorType.values()[typeId]);
}
}
public Object getObject(int index) {
ValueVector vector = getVector(index);
if (vector != null) {
return vector.getObject(index);
}
return null;
}
public byte[] get(int index) {
return null;
}
public void get(int index, ComplexHolder holder) {
}
public void get(int index, UnionHolder holder) {
FieldReader reader = new UnionReader(UnionVector.this);
reader.setPosition(index);
holder.reader = reader;
}
public int getValueCount() {
return valueCount;
}
public boolean isNull(int index) {
ValueVector vec = getVector(index);
if (vec == null) {
return true;
}
return vec.isNull(index);
}
@Override
public int getNullCount() {
int nullCount = 0;
for (int i = 0; i < getValueCount(); i++) {
if (isNull(i)) {
nullCount++;
}
}
return nullCount;
}
public int isSet(int index) {
return isNull(index) ? 0 : 1;
}
UnionWriter writer;
public void setValueCount(int valueCount) {
this.valueCount = valueCount;
while (valueCount > getTypeBufferValueCapacity()) {
reallocTypeBuffer();
}
internalStruct.setValueCount(valueCount);
}
public void setSafe(int index, UnionHolder holder) {
setSafe(index, holder, null);
}
public void setSafe(int index, UnionHolder holder, ArrowType arrowType) {
FieldReader reader = holder.reader;
if (writer == null) {
writer = new UnionWriter(UnionVector.this);
}
writer.setPosition(index);
MinorType type = reader.getMinorType();
switch (type) {
<#list vv.types as type>
<#list type.minor as minor>
<#assign name = minor.class?cap_first />
<#assign fields = minor.fields!type.fields />
<#assign uncappedName = name?uncap_first/>
<#if !minor.typeParams?? || minor.class == "Decimal" >
case ${name?upper_case}:
Nullable${name}Holder ${uncappedName}Holder = new Nullable${name}Holder();
reader.read(${uncappedName}Holder);
setSafe(index, ${uncappedName}Holder<#if minor.class == "Decimal">, arrowType#if>);
break;
#if>
#list>
#list>
case STRUCT: {
ComplexCopier.copy(reader, writer);
break;
}
case LIST: {
ComplexCopier.copy(reader, writer);
break;
}
default:
throw new UnsupportedOperationException();
}
}
<#list vv.types as type>
<#list type.minor as minor>
<#assign name = minor.class?cap_first />
<#assign fields = minor.fields!type.fields />
<#assign uncappedName = name?uncap_first/>
<#if !minor.typeParams?? || minor.class == "Decimal" >
public void setSafe(int index, Nullable${name}Holder holder<#if minor.class == "Decimal">, ArrowType arrowType#if>) {
setType(index, MinorType.${name?upper_case});
get${name}Vector(<#if minor.class == "Decimal">arrowType#if>).setSafe(index, holder);
}
#if>
#list>
#list>
public void setType(int index, MinorType type) {
while (index >= getTypeBufferValueCapacity()) {
reallocTypeBuffer();
}
typeBuffer.setByte(index * TYPE_WIDTH , (byte) type.ordinal());
}
private int getTypeBufferValueCapacity() {
return capAtMaxInt(typeBuffer.capacity() / TYPE_WIDTH);
}
@Override
public int hashCode(int index) {
return hashCode(index, null);
}
@Override
public int hashCode(int index, ArrowBufHasher hasher) {
ValueVector vec = getVector(index);
if (vec == null) {
return ArrowBufPointer.NULL_HASH_CODE;
}
return vec.hashCode(index, hasher);
}
@Override
public OUT accept(VectorVisitor visitor, IN value) {
return visitor.visit(this, value);
}
@Override
public String getName() {
return name;
}
@Override
public String toString() {
return ValueVectorUtility.getToString(this, 0, getValueCount());
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy