作为一个新手菜鸟,在对presto 函数进行开发的时候遇到了很多很多的问题,虽然花费了很多的时间,但最后还是成功的开发了出来UDF函数。
相信很多人都看过一篇《如何开发 Presto 自定义函数(UDF) 》的文章,其实那篇文章讲的很好,但是其中有一些细节并没有写出来,可能对一部分人来说,在开发过程中存在问题。现在分享一下我开发的过程,希望可以帮助到大家。
步骤:
1、创建maven工程
2、修改pom文件
pom文件可以参考链接:https://blog.csdn.net/szd_8482/article/details/80392796
(注:上面链接是我自己的pom文件,仅供参考)
亦或者去GitHub上面参考presto源码中的pom
3、编写UDF函数
具体参数介绍这里不多说,请参考上方链接,说的已经很详细了
在这里以聚合函数为例,实现自定义UDF编写
AVG函数:
import static com.facebook.presto.spi.type.DoubleType.DOUBLE; import com.facebook.presto.spi.block.BlockBuilder; import com.facebook.presto.spi.function.AggregationFunction; import com.facebook.presto.spi.function.AggregationState; import com.facebook.presto.spi.function.CombineFunction; import com.facebook.presto.spi.function.InputFunction; import com.facebook.presto.spi.function.OutputFunction; import com.facebook.presto.spi.function.SqlType; import com.facebook.presto.spi.type.StandardTypes; import com.presto.state.LongAndDoubleState; import com.presto.utils.PrecisionUtil; @AggregationFunction("_avg") public final class AVG{ private Avg() { } @InputFunction public static void input(@AggregationState LongAndDoubleState state, @SqlType(StandardTypes.BIGINT) long value) { state.setLong(state.getLong() + 1); state.setDouble(state.getDouble() + value); } @InputFunction public static void input(@AggregationState LongAndDoubleState state, @SqlType(StandardTypes.DOUBLE) double value) { state.setLong(state.getLong() + 1); state.setDouble(state.getDouble() + value); } @CombineFunction public static void combine(@AggregationState LongAndDoubleState state, @AggregationState LongAndDoubleState otherState) { state.setLong(state.getLong() + otherState.getLong()); state.setDouble(state.getDouble() + otherState.getDouble()); } @OutputFunction(StandardTypes.DOUBLE) public static void output(@AggregationState LongAndDoubleState state, BlockBuilder out) { long count = state.getLong(); if (count == 0) { out.appendNull(); } else { double value = state.getDouble(); double tmp = Double.valueOf(PrecisionUtil.getPrecision(value / count)); DOUBLE.writeDouble(out, tmp); } } }
LongAndDoubleState:
import com.facebook.presto.spi.function.AccumulatorState; public interface LongAndDoubleState extends AccumulatorState{ long getLong(); void setLong(long value); double getDouble(); void setDouble(double value); }
工具类:精确小数点后位数
import java.text.DecimalFormat; /** * double类型 小数点后保留四位 * * @author xueqing-dev * */ public class PrecisionUtil { public static double getPrecision(double value) { DecimalFormat df = new DecimalFormat("####0.0000"); double tmp = Double.valueOf(df.format(value)); return tmp; } }
4、plugin插件注册:
将UDF函数的逻辑写好之后,需要把相关的类注册到plugin中,才能被presto识别
package com.xqy.szd.presto.plugin; import java.util.Set; import com.facebook.presto.spi.Plugin; import com.google.common.collect.ImmutableSet; public class UDF_Plugin implements Plugin{ @Override public Set<Class<?>> getFunctions(){ return ImmutableSet.<Class<?>>builder() .add(AVG.class) .build(); } }
5、在 src/main/resources/META-INF/services 中新建名为 com.facebook.presto.spi.Plugin 的文本文件,内容就是之前实现 Plugin 接口的类名
如果没有resources,需要自己建立并且加入source中(右击-->Build Path)
6、package 打包
函数开发好之后,需要通过maven打包,然后把jar包上传到presto中的plugin中
maven中 运行package 完成打包过程
打包完成后,需要上传的是后缀为 .zip 的包,这里面包括函数所需要的依赖
7、上传到presto中的plugin中 ,解压
unzip demo-0.0.1-SNAPHOT.zip
8、重启presto
9、查询是否注册
show functions;
至此 我的UDF函数开发过程分享完成,希望对大家有所帮助