自定義presto函數

1、引入依賴jar包

        <dependency>
            <groupId>com.facebook.presto</groupId>
            <artifactId>presto-main</artifactId>
            <version>0.220</version>
            <scope>test</scope>
        </dependency>

2、實現代碼,實現兩個數相除保留小數點的函數。

import com.facebook.presto.spi.Plugin;
import com.facebook.presto.udf.*;
import com.google.common.collect.ImmutableSet;
import java.util.Set;

public class TdPlugin implements Plugin {
    public Set<Class<?>> getFunctions() {
        return ImmutableSet.<Class<?>>builder()
                .add(DivideFunc.class)
                .build();
    }
}

package com.facebook.presto.udf;

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 java.math.RoundingMode;
import java.text.NumberFormat;

/**
 * Created by zheng on 2019-09-09.
 */
public class DivideFunc {
    @ScalarFunction(value = "divide")
    @Description("兩個數相除")
    @SqlType(StandardTypes.DOUBLE)
    public static double divide(@SqlType(StandardTypes.DOUBLE) double num1, @SqlType(StandardTypes.DOUBLE) double num2) {
        return num1 / num2;
    }

	//保留point位小數點
    @ScalarFunction(value = "divide")
    @Description("兩個數相除")
    @SqlType(StandardTypes.DOUBLE)
    public static double divide(@SqlType(StandardTypes.DOUBLE) double num1, @SqlType(StandardTypes.DOUBLE) double num2, @SqlType(StandardTypes.INTEGER) long point) {
        double result = num1 / num2;

        return format(result, point);
    }

    @ScalarFunction(value = "divide")
    @Description("兩個數相除")
    @SqlType(StandardTypes.DOUBLE)
    public static double divide(@SqlType(StandardTypes.INTEGER) long num1, @SqlType(StandardTypes.DOUBLE) double num2) {
        return Double.valueOf(String.valueOf(num1)) / num2;
    }

    @ScalarFunction(value = "divide")
    @Description("兩個數相除")
    @SqlType(StandardTypes.DOUBLE)
    public static double divide(@SqlType(StandardTypes.INTEGER) long num1, @SqlType(StandardTypes.DOUBLE) double num2, @SqlType(StandardTypes.INTEGER) long point) {
        double result = Double.valueOf(String.valueOf(num1)) / num2;

        return format(result, point);
    }

    @ScalarFunction(value = "divide")
    @Description("兩個數相除")
    @SqlType(StandardTypes.DOUBLE)
    public static double divide(@SqlType(StandardTypes.DOUBLE) double num1, @SqlType(StandardTypes.INTEGER) long num2) {
        return num1 / Double.valueOf(String.valueOf(num2));
    }

    @ScalarFunction(value = "divide")
    @Description("兩個數相除")
    @SqlType(StandardTypes.DOUBLE)
    public static double divide(@SqlType(StandardTypes.DOUBLE) double num1, @SqlType(StandardTypes.INTEGER) long num2, @SqlType(StandardTypes.INTEGER) long point) {
        double result = num1 / Double.valueOf(String.valueOf(num2));
        return format(result, point);
    }

    @ScalarFunction(value = "divide")
    @Description("兩個數相除")
    @SqlType(StandardTypes.DOUBLE)
    public static double divide(@SqlType(StandardTypes.INTEGER) long num1, @SqlType(StandardTypes.INTEGER) long num2) {
        return Double.valueOf(String.valueOf(num1)) / Double.valueOf(String.valueOf(num2));
    }

    @ScalarFunction(value = "divide")
    @Description("兩個數相除")
    @SqlType(StandardTypes.DOUBLE)
    public static double divide(@SqlType(StandardTypes.INTEGER) long num1, @SqlType(StandardTypes.INTEGER) long num2, @SqlType(StandardTypes.INTEGER) long point) {
        double result = Double.valueOf(String.valueOf(num1)) / Double.valueOf(String.valueOf(num2));
        return format(result, point);
    }

    private static double format(double num, long point) {
        NumberFormat nf = NumberFormat.getNumberInstance();
        nf.setMaximumFractionDigits((int) point);
        // 如果不需要四捨五入,可以使用RoundingMode.DOWN
        nf.setRoundingMode(RoundingMode.UP);
        return Double.valueOf(nf.format(num));
    }
}

presto官方示例文檔:https://prestodb.github.io/docs/current/develop/functions.html
注意:
(1)、DivideFunc類爲什麼看起來這麼多重載類?presto對傳參要求比較嚴格,爲了兼容用戶不同類型的傳參
(2)、例如傳入divide(2,4),看起來2和4在代碼裏用int類型就可以接了,但是會報java兼容問題,自定義函數裏需要long類型才能接
(3)、傳參,返回值爲字符串類型,字符串類型需要 io.airlift.slice.Slice類接,示例:

    @LiteralParameters("x")
    @SqlType(StandardTypes.VARCHAR)
    public static Slice dateFormatWithString(@SqlType("varchar(x)") Slice dateTime, @SqlType("varchar(x)") Slice formatString) {
        String date = DateUtils.formateStr(dateTime.toStringUtf8(), formatString.toStringUtf8());
        return utf8Slice(date);
    }

3、打包。
打包需要把依賴的jar包都打進去,pom.xml文件

   <build>
        <finalName>tdplugin</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                    <maxmem>1024m</maxmem>
                    <fork>true</fork>
                    <compilerArgs>
                        <arg>-Xlint:all,-serial,-path</arg>
                    </compilerArgs>
                </configuration>
            </plugin>

            <plugin>
                <groupId>com.facebook.presto</groupId>
                <artifactId>presto-maven-plugin</artifactId>
                <version>0.3</version>
                <extensions>true</extensions>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.2.1</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <artifactSet>
                        <excludes>
                            <exclude>com.fasterxml.jackson.*:*</exclude>
                        </excludes>
                    </artifactSet>
                </configuration>
            </plugin>
        </plugins>
    </build>

4、執行打包命令,生成名爲customPlugin.jar的文件

 mvn clean package -Dmaven.test.skip=true

5、當前測試presto版本爲0.220版本,
在/presto-server-0.220/plugin目錄下創建名爲customPlugin的文件夾,再把customPlugin.jar上傳到customPlugin文件夾下。重啓presto服務

6、測試結果:

presto> select divide(2,4),divide(0.5,4),divide(0.2,0.5),divide(2,0.6),divide(2,0.6,3);
 _col0 | _col1 | _col2 |       _col3        | _col4
-------+-------+-------+--------------------+-------
   0.5 | 0.125 |   0.4 | 3.3333333333333335 | 3.334
(1 row)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章