| /* |
| * 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.drill.exec.record; |
| |
| import org.apache.commons.lang3.ArrayUtils; |
| import org.apache.drill.common.expression.SchemaPath; |
| import org.apache.drill.exec.memory.BufferAllocator; |
| import org.apache.drill.exec.vector.ValueVector; |
| import org.apache.drill.exec.vector.complex.AbstractMapVector; |
| import org.apache.drill.exec.vector.complex.FieldIdUtil; |
| |
| import com.google.common.base.Preconditions; |
| |
| import java.lang.reflect.Array; |
| |
| |
| public class HyperVectorWrapper<T extends ValueVector> implements VectorWrapper<T>{ |
| static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(HyperVectorWrapper.class); |
| |
| private T[] vectors; |
| private MaterializedField f; |
| private final boolean releasable; |
| |
| public HyperVectorWrapper(MaterializedField f, T[] v) { |
| this(f, v, true); |
| } |
| |
| public HyperVectorWrapper(MaterializedField f, T[] v, boolean releasable) { |
| assert(v.length > 0); |
| this.f = f; |
| this.vectors = v; |
| this.releasable = releasable; |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Override |
| public Class<T> getVectorClass() { |
| return (Class<T>) vectors.getClass().getComponentType(); |
| } |
| |
| @Override |
| public MaterializedField getField() { |
| return f; |
| } |
| |
| @Override |
| public T getValueVector() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public T[] getValueVectors() { |
| return vectors; |
| } |
| |
| @Override |
| public boolean isHyper() { |
| return true; |
| } |
| |
| @Override |
| public void clear() { |
| if (!releasable) { |
| return; |
| } |
| for (final T x : vectors) { |
| x.clear(); |
| } |
| } |
| |
| @Override |
| public VectorWrapper<?> getChildWrapper(int[] ids) { |
| if (ids.length == 1) { |
| return this; |
| } |
| |
| final ValueVector[] vectors = new ValueVector[this.vectors.length]; |
| int index = 0; |
| |
| for (final ValueVector v : this.vectors) { |
| ValueVector vector = v; |
| for (int i = 1; i < ids.length; i++) { |
| final AbstractMapVector mapLike = AbstractMapVector.class.cast(vector); |
| if (mapLike == null) { |
| return null; |
| } |
| vector = mapLike.getChildByOrdinal(ids[i]); |
| } |
| vectors[index] = vector; |
| index++; |
| } |
| return new HyperVectorWrapper<ValueVector>(vectors[0].getField(), vectors); |
| } |
| |
| @Override |
| public TypedFieldId getFieldIdIfMatches(int id, SchemaPath expectedPath) { |
| final ValueVector v = vectors[0]; |
| return FieldIdUtil.getFieldId(v, id, expectedPath, true); |
| } |
| |
| @Override |
| public VectorWrapper<T> cloneAndTransfer(BufferAllocator allocator) { |
| return new HyperVectorWrapper<T>(f, vectors, false); |
| // T[] newVectors = (T[]) Array.newInstance(vectors.getClass().getComponentType(), vectors.length); |
| // for(int i =0; i < newVectors.length; i++) { |
| // TransferPair tp = vectors[i].getTransferPair(); |
| // tp.transfer(); |
| // newVectors[i] = (T) tp.getTo(); |
| // } |
| // return new HyperVectorWrapper<T>(f, newVectors); |
| } |
| |
| public static <T extends ValueVector> HyperVectorWrapper<T> create(MaterializedField f, T[] v, boolean releasable) { |
| return new HyperVectorWrapper<T>(f, v, releasable); |
| } |
| |
| @SuppressWarnings("unchecked") |
| public void addVector(ValueVector v) { |
| Preconditions.checkArgument(v.getClass() == this.getVectorClass(), String.format("Cannot add vector type %s to hypervector type %s for field %s", |
| v.getClass(), this.getVectorClass(), v.getField())); |
| vectors = (T[]) ArrayUtils.add(vectors, v);// TODO optimize this so not copying every time |
| } |
| |
| @SuppressWarnings("unchecked") |
| public void addVectors(ValueVector[] vv) { |
| vectors = (T[]) ArrayUtils.addAll(vectors, vv); |
| } |
| |
| /** |
| * Transfer vectors to destination HyperVectorWrapper. |
| * Both this and destination must be of same type and have same number of vectors. |
| * @param destination destination HyperVectorWrapper. |
| */ |
| @Override |
| public void transfer(VectorWrapper<?> destination) { |
| Preconditions.checkArgument(destination instanceof HyperVectorWrapper); |
| Preconditions.checkArgument(getField().getType().equals(destination.getField().getType())); |
| Preconditions.checkArgument(vectors.length == ((HyperVectorWrapper<?>)destination).vectors.length); |
| |
| final ValueVector[] destionationVectors = ((HyperVectorWrapper<?>)destination).vectors; |
| for (int i = 0; i < vectors.length; ++i) { |
| vectors[i].makeTransferPair(destionationVectors[i]).transfer(); |
| } |
| } |
| |
| /** |
| * Method to replace existing list of vectors with the newly provided ValueVectors list in this HyperVectorWrapper |
| * @param vv - New list of ValueVectors to be stored |
| */ |
| @SuppressWarnings("unchecked") |
| public void updateVectorList(ValueVector[] vv) { |
| Preconditions.checkArgument(vv.length > 0); |
| Preconditions.checkArgument(getField().getType().equals(vv[0].getField().getType())); |
| // vectors.length will always be > 0 since in constructor that is enforced |
| Preconditions.checkArgument(vv[0].getClass().equals(vectors[0].getClass())); |
| clear(); |
| |
| final Class<?> clazz = vv[0].getClass(); |
| final ValueVector[] c = (ValueVector[]) Array.newInstance(clazz, vv.length); |
| System.arraycopy(vv, 0, c, 0, vv.length); |
| vectors = (T[])c; |
| } |
| } |