跳至主要內容

多语言远程 UDF(C / C++ / Java / ...)

大约 4 分钟

多语言远程 UDF(C / C++ / Java / ...)

Remote UDF Service 支持通过 RPC 的方式访问用户提供的 UDF Service,以实现用户自定义函数的执行。
相比于 Native 的 UDF 实现,Remote UDF Service 有如下优势:

  • 跨语言:可以用 Protobuf 支持的各类语言编写 UDF Service。
  • 安全:UDF 执行失败或崩溃,仅会影响 UDF Service 自身,而不会导致 IoTDB 进程崩溃。
  • 灵活:UDF Service 中可以调用任意其他服务或程序库类,以满足更多样的业务需求。

依赖

protobuf 编译安装

./autogen.sh
./configure --prefix=/XX/bin/protobuflib/
make
make install

如果你使用的是 Java 或 C++等,完成以上步骤就已经可以使用生成的protobuf可执行程序生产protobuf相关文件了。

protobuf-c 编译安装(C 语言远程 UDF 需此步骤)

PKG_CONFIG_PATH=/XX/bin/protobuflib/
export PKG_CONFIG_PATH
  • 下载protobuf-c,解压
  • 编译 (用于生成编译服务器下可执行程序):
./autogen.sh
./configure --prefix=/XX/bin/protobufc/
make
make install

protobufc下生成的文件,即为编译生成的依赖库、protobuf-c可执行程序,使用protobuf-c可执行程序可以根据proto文件生成.c和.h文件

编写 UDF 函数

拷贝 proto 文件

function_service.proto 和 types.proto 拷贝到 Rpc 服务中

  • function_service.proto
    • PFunctionCallRequest
      • function_name:函数名称,对应创建函数时指定的symbol
      • args:方法传递的参数
      • context:查询上下文信息
    • PFunctionCallResponse
      • result:结果
      • status:状态,0代表正常
    • PCheckFunctionRequest
      • function:函数相关信息
      • match_type:匹配类型
    • PCheckFunctionResponse
      • status:状态,0代表正常

生成接口

通过 protoc 生成代码,具体参数通过 protoc -h 查看

实现接口

共需要实现以下三个方法

  • fnCall:用于编写计算逻辑
  • checkFn:用于创建 UDF 时校验,校验函数名/参数/返回值等是否合法
  • handShake:用于接口探活

创建 UDF

CREATE FUNCTION <UDF-NAME> AS 
    SYMBOL = <SYMBOL>,
    OBJECT_FILE = <OBJECT_FILE>,
    LANGUAGE PROTOBUF

说明:

  1. symbol表示的是 rpc 调用传递的方法名,这个参数是必须设定的。
  2. object_file表示的 rpc 服务地址,目前支持单个地址和 brpc 兼容格式的集群地址。

示例:

CREATE FUNCTION rpc_udf1 AS 
    SYMBOL = "fnCall",
    OBJECT_FILE = "127.0.0.1:9090",
    LANGUAGE PROTOBUF;

UDF 卸载

卸载 UDF 的 SQL 语法如下:

DROP FUNCTION <UDF-NAME>

例如:

DROP FUNCTION rpc_udf1

UDF 查询

UDF 的使用方法与普通内建函数的类似。

支持的基础 SQL 语法

  • SLIMIT / SOFFSET
  • LIMIT / OFFSET
  • 支持值过滤
  • 支持时间过滤

带 * 查询

假定现在有时间序列 root.sg.d1.s1root.sg.d1.s2

  • 执行SELECT example(*) from root.sg.d1

那么结果集中将包括example(root.sg.d1.s1)example(root.sg.d1.s2)的结果。

  • 执行SELECT example(s1, *) from root.sg.d1

那么结果集中将包括example(root.sg.d1.s1, root.sg.d1.s1)example(root.sg.d1.s1, root.sg.d1.s2)的结果。

  • 执行SELECT example(*, *) from root.sg.d1

那么结果集中将包括example(root.sg.d1.s1, root.sg.d1.s1)example(root.sg.d1.s2, root.sg.d1.s1)example(root.sg.d1.s1, root.sg.d1.s2)example(root.sg.d1.s2, root.sg.d1.s2)的结果。

带自定义输入参数的查询

您可以在进行 UDF 查询的时候,向 UDF 传入任意数量的键值对参数。键值对中的键和值都需要被单引号或者双引号引起来。注意,键值对参数只能在所有时间序列后传入。下面是一组例子:

SELECT example(s1, 'key1'='value1', 'key2'='value2'), example(*, 'key3'='value3') FROM root.sg.d1;
SELECT example(s1, s2, 'key1'='value1', 'key2'='value2') FROM root.sg.d1;

与其他查询的嵌套查询

SELECT s1, s2, example(s1, s2) FROM root.sg.d1;
SELECT *, example(*) FROM root.sg.d1 DISABLE ALIGN;
SELECT s1 * example(* / s1 + s2) FROM root.sg.d1;
SELECT s1, s2, s1 + example(s1, s2), s1 - example(s1 + example(s1, s2) / s2) FROM root.sg.d1;

查看所有注册的 UDF

SHOW FUNCTIONS

用户权限管理

用户在使用 UDF 时会涉及到 3 种权限:

  • CREATE_FUNCTION:具备该权限的用户才被允许执行 UDF 注册操作
  • DROP_FUNCTION:具备该权限的用户才被允许执行 UDF 卸载操作
  • READ_TIMESERIES:具备该权限的用户才被允许使用 UDF 进行查询

更多用户权限相关的内容,请参考 权限管理语句

Copyright © 2023 The Apache Software Foundation.
Apache and the Apache feather logo are trademarks of The Apache Software Foundation

Have a question? Connect with us on QQ, WeChat, or Slack. Join the community now.

We use Google Analytics to collect anonymous, aggregated usage information.