在 eKuiper SQL 语法中,向服务器提供了许多内置函数,用于各种可重用的业务逻辑。 但是,用户仍然可能需要其他未被内置插件覆盖的可重用的业务逻辑。 提供函数扩展是为了自定义函数。
为 eKuiper 开发函数的过程,就是实现 api.Function 接口并将其导出为 golang 插件。
在开始开发之前,您必须为 golang 插件设置环境。
为了开发函数,首先要实现 Validate 方法。 在 SQL 验证期间将调用此方法。 在此方法中,将传递 xsql.Expr 的切片作为参数,该参数包含运行时该函数的参数。 开发人员可以对其进行验证,以检查参数计数和类型等。如果验证成功,则返回 nil。 否则,返回一个错误对象。
//The argument is a list of xsql.Expr
Validate(args []interface{}) error
函数有2种类型:聚合函数和通用函数。 对于聚合函数,如果参数为列,则接收的值将始终是组中列值的一部分。 扩展函数必须通过实施 IsAggregate 方法来区分函数类型。
//If this function is an aggregate function. Each parameter of an aggregate function will be a slice
IsAggregate() bool
函数的主任务是实现 exec 方法。 该方法将用于计算 SQL 中函数的结果。 参数是函数参数值的一部分。 您可以使用它们进行计算。 如果计算成功,则返回结果并返回 true; 否则,返回 nil 和 false。
//执行函数,如果执行成功,返回结果,如果执行失败,返回错误和 false。
Exec(args []interface{}) (interface{}, bool)
由于该函数本身是一个插件,因此必须位于 main 程序包中。 给定的函数结构名称为 myFunction。 在文件的最后,必须将源文件作为符号导出,如下所示。 有2种类型的导出符号被支持。 对于函数扩展,如果没有内部状态,建议导出单例实例。
var MyFunction myFunction
Echo Function 是一个很好的示例。
开发者可在一个函数插件中导出多个函数。每个函数均需实现 api.Function 接口,正如 开发一个定制函数 所描述的那样。需要确保所有函数都导出了,如下所示:
var(
Function1 function1
Function2 function2
Functionn functionn
)
同一类的函数可以在一个插件里开发和导出以减少构建和部署开销。
将实现的函数构建为 go 插件,并确保输出 so 文件位于 plugins/functions 文件夹中。
go build -trimpath --buildmode=plugin -o plugins/functions/MyFunction.so extensions/functions/my_function.go
eKuiper 启动时会自动载入插件目录里已编译好的插件。自动载入的函数插件假设插件里仅导出一个同名的函数。如果插件导出多个函数,则需要显示运行一次注册操作。有两种方法可以注册函数:
- 在开发环境中,建议直接构建插件 .so 文件到插件目录中以便 eKuiper 自动载入。构建完成后,运行 CLI 注册函数命令 or REST 注册函数 API 进行注册。
- 在生产环境中,打包插件到 zip 压缩包,然后运行 CLI 创建函数插件命令 或者 REST 创建函数 API 并设置 functions 参数以指定导出函数名。
如果自定义函数遵循以下约定,则可以直接在规则的 SQL 中使用。
如果已经开发了函数实现 MyFunction,则应该具有:
- 在插件文件中,将导出符号 MyFunction。
- 编译的 MyFunction.so 文件位于 plugins/functions 内部
要使用它,只需在规则定义中的 SQL 中调用它:
{
"id": "rule1",
"sql": "SELECT myFunction(name) from demo",
"actions": [
{
"log": {
}
}
]
}