/**
* 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.serde2.objectinspector.primitive;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.nio.charset.CharacterCodingException;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.hive.common.type.HiveChar;
import org.apache.hadoop.hive.common.type.HiveDecimal;
import org.apache.hadoop.hive.common.type.HiveVarchar;
import org.apache.hadoop.hive.serde.serdeConstants;
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.HiveVarcharWritable;
import org.apache.hadoop.hive.serde2.io.ShortWritable;
import org.apache.hadoop.hive.serde2.io.TimestampWritable;
import org.apache.hadoop.hive.serde2.lazy.LazyInteger;
import org.apache.hadoop.hive.serde2.lazy.LazyLong;
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.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.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.Writable;
import org.apache.hadoop.io.WritableUtils;
/**
* ObjectInspectorFactory is the primary way to create new ObjectInspector
* instances.
*
* SerDe classes should call the static functions in this library to create an
* ObjectInspector to return to the caller of SerDe2.getObjectInspector().
*/
public final class PrimitiveObjectInspectorUtils {
private static Log LOG = LogFactory.getLog(PrimitiveObjectInspectorUtils.class);
/**
* TypeEntry stores information about a Hive Primitive TypeInfo.
*/
public static class PrimitiveTypeEntry implements Writable, Cloneable {
/**
* The category of the PrimitiveType.
*/
public PrimitiveObjectInspector.PrimitiveCategory primitiveCategory;
/**
* primitiveJavaType refers to java types like int, double, etc.
*/
public Class<?> primitiveJavaType;
/**
* primitiveJavaClass refers to java classes like Integer, Double, String
* etc.
*/
public Class<?> primitiveJavaClass;
/**
* writableClass refers to hadoop Writable classes like IntWritable,
* DoubleWritable, Text etc.
*/
public Class<?> primitiveWritableClass;
/**
* typeName is the name of the type as in DDL.
*/
public String typeName;
protected PrimitiveTypeEntry() {
super();
}
PrimitiveTypeEntry(
PrimitiveObjectInspector.PrimitiveCategory primitiveCategory,
String typeName, Class<?> primitiveType, Class<?> javaClass,
Class<?> hiveClass) {
this.primitiveCategory = primitiveCategory;
primitiveJavaType = primitiveType;
primitiveJavaClass = javaClass;
primitiveWritableClass = hiveClass;
this.typeName = typeName;
}
@Override
public void readFields(DataInput in) throws IOException {
primitiveCategory = WritableUtils.readEnum(in,
PrimitiveObjectInspector.PrimitiveCategory.class);
typeName = WritableUtils.readString(in);
try {
primitiveJavaType = Class.forName(WritableUtils.readString(in));
primitiveJavaClass = Class.forName(WritableUtils.readString(in));
primitiveWritableClass = Class.forName(WritableUtils.readString(in));
} catch (ClassNotFoundException e) {
throw new IOException(e);
}
}
@Override
public void write(DataOutput out) throws IOException {
WritableUtils.writeEnum(out, primitiveCategory);
WritableUtils.writeString(out, typeName);
WritableUtils.writeString(out, primitiveJavaType.getName());
WritableUtils.writeString(out, primitiveJavaClass.getName());
WritableUtils.writeString(out, primitiveWritableClass.getName());
}
@Override
public Object clone() {
PrimitiveTypeEntry result = new PrimitiveTypeEntry(
this.primitiveCategory,
this.typeName,
this.primitiveJavaType,
this.primitiveJavaClass,
this.primitiveWritableClass);
return result;
}
@Override
public String toString() {
return typeName;
}
}
static final Map<PrimitiveCategory, PrimitiveTypeEntry> primitiveCategoryToTypeEntry = new HashMap<PrimitiveCategory, PrimitiveTypeEntry>();
static final Map<Class<?>, PrimitiveTypeEntry> primitiveJavaTypeToTypeEntry = new HashMap<Class<?>, PrimitiveTypeEntry>();
static final Map<Class<?>, PrimitiveTypeEntry> primitiveJavaClassToTypeEntry = new HashMap<Class<?>, PrimitiveTypeEntry>();
static final Map<Class<?>, PrimitiveTypeEntry> primitiveWritableClassToTypeEntry = new HashMap<Class<?>, PrimitiveTypeEntry>();
// Base type name to PrimitiveTypeEntry map.
private static final Map<String, PrimitiveTypeEntry> typeNameToTypeEntry = new HashMap<String, PrimitiveTypeEntry>();
static void addParameterizedType(PrimitiveTypeEntry t) {
typeNameToTypeEntry.put(t.toString(), t);
}
static void registerType(PrimitiveTypeEntry t) {
if (t.primitiveCategory != PrimitiveCategory.UNKNOWN) {
primitiveCategoryToTypeEntry.put(t.primitiveCategory, t);
}
if (t.primitiveJavaType != null) {
primitiveJavaTypeToTypeEntry.put(t.primitiveJavaType, t);
}
if (t.primitiveJavaClass != null) {
primitiveJavaClassToTypeEntry.put(t.primitiveJavaClass, t);
}
if (t.primitiveWritableClass != null) {
primitiveWritableClassToTypeEntry.put(t.primitiveWritableClass, t);
}
if (t.typeName != null) {
typeNameToTypeEntry.put(t.typeName, t);
}
}
public static final PrimitiveTypeEntry binaryTypeEntry = new PrimitiveTypeEntry(
PrimitiveCategory.BINARY, serdeConstants.BINARY_TYPE_NAME, byte[].class,
byte[].class, BytesWritable.class);
public static final PrimitiveTypeEntry stringTypeEntry = new PrimitiveTypeEntry(
PrimitiveCategory.STRING, serdeConstants.STRING_TYPE_NAME, null, String.class,
Text.class);
public static final PrimitiveTypeEntry booleanTypeEntry = new PrimitiveTypeEntry(
PrimitiveCategory.BOOLEAN, serdeConstants.BOOLEAN_TYPE_NAME, Boolean.TYPE,
Boolean.class, BooleanWritable.class);
public static final PrimitiveTypeEntry intTypeEntry = new PrimitiveTypeEntry(
PrimitiveCategory.INT, serdeConstants.INT_TYPE_NAME, Integer.TYPE,
Integer.class, IntWritable.class);
public static final PrimitiveTypeEntry longTypeEntry = new PrimitiveTypeEntry(
PrimitiveCategory.LONG, serdeConstants.BIGINT_TYPE_NAME, Long.TYPE,
Long.class, LongWritable.class);
public static final PrimitiveTypeEntry floatTypeEntry = new PrimitiveTypeEntry(
PrimitiveCategory.FLOAT, serdeConstants.FLOAT_TYPE_NAME, Float.TYPE,
Float.class, FloatWritable.class);
public static final PrimitiveTypeEntry voidTypeEntry = new PrimitiveTypeEntry(
PrimitiveCategory.VOID, serdeConstants.VOID_TYPE_NAME, Void.TYPE, Void.class,
NullWritable.class);
// No corresponding Writable classes for the following 3 in hadoop 0.17.0
public static final PrimitiveTypeEntry doubleTypeEntry = new PrimitiveTypeEntry(
PrimitiveCategory.DOUBLE, serdeConstants.DOUBLE_TYPE_NAME, Double.TYPE,
Double.class, DoubleWritable.class);
public static final PrimitiveTypeEntry byteTypeEntry = new PrimitiveTypeEntry(
PrimitiveCategory.BYTE, serdeConstants.TINYINT_TYPE_NAME, Byte.TYPE,
Byte.class, ByteWritable.class);
public static final PrimitiveTypeEntry shortTypeEntry = new PrimitiveTypeEntry(
PrimitiveCategory.SHORT, serdeConstants.SMALLINT_TYPE_NAME, Short.TYPE,
Short.class, ShortWritable.class);
public static final PrimitiveTypeEntry dateTypeEntry = new PrimitiveTypeEntry(
PrimitiveCategory.DATE, serdeConstants.DATE_TYPE_NAME, null,
Date.class, DateWritable.class);
public static final PrimitiveTypeEntry timestampTypeEntry = new PrimitiveTypeEntry(
PrimitiveCategory.TIMESTAMP, serdeConstants.TIMESTAMP_TYPE_NAME, null,
Timestamp.class, TimestampWritable.class);
public static final PrimitiveTypeEntry decimalTypeEntry = new PrimitiveTypeEntry(
PrimitiveCategory.DECIMAL, serdeConstants.DECIMAL_TYPE_NAME, null,
HiveDecimal.class, HiveDecimalWritable.class);
public static final PrimitiveTypeEntry varcharTypeEntry = new PrimitiveTypeEntry(
PrimitiveCategory.VARCHAR, serdeConstants.VARCHAR_TYPE_NAME, null, HiveVarchar.class,
HiveVarcharWritable.class);
public static final PrimitiveTypeEntry charTypeEntry = new PrimitiveTypeEntry(
PrimitiveCategory.CHAR, serdeConstants.CHAR_TYPE_NAME, null, HiveChar.class,
HiveCharWritable.class);
// The following is a complex type for special handling
public static final PrimitiveTypeEntry unknownTypeEntry = new PrimitiveTypeEntry(
PrimitiveCategory.UNKNOWN, "unknown", null, Object.class, null);
static {
registerType(binaryTypeEntry);
registerType(stringTypeEntry);
registerType(charTypeEntry);
registerType(varcharTypeEntry);
registerType(booleanTypeEntry);
registerType(intTypeEntry);
registerType(longTypeEntry);
registerType(floatTypeEntry);
registerType(voidTypeEntry);
registerType(doubleTypeEntry);
registerType(byteTypeEntry);
registerType(shortTypeEntry);
registerType(dateTypeEntry);
registerType(timestampTypeEntry);
registerType(decimalTypeEntry);
registerType(unknownTypeEntry);
}
/**
* Return Whether the class is a Java Primitive type or a Java Primitive
* class.
*/
public static Class<?> primitiveJavaTypeToClass(Class<?> clazz) {
PrimitiveTypeEntry t = primitiveJavaTypeToTypeEntry.get(clazz);
return t == null ? clazz : t.primitiveJavaClass;
}
/**
* Whether the class is a Java Primitive type or a Java Primitive class.
*/
public static boolean isPrimitiveJava(Class<?> clazz) {
return primitiveJavaTypeToTypeEntry.get(clazz) != null
|| primitiveJavaClassToTypeEntry.get(clazz) != null;
}
/**
* Whether the class is a Java Primitive type.
*/
public static boolean isPrimitiveJavaType(Class<?> clazz) {
return primitiveJavaTypeToTypeEntry.get(clazz) != null;
}
/**
* Whether the class is a Java Primitive class.
*/
public static boolean isPrimitiveJavaClass(Class<?> clazz) {
return primitiveJavaClassToTypeEntry.get(clazz) != null;
}
/**
* Whether the class is a Hive Primitive Writable class.
*/
public static boolean isPrimitiveWritableClass(Class<?> clazz) {
return primitiveWritableClassToTypeEntry.get(clazz) != null;
}
/**
* Get the typeName from a Java Primitive Type or Java PrimitiveClass.
*/
public static String getTypeNameFromPrimitiveJava(Class<?> clazz) {
PrimitiveTypeEntry t = primitiveJavaTypeToTypeEntry.get(clazz);
if (t == null) {
t = primitiveJavaClassToTypeEntry.get(clazz);
}
return t == null ? null : t.typeName;
}
/**
* Get the typeName from a Primitive Writable Class.
*/
public static String getTypeNameFromPrimitiveWritable(Class<?> clazz) {
PrimitiveTypeEntry t = primitiveWritableClassToTypeEntry.get(clazz);
return t == null ? null : t.typeName;
}
/**
* Get the typeName from a Java Primitive Type or Java PrimitiveClass.
*/
public static PrimitiveTypeEntry getTypeEntryFromPrimitiveCategory(
PrimitiveCategory category) {
return primitiveCategoryToTypeEntry.get(category);
}
/**
* Get the TypeEntry for a Java Primitive Type or Java PrimitiveClass.
*/
public static PrimitiveTypeEntry getTypeEntryFromPrimitiveJava(Class<?> clazz) {
PrimitiveTypeEntry t = primitiveJavaTypeToTypeEntry.get(clazz);
if (t == null) {
t = primitiveJavaClassToTypeEntry.get(clazz);
}
return t;
}
/**
* Get the TypeEntry for a Java Primitive Type or Java PrimitiveClass.
*/
public static PrimitiveTypeEntry getTypeEntryFromPrimitiveJavaType(
Class<?> clazz) {
return primitiveJavaTypeToTypeEntry.get(clazz);
}
/**
* Get the TypeEntry for a Java Primitive Type or Java PrimitiveClass.
*/
public static PrimitiveTypeEntry getTypeEntryFromPrimitiveJavaClass(
Class<?> clazz) {
return primitiveJavaClassToTypeEntry.get(clazz);
}
/**
* Get the TypeEntry for a Primitive Writable Class.
*/
public static PrimitiveTypeEntry getTypeEntryFromPrimitiveWritableClass(
Class<?> clazz) {
return primitiveWritableClassToTypeEntry.get(clazz);
}
/**
* Get the TypeEntry for the given base type name (int, varchar, etc).
*/
public static PrimitiveTypeEntry getTypeEntryFromTypeName(String typeName) {
return typeNameToTypeEntry.get(typeName);
}
/**
* Compare 2 primitive objects. Conversion not allowed. Note that NULL does
* not equal to NULL according to SQL standard.
*/
public static boolean comparePrimitiveObjects(Object o1,
PrimitiveObjectInspector oi1, Object o2, PrimitiveObjectInspector oi2) {
if (o1 == null || o2 == null) {
return false;
}
if (oi1.getPrimitiveCategory() != oi2.getPrimitiveCategory()) {
return false;
}
switch (oi1.getPrimitiveCategory()) {
case BOOLEAN: {
return ((BooleanObjectInspector) oi1).get(o1) == ((BooleanObjectInspector) oi2)
.get(o2);
}
case BYTE: {
return ((ByteObjectInspector) oi1).get(o1) == ((ByteObjectInspector) oi2)
.get(o2);
}
case SHORT: {
return ((ShortObjectInspector) oi1).get(o1) == ((ShortObjectInspector) oi2)
.get(o2);
}
case INT: {
return ((IntObjectInspector) oi1).get(o1) == ((IntObjectInspector) oi2)
.get(o2);
}
case LONG: {
return ((LongObjectInspector) oi1).get(o1) == ((LongObjectInspector) oi2)
.get(o2);
}
case FLOAT: {
return ((FloatObjectInspector) oi1).get(o1) == ((FloatObjectInspector) oi2)
.get(o2);
}
case DOUBLE: {
return ((DoubleObjectInspector) oi1).get(o1) == ((DoubleObjectInspector) oi2)
.get(o2);
}
case STRING: {
Writable t1 = ((StringObjectInspector) oi1)
.getPrimitiveWritableObject(o1);
Writable t2 = ((StringObjectInspector) oi2)
.getPrimitiveWritableObject(o2);
return t1.equals(t2);
}
case CHAR: {
return ((HiveCharObjectInspector)oi1).getPrimitiveWritableObject(o1)
.equals(((HiveCharObjectInspector)oi2).getPrimitiveWritableObject(o2));
}
case VARCHAR: {
return ((HiveVarcharObjectInspector)oi1).getPrimitiveWritableObject(o1)
.equals(((HiveVarcharObjectInspector)oi2).getPrimitiveWritableObject(o2));
}
case DATE: {
return ((DateObjectInspector) oi1).getPrimitiveWritableObject(o1)
.equals(((DateObjectInspector) oi2).getPrimitiveWritableObject(o2));
}
case TIMESTAMP: {
return ((TimestampObjectInspector) oi1).getPrimitiveWritableObject(o1)
.equals(((TimestampObjectInspector) oi2).getPrimitiveWritableObject(o2));
}
case BINARY: {
return ((BinaryObjectInspector) oi1).getPrimitiveWritableObject(o1).
equals(((BinaryObjectInspector) oi2).getPrimitiveWritableObject(o2));
}
case DECIMAL: {
return ((HiveDecimalObjectInspector) oi1).getPrimitiveJavaObject(o1)
.compareTo(((HiveDecimalObjectInspector) oi2).getPrimitiveJavaObject(o2)) == 0;
}
default:
return false;
}
}
/**
* Convert a primitive object to double.
*/
public static double convertPrimitiveToDouble(Object o, PrimitiveObjectInspector oi) {
switch (oi.getPrimitiveCategory()) {
case BOOLEAN:
return ((BooleanObjectInspector) oi).get(o) ? 1 : 0;
case BYTE:
return ((ByteObjectInspector) oi).get(o);
case SHORT:
return ((ShortObjectInspector) oi).get(o);
case INT:
return ((IntObjectInspector) oi).get(o);
case LONG:
return ((LongObjectInspector) oi).get(o);
case FLOAT:
return ((FloatObjectInspector) oi).get(o);
case DOUBLE:
return ((DoubleObjectInspector) oi).get(o);
case STRING:
return Double.valueOf(((StringObjectInspector) oi).getPrimitiveJavaObject(o));
case TIMESTAMP:
return ((TimestampObjectInspector) oi).getPrimitiveWritableObject(o)
.getDouble();
case DECIMAL:
return ((HiveDecimalObjectInspector) oi).getPrimitiveJavaObject(o).doubleValue();
case DATE: // unsupported conversion
default:
throw new NumberFormatException();
}
}
/**
* Compare 2 Primitive Objects with their Object Inspector, conversions
* allowed. Note that NULL does not equal to NULL according to SQL standard.
*/
public static boolean comparePrimitiveObjectsWithConversion(Object o1,
PrimitiveObjectInspector oi1, Object o2, PrimitiveObjectInspector oi2) {
if (o1 == null || o2 == null) {
return false;
}
if (oi1.getPrimitiveCategory() == oi2.getPrimitiveCategory()) {
return comparePrimitiveObjects(o1, oi1, o2, oi2);
}
// If not equal, convert all to double and compare
try {
return convertPrimitiveToDouble(o1, oi1) == convertPrimitiveToDouble(o2,
oi2);
} catch (NumberFormatException e) {
return false;
}
}
/**
* Get the boolean value out of a primitive object. Note that
* NullPointerException will be thrown if o is null. Note that
* NumberFormatException will be thrown if o is not a valid number.
*/
public static boolean getBoolean(Object o, PrimitiveObjectInspector oi) {
boolean result = false;
switch (oi.getPrimitiveCategory()) {
case VOID:
result = false;
break;
case BOOLEAN:
result = ((BooleanObjectInspector) oi).get(o);
break;
case BYTE:
result = ((ByteObjectInspector) oi).get(o) != 0;
break;
case SHORT:
result = ((ShortObjectInspector) oi).get(o) != 0;
break;
case INT:
result = ((IntObjectInspector) oi).get(o) != 0;
break;
case LONG:
result = (int) ((LongObjectInspector) oi).get(o) != 0;
break;
case FLOAT:
result = (int) ((FloatObjectInspector) oi).get(o) != 0;
break;
case DOUBLE:
result = (int) ((DoubleObjectInspector) oi).get(o) != 0;
break;
case STRING:
StringObjectInspector soi = (StringObjectInspector) oi;
if (soi.preferWritable()) {
Text t = soi.getPrimitiveWritableObject(o);
result = t.getLength() != 0;
} else {
String s = soi.getPrimitiveJavaObject(o);
result = s.length() != 0;
}
break;
case TIMESTAMP:
result = (((TimestampObjectInspector) oi)
.getPrimitiveWritableObject(o).getSeconds() != 0);
break;
case DECIMAL:
result = HiveDecimal.ZERO.compareTo(
((HiveDecimalObjectInspector) oi).getPrimitiveJavaObject(o)) != 0;
break;
case DATE: // unsupported conversion
default:
throw new RuntimeException("Hive 2 Internal error: unsupported conversion from type: "
+ oi.getTypeName());
}
return result;
}
/**
* Get the byte value out of a primitive object. Note that
* NullPointerException will be thrown if o is null. Note that
* NumberFormatException will be thrown if o is not a valid number.
*/
public static byte getByte(Object o, PrimitiveObjectInspector oi) {
return (byte) getInt(o, oi);
}
/**
* Get the short value out of a primitive object. Note that
* NullPointerException will be thrown if o is null. Note that
* NumberFormatException will be thrown if o is not a valid number.
*/
public static short getShort(Object o, PrimitiveObjectInspector oi) {
return (short) getInt(o, oi);
}
/**
* Get the integer value out of a primitive object. Note that
* NullPointerException will be thrown if o is null. Note that
* NumberFormatException will be thrown if o is not a valid number.
*/
public static int getInt(Object o, PrimitiveObjectInspector oi) {
int result = 0;
switch (oi.getPrimitiveCategory()) {
case VOID: {
result = 0;
break;
}
case BOOLEAN: {
result = (((BooleanObjectInspector) oi).get(o) ? 1 : 0);
break;
}
case BYTE: {
result = ((ByteObjectInspector) oi).get(o);
break;
}
case SHORT: {
result = ((ShortObjectInspector) oi).get(o);
break;
}
case INT: {
result = ((IntObjectInspector) oi).get(o);
break;
}
case LONG: {
result = (int) ((LongObjectInspector) oi).get(o);
break;
}
case FLOAT: {
result = (int) ((FloatObjectInspector) oi).get(o);
break;
}
case DOUBLE: {
result = (int) ((DoubleObjectInspector) oi).get(o);
break;
}
case STRING: {
StringObjectInspector soi = (StringObjectInspector) oi;
if (soi.preferWritable()) {
Text t = soi.getPrimitiveWritableObject(o);
result = LazyInteger.parseInt(t.getBytes(), 0, t.getLength());
} else {
String s = soi.getPrimitiveJavaObject(o);
result = Integer.parseInt(s);
}
break;
}
case CHAR:
case VARCHAR: {
result = Integer.parseInt(getString(o, oi));
break;
}
case TIMESTAMP:
result = (int) (((TimestampObjectInspector) oi)
.getPrimitiveWritableObject(o).getSeconds());
break;
case DECIMAL:
result = ((HiveDecimalObjectInspector) oi)
.getPrimitiveJavaObject(o).intValue();
break;
case DATE: // unsupported conversion
default: {
throw new RuntimeException("Hive 2 Internal error: unsupported conversion from type: "
+ oi.getTypeName());
}
}
return result;
}
/**
* Get the long value out of a primitive object. Note that
* NullPointerException will be thrown if o is null. Note that
* NumberFormatException will be thrown if o is not a valid number.
*/
public static long getLong(Object o, PrimitiveObjectInspector oi) {
long result = 0;
switch (oi.getPrimitiveCategory()) {
case VOID:
result = 0;
break;
case BOOLEAN:
result = (((BooleanObjectInspector) oi).get(o) ? 1 : 0);
break;
case BYTE:
result = ((ByteObjectInspector) oi).get(o);
break;
case SHORT:
result = ((ShortObjectInspector) oi).get(o);
break;
case INT:
result = ((IntObjectInspector) oi).get(o);
break;
case LONG:
result = ((LongObjectInspector) oi).get(o);
break;
case FLOAT:
result = (long) ((FloatObjectInspector) oi).get(o);
break;
case DOUBLE:
result = (long) ((DoubleObjectInspector) oi).get(o);
break;
case STRING:
StringObjectInspector soi = (StringObjectInspector) oi;
if (soi.preferWritable()) {
Text t = soi.getPrimitiveWritableObject(o);
result = LazyLong.parseLong(t.getBytes(), 0, t.getLength());
} else {
String s = soi.getPrimitiveJavaObject(o);
result = Long.parseLong(s);
}
break;
case CHAR:
case VARCHAR: {
result = Long.parseLong(getString(o, oi));
break;
}
case TIMESTAMP:
result = ((TimestampObjectInspector) oi).getPrimitiveWritableObject(o)
.getSeconds();
break;
case DECIMAL:
result = ((HiveDecimalObjectInspector) oi)
.getPrimitiveJavaObject(o).longValue();
break;
case DATE: // unsupported conversion
default:
throw new RuntimeException("Hive 2 Internal error: unsupported conversion from type: "
+ oi.getTypeName());
}
return result;
}
/**
* Get the double value out of a primitive object. Note that
* NullPointerException will be thrown if o is null. Note that
* NumberFormatException will be thrown if o is not a valid number.
*/
public static double getDouble(Object o, PrimitiveObjectInspector oi) {
double result = 0;
switch (oi.getPrimitiveCategory()) {
case VOID:
result = 0;
break;
case BOOLEAN:
result = (((BooleanObjectInspector) oi).get(o) ? 1 : 0);
break;
case BYTE:
result = ((ByteObjectInspector) oi).get(o);
break;
case SHORT:
result = ((ShortObjectInspector) oi).get(o);
break;
case INT:
result = ((IntObjectInspector) oi).get(o);
break;
case LONG:
result = ((LongObjectInspector) oi).get(o);
break;
case FLOAT:
result = ((FloatObjectInspector) oi).get(o);
break;
case DOUBLE:
result = ((DoubleObjectInspector) oi).get(o);
break;
case STRING:
StringObjectInspector soi = (StringObjectInspector) oi;
String s = soi.getPrimitiveJavaObject(o);
result = Double.parseDouble(s);
break;
case CHAR:
case VARCHAR:
result = Double.parseDouble(getString(o, oi));
break;
case TIMESTAMP:
result = ((TimestampObjectInspector) oi).getPrimitiveWritableObject(o).getDouble();
break;
case DECIMAL:
result = ((HiveDecimalObjectInspector) oi)
.getPrimitiveJavaObject(o).doubleValue();
break;
case DATE: // unsupported conversion
default:
throw new RuntimeException("Hive 2 Internal error: unsupported conversion from type: "
+ oi.getTypeName());
}
return result;
}
/**
* Get the float value out of a primitive object. Note that
* NullPointerException will be thrown if o is null. Note that
* NumberFormatException will be thrown if o is not a valid number.
*/
public static float getFloat(Object o, PrimitiveObjectInspector oi) {
return (float) getDouble(o, oi);
}
/**
* Get the String value out of a primitive object. Note that
* NullPointerException will be thrown if o is null. Note that
* RuntimeException will be thrown if o is not a valid string.
*/
public static String getString(Object o, PrimitiveObjectInspector oi) {
if (o == null) {
return null;
}
String result = null;
switch (oi.getPrimitiveCategory()) {
case VOID:
result = null;
break;
case BINARY:
try {
byte[] bytes = ((BinaryObjectInspector) oi).getPrimitiveWritableObject(o).getBytes();
int byteLen = ((BinaryObjectInspector) oi).getPrimitiveWritableObject(o).getLength();
result = Text.decode(bytes, 0, byteLen);
} catch (CharacterCodingException err) {
// we tried ..
result = null;
}
break;
case BOOLEAN:
result = String.valueOf((((BooleanObjectInspector) oi).get(o)));
break;
case BYTE:
result = String.valueOf((((ByteObjectInspector) oi).get(o)));
break;
case SHORT:
result = String.valueOf((((ShortObjectInspector) oi).get(o)));
break;
case INT:
result = String.valueOf((((IntObjectInspector) oi).get(o)));
break;
case LONG:
result = String.valueOf((((LongObjectInspector) oi).get(o)));
break;
case FLOAT:
result = String.valueOf((((FloatObjectInspector) oi).get(o)));
break;
case DOUBLE:
result = String.valueOf((((DoubleObjectInspector) oi).get(o)));
break;
case STRING:
StringObjectInspector soi = (StringObjectInspector) oi;
result = soi.getPrimitiveJavaObject(o);
break;
case CHAR:
// when converting from char to string/varchar, strip any trailing spaces
result = ((HiveCharObjectInspector) oi).getPrimitiveJavaObject(o).getStrippedValue();
break;
case VARCHAR:
HiveVarcharObjectInspector hcoi = (HiveVarcharObjectInspector) oi;
result = hcoi.getPrimitiveJavaObject(o).toString();
break;
case DATE:
result = ((DateObjectInspector) oi).getPrimitiveWritableObject(o).toString();
break;
case TIMESTAMP:
result = ((TimestampObjectInspector) oi).getPrimitiveWritableObject(o).toString();
break;
case DECIMAL:
result = ((HiveDecimalObjectInspector) oi)
.getPrimitiveJavaObject(o).toString();
break;
default:
throw new RuntimeException("Hive 2 Internal error: unknown type: "
+ oi.getTypeName());
}
return result;
}
public static HiveChar getHiveChar(Object o, PrimitiveObjectInspector oi) {
if (o == null) {
return null;
}
HiveChar result = null;
switch (oi.getPrimitiveCategory()) {
case CHAR:
result = ((HiveCharObjectInspector) oi).getPrimitiveJavaObject(o);
break;
default:
// No char length available, copy whole string value here.
result = new HiveChar();
result.setValue(getString(o, oi));
break;
}
return result;
}
public static HiveVarchar getHiveVarchar(Object o, PrimitiveObjectInspector oi) {
if (o == null) {
return null;
}
HiveVarchar result = null;
switch (oi.getPrimitiveCategory()) {
case VARCHAR:
result = ((HiveVarcharObjectInspector)oi).getPrimitiveJavaObject(o);
break;
default:
// Is there a way to provide char length here?
// It might actually be ok as long as there is an object inspector (with char length)
// receiving this value.
result = new HiveVarchar();
result.setValue(getString(o, oi));
break;
}
return result;
}
public static BytesWritable getBinaryFromText(Text text) {
BytesWritable bw = new BytesWritable();
bw.set(text.getBytes(), 0, text.getLength());
return bw;
}
public static BytesWritable getBinary(Object o, PrimitiveObjectInspector oi) {
if (null == o) {
return null;
}
switch (oi.getPrimitiveCategory()) {
case VOID:
return null;
case STRING:
Text text = ((StringObjectInspector) oi).getPrimitiveWritableObject(o);
return getBinaryFromText(text);
case CHAR:
// char to binary conversion: include trailing spaces?
return getBinaryFromText(
((HiveCharObjectInspector) oi).getPrimitiveWritableObject(o).getPaddedValue());
case VARCHAR:
return getBinaryFromText(
((HiveVarcharObjectInspector) oi).getPrimitiveWritableObject(o).getTextValue());
case BINARY:
return ((BinaryObjectInspector) oi).getPrimitiveWritableObject(o);
default:
throw new RuntimeException("Cannot convert to Binary from: "
+ oi.getTypeName());
}
}
public static HiveDecimal getHiveDecimal(Object o, PrimitiveObjectInspector oi) {
if (o == null) {
return null;
}
HiveDecimal result = null;
switch (oi.getPrimitiveCategory()) {
case VOID:
result = null;
break;
case BOOLEAN:
result = ((BooleanObjectInspector) oi).get(o) ?
HiveDecimal.ONE : HiveDecimal.ZERO;
break;
case BYTE:
result = HiveDecimal.create(((ByteObjectInspector) oi).get(o));
break;
case SHORT:
result = HiveDecimal.create(((ShortObjectInspector) oi).get(o));
break;
case INT:
result = HiveDecimal.create(((IntObjectInspector) oi).get(o));
break;
case LONG:
result = HiveDecimal.create(((LongObjectInspector) oi).get(o));
break;
case FLOAT:
Float f = ((FloatObjectInspector) oi).get(o);
result = HiveDecimal.create(f.toString());
break;
case DOUBLE:
Double d = ((DoubleObjectInspector) oi).get(o);
result = HiveDecimal.create(d.toString());
break;
case STRING:
result = HiveDecimal.create(((StringObjectInspector) oi).getPrimitiveJavaObject(o));
break;
case CHAR:
case VARCHAR:
result = HiveDecimal.create(getString(o, oi));
break;
case TIMESTAMP:
Double ts = ((TimestampObjectInspector) oi).getPrimitiveWritableObject(o)
.getDouble();
result = HiveDecimal.create(ts.toString());
break;
case DECIMAL:
result = ((HiveDecimalObjectInspector) oi).getPrimitiveJavaObject(o);
break;
case DATE: // unsupported conversion
default:
throw new RuntimeException("Hive 2 Internal error: unsupported conversion from type: "
+ oi.getTypeName());
}
return result;
}
public static Date getDate(Object o, PrimitiveObjectInspector oi) {
if (o == null) {
return null;
}
Date result = null;
switch (oi.getPrimitiveCategory()) {
case VOID:
result = null;
break;
case STRING:
StringObjectInspector soi = (StringObjectInspector) oi;
String s = soi.getPrimitiveJavaObject(o).trim();
try {
result = Date.valueOf(s);
} catch (IllegalArgumentException e) {
result = null;
}
break;
case CHAR:
case VARCHAR: {
try {
String val = getString(o, oi).trim();
result = Date.valueOf(val);
} catch (IllegalArgumentException e) {
result = null;
}
break;
}
case DATE:
result = ((DateObjectInspector) oi).getPrimitiveWritableObject(o).get();
break;
case TIMESTAMP:
result = DateWritable.timeToDate(
((TimestampObjectInspector) oi).getPrimitiveWritableObject(o).getSeconds());
break;
default:
throw new RuntimeException("Cannot convert to Date from: "
+ oi.getTypeName());
}
return result;
}
public static Timestamp getTimestamp(Object o, PrimitiveObjectInspector oi) {
if (o == null) {
return null;
}
Timestamp result = null;
switch (oi.getPrimitiveCategory()) {
case VOID:
result = null;
break;
case BOOLEAN:
result = new Timestamp(((BooleanObjectInspector) oi).get(o) ? 1 : 0);
break;
case BYTE:
result = new Timestamp(((ByteObjectInspector) oi).get(o));
break;
case SHORT:
result = new Timestamp(((ShortObjectInspector) oi).get(o));
break;
case INT:
result = new Timestamp(((IntObjectInspector) oi).get(o));
break;
case LONG:
result = new Timestamp(((LongObjectInspector) oi).get(o));
break;
case FLOAT:
result = TimestampWritable.floatToTimestamp(((FloatObjectInspector) oi).get(o));
break;
case DOUBLE:
result = TimestampWritable.doubleToTimestamp(((DoubleObjectInspector) oi).get(o));
break;
case DECIMAL:
result = TimestampWritable.decimalToTimestamp(((HiveDecimalObjectInspector) oi)
.getPrimitiveJavaObject(o));
break;
case STRING:
StringObjectInspector soi = (StringObjectInspector) oi;
String s = soi.getPrimitiveJavaObject(o);
result = getTimestampFromString(s);
break;
case CHAR:
case VARCHAR:
result = getTimestampFromString(getString(o, oi));
break;
case DATE:
result = new Timestamp(
((DateObjectInspector) oi).getPrimitiveWritableObject(o).get().getTime());
break;
case TIMESTAMP:
result = ((TimestampObjectInspector) oi).getPrimitiveWritableObject(o).getTimestamp();
break;
default:
throw new RuntimeException("Hive 2 Internal error: unknown type: "
+ oi.getTypeName());
}
return result;
}
static Timestamp getTimestampFromString(String s) {
Timestamp result;
s = s.trim();
// Throw away extra if more than 9 decimal places
int periodIdx = s.indexOf(".");
if (periodIdx != -1) {
if (s.length() - periodIdx > 9) {
s = s.substring(0, periodIdx + 10);
}
}
try {
result = Timestamp.valueOf(s);
} catch (IllegalArgumentException e) {
result = null;
}
return result;
}
public static Class<?> getJavaPrimitiveClassFromObjectInspector(ObjectInspector oi) {
if (oi.getCategory() != Category.PRIMITIVE) {
return null;
}
PrimitiveObjectInspector poi = (PrimitiveObjectInspector) oi;
PrimitiveTypeEntry t =
getTypeEntryFromPrimitiveCategory(poi.getPrimitiveCategory());
return t == null ? null : t.primitiveJavaClass;
}
/**
* Provide a general grouping for each primitive data type.
*/
public static enum PrimitiveGrouping {
NUMERIC_GROUP, STRING_GROUP, BOOLEAN_GROUP, DATE_GROUP, BINARY_GROUP,
VOID_GROUP, UNKNOWN_GROUP
};
/**
* Based on the PrimitiveCategory of a type, return the PrimitiveGrouping
* that the PrimitiveCategory belongs to (numeric, string, date, etc).
* @param primitiveCategory Primitive category of the type
* @return PrimitveGrouping corresponding to the PrimitiveCategory,
* or UNKNOWN_GROUP if the type does not match to a grouping.
*/
public static PrimitiveGrouping getPrimitiveGrouping(PrimitiveCategory primitiveCategory) {
switch (primitiveCategory) {
case BYTE:
case SHORT:
case INT:
case LONG:
case FLOAT:
case DOUBLE:
case DECIMAL:
return PrimitiveGrouping.NUMERIC_GROUP;
case STRING:
case CHAR:
case VARCHAR:
return PrimitiveGrouping.STRING_GROUP;
case BOOLEAN:
return PrimitiveGrouping.BOOLEAN_GROUP;
case TIMESTAMP:
case DATE:
return PrimitiveGrouping.DATE_GROUP;
case BINARY:
return PrimitiveGrouping.BINARY_GROUP;
case VOID:
return PrimitiveGrouping.VOID_GROUP;
default:
return PrimitiveGrouping.UNKNOWN_GROUP;
}
}
private PrimitiveObjectInspectorUtils() {
// prevent instantiation
}
}