Hive-自定义函数

发布于:2025-03-03 ⋅ 阅读:(93) ⋅ 点赞:(0)

#hive #函数

自定义函数开发和注册

import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;

public class ToUpperCaseUDF extends UDF {
    public Text evaluate(Text input) {
        if (input == null) {
            return null;
        }
        return new Text(input.toString().toUpperCase());
    }
}

编译和打包成jar

javac -cp $(hadoop classpath) ToUpperCaseUDF.java
jar cf to_uppercase.jar ToUpperCaseUDF.class

上传到HDFS

注册自定义函数

-- 创建临时函数(会话结束后失效)
CREATE TEMPORARY FUNCTION to_uppercase AS 'com.example.ToUpperCaseUDF';

-- 或创建永久函数(需写入 Hive 元数据库)
CREATE FUNCTION to_uppercase AS 'com.example.ToUpperCaseUDF' USING JAR '/path/to/to_uppercase.jar';

使用:

SELECT to_uppercase(name) FROM users WHERE age > 30;

GenericUDF

普通UDF通常处理固定的输入输出类型,比如Text或IntWritable,而GenericUDF允许处理任意类型的参数和返回类型,这使得它在处理复杂数据结构时更加灵活。

  • 动态类型支持:无需预先声明输入/输出类型,可自动适应不同数据类型(如 intstringarray 等)。
  • 复杂逻辑处理:适合需要类型判断、多条件分支的场景(例如 IF 函数)。
  • 元数据兼容:直接与 Hive 的元数据系统集成。
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFReturnType;
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.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.TypeInfo;

import java.util.List;

public class DynamicAddUDF extends GenericUDF {

    @Override
    public ObjectInspector initialize(ObjectInspector[] parameters) throws UDFArgumentException {
        // 验证参数数量(必须为2个)
        if (parameters.length != 2) {
            throw new UDFArgumentException("DynamicAddUDF requires exactly 2 arguments");
        }

        // 支持数值类型(int, double, long)和字符串相加
        TypeInfo typeInfo1 = parameters[0].getTypeInfo();
        TypeInfo typeInfo2 = parameters[1].getTypeInfo();

        // 检查是否为数值类型或字符串
        if (!(typeInfo1.getCategory() == TypeInfo.Category.NUMERIC ||
              typeInfo1.getCategory() == TypeInfo.Category.STRING)) {
            throw new UDFArgumentException("First argument must be numeric or string");
        }
        if (!(typeInfo2.getCategory() == TypeInfo.Category.NUMERIC ||
              typeInfo2.getCategory() == TypeInfo.Category.STRING)) {
            throw new UDFArgumentException("Second argument must be numeric or string");
        }

        // 返回值类型与第一个参数相同(如果两个参数都为数值,则统一为最大精度)
        return parameters[0];
    }

    @Override
    public Object evaluate(DeferredObject[] arguments) throws HiveException {
        if (arguments[0].get() == null || arguments[1].get() == null) {
            return null;
        }

        ObjectInspector inspector1 = arguments[0].getObjectInspector();
        ObjectInspector inspector2 = arguments[1].getObjectInspector();

        // 获取原始值
        Object val1 = arguments[0].get();
        Object val2 = arguments[1].get();

        // 处理数值类型相加
        if (inspector1 instanceof PrimitiveObjectInspector &&
            inspector2 instanceof PrimitiveObjectInspector) {

            PrimitiveObjectInspector poi1 = (PrimitiveObjectInspector) inspector1;
            PrimitiveObjectInspector poi2 = (PrimitiveObjectInspector) inspector2;

            Class<?> clazz1 = poi1.getObjectClass();
            Class<?> clazz2 = poi2.getObjectClass();

            if (clazz1 == Long.class && clazz2 == Long.class) {
                return Long.valueOf(val1.toString()) + Long.valueOf(val2.toString());
            } else if (clazz1 == Double.class && clazz2 == Double.class) {
                return Double.valueOf(val1.toString()) + Double.valueOf(val2.toString());
            } else if (clazz1 == Integer.class && clazz2 == Integer.class) {
                return Integer.valueOf(val1.toString()) + Integer.valueOf(val2.toString());
            }
        }

        // 处理字符串拼接
        if (inspector1.getTypeInfo().getCategory() == TypeInfo.Category.STRING &&
            inspector2.getTypeInfo().getCategory() == TypeInfo.Category.STRING) {
            return val1.toString() + val2.toString();
        }

        throw new HiveException("Unsupported operand types for DynamicAddUDF");
    }

    @Override
    public String getDisplayString(String[] children) {
        return "DynamicAddUDF(" + children[0] + ", " + children[1] + ")";
    }
}
方法 作用
initialize 初始化函数,用于参数校验和返回类型确定(通过 ObjectInspector)。
evaluate 核心逻辑实现,动态处理不同类型的参数。
getDisplayString 定义函数在 Hive SQL 中的显示名称(可选)。

网站公告

今日签到

点亮在社区的每一天
去签到