| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.drill.exec.fn.hive; |
| |
| 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.ql.exec.Description; |
| import org.apache.hadoop.hive.ql.exec.UDFArgumentException; |
| import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; |
| import org.apache.hadoop.hive.ql.metadata.HiveException; |
| import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; |
| 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.primitive.BinaryObjectInspector; |
| import org.apache.hadoop.hive.serde2.objectinspector.primitive.BooleanObjectInspector; |
| import org.apache.hadoop.hive.serde2.objectinspector.primitive.ByteObjectInspector; |
| import org.apache.hadoop.hive.serde2.objectinspector.primitive.DateObjectInspector; |
| import org.apache.hadoop.hive.serde2.objectinspector.primitive.DoubleObjectInspector; |
| import org.apache.hadoop.hive.serde2.objectinspector.primitive.FloatObjectInspector; |
| import org.apache.hadoop.hive.serde2.objectinspector.primitive.HiveCharObjectInspector; |
| import org.apache.hadoop.hive.serde2.objectinspector.primitive.HiveDecimalObjectInspector; |
| import org.apache.hadoop.hive.serde2.objectinspector.primitive.HiveVarcharObjectInspector; |
| import org.apache.hadoop.hive.serde2.objectinspector.primitive.IntObjectInspector; |
| import org.apache.hadoop.hive.serde2.objectinspector.primitive.LongObjectInspector; |
| import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; |
| import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils; |
| import org.apache.hadoop.hive.serde2.objectinspector.primitive.ShortObjectInspector; |
| import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector; |
| import org.apache.hadoop.hive.serde2.objectinspector.primitive.TimestampObjectInspector; |
| |
| /** |
| * Contains test Hive UDF that take a particular data type and return the same data type and value. |
| * These test UDFs exercise the code paths in Drill ObjectInspectors and parsing the return value from Hive UDF |
| * for all supported data types in Hive UDF. |
| */ |
| public class HiveTestUDFImpls { |
| public static abstract class GenericUDFTestBase extends GenericUDF { |
| protected final String udfName; |
| protected final PrimitiveCategory inputType; |
| protected final PrimitiveCategory outputType; |
| protected ObjectInspector argumentOI; |
| |
| public GenericUDFTestBase(String udfName, PrimitiveCategory type) { |
| this(udfName, type, type); |
| } |
| |
| public GenericUDFTestBase(String udfName, PrimitiveCategory inputType, PrimitiveCategory outputType) { |
| this.udfName = udfName; |
| this.inputType = inputType; |
| this.outputType = outputType; |
| } |
| |
| @Override |
| public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { |
| if (arguments.length != 1) { |
| throw new UDFArgumentLengthException(String.format("%s needs 1 argument, got %d", udfName, arguments.length)); |
| } |
| |
| if (arguments[0].getCategory() != Category.PRIMITIVE || |
| ((PrimitiveObjectInspector) arguments[0]).getPrimitiveCategory() != inputType) { |
| String actual = arguments[0].getCategory() + (arguments[0].getCategory() == Category.PRIMITIVE ? |
| "[" + ((PrimitiveObjectInspector) arguments[0]).getPrimitiveCategory() + "]" : ""); |
| throw new UDFArgumentException( |
| String.format("%s only takes primitive type %s, got %s", udfName, inputType, actual)); |
| } |
| argumentOI = arguments[0]; |
| return PrimitiveObjectInspectorFactory.getPrimitiveJavaObjectInspector(outputType); |
| } |
| |
| @Override |
| public String getDisplayString(String[] children) { |
| StringBuilder sb = new StringBuilder(); |
| sb.append(udfName); |
| sb.append("("); |
| if (children.length > 0) { |
| sb.append(children[0]); |
| for (int i = 1; i < children.length; i++) { |
| sb.append(","); |
| sb.append(children[i]); |
| } |
| } |
| sb.append(")"); |
| return sb.toString(); |
| } |
| |
| @Override |
| public Object evaluate(DeferredObject[] arguments) throws HiveException { |
| if (arguments[0] == null || arguments[0].get() == null) { |
| return null; |
| } |
| |
| Object input = arguments[0].get(); |
| switch(inputType) { |
| case BOOLEAN: |
| return ((BooleanObjectInspector)argumentOI).get(input) ? Boolean.TRUE : Boolean.FALSE; |
| case BYTE: |
| return Byte.valueOf(((ByteObjectInspector)argumentOI).get(input)); |
| case SHORT: |
| return Short.valueOf(((ShortObjectInspector)argumentOI).get(input)); |
| case INT: |
| return Integer.valueOf(((IntObjectInspector)argumentOI).get(input)); |
| case LONG: |
| return Long.valueOf(((LongObjectInspector)argumentOI).get(input)); |
| case FLOAT: |
| return Float.valueOf(((FloatObjectInspector)argumentOI).get(input)); |
| case DOUBLE: |
| return Double.valueOf(((DoubleObjectInspector)argumentOI).get(input)); |
| case STRING: |
| return PrimitiveObjectInspectorUtils.getString(input, (StringObjectInspector)argumentOI); |
| case BINARY: |
| return PrimitiveObjectInspectorUtils.getBinary(input, (BinaryObjectInspector) argumentOI).getBytes(); |
| case VARCHAR: |
| if (outputType == PrimitiveCategory.CHAR) { |
| HiveVarchar hiveVarchar = PrimitiveObjectInspectorUtils.getHiveVarchar(input, (HiveVarcharObjectInspector) argumentOI); |
| return new HiveChar(hiveVarchar.getValue(), HiveChar.MAX_CHAR_LENGTH); |
| } else { |
| return PrimitiveObjectInspectorUtils.getHiveVarchar(input, (HiveVarcharObjectInspector)argumentOI); |
| } |
| case CHAR: |
| return PrimitiveObjectInspectorUtils.getHiveChar(input, (HiveCharObjectInspector) argumentOI); |
| case DATE: |
| return PrimitiveObjectInspectorUtils.getDate(input, (DateObjectInspector) argumentOI); |
| case TIMESTAMP: |
| return PrimitiveObjectInspectorUtils.getTimestamp(input, (TimestampObjectInspector) argumentOI); |
| case DECIMAL: |
| // return type is a HiveVarchar |
| HiveDecimal decimalValue = |
| PrimitiveObjectInspectorUtils.getHiveDecimal(input, (HiveDecimalObjectInspector) argumentOI); |
| return new HiveVarchar(decimalValue.toString(), HiveVarchar.MAX_VARCHAR_LENGTH); |
| } |
| |
| throw new UnsupportedOperationException(String.format("Unexpected input type '%s' in Test UDF", inputType)); |
| } |
| } |
| |
| @Description(name = "testHiveUDFBOOLEAN", value = "_FUNC_(BOOLEAN) - Tests boolean data as input and output") |
| public static class GenericUDFTestBOOLEAN extends GenericUDFTestBase { |
| public GenericUDFTestBOOLEAN() { |
| super("testHiveUDFBOOLEAN", PrimitiveCategory.BOOLEAN); |
| } |
| } |
| |
| // TODO(DRILL-2470) - re-enable the test case for this function in TestSampleHiveUDFs |
| @Description(name = "testHiveUDFBYTE", value = "_FUNC_(BYTE) - Tests byte data as input and output") |
| public static class GenericUDFTestBYTE extends GenericUDFTestBase { |
| public GenericUDFTestBYTE() { |
| super("testHiveUDFBYTE", PrimitiveCategory.BYTE); |
| } |
| } |
| |
| // TODO(DRILL-2470) - re-enable the test case for this function in TestSampleHiveUDFs |
| @Description(name = "testHiveUDFSHORT", value = "_FUNC_(SHORT) - Tests short data as input and output") |
| public static class GenericUDFTestSHORT extends GenericUDFTestBase { |
| public GenericUDFTestSHORT() { |
| super("testHiveUDFSHORT", PrimitiveCategory.SHORT); |
| } |
| } |
| |
| @Description(name = "testHiveUDFINT", value = "_FUNC_(INT) - Tests int data as input and output") |
| public static class GenericUDFTestINT extends GenericUDFTestBase { |
| public GenericUDFTestINT() { |
| super("testHiveUDFINT", PrimitiveCategory.INT); |
| } |
| } |
| |
| @Description(name = "testHiveUDFLONG", value = "_FUNC_(LONG) - Tests long data as input and output") |
| public static class GenericUDFTestLONG extends GenericUDFTestBase { |
| public GenericUDFTestLONG() { |
| super("testHiveUDFLONG", PrimitiveCategory.LONG); |
| } |
| } |
| |
| @Description(name = "testHiveUDFFLOAT", value = "_FUNC_(FLOAT) - Tests float data as input and output") |
| public static class GenericUDFTestFLOAT extends GenericUDFTestBase { |
| public GenericUDFTestFLOAT() { |
| super("testHiveUDFFLOAT", PrimitiveCategory.FLOAT); |
| } |
| } |
| |
| @Description(name = "testHiveUDFDOUBLE", value = "_FUNC_(DOUBLE) - Tests double data as input and output") |
| public static class GenericUDFTestDOUBLE extends GenericUDFTestBase { |
| public GenericUDFTestDOUBLE() { |
| super("testHiveUDFDOUBLE", PrimitiveCategory.DOUBLE); |
| } |
| } |
| |
| @Description(name = "testHiveUDFVARCHAR", value = "_FUNC_(VARCHAR) - Tests varchar data as input and output") |
| public static class GenericUDFTestVARCHAR extends GenericUDFTestBase { |
| public GenericUDFTestVARCHAR() { |
| super("testHiveUDFVARCHAR", PrimitiveCategory.VARCHAR); |
| } |
| } |
| |
| @Description(name = "testHiveUDFCHAR", value = "_FUNC_(VARCHAR) - Tests varchar data as input and char data as output") |
| public static class GenericUDFTestCHAR extends GenericUDFTestBase { |
| public GenericUDFTestCHAR() { |
| super("testHiveUDFCHAR", PrimitiveCategory.VARCHAR, PrimitiveCategory.CHAR); |
| } |
| } |
| |
| @Description(name = "testHiveUDFSTRING", value = "_FUNC_(STRING) - Tests string data as input and output") |
| public static class GenericUDFTestSTRING extends GenericUDFTestBase { |
| public GenericUDFTestSTRING() { |
| super("testHiveUDFSTRING", PrimitiveCategory.STRING); |
| } |
| } |
| |
| @Description(name = "testHiveUDFBINARY", value = "_FUNC_(BINARY) - Tests binary data as input and output") |
| public static class GenericUDFTestBINARY extends GenericUDFTestBase { |
| public GenericUDFTestBINARY() { |
| super("testHiveUDFBINARY", PrimitiveCategory.BINARY); |
| } |
| } |
| |
| @Description(name = "testHiveUDFTIMESTAMP", value = "_FUNC_(TIMESTAMP) - Tests timestamp data as input and output") |
| public static class GenericUDFTestTIMESTAMP extends GenericUDFTestBase { |
| public GenericUDFTestTIMESTAMP() { |
| super("testHiveUDFTIMESTAMP", PrimitiveCategory.TIMESTAMP); |
| } |
| } |
| |
| @Description(name = "testHiveUDFDATE", value = "_FUNC_(DATE) - Tests date data as input and output") |
| public static class GenericUDFTestDATE extends GenericUDFTestBase { |
| public GenericUDFTestDATE() { |
| super("testHiveUDFDATE", PrimitiveCategory.DATE); |
| } |
| } |
| |
| @Description(name = "testHiveUDFDECIMAL", value = "_FUNC_(DECIMAL) - Tests decimal data as input and output") |
| public static class GenericUDFTestDECIMAL extends GenericUDFTestBase { |
| public GenericUDFTestDECIMAL() { |
| super("testHiveUDFDECIMAL", PrimitiveCategory.DECIMAL, PrimitiveCategory.VARCHAR); |
| } |
| } |
| } |