文章目录
本文会从函数注册到函数的具体实现详细讲解Presto Functions的开发过程。需要注意的是Presto Functions并不能像Hive UDF一样动态加载。
Function注册
Function的注册是通过FunctionAndTypeManager来完成的,在MetadataManager构造方法中会初始化FunctionAndTypeManager实例。在FunctionAndTypeManager的构造方法中,会调用新建FunctionNamespaceManager实例,其中的一个实现类即为BuiltInTypeAndFunctionNamespaceManager,在该类的构造方法中会注册目前Presto中所有的Functions。
ConnectorManager.ConnectorManager
MetadataManager.MetadataManager
FunctionAndTypeManager.FunctionAndTypeManager
FunctionAndTypeManager.resolveBuiltInFunction
FunctionAndTypeManager.resolveBuiltInFunction
FunctionNamespaceManager.getFunctionHandle
BuiltInTypeAndFunctionNamespaceManager.getBuildInFunctions
其中BuiltInTypeAndFunctionNamespaceManager.getBuildInFunctions方法会获取目前Presto中所有的Functions:
// BuiltInTypeAndFunctionNamespaceManager.java
private List<? extends SqlFunction> getBuildInFunctions(FeaturesConfig featuresConfig)
{
FunctionListBuilder builder = new FunctionListBuilder()
.window(FirstValueFunction.class)
.window(LastValueFunction.class)
.window(NthValueFunction.class)
.window(LagFunction.class)
.window(LeadFunction.class)
.aggregate(ApproximateCountDistinctAggregation.class)
.aggregate(DefaultApproximateCountDistinctAggregation.class)
.aggregate(SumDataSizeForStats.class)
.aggregate(MaxDataSizeForStats.class)
.aggregates(CountAggregation.class)
.scalars(MathFunctions.class)
.scalar(MathFunctions.Abs.class)
.scalar(MathFunctions.Sign.class)
.scalar(MathFunctions.Round.class)
.scalar(MathFunctions.RoundN.class)
.scalar(MathFunctions.Truncate.class)
.scalar(MathFunctions.TruncateN.class)
.scalar(MathFunctions.Ceiling.class)
.scalar(MathFunctions.Floor.class);
return builder.getFunctions();
}
然后通过registerBuiltInFunctions方法将构造的Function注册到FunctionMap,FunctionMap维护了一个function name
为key,function information
为value的map。
public BuiltInTypeAndFunctionNamespaceManager(
BlockEncodingSerde blockEncodingSerde,
FeaturesConfig featuresConfig,
Set<Type> types,
FunctionAndTypeManager functionAndTypeManager)
{
registerBuiltInFunctions(getBuildInFunctions(featuresConfig));
}
此外,在PluginManager插件管理中加载Plugin(
installPlugin
方法)时,也可以在各个Plugin中注册自定义Function。
窗口函数
窗口函数可以被理解为分析型函数,即将某一列多选中的值按照一定的聚合规则进行计算。Presto默认提供了很多的窗口函数,窗口函数默认要和over函数配合使用,over函数中可以定义分组和排序规则。
窗口函数需要继承com.facebook.presto.operator.window.WindowFunction
接口,并定义实现以下两个方法:
- reset(WindowIndex windowIndex):初始化窗口函数时将会调用该方法,WindowIndex包含了返回的结果集信息。
- processRow(BlockBuilder output, int peerGroupStart, int peerGroupEnd, int frameStart, int frameEnd):窗口函数功能的实