hive创建udf函数流程

1.编写udf函数

引入pom文件


   


        org.apache.commons
        commons-jexl3
        3.1
   
   
        org.apache.hive
        hive-exec
        3.1.2
        provided
   

先确定好你要写什么函数比如我要写一个 计算字符串表达式。

hive创建udf函数流程_第1张图片 

 开始继承hive的udf接口,有很多小伙伴这个时候就喜欢看别人是怎么写的,这个时候就是体现个人差距的时候了,如何不看别人文档自己写呢?比如没网的条件下?

抄别人的 为啥不直接抄hive的呢? 想想hive什么udf函数最简单,lower/upper。照着抄就行。

public class StringCal extends GenericUDF 实现三个方法

initialize 初始化 校验参数的

evaluate 真正执行的方法

getDisplayString: desc function时 打印的话


import org.apache.commons.jexl3.JexlBuilder;
import org.apache.commons.jexl3.JexlEngine;
import org.apache.commons.jexl3.JexlExpression;
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.ql.udf.generic.GenericUDFUtils;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorConverter;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.typeinfo.BaseCharTypeInfo;
import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
//有时间的这里写下,免得后面自己都不知道是干嘛的了。
@Description(name = "StringCal",
        value = "_FUNC_(str) - Returns str with calculate result",
        extended = "Example:\n"
                + "  > SELECT _FUNC_('1+(-1+2.0-3.0+(4.0-5.0))+3.1-4.1+2*3+1.1*4') FROM src LIMIT 1;\n" + "  '-7.2'")
public class StringCal extends GenericUDF {
    private transient PrimitiveObjectInspector argumentOI;
    private transient PrimitiveObjectInspectorConverter.StringConverter stringConverter;
    private transient PrimitiveObjectInspector.PrimitiveCategory returnType = PrimitiveObjectInspector.PrimitiveCategory.STRING;
    private transient GenericUDFUtils.StringHelper returnHelper;

//这里一大串校验,校验是不是普通类型啥的,校验是字符串还是啥,哪那么多事,反正照着抄就行,不写也没啥你自己定义的函数,别人也不会用。
    @Override
    public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
        if (arguments.length != 1) {
            throw new UDFArgumentLengthException(
                    "StringCal requires 1 argument, got " + arguments.length);
        }

        if (arguments[0].getCategory() != ObjectInspector.Category.PRIMITIVE) {
            throw new UDFArgumentException(
                    "StringCal only takes primitive types, got " + argumentOI.getTypeName());
        }
        argumentOI = (PrimitiveObjectInspector) arguments[0];

        stringConverter = new PrimitiveObjectInspectorConverter.StringConverter(argumentOI);
        PrimitiveObjectInspector.PrimitiveCategory inputType = argumentOI.getPrimitiveCategory();
        ObjectInspector outputOI = null;
        BaseCharTypeInfo typeInfo;
        switch (inputType) {
            case CHAR:
                // return type should have same length as the input.
                returnType = inputType;
                typeInfo = TypeInfoFactory.getCharTypeInfo(
                        GenericUDFUtils.StringHelper.getFixedStringSizeForType(argumentOI));
                outputOI = PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(
                        typeInfo);
                break;
            case VARCHAR:
                // return type should have same length as the input.
                returnType = inputType;
                typeInfo = TypeInfoFactory.getVarcharTypeInfo(
                        GenericUDFUtils.StringHelper.getFixedStringSizeForType(argumentOI));
                outputOI = PrimitiveObjectInspectorFactory.getPrimitiveWritableObjectInspector(
                        typeInfo);
                break;
            default:
                returnType = PrimitiveObjectInspector.PrimitiveCategory.STRING;
                outputOI = PrimitiveObjectInspectorFactory.writableStringObjectInspector;
                break;
        }
        returnHelper = new GenericUDFUtils.StringHelper(returnType);
        return outputOI;
    }

    @Override
    public Object evaluate(DeferredObject[] arguments) throws HiveException {
        String val = null;
        if (arguments[0] != null) {
            val = (String) stringConverter.convert(arguments[0].get());
        }
        if (val == null) {
            return null;
        }
//就这里是我自己写的 其他的都是抄的lowerUdf的。
//        String expressionString = "1+(-1+2.0-3.0+(4.0-5.0))+3.1-4.1+2*3+1.1*4";
        JexlEngine jexlEngine = new JexlBuilder().create();
        JexlExpression jexlExpression = jexlEngine.createExpression(val);
        Object evaluate = jexlExpression.evaluate(null);
        return returnHelper.setReturnValue(evaluate.toString());
    }

    @Override
    public String getDisplayString(String[] children) {
        return null;
    }
}

然后打包成一个jar,上传的hdfs

 我嫌弃打的包不好听就直接改了个名字。

然后创建函数

create function default.stringCal as 'com.tencent.s2.function.StringCal' using jar 'hdfs:///user/hive/function/stringcalculate.jar';

注意啊 这里加上数据库的名字,否则退出会话就没了。

hive创建udf函数流程_第2张图片 这里我创建了两次。就是因为没加数据库的名字,反正建议各位加下。

也可以 

 drop function dwdmdata.stringcal

 最后享受下劳动成果。有精度误差,无伤大雅。 

hive创建udf函数流程_第3张图片

你可能感兴趣的:(hive,大数据,hadoop)