/**
* 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.hadoop.hive.ql.exec.vector;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.List;
import java.util.Map;
import org.apache.hadoop.hive.serde2.objectinspector.StandardUnionObjectInspector.StandardUnion;
import org.apache.hadoop.hive.serde2.typeinfo.ListTypeInfo;
import org.apache.hadoop.hive.serde2.typeinfo.MapTypeInfo;
import org.apache.hadoop.hive.serde2.typeinfo.StructTypeInfo;
import org.apache.hadoop.hive.serde2.typeinfo.UnionTypeInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.hadoop.hive.common.type.HiveChar;
import org.apache.hadoop.hive.common.type.HiveDecimal;
import org.apache.hadoop.hive.common.type.HiveIntervalDayTime;
import org.apache.hadoop.hive.common.type.HiveIntervalYearMonth;
import org.apache.hadoop.hive.common.type.HiveVarchar;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.plan.VectorPartitionConversion;
import org.apache.hadoop.hive.serde2.io.ByteWritable;
import org.apache.hadoop.hive.serde2.io.DateWritable;
import org.apache.hadoop.hive.serde2.io.DoubleWritable;
import org.apache.hadoop.hive.serde2.io.HiveCharWritable;
import org.apache.hadoop.hive.serde2.io.HiveDecimalWritable;
import org.apache.hadoop.hive.serde2.io.HiveIntervalDayTimeWritable;
import org.apache.hadoop.hive.serde2.io.HiveIntervalYearMonthWritable;
import org.apache.hadoop.hive.serde2.io.HiveVarcharWritable;
import org.apache.hadoop.hive.serde2.io.ShortWritable;
import org.apache.hadoop.hive.serde2.io.TimestampWritable;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector.Category;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory;
import org.apache.hadoop.hive.serde2.objectinspector.StructField;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils;
import org.apache.hadoop.hive.serde2.typeinfo.CharTypeInfo;
import org.apache.hadoop.hive.serde2.typeinfo.PrimitiveTypeInfo;
import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoUtils;
import org.apache.hadoop.hive.serde2.typeinfo.VarcharTypeInfo;
import org.apache.hadoop.io.BooleanWritable;
import org.apache.hadoop.io.BytesWritable;
import org.apache.hadoop.io.FloatWritable;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
import com.google.common.base.Preconditions;
/**
* This class assigns specified columns of a row from a Writable row objects.
*
* The caller provides the data types and projection column numbers of a subset of the columns
* to assign.
*/
public class VectorAssignRow {
private static final long serialVersionUID = 1L;
private static final Logger LOG = LoggerFactory.getLogger(VectorAssignRow.class);
/*
* These members have information for assigning a row column objects into the VectorizedRowBatch
* columns.
*
* We say "target" because when there is conversion the data type being converted is the source.
*/
boolean[] isConvert;
// For each column, are we converting the row column object?
int[] projectionColumnNums;
// Assigning can be a subset of columns, so this is the projection --
// the batch column numbers.
TypeInfo[] targetTypeInfos;
// The type info of each column being assigned.
int[] maxLengths;
// For the CHAR and VARCHAR data types, the maximum character length of
// the columns. Otherwise, 0.
/*
* These members have information for data type conversion.
* Not defined if there is no conversion.
*/
PrimitiveObjectInspector[] convertSourcePrimitiveObjectInspectors;
// The primitive object inspector of the source data type for any column being
// converted. Otherwise, null.
Writable[] convertTargetWritables;
// Conversion to the target data type requires a "helper" target writable in a
// few cases.
/*
* Allocate the target related arrays.
*/
private void allocateArrays(int count) {
isConvert = new boolean[count];
projectionColumnNums = new int[count];
targetTypeInfos = new TypeInfo[count];
maxLengths = new int[count];
}
/*
* Allocate the source conversion related arrays (optional).
*/
private void allocateConvertArrays(int count) {
convertSourcePrimitiveObjectInspectors = new PrimitiveObjectInspector[count];
convertTargetWritables = new Writable[count];
}
/*
* Initialize one column's target related arrays.
*/
private void initTargetEntry(int logicalColumnIndex, int projectionColumnNum, TypeInfo typeInfo) {
isConvert[logicalColumnIndex] = false;
projectionColumnNums[logicalColumnIndex] = projectionColumnNum;
targetTypeInfos[logicalColumnIndex] = typeInfo;
if (typeInfo.getCategory() == Category.PRIMITIVE) {
final PrimitiveTypeInfo primitiveTypeInfo = (PrimitiveTypeInfo) typeInfo;
final PrimitiveCategory primitiveCategory = primitiveTypeInfo.getPrimitiveCategory();
switch (primitiveCategory) {
case CHAR:
maxLengths[logicalColumnIndex] = ((CharTypeInfo) primitiveTypeInfo).getLength();
break;
case VARCHAR:
maxLengths[logicalColumnIndex] = ((VarcharTypeInfo) primitiveTypeInfo).getLength();
break;
default:
// No additional data type specific setting.
break;
}
}
}
/*
* Initialize one column's source conversion related arrays.
* Assumes initTargetEntry has already been called.
*/
private void initConvertSourceEntry(int logicalColumnIndex, TypeInfo convertSourceTypeInfo) {
isConvert[logicalColumnIndex] = true;
final Category convertSourceCategory = convertSourceTypeInfo.getCategory();
if (convertSourceCategory == Category.PRIMITIVE) {
final PrimitiveTypeInfo convertSourcePrimitiveTypeInfo = (PrimitiveTypeInfo) convertSourceTypeInfo;
convertSourcePrimitiveObjectInspectors[logicalColumnIndex] =
PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(
convertSourcePrimitiveTypeInfo);
// These need to be based on the target.
final PrimitiveCategory targetPrimitiveCategory =
((PrimitiveTypeInfo) targetTypeInfos[logicalColumnIndex]).getPrimitiveCategory();
switch (targetPrimitiveCategory) {
case DATE:
convertTargetWritables[logicalColumnIndex] = new DateWritable();
break;
case STRING:
convertTargetWritables[logicalColumnIndex] = new Text();
break;
default:
// No additional data type specific setting.
break;
}
}
}
/*
* Initialize using an StructObjectInspector and a column projection list.
*/
public void init(StructObjectInspector structObjectInspector, List<Integer> projectedColumns)
throws HiveException {
final List<? extends StructField> fields = structObjectInspector.getAllStructFieldRefs();
final int count = fields.size();
allocateArrays(count);
for (int i = 0; i < count; i++) {
final int projectionColumnNum = projectedColumns.get(i);
final StructField field = fields.get(i);
final ObjectInspector fieldInspector = field.getFieldObjectInspector();
final TypeInfo typeInfo =
TypeInfoUtils.getTypeInfoFromTypeString(fieldInspector.getTypeName());
initTargetEntry(i, projectionColumnNum, typeInfo);
}
}
/*
* Initialize using an StructObjectInspector.
* No projection -- the column range 0 .. fields.size()-1
*/
public void init(StructObjectInspector structObjectInspector) throws HiveException {
final List<? extends StructField> fields = structObjectInspector.getAllStructFieldRefs();
final int count = fields.size();
allocateArrays(count);
for (int i = 0; i < count; i++) {
final StructField field = fields.get(i);
final ObjectInspector fieldInspector = field.getFieldObjectInspector();
final TypeInfo typeInfo =
TypeInfoUtils.getTypeInfoFromTypeString(fieldInspector.getTypeName());
initTargetEntry(i, i, typeInfo);
}
}
/*
* Initialize using target data type names.
* No projection -- the column range 0 .. types.size()-1
*/
public void init(List<String> typeNames) throws HiveException {
final int count = typeNames.size();
allocateArrays(count);
for (int i = 0; i < count; i++) {
final TypeInfo typeInfo =
TypeInfoUtils.getTypeInfoFromTypeString(typeNames.get(i));
initTargetEntry(i, i, typeInfo);
}
}
/**
* Initialize for conversion from a provided (source) data types to the target data types
* desired in the VectorizedRowBatch.
*
* No projection -- the column range 0 .. count-1
*
* where count is the minimum of the target data type array size, included array size,
* and source data type array size.
*
* @param sourceTypeInfos
* @param targetTypeInfos
* @param columnsToIncludeTruncated
* Flag array indicating which columns are to be included.
* "Truncated" because all false entries on the end of the array have been
* eliminated.
* @return the minimum count described above is returned. That is, the number of columns
* that will be processed by assign.
*/
public int initConversion(TypeInfo[] sourceTypeInfos, TypeInfo[] targetTypeInfos,
boolean[] columnsToIncludeTruncated) {
final int targetColumnCount;
if (columnsToIncludeTruncated == null) {
targetColumnCount = targetTypeInfos.length;
} else {
targetColumnCount = Math.min(targetTypeInfos.length, columnsToIncludeTruncated.length);
}
final int sourceColumnCount = Math.min(sourceTypeInfos.length, targetColumnCount);
allocateArrays(sourceColumnCount);
allocateConvertArrays(sourceColumnCount);
for (int i = 0; i < sourceColumnCount; i++) {
if (columnsToIncludeTruncated != null && !columnsToIncludeTruncated[i]) {
// Field not included in query.
} else {
final TypeInfo targetTypeInfo = targetTypeInfos[i];
if (targetTypeInfo.getCategory() != ObjectInspector.Category.PRIMITIVE) {
// For now, we don't have an assigner for complex types...
} else {
final TypeInfo sourceTypeInfo = sourceTypeInfos[i];
if (!sourceTypeInfo.equals(targetTypeInfo)) {
if (VectorPartitionConversion.isImplicitVectorColumnConversion(
sourceTypeInfo, targetTypeInfo)) {
// Do implicit conversion accepting the source type and putting it in the same
// target type ColumnVector type.
initTargetEntry(i, i, sourceTypeInfo);
} else {
// Do formal conversion...
initTargetEntry(i, i, targetTypeInfo);
initConvertSourceEntry(i, sourceTypeInfo);
}
} else {
// No conversion.
initTargetEntry(i, i, targetTypeInfo);
}
}
}
}
return sourceColumnCount;
}
/**
* Assign a row's column object to the ColumnVector at batchIndex in the VectorizedRowBatch.
*
* @param batch
* @param batchIndex
* @param logicalColumnIndex
* @param object The row column object whose type is the target data type.
*/
public void assignRowColumn(
VectorizedRowBatch batch, int batchIndex, int logicalColumnIndex, Object object) {
final int projectionColumnNum = projectionColumnNums[logicalColumnIndex];
final TypeInfo targetTypeInfo = targetTypeInfos[logicalColumnIndex];
if (targetTypeInfo == null || targetTypeInfo.getCategory() == null) {
/*
* This is a column that we don't want (i.e. not included) -- we are done.
*/
return;
}
assignRowColumn(batch.cols[projectionColumnNum], batchIndex, targetTypeInfo, object);
}
private void assignRowColumn(
ColumnVector columnVector, int batchIndex, TypeInfo targetTypeInfo, Object object) {
if (object == null) {
VectorizedBatchUtil.setNullColIsNullValue(columnVector, batchIndex);
return;
}
switch (targetTypeInfo.getCategory()) {
case PRIMITIVE:
{
final PrimitiveCategory targetPrimitiveCategory =
((PrimitiveTypeInfo) targetTypeInfo).getPrimitiveCategory();
switch (targetPrimitiveCategory) {
case VOID:
VectorizedBatchUtil.setNullColIsNullValue(columnVector, batchIndex);
return;
case BOOLEAN:
((LongColumnVector) columnVector).vector[batchIndex] =
(((BooleanWritable) object).get() ? 1 : 0);
break;
case BYTE:
((LongColumnVector) columnVector).vector[batchIndex] =
((ByteWritable) object).get();
break;
case SHORT:
((LongColumnVector) columnVector).vector[batchIndex] =
((ShortWritable) object).get();
break;
case INT:
((LongColumnVector) columnVector).vector[batchIndex] =
((IntWritable) object).get();
break;
case LONG:
((LongColumnVector) columnVector).vector[batchIndex] =
((LongWritable) object).get();
break;
case TIMESTAMP:
((TimestampColumnVector) columnVector).set(
batchIndex, ((TimestampWritable) object).getTimestamp());
break;
case DATE:
((LongColumnVector) columnVector).vector[batchIndex] =
((DateWritable) object).getDays();
break;
case FLOAT:
((DoubleColumnVector) columnVector).vector[batchIndex] =
((FloatWritable) object).get();
break;
case DOUBLE:
((DoubleColumnVector) columnVector).vector[batchIndex] =
((DoubleWritable) object).get();
break;
case BINARY:
{
BytesWritable bw = (BytesWritable) object;
((BytesColumnVector) columnVector).setVal(
batchIndex, bw.getBytes(), 0, bw.getLength());
}
break;
case STRING:
{
Text tw = (Text) object;
((BytesColumnVector) columnVector).setVal(
batchIndex, tw.getBytes(), 0, tw.getLength());
}
break;
case VARCHAR:
{
// UNDONE: Performance problem with conversion to String, then bytes...
// We store VARCHAR type stripped of pads.
HiveVarchar hiveVarchar;
if (object instanceof HiveVarchar) {
hiveVarchar = (HiveVarchar) object;
} else {
hiveVarchar = ((HiveVarcharWritable) object).getHiveVarchar();
}
// TODO: HIVE-13624 Do we need maxLength checking?
byte[] bytes = hiveVarchar.getValue().getBytes();
((BytesColumnVector) columnVector).setVal(
batchIndex, bytes, 0, bytes.length);
}
break;
case CHAR:
{
// UNDONE: Performance problem with conversion to String, then bytes...
// We store CHAR type stripped of pads.
HiveChar hiveChar;
if (object instanceof HiveChar) {
hiveChar = (HiveChar) object;
} else {
hiveChar = ((HiveCharWritable) object).getHiveChar();
}
// TODO: HIVE-13624 Do we need maxLength checking?
// We store CHAR in vector row batch with padding stripped.
byte[] bytes = hiveChar.getStrippedValue().getBytes();
((BytesColumnVector) columnVector).setVal(
batchIndex, bytes, 0, bytes.length);
}
break;
case DECIMAL:
if (object instanceof HiveDecimal) {
((DecimalColumnVector) columnVector).set(
batchIndex, (HiveDecimal) object);
} else {
((DecimalColumnVector) columnVector).set(
batchIndex, (HiveDecimalWritable) object);
}
break;
case INTERVAL_YEAR_MONTH:
((LongColumnVector) columnVector).vector[batchIndex] =
((HiveIntervalYearMonthWritable) object).getHiveIntervalYearMonth().getTotalMonths();
break;
case INTERVAL_DAY_TIME:
((IntervalDayTimeColumnVector) columnVector).set(
batchIndex, ((HiveIntervalDayTimeWritable) object).getHiveIntervalDayTime());
break;
default:
throw new RuntimeException("Primitive category " + targetPrimitiveCategory.name() +
" not supported");
}
}
break;
case LIST:
{
final ListColumnVector listColumnVector = (ListColumnVector) columnVector;
final ListTypeInfo listTypeInfo = (ListTypeInfo) targetTypeInfo;
final TypeInfo elementTypeInfo = listTypeInfo.getListElementTypeInfo();
final List list = (List) object;
final int size = list.size();
final int childCount = listColumnVector.childCount;
listColumnVector.offsets[batchIndex] = childCount;
listColumnVector.lengths[batchIndex] = size;
listColumnVector.childCount = childCount + size;
listColumnVector.child.ensureSize(childCount + size, true);
for (int i = 0; i < size; i++) {
assignRowColumn(listColumnVector.child, childCount + i, elementTypeInfo, list.get(i));
}
}
break;
case MAP:
{
final MapColumnVector mapColumnVector = (MapColumnVector) columnVector;
final MapTypeInfo mapTypeInfo = (MapTypeInfo) targetTypeInfo;
final Map<Object, Object> map = (Map<Object, Object>) object;
final int size = map.size();
int childCount = mapColumnVector.childCount;
mapColumnVector.offsets[batchIndex] = childCount;
mapColumnVector.lengths[batchIndex] = size;
mapColumnVector.keys.ensureSize(childCount + size, true);
mapColumnVector.values.ensureSize(childCount + size, true);
for (Map.Entry<Object, Object> entry : map.entrySet()) {
assignRowColumn(mapColumnVector.keys, childCount, mapTypeInfo.getMapKeyTypeInfo(), entry.getKey());
assignRowColumn(mapColumnVector.values, childCount, mapTypeInfo.getMapValueTypeInfo(), entry.getValue());
childCount++;
}
mapColumnVector.childCount = childCount;
}
break;
case STRUCT:
{
final StructColumnVector structColumnVector = (StructColumnVector) columnVector;
final StructTypeInfo structTypeInfo = (StructTypeInfo) targetTypeInfo;
final List<TypeInfo> fieldStructTypeInfos = structTypeInfo.getAllStructFieldTypeInfos();
final int size = fieldStructTypeInfos.size();
if (object instanceof List) {
final List struct = (List) object;
for (int i = 0; i < size; i++) {
assignRowColumn(structColumnVector.fields[i], batchIndex, fieldStructTypeInfos.get(i), struct.get(i));
}
} else {
final Object[] array = (Object[]) object;
for (int i = 0; i < size; i++) {
assignRowColumn(structColumnVector.fields[i], batchIndex, fieldStructTypeInfos.get(i), array[i]);
}
}
}
break;
case UNION:
{
final StandardUnion union = (StandardUnion) object;
final UnionColumnVector unionColumnVector = (UnionColumnVector) columnVector;
final UnionTypeInfo unionTypeInfo = (UnionTypeInfo) targetTypeInfo;
final List<TypeInfo> objectTypeInfos = unionTypeInfo.getAllUnionObjectTypeInfos();
final byte tag = union.getTag();
unionColumnVector.tags[batchIndex] = tag;
assignRowColumn(unionColumnVector.fields[tag], batchIndex, objectTypeInfos.get(tag), union.getObject());
}
break;
default:
throw new RuntimeException("Category " + targetTypeInfo.getCategory().name() + " not supported");
}
/*
* We always set the null flag to false when there is a value.
*/
columnVector.isNull[batchIndex] = false;
}
/**
* Convert row's column object and then assign it the ColumnVector at batchIndex
* in the VectorizedRowBatch.
*
* Public so VectorDeserializeRow can use this method to convert a row's column object.
*
* @param batch
* @param batchIndex
* @param logicalColumnIndex
* @param object The row column object whose type is the VectorAssignRow.initConversion
* source data type.
*
*/
public void assignConvertRowColumn(VectorizedRowBatch batch, int batchIndex,
int logicalColumnIndex, Object object) {
Preconditions.checkState(isConvert[logicalColumnIndex]);
final Category targetCategory = targetTypeInfos[logicalColumnIndex].getCategory();
if (targetCategory == null) {
/*
* This is a column that we don't want (i.e. not included) -- we are done.
*/
return;
}
final int projectionColumnNum = projectionColumnNums[logicalColumnIndex];
if (object == null) {
VectorizedBatchUtil.setNullColIsNullValue(batch.cols[projectionColumnNum], batchIndex);
return;
}
try {
switch (targetCategory) {
case PRIMITIVE:
final PrimitiveCategory targetPrimitiveCategory =
((PrimitiveTypeInfo) targetTypeInfos[logicalColumnIndex]).getPrimitiveCategory();
switch (targetPrimitiveCategory) {
case VOID:
VectorizedBatchUtil.setNullColIsNullValue(batch.cols[projectionColumnNum], batchIndex);
return;
case BOOLEAN:
((LongColumnVector) batch.cols[projectionColumnNum]).vector[batchIndex] =
(PrimitiveObjectInspectorUtils.getBoolean(
object, convertSourcePrimitiveObjectInspectors[logicalColumnIndex]) ? 1 : 0);
break;
case BYTE:
((LongColumnVector) batch.cols[projectionColumnNum]).vector[batchIndex] =
PrimitiveObjectInspectorUtils.getByte(
object, convertSourcePrimitiveObjectInspectors[logicalColumnIndex]);
break;
case SHORT:
((LongColumnVector) batch.cols[projectionColumnNum]).vector[batchIndex] =
PrimitiveObjectInspectorUtils.getShort(
object, convertSourcePrimitiveObjectInspectors[logicalColumnIndex]);
break;
case INT:
((LongColumnVector) batch.cols[projectionColumnNum]).vector[batchIndex] =
PrimitiveObjectInspectorUtils.getInt(
object, convertSourcePrimitiveObjectInspectors[logicalColumnIndex]);
break;
case LONG:
((LongColumnVector) batch.cols[projectionColumnNum]).vector[batchIndex] =
PrimitiveObjectInspectorUtils.getLong(
object, convertSourcePrimitiveObjectInspectors[logicalColumnIndex]);
break;
case TIMESTAMP:
{
final Timestamp timestamp =
PrimitiveObjectInspectorUtils.getTimestamp(
object, convertSourcePrimitiveObjectInspectors[logicalColumnIndex]);
if (timestamp == null) {
VectorizedBatchUtil.setNullColIsNullValue(batch.cols[projectionColumnNum], batchIndex);
return;
}
((TimestampColumnVector) batch.cols[projectionColumnNum]).set(
batchIndex, timestamp);
}
break;
case DATE:
{
final Date date = PrimitiveObjectInspectorUtils.getDate(
object, convertSourcePrimitiveObjectInspectors[logicalColumnIndex]);
if (date == null) {
VectorizedBatchUtil.setNullColIsNullValue(batch.cols[projectionColumnNum], batchIndex);
return;
}
final DateWritable dateWritable = (DateWritable) convertTargetWritables[logicalColumnIndex];
dateWritable.set(date);
((LongColumnVector) batch.cols[projectionColumnNum]).vector[batchIndex] =
dateWritable.getDays();
}
break;
case FLOAT:
((DoubleColumnVector) batch.cols[projectionColumnNum]).vector[batchIndex] =
PrimitiveObjectInspectorUtils.getFloat(
object, convertSourcePrimitiveObjectInspectors[logicalColumnIndex]);
break;
case DOUBLE:
((DoubleColumnVector) batch.cols[projectionColumnNum]).vector[batchIndex] =
PrimitiveObjectInspectorUtils.getDouble(
object, convertSourcePrimitiveObjectInspectors[logicalColumnIndex]);
break;
case BINARY:
{
final BytesWritable bytesWritable =
PrimitiveObjectInspectorUtils.getBinary(
object, convertSourcePrimitiveObjectInspectors[logicalColumnIndex]);
if (bytesWritable == null) {
VectorizedBatchUtil.setNullColIsNullValue(batch.cols[projectionColumnNum], batchIndex);
return;
}
((BytesColumnVector) batch.cols[projectionColumnNum]).setVal(
batchIndex, bytesWritable.getBytes(), 0, bytesWritable.getLength());
}
break;
case STRING:
{
final String string = PrimitiveObjectInspectorUtils.getString(
object, convertSourcePrimitiveObjectInspectors[logicalColumnIndex]);
if (string == null) {
VectorizedBatchUtil.setNullColIsNullValue(batch.cols[projectionColumnNum], batchIndex);
return;
}
Text text = (Text) convertTargetWritables[logicalColumnIndex];
text.set(string);
((BytesColumnVector) batch.cols[projectionColumnNum]).setVal(
batchIndex, text.getBytes(), 0, text.getLength());
}
break;
case VARCHAR:
{
// UNDONE: Performance problem with conversion to String, then bytes...
final HiveVarchar hiveVarchar =
PrimitiveObjectInspectorUtils.getHiveVarchar(
object, convertSourcePrimitiveObjectInspectors[logicalColumnIndex]);
if (hiveVarchar == null) {
VectorizedBatchUtil.setNullColIsNullValue(batch.cols[projectionColumnNum], batchIndex);
return;
}
// TODO: Do we need maxLength checking?
byte[] bytes = hiveVarchar.getValue().getBytes();
((BytesColumnVector) batch.cols[projectionColumnNum]).setVal(
batchIndex, bytes, 0, bytes.length);
}
break;
case CHAR:
{
// UNDONE: Performance problem with conversion to String, then bytes...
final HiveChar hiveChar =
PrimitiveObjectInspectorUtils.getHiveChar(
object, convertSourcePrimitiveObjectInspectors[logicalColumnIndex]);
if (hiveChar == null) {
VectorizedBatchUtil.setNullColIsNullValue(batch.cols[projectionColumnNum], batchIndex);
return;
}
// We store CHAR in vector row batch with padding stripped.
// TODO: Do we need maxLength checking?
final byte[] bytes = hiveChar.getStrippedValue().getBytes();
((BytesColumnVector) batch.cols[projectionColumnNum]).setVal(
batchIndex, bytes, 0, bytes.length);
}
break;
case DECIMAL:
{
final HiveDecimal hiveDecimal =
PrimitiveObjectInspectorUtils.getHiveDecimal(
object, convertSourcePrimitiveObjectInspectors[logicalColumnIndex]);
if (hiveDecimal == null) {
VectorizedBatchUtil.setNullColIsNullValue(batch.cols[projectionColumnNum], batchIndex);
return;
}
((DecimalColumnVector) batch.cols[projectionColumnNum]).set(
batchIndex, hiveDecimal);
}
break;
case INTERVAL_YEAR_MONTH:
{
final HiveIntervalYearMonth intervalYearMonth =
PrimitiveObjectInspectorUtils.getHiveIntervalYearMonth(
object, convertSourcePrimitiveObjectInspectors[logicalColumnIndex]);
if (intervalYearMonth == null) {
VectorizedBatchUtil.setNullColIsNullValue(batch.cols[projectionColumnNum], batchIndex);
return;
}
((LongColumnVector) batch.cols[projectionColumnNum]).vector[batchIndex] =
intervalYearMonth.getTotalMonths();
}
break;
case INTERVAL_DAY_TIME:
{
final HiveIntervalDayTime intervalDayTime =
PrimitiveObjectInspectorUtils.getHiveIntervalDayTime(
object, convertSourcePrimitiveObjectInspectors[logicalColumnIndex]);
if (intervalDayTime == null) {
VectorizedBatchUtil.setNullColIsNullValue(batch.cols[projectionColumnNum], batchIndex);
return;
}
((IntervalDayTimeColumnVector) batch.cols[projectionColumnNum]).set(
batchIndex, intervalDayTime);
}
break;
default:
throw new RuntimeException("Primitive category " + targetPrimitiveCategory.name() +
" not supported");
}
break;
default:
throw new RuntimeException("Category " + targetCategory.name() + " not supported");
}
} catch (NumberFormatException e) {
// Some of the conversion methods throw this exception on numeric parsing errors.
VectorizedBatchUtil.setNullColIsNullValue(batch.cols[projectionColumnNum], batchIndex);
return;
}
// We always set the null flag to false when there is a value.
batch.cols[projectionColumnNum].isNull[batchIndex] = false;
}
/*
* Assign a row from an array of objects.
*/
public void assignRow(VectorizedRowBatch batch, int batchIndex, Object[] objects) {
final int count = isConvert.length;
for (int i = 0; i < count; i++) {
if (isConvert[i]) {
assignConvertRowColumn(batch, batchIndex, i, objects[i]);
} else {
assignRowColumn(batch, batchIndex, i, objects[i]);
}
}
}
/*
* Assign a row from a list of standard objects up to a count
*/
public void assignRow(VectorizedRowBatch batch, int batchIndex,
List<Object> standardObjects, int columnCount) {
for (int i = 0; i < columnCount; i++) {
if (isConvert[i]) {
assignConvertRowColumn(batch, batchIndex, i, standardObjects.get(i));
} else {
assignRowColumn(batch, batchIndex, i, standardObjects.get(i));
}
}
}
}