| /* |
| * 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 org.apache.drill.common.types.TypeProtos; |
| import org.apache.drill.exec.vector.UntypedNullHolder; |
| import org.apache.drill.exec.vector.UntypedNullVector; |
| import org.apache.drill.exec.vector.complex.DictVector; |
| import org.apache.drill.exec.vector.complex.impl.UntypedHolderReaderImpl; |
| |
| <@pp.dropOutputFile /> |
| <@pp.changeOutputFile name="/org/apache/drill/exec/expr/BasicTypeHelper.java" /> |
| |
| <#include "/@includes/license.ftl" /> |
| |
| package org.apache.drill.exec.expr; |
| |
| <#include "/@includes/vv_imports.ftl" /> |
| import org.apache.drill.exec.vector.complex.UnionVector; |
| import org.apache.drill.common.types.TypeProtos.DataMode; |
| import org.apache.drill.common.types.TypeProtos.MinorType; |
| import org.apache.drill.common.types.TypeProtos.MajorType; |
| import org.apache.drill.exec.record.MaterializedField; |
| import org.apache.drill.exec.vector.complex.RepeatedMapVector; |
| import org.apache.drill.exec.vector.complex.DictVector; |
| import org.apache.drill.exec.util.CallBack; |
| import org.apache.drill.common.types.Types; |
| import com.google.common.annotations.VisibleForTesting; |
| |
| import java.util.List; |
| |
| /* |
| * This class is generated using freemarker and the ${.template_name} template. |
| */ |
| public class BasicTypeHelper { |
| static final org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(BasicTypeHelper.class); |
| |
| @VisibleForTesting |
| public static final int WIDTH_ESTIMATE = 50; |
| |
| protected static String buildErrorMessage(final String operation, final MinorType type, final DataMode mode) { |
| return String.format("Unable to %s for minor type [%s] and mode [%s]", operation, type, mode); |
| } |
| |
| protected static String buildErrorMessage(final String operation, final MajorType type) { |
| return buildErrorMessage(operation, type.getMinorType(), type.getMode()); |
| } |
| |
| public static int getSize(MajorType major) { |
| switch (major.getMinorType()) { |
| <#list vv.types as type> |
| <#list type.minor as minor> |
| case ${minor.class?upper_case}: |
| return ${type.width}<#if minor.class?substring(0, 3) == "Var" || |
| minor.class?substring(0, 3) == "PRO" || |
| minor.class?substring(0, 3) == "MSG"> + WIDTH_ESTIMATE</#if>; |
| </#list> |
| </#list> |
| case FIXEDCHAR: return major.getPrecision(); |
| case FIXED16CHAR: return major.getPrecision(); |
| case FIXEDBINARY: return major.getPrecision(); |
| case NULL: |
| return 0; |
| } |
| throw new UnsupportedOperationException(buildErrorMessage("get size", major)); |
| } |
| |
| public static Class<? extends ValueVector> getValueVectorClass(MinorType type, DataMode mode){ |
| switch (type) { |
| case UNION: |
| return UnionVector.class; |
| case MAP: |
| switch (mode) { |
| case OPTIONAL: |
| case REQUIRED: |
| return MapVector.class; |
| case REPEATED: |
| return RepeatedMapVector.class; |
| } |
| |
| case DICT: |
| switch (mode) { |
| case OPTIONAL: |
| case REQUIRED: |
| return DictVector.class; |
| case REPEATED: |
| return RepeatedDictVector.class; |
| } |
| case LIST: |
| switch (mode) { |
| case REPEATED: |
| return RepeatedListVector.class; |
| case REQUIRED: |
| case OPTIONAL: |
| return ListVector.class; |
| } |
| |
| <#list vv.types as type> |
| <#list type.minor as minor> |
| case ${minor.class?upper_case}: |
| switch (mode) { |
| case REQUIRED: |
| return ${minor.class}Vector.class; |
| case OPTIONAL: |
| return Nullable${minor.class}Vector.class; |
| case REPEATED: |
| return Repeated${minor.class}Vector.class; |
| } |
| </#list> |
| </#list> |
| case GENERIC_OBJECT : |
| return ObjectVector.class ; |
| case NULL: |
| return UntypedNullVector.class; |
| default: |
| break; |
| } |
| throw new UnsupportedOperationException(buildErrorMessage("get value vector class", type, mode)); |
| } |
| public static Class<?> getReaderClassName( MinorType type, DataMode mode, boolean isSingularRepeated){ |
| switch (type) { |
| case MAP: |
| switch (mode) { |
| case REQUIRED: |
| if (!isSingularRepeated) |
| return SingleMapReaderImpl.class; |
| else |
| return SingleLikeRepeatedMapReaderImpl.class; |
| case REPEATED: |
| return RepeatedMapReaderImpl.class; |
| } |
| case DICT: |
| switch (mode) { |
| case REQUIRED: |
| if (!isSingularRepeated) { |
| return SingleDictReaderImpl.class; |
| } else { |
| throw new UnsupportedOperationException("DictVector required singular repeated reader is not supported yet"); |
| } |
| case REPEATED: |
| return RepeatedDictReaderImpl.class; |
| } |
| case LIST: |
| switch (mode) { |
| case REQUIRED: |
| return SingleListReaderImpl.class; |
| case REPEATED: |
| return RepeatedListReaderImpl.class; |
| } |
| |
| <#list vv.types as type> |
| <#list type.minor as minor> |
| case ${minor.class?upper_case}: |
| switch (mode) { |
| case REQUIRED: |
| return ${minor.class}ReaderImpl.class; |
| case OPTIONAL: |
| return Nullable${minor.class}ReaderImpl.class; |
| case REPEATED: |
| return Repeated${minor.class}ReaderImpl.class; |
| } |
| </#list> |
| </#list> |
| default: |
| throw new UnsupportedOperationException(buildErrorMessage("get reader class name", type, mode)); |
| } |
| } |
| |
| public static Class<?> getWriterInterface( MinorType type, DataMode mode){ |
| switch (type) { |
| case UNION: return UnionWriter.class; |
| case MAP: return MapWriter.class; |
| case DICT: return DictWriter.class; |
| case LIST: return ListWriter.class; |
| <#list vv.types as type> |
| <#list type.minor as minor> |
| case ${minor.class?upper_case}: return ${minor.class}Writer.class; |
| </#list> |
| </#list> |
| default: |
| throw new UnsupportedOperationException(buildErrorMessage("get writer interface", type, mode)); |
| } |
| } |
| |
| public static Class<?> getWriterImpl( MinorType type, DataMode mode){ |
| switch (type) { |
| case UNION: |
| return UnionWriter.class; |
| case MAP: |
| switch (mode) { |
| case REQUIRED: |
| case OPTIONAL: |
| return SingleMapWriter.class; |
| case REPEATED: |
| return RepeatedMapWriter.class; |
| } |
| case DICT: |
| switch (mode) { |
| case REQUIRED: |
| case OPTIONAL: |
| return SingleDictWriter.class; |
| case REPEATED: |
| return RepeatedDictWriter.class; |
| } |
| case LIST: |
| switch (mode) { |
| case REQUIRED: |
| case OPTIONAL: |
| return UnionListWriter.class; |
| case REPEATED: |
| return RepeatedListWriter.class; |
| } |
| |
| <#list vv.types as type> |
| <#list type.minor as minor> |
| case ${minor.class?upper_case}: |
| switch (mode) { |
| case REQUIRED: |
| return ${minor.class}WriterImpl.class; |
| case OPTIONAL: |
| return Nullable${minor.class}WriterImpl.class; |
| case REPEATED: |
| return Repeated${minor.class}WriterImpl.class; |
| } |
| </#list> |
| </#list> |
| default: |
| throw new UnsupportedOperationException(buildErrorMessage("get writer implementation", type, mode)); |
| } |
| } |
| |
| /** |
| * Creates and returns {@link FieldReader} instance for specified {@code MajorType type} using specisied {@code ValueHolder} |
| * |
| * @param type type of resulting {@link FieldReader} instance |
| * @param holder value holder for {@link FieldReader} creation |
| * @return {@link FieldReader} instance |
| */ |
| public static FieldReader getHolderReaderImpl(MajorType type, ValueHolder holder) { |
| switch (type.getMinorType()) { |
| <#list vv.types as type> |
| <#list type.minor as minor> |
| case ${minor.class?upper_case}: |
| switch (type.getMode()) { |
| case REQUIRED: |
| return new ${minor.class}HolderReaderImpl((${minor.class}Holder) holder); |
| case OPTIONAL: |
| return new Nullable${minor.class}HolderReaderImpl((Nullable${minor.class}Holder) holder); |
| case REPEATED: |
| return new Repeated${minor.class}HolderReaderImpl((Repeated${minor.class}Holder) holder); |
| } |
| </#list> |
| </#list> |
| case NULL: |
| return new UntypedHolderReaderImpl((UntypedNullHolder) holder); |
| default: |
| throw new UnsupportedOperationException(buildErrorMessage("get holder reader implementation", type.getMinorType(), type.getMode())); |
| } |
| } |
| |
| public static Class<?> getHolderReaderImpl(MinorType type, DataMode mode) { |
| switch (type) { |
| <#list vv.types as type> |
| <#list type.minor as minor> |
| case ${minor.class?upper_case}: |
| switch (mode) { |
| case REQUIRED: |
| return ${minor.class}HolderReaderImpl.class; |
| case OPTIONAL: |
| return Nullable${minor.class}HolderReaderImpl.class; |
| case REPEATED: |
| return Repeated${minor.class}HolderReaderImpl.class; |
| } |
| </#list> |
| </#list> |
| case NULL: |
| return UntypedHolderReaderImpl.class; |
| default: |
| throw new UnsupportedOperationException(buildErrorMessage("get holder reader implementation", type, mode)); |
| } |
| } |
| |
| public static ValueVector getNewVector(String name, BufferAllocator allocator, MajorType type, CallBack callback) { |
| MaterializedField field = MaterializedField.create(name, type); |
| return getNewVector(field, allocator, callback); |
| } |
| |
| public static ValueVector getNewVector(MaterializedField field, BufferAllocator allocator){ |
| return getNewVector(field, allocator, null); |
| } |
| |
| public static ValueVector getNewVector(MaterializedField field, BufferAllocator allocator, CallBack callBack) { |
| return getNewVector(field, field.getType(), allocator, callBack); |
| } |
| |
| // Creates an internal or external vector. Internal vectors may have |
| // types that disagree with their materialized field. |
| |
| public static ValueVector getNewVector(MaterializedField field, MajorType type, BufferAllocator allocator, CallBack callBack) { |
| |
| switch (type.getMinorType()) { |
| case UNION: |
| return new UnionVector(field, allocator, callBack); |
| |
| case MAP: |
| switch (type.getMode()) { |
| case REQUIRED: |
| case OPTIONAL: |
| return new MapVector(field, allocator, callBack); |
| case REPEATED: |
| return new RepeatedMapVector(field, allocator, callBack); |
| } |
| case DICT: |
| switch (type.getMode()) { |
| case REQUIRED: |
| case OPTIONAL: |
| return new DictVector(field, allocator, callBack); |
| case REPEATED: |
| return new RepeatedDictVector(field, allocator, callBack); |
| } |
| case LIST: |
| switch (type.getMode()) { |
| case REPEATED: |
| return new RepeatedListVector(field, allocator, callBack); |
| case OPTIONAL: |
| case REQUIRED: |
| return new ListVector(field, allocator, callBack); |
| } |
| <#list vv. types as type> |
| <#list type.minor as minor> |
| case ${minor.class?upper_case}: |
| switch (type.getMode()) { |
| case REQUIRED: |
| return new ${minor.class}Vector(field, allocator); |
| case OPTIONAL: |
| return new Nullable${minor.class}Vector(field, allocator); |
| case REPEATED: |
| return new Repeated${minor.class}Vector(field, allocator); |
| } |
| </#list> |
| </#list> |
| case GENERIC_OBJECT: |
| return new ObjectVector(field, allocator) ; |
| case NULL: |
| return new UntypedNullVector(field, allocator); |
| default: |
| // All ValueVector types have been handled. |
| throw new UnsupportedOperationException(buildErrorMessage("get new vector", type)); |
| } |
| } |
| |
| public static ValueHolder getValue(ValueVector vector, int index) { |
| MajorType type = vector.getField().getType(); |
| ValueHolder holder; |
| switch(type.getMinorType()) { |
| <#list vv.types as type> |
| <#list type.minor as minor> |
| case ${minor.class?upper_case} : |
| <#if minor.class?starts_with("Var") || minor.class == "IntervalDay" || minor.class == "Interval" || |
| minor.class?starts_with("Decimal28") || minor.class?starts_with("Decimal38")> |
| switch (type.getMode()) { |
| case REQUIRED: |
| holder = new ${minor.class}Holder(); |
| ((${minor.class}Vector) vector).getAccessor().get(index, (${minor.class}Holder)holder); |
| return holder; |
| case OPTIONAL: |
| holder = new Nullable${minor.class}Holder(); |
| ((Nullable${minor.class}Holder)holder).isSet = ((Nullable${minor.class}Vector) vector).getAccessor().isSet(index); |
| if (((Nullable${minor.class}Holder)holder).isSet == 1) { |
| ((Nullable${minor.class}Vector) vector).getAccessor().get(index, (Nullable${minor.class}Holder)holder); |
| } |
| return holder; |
| default: |
| } |
| <#else> |
| switch (type.getMode()) { |
| case REQUIRED: |
| holder = new ${minor.class}Holder(); |
| ((${minor.class}Holder)holder).value = ((${minor.class}Vector) vector).getAccessor().get(index); |
| return holder; |
| case OPTIONAL: |
| holder = new Nullable${minor.class}Holder(); |
| ((Nullable${minor.class}Holder)holder).isSet = ((Nullable${minor.class}Vector) vector).getAccessor().isSet(index); |
| if (((Nullable${minor.class}Holder)holder).isSet == 1) { |
| ((Nullable${minor.class}Holder)holder).value = ((Nullable${minor.class}Vector) vector).getAccessor().get(index); |
| } |
| return holder; |
| default: |
| } |
| </#if> |
| </#list> |
| </#list> |
| case GENERIC_OBJECT: |
| holder = new ObjectHolder(); |
| ((ObjectHolder)holder).obj = ((ObjectVector) vector).getAccessor().getObject(index) ; |
| break; |
| default: |
| } |
| throw new UnsupportedOperationException(buildErrorMessage("get value", type)); |
| } |
| |
| public static void setValue(ValueVector vector, int index, ValueHolder holder) { |
| MajorType type = vector.getField().getType(); |
| |
| switch(type.getMinorType()) { |
| <#list vv.types as type> |
| <#list type.minor as minor> |
| case ${minor.class?upper_case} : |
| switch (type.getMode()) { |
| case REQUIRED: |
| ((${minor.class}Vector) vector).getMutator().setSafe(index, (${minor.class}Holder) holder); |
| return; |
| case OPTIONAL: |
| if (((Nullable${minor.class}Holder) holder).isSet == 1) { |
| ((Nullable${minor.class}Vector) vector).getMutator().setSafe(index, (Nullable${minor.class}Holder) holder); |
| } |
| return; |
| } |
| </#list> |
| </#list> |
| case GENERIC_OBJECT: |
| ((ObjectVector) vector).getMutator().setSafe(index, (ObjectHolder) holder); |
| return; |
| case NULL: |
| ((UntypedNullVector) vector).getMutator().setSafe(index, (UntypedNullHolder) holder); |
| default: |
| throw new UnsupportedOperationException(buildErrorMessage("set value", type)); |
| } |
| } |
| |
| public static void setValueSafe(ValueVector vector, int index, ValueHolder holder) { |
| MajorType type = vector.getField().getType(); |
| |
| switch(type.getMinorType()) { |
| <#list vv.types as type> |
| <#list type.minor as minor> |
| case ${minor.class?upper_case} : |
| switch (type.getMode()) { |
| case REQUIRED: |
| ((${minor.class}Vector) vector).getMutator().setSafe(index, (${minor.class}Holder) holder); |
| return; |
| case OPTIONAL: |
| if (((Nullable${minor.class}Holder) holder).isSet == 1) { |
| ((Nullable${minor.class}Vector) vector).getMutator().setSafe(index, (Nullable${minor.class}Holder) holder); |
| } else { |
| ((Nullable${minor.class}Vector) vector).getMutator().isSafe(index); |
| } |
| return; |
| } |
| </#list> |
| </#list> |
| case GENERIC_OBJECT: |
| ((ObjectVector) vector).getMutator().setSafe(index, (ObjectHolder) holder); |
| case NULL: |
| ((UntypedNullVector) vector).getMutator().setSafe(index, (UntypedNullHolder) holder); |
| default: |
| throw new UnsupportedOperationException(buildErrorMessage("set value safe", type)); |
| } |
| } |
| |
| public static boolean compareValues(ValueVector v1, int v1index, ValueVector v2, int v2index) { |
| MajorType type1 = v1.getField().getType(); |
| MajorType type2 = v2.getField().getType(); |
| |
| if (type1.getMinorType() != type2.getMinorType() |
| || type1.getScale() != type1.getScale() |
| || type1.getPrecision() != type1.getPrecision()) { |
| return false; |
| } |
| |
| switch(type1.getMinorType()) { |
| <#list vv.types as type> |
| <#list type.minor as minor> |
| case ${minor.class?upper_case} : |
| return ((${minor.class}Vector) v1).getAccessor().get(v1index) == |
| ((${minor.class}Vector) v2).getAccessor().get(v2index); |
| </#list> |
| </#list> |
| default: |
| return false; |
| } |
| } |
| |
| /** |
| * Create a ValueHolder of MajorType. |
| * @param type |
| * @return |
| */ |
| public static ValueHolder createValueHolder(MajorType type) { |
| switch(type.getMinorType()) { |
| <#list vv.types as type> |
| <#list type.minor as minor> |
| case ${minor.class?upper_case} : |
| |
| switch (type.getMode()) { |
| case REQUIRED: |
| return new ${minor.class}Holder(); |
| case OPTIONAL: |
| return new Nullable${minor.class}Holder(); |
| case REPEATED: |
| return new Repeated${minor.class}Holder(); |
| } |
| </#list> |
| </#list> |
| case GENERIC_OBJECT: |
| return new ObjectHolder(); |
| case NULL: |
| return new UntypedNullHolder(); |
| default: |
| throw new UnsupportedOperationException(buildErrorMessage("create value holder", type)); |
| } |
| } |
| |
| public static boolean isNull(ValueHolder holder) { |
| MajorType type = getValueHolderType(holder); |
| |
| switch(type.getMinorType()) { |
| <#list vv.types as type> |
| <#list type.minor as minor> |
| case ${minor.class?upper_case} : |
| |
| switch (type.getMode()) { |
| case REQUIRED: |
| return true; |
| case OPTIONAL: |
| return ((Nullable${minor.class}Holder) holder).isSet == 0; |
| case REPEATED: |
| return true; |
| } |
| </#list> |
| </#list> |
| case NULL: |
| return true; |
| default: |
| throw new UnsupportedOperationException(buildErrorMessage("check is null", type)); |
| } |
| } |
| |
| public static ValueHolder deNullify(ValueHolder holder) { |
| MajorType type = getValueHolderType(holder); |
| |
| switch(type.getMinorType()) { |
| <#list vv.types as type> |
| <#list type.minor as minor> |
| case ${minor.class?upper_case} : |
| |
| switch (type.getMode()) { |
| case REQUIRED: |
| return holder; |
| case OPTIONAL: |
| if( ((Nullable${minor.class}Holder) holder).isSet == 1) { |
| ${minor.class}Holder newHolder = new ${minor.class}Holder(); |
| |
| <#assign fields = minor.fields!type.fields /> |
| <#list fields as field> |
| newHolder.${field.name} = ((Nullable${minor.class}Holder) holder).${field.name}; |
| </#list> |
| |
| return newHolder; |
| } else { |
| throw new UnsupportedOperationException("You can not convert a null value into a non-null value!"); |
| } |
| case REPEATED: |
| return holder; |
| } |
| </#list> |
| </#list> |
| default: |
| throw new UnsupportedOperationException(buildErrorMessage("deNullify", type)); |
| } |
| } |
| |
| public static ValueHolder nullify(ValueHolder holder) { |
| MajorType type = getValueHolderType(holder); |
| |
| switch(type.getMinorType()) { |
| <#list vv.types as type> |
| <#list type.minor as minor> |
| case ${minor.class?upper_case} : |
| switch (type.getMode()) { |
| case REQUIRED: |
| Nullable${minor.class}Holder newHolder = new Nullable${minor.class}Holder(); |
| newHolder.isSet = 1; |
| <#assign fields = minor.fields!type.fields /> |
| <#list fields as field> |
| newHolder.${field.name} = ((${minor.class}Holder) holder).${field.name}; |
| </#list> |
| return newHolder; |
| case OPTIONAL: |
| return holder; |
| case REPEATED: |
| throw new UnsupportedOperationException("You can not convert repeated type " + type + " to nullable type!"); |
| } |
| </#list> |
| </#list> |
| default: |
| throw new UnsupportedOperationException(buildErrorMessage("nullify", type)); |
| } |
| } |
| |
| public static MajorType getValueHolderType(ValueHolder holder) { |
| if (0 == 1) { |
| return null; |
| } |
| <#list vv.types as type> |
| <#list type.minor as minor> |
| <#if minor.class.contains("Decimal")> |
| else if (holder instanceof ${minor.class}Holder) { |
| return getType((${minor.class}Holder) holder); |
| } else if (holder instanceof Nullable${minor.class}Holder) { |
| return getType((Nullable${minor.class}Holder) holder); |
| } |
| <#else> |
| else if (holder instanceof ${minor.class}Holder) { |
| return ((${minor.class}Holder) holder).TYPE; |
| } else if (holder instanceof Nullable${minor.class}Holder) { |
| return ((Nullable${minor.class}Holder) holder).TYPE; |
| } |
| </#if> |
| </#list> |
| </#list> |
| else if (holder instanceof UntypedNullHolder) { |
| return UntypedNullHolder.TYPE; |
| } |
| throw new UnsupportedOperationException("ValueHolder is not supported for 'getValueHolderType' method."); |
| } |
| |
| <#list vv.types as type> |
| <#list type.minor as minor> |
| <#if minor.class.contains("Decimal")> |
| <#list ["Nullable", "", "Repeated"] as dataMode> |
| public static MajorType getType(${dataMode}${minor.class}Holder holder) { |
| return MajorType.newBuilder() |
| .setMinorType(MinorType.${minor.class?upper_case}) |
| <#if dataMode == "Nullable"> |
| .setMode(DataMode.OPTIONAL) |
| .setScale(holder.scale) |
| .setPrecision(holder.precision) |
| <#elseif dataMode == "Repeated"> |
| .setMode(DataMode.REPEATED) |
| .setScale(holder.vector.getField().getScale()) |
| .setPrecision(holder.vector.getField().getPrecision()) |
| <#else> |
| .setMode(DataMode.REQUIRED) |
| .setScale(holder.scale) |
| .setPrecision(holder.precision) |
| </#if> |
| .build(); |
| } |
| </#list> |
| </#if> |
| </#list> |
| </#list> |
| } |