前言:

接上文:

之前编写presto函数是在presto代码工程下新建模块,然后进行自定义函数开发。

但是使用这种方法,在maven 编译时会遇到很多的报错,大多是格式文件,如头文件没有Licensed信息,有多个换行,文件结尾没有换行,文件结尾有多个空行,诸如此类的格式文件搞的人很头疼。

虽然最后成功编译,但是感觉这种方法,比较麻烦。

然后网上有基于新建项目的方式来完成函数开发的方法,这种测试后感觉简单了不少。这里整理并记录一下。

二、准备:

1. 新建maven项目

presto表关联 presto创建表_presto

2. pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.facebook.presto</groupId>
    <artifactId>presto-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.facebook.presto</groupId>
            <artifactId>presto-spi</artifactId>
            <version>0.220</version>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>18.0</version>
        </dependency>


    </dependencies>
    <!-- 屏蔽parent中的plugin 避免打包报错 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <classesDirectory>target/classes/</classesDirectory>
                    <archive>
                        <manifest>
                            <mainClass>com.alibaba.dubbo.container.Main</mainClass>
                            <!-- 打包时 MANIFEST.MF文件不记录的时间戳版本 -->
                            <useUniqueVersions>false</useUniqueVersions>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                        </manifest>
                        <manifestEntries>
                            <Class-Path>.</Class-Path>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <type>jar</type>
                            <includeTypes>jar</includeTypes>
                            <outputDirectory>
                                ${project.build.directory}/lib
                            </outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>com.facebook.presto</groupId>
                <artifactId>presto-maven-plugin</artifactId>
                <version>0.3</version>
                <extensions>true</extensions>
            </plugin>


        </plugins>
    </build>

</project>

三、函数开发:

1. Function实现

package com.facebook.presto.demo;

import com.facebook.presto.spi.function.Description;
import com.facebook.presto.spi.function.ScalarFunction;
import com.facebook.presto.spi.function.SqlType;
import com.facebook.presto.spi.type.StandardTypes;
import io.airlift.slice.Slice;
import io.airlift.slice.Slices;

/**
 * 提取字段中 3=...后面的字符串
 */
public final class MyFunctions
{
    @ScalarFunction("to_upper") // 固定参数,表示函数名的意思,也就我们在使用Presto的时候用的函数名
    @Description("我的大小写转换函数") // 函数的注释
    @SqlType(StandardTypes.VARCHAR) // 表示数据类型
    public static Slice toUpper(
            @SqlType(StandardTypes.VARCHAR) Slice input)
    {
        // 将获取到的数据转换大写
        String s = input.toStringUtf8().toUpperCase();
        // 在转换后的数据放入内存返回
        return Slices.utf8Slice(s);
    }

    private MyFunctions()
    {
    }
}

2. Plugin实现

package com.facebook.presto.demo;

import com.facebook.presto.spi.Plugin;
import com.google.common.collect.ImmutableSet;

import java.util.Set;

public class MDAFunctionPlugin implements Plugin {
    @Override
    public Set<Class<?>> getFunctions() {
        return ImmutableSet.<Class<?>>builder()
                .add(MyFunctions.class)              //可添加多个函数方法名
                .build();
    }
}

3. 加载plugin

src/main/resources下创建目录,注意META-INF是父目录services是子目录,只是idea合并显示了,不是说文件名里面有点.
然后创建文件com.facebook.presto.spi.Plugin

然后文件内容为:

com.facebook.presto.demo.MDAFunctionPlugin

注: 包名 + 插件类名

presto表关联 presto创建表_presto_02

4. 打包
mvn package

presto表关联 presto创建表_maven_03

5. 新建一个插件包文件

在生产环境上在$PRESTO_HOME/plugin目录下新建一个文件夹,用来存放自己的写的UDF Function

mdkir -p /home/rong/presto/presto-server/plugin/demo

6. 上传jar包

将package 后的jar包和相关的依赖,上传到我们上一步新建的文件夹中。
presto表关联 presto创建表_apache_04

注意:插件必须安装在Presto集群中的所有节点上(协调器和工作器)。相关的依赖也需要上传。

presto表关联 presto创建表_facebook_05

打包的相关依赖会放到target的lib 目录下,需要将相关的依赖也上传上去。

6. 重启服务

${PRESTO_HOME}/bin/launcher restart

7. 查看function

重启presto服务后,使用客户端连接presto。

${PRESTO_HOME}/bin/presto --catalog hive

输入show functions就可以看到我们注册的方法。

四、总结

实现presto函数的开发,使用新建maven工程的方式,要比在presto代码下新建子工程的方式简单的多,推荐大家使用方法二。其实核心内容没有什么大的变化,主要变得就是pom文件的bulid pulgin。