Java tutorial
/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.arrow.vector.complex; import static com.google.common.base.Preconditions.checkNotNull; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.annotation.Nullable; import com.google.common.collect.Ordering; import com.google.common.primitives.Ints; import io.netty.buffer.ArrowBuf; import org.apache.arrow.memory.BufferAllocator; import org.apache.arrow.vector.*; import org.apache.arrow.vector.complex.impl.SingleStructReaderImpl; import org.apache.arrow.vector.complex.reader.FieldReader; import org.apache.arrow.vector.holders.ComplexHolder; import org.apache.arrow.vector.types.Types.MinorType; import org.apache.arrow.vector.types.pojo.ArrowType; import org.apache.arrow.vector.types.pojo.Field; import org.apache.arrow.vector.types.pojo.FieldType; import org.apache.arrow.vector.util.CallBack; import org.apache.arrow.vector.util.JsonStringHashMap; import org.apache.arrow.vector.util.TransferPair; public class NonNullableStructVector extends AbstractStructVector { public static NonNullableStructVector empty(String name, BufferAllocator allocator) { FieldType fieldType = new FieldType(false, ArrowType.Struct.INSTANCE, null, null); return new NonNullableStructVector(name, allocator, fieldType, null); } private final SingleStructReaderImpl reader = new SingleStructReaderImpl(this); protected final FieldType fieldType; public int valueCount; // deprecated, use FieldType or static constructor instead @Deprecated public NonNullableStructVector(String name, BufferAllocator allocator, CallBack callBack) { this(name, allocator, new FieldType(false, ArrowType.Struct.INSTANCE, null, null), callBack); } public NonNullableStructVector(String name, BufferAllocator allocator, FieldType fieldType, CallBack callBack) { super(name, allocator, callBack); this.fieldType = checkNotNull(fieldType); this.valueCount = 0; } @Override public FieldReader getReader() { return reader; } transient private StructTransferPair ephPair; public void copyFromSafe(int fromIndex, int thisIndex, NonNullableStructVector from) { if (ephPair == null || ephPair.from != from) { ephPair = (StructTransferPair) from.makeTransferPair(this); } ephPair.copyValueSafe(fromIndex, thisIndex); } @Override protected boolean supportsDirectRead() { return true; } public Iterator<String> fieldNameIterator() { return getChildFieldNames().iterator(); } @Override public void setInitialCapacity(int numRecords) { for (final ValueVector v : (Iterable<ValueVector>) this) { v.setInitialCapacity(numRecords); } } @Override public void setInitialCapacity(int valueCount, double density) { for (final ValueVector vector : (Iterable<ValueVector>) this) { if (vector instanceof DensityAwareVector) { ((DensityAwareVector) vector).setInitialCapacity(valueCount, density); } else { vector.setInitialCapacity(valueCount); } } } @Override public int getBufferSize() { if (valueCount == 0 || size() == 0) { return 0; } long buffer = 0; for (final ValueVector v : (Iterable<ValueVector>) this) { buffer += v.getBufferSize(); } return (int) buffer; } @Override public int getBufferSizeFor(final int valueCount) { if (valueCount == 0) { return 0; } long bufferSize = 0; for (final ValueVector v : (Iterable<ValueVector>) this) { bufferSize += v.getBufferSizeFor(valueCount); } return (int) bufferSize; } @Override public ArrowBuf getValidityBuffer() { throw new UnsupportedOperationException(); } @Override public ArrowBuf getDataBuffer() { throw new UnsupportedOperationException(); } @Override public ArrowBuf getOffsetBuffer() { throw new UnsupportedOperationException(); } @Override public TransferPair getTransferPair(BufferAllocator allocator) { return getTransferPair(name, allocator, null); } @Override public TransferPair getTransferPair(String ref, BufferAllocator allocator, CallBack callBack) { return new StructTransferPair(this, new NonNullableStructVector(name, allocator, fieldType, callBack), false); } @Override public TransferPair makeTransferPair(ValueVector to) { return new StructTransferPair(this, (NonNullableStructVector) to); } @Override public TransferPair getTransferPair(String ref, BufferAllocator allocator) { return new StructTransferPair(this, new NonNullableStructVector(ref, allocator, fieldType, callBack), false); } protected static class StructTransferPair implements TransferPair { private final TransferPair[] pairs; private final NonNullableStructVector from; private final NonNullableStructVector to; public StructTransferPair(NonNullableStructVector from, NonNullableStructVector to) { this(from, to, true); } protected StructTransferPair(NonNullableStructVector from, NonNullableStructVector to, boolean allocate) { this.from = from; this.to = to; this.pairs = new TransferPair[from.size()]; this.to.ephPair = null; int i = 0; FieldVector vector; for (String child : from.getChildFieldNames()) { int preSize = to.size(); vector = from.getChild(child); if (vector == null) { continue; } //DRILL-1872: we add the child fields for the vector, looking up the field by name. For a map vector, // the child fields may be nested fields of the top level child. For example if the structure // of a child field is oa.oab.oabc then we add oa, then add oab to oa then oabc to oab. // But the children member of a Materialized field is a HashSet. If the fields are added in the // children HashSet, and the hashCode of the Materialized field includes the hash code of the // children, the hashCode value of oa changes *after* the field has been added to the HashSet. // (This is similar to what happens in ScanBatch where the children cannot be added till they are // read). To take care of this, we ensure that the hashCode of the MaterializedField does not // include the hashCode of the children but is based only on MaterializedField$key. final FieldVector newVector = to.addOrGet(child, vector.getField().getFieldType(), vector.getClass()); if (allocate && to.size() != preSize) { newVector.allocateNew(); } pairs[i++] = vector.makeTransferPair(newVector); } } @Override public void transfer() { for (final TransferPair p : pairs) { p.transfer(); } to.valueCount = from.valueCount; from.clear(); } @Override public ValueVector getTo() { return to; } @Override public void copyValueSafe(int from, int to) { for (TransferPair p : pairs) { p.copyValueSafe(from, to); } } @Override public void splitAndTransfer(int startIndex, int length) { for (TransferPair p : pairs) { p.splitAndTransfer(startIndex, length); } to.setValueCount(length); } } @Override public int getValueCapacity() { if (size() == 0) { return 0; } final Ordering<ValueVector> natural = new Ordering<ValueVector>() { @Override public int compare(@Nullable ValueVector left, @Nullable ValueVector right) { return Ints.compare(checkNotNull(left).getValueCapacity(), checkNotNull(right).getValueCapacity()); } }; return natural.min(getChildren()).getValueCapacity(); } @Override public Object getObject(int index) { Map<String, Object> vv = new JsonStringHashMap<>(); for (String child : getChildFieldNames()) { ValueVector v = getChild(child); if (v != null && index < v.getValueCount()) { Object value = v.getObject(index); if (value != null) { vv.put(child, value); } } } return vv; } @Override public boolean isNull(int index) { return false; } @Override public int getNullCount() { return 0; } public void get(int index, ComplexHolder holder) { reader.setPosition(index); holder.reader = reader; } @Override public int getValueCount() { return valueCount; } public ValueVector getVectorById(int id) { return getChildByOrdinal(id); } @Override public void setValueCount(int valueCount) { for (final ValueVector v : getChildren()) { v.setValueCount(valueCount); } NonNullableStructVector.this.valueCount = valueCount; } @Override public void clear() { for (final ValueVector v : getChildren()) { v.clear(); } valueCount = 0; } @Override public void reset() { for (final ValueVector v : getChildren()) { v.reset(); } valueCount = 0; } @Override public Field getField() { List<Field> children = new ArrayList<>(); for (ValueVector child : getChildren()) { children.add(child.getField()); } return new Field(name, fieldType, children); } @Override public MinorType getMinorType() { return MinorType.STRUCT; } @Override public void close() { final Collection<FieldVector> vectors = getChildren(); for (final FieldVector v : vectors) { v.close(); } vectors.clear(); valueCount = 0; super.close(); } public void initializeChildrenFromFields(List<Field> children) { for (Field field : children) { FieldVector vector = (FieldVector) this.add(field.getName(), field.getFieldType()); vector.initializeChildrenFromFields(field.getChildren()); } } public List<FieldVector> getChildrenFromFields() { return getChildren(); } }