blob: a34649fe377a6d18dcc04b714d3ddff7c9be545e [file] [log] [blame]
/*
* 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>
}