大家想要的ClickHouse UDF这次终于来啦

2021-10-12 16:21:00 浏览数 (1)

大家一直想要的自定义函数,这次终于来啦,虽然目前还有点简单,不过 CH 的功能进一步丰富了。

这几天发现,一直有关注的自定义simple lambda function 这个 feature 被合并到主线了,那还不赶紧试一试?(文末会放上PR地址)

自定义 lambda 函数的语法如下:

代码语言:javascript复制
CREATE FUNCTION {fn_name} as ({parameters}) -> {code}

例如创建一个自定义函数 testFunc:

代码语言:javascript复制
CREATE FUNCTION testFunc AS (a, b) -> (a   b)

Query id: da558806-259f-428b-b777-5ecbbea8bae1

Ok.

0 rows in set. Elapsed: 0.004 sec.

创建之后,就可以在查询中使用了:

代码语言:javascript复制
SELECT testFunc(1, 2)

Query id: 9fba3a87-e577-44ae-bfe2-332c587aa180

┌─plus(1, 2)─┐
│          3 │
└────────────┘

1 rows in set. Elapsed: 0.003 sec.

让我们来一点复杂的情况:

代码语言:javascript复制
CREATE FUNCTION testFunc1 AS (a, b, c) -> a   b > c AND c < 20

验证结果:

代码语言:javascript复制
SELECT
    testFunc1(5, 6, 1),
    testFunc1(5, 6, 19),
    testFunc1(20, 40, 30)

Query id: 17cfe0a7-681f-4b28-81fa-718fe38f8a2a

┌─and(greater(plus(5, 6), 1), less(1, 20))─┬─and(greater(plus(5, 6), 19), less(19, 20))─┬─and(greater(plus(20, 40), 30), less(30, 20))─┐
│                                        1 │                                          0 │                                            0 │
└──────────────────────────────────────────┴────────────────────────────────────────────┴──────────────────────────────────────────────┘

1 rows in set. Elapsed: 0.003 sec.

在自定义函数中,尝试调用系统函数:

代码语言:javascript复制
create function createInfo as (perfix,state) -> multiIf(state==0,concat(perfix,'未开始'),state>0 and state<1 ,concat(perfix,'进行中'),state>=1 ,concat(perfix,'已完成'),'未知状态')

查询是OK的,但是好像列名没有办法设置别名:

代码语言:javascript复制
SELECT create_info('任务', 0) AS n1

Query id: 46c12694-3335-4d0b-8d55-e60802c68d2e

┌─multiIf(equals(0, 0), concat('任务', '未开始'), and(greater(0, 0), less(0, 1)), concat('任务', '进行中'), greaterOrEquals(0, 1), concat('任务', '已完成'), '未知状态')─┐
│ 任务未开始                                                                                                                                                             │
└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

1 rows in set. Elapsed: 0.003 sec.

直接使用表字段也没有问题:

代码语言:javascript复制
SELECT
    testFunc(JavaEnable, GoodEvent),
    JavaEnable,
    GoodEvent
FROM hits_100m_obfuscated
LIMIT 5

Query id: 30e05cdd-da21-46db-8a11-49c5fb348668

┌─plus(JavaEnable, GoodEvent)─┬─JavaEnable─┬─GoodEvent─┐
│                           1 │          0 │         1 │
│                           1 │          0 │         1 │
│                           1 │          0 │         1 │
│                           1 │          0 │         1 │
│                           1 │          0 │         1 │
└─────────────────────────────┴────────────┴───────────┘

5 rows in set. Elapsed: 0.006 sec.

进到 ClickHouse 的存储目录,会发现多了一个 user_defined 目录,专门用于保存 UDF 的元数据:

代码语言:javascript复制
% data/user_defined % ls -l
total 16
-rw-r-----  1 nauu  staff  46  9 18 08:00 function_testFunc.sql
-rw-r-----  1 nauu  staff  71  9 18 08:03 function_testFunc1.sql
代码语言:javascript复制
% cat ./function_testFunc.sql 
CREATE FUNCTION testFunc AS (a, b) -> (a   b)

我们也可以使用 Drop Function 删除 UDF:

代码语言:javascript复制
DROP FUNCTION testFunc1

Query id: 41b61849-a186-47b9-8072-c4af18be6bab

Ok.

0 rows in set. Elapsed: 0.006 sec.

自定义的函数也会被添加到系统表:

代码语言:javascript复制
SELECT *
FROM system.functions
WHERE name = 'testFunc'

Query id: 97037df5-cda6-471f-933f-278670f3b113

┌─name─────┬─is_aggregate─┬─case_insensitive─┬─alias_to─┬─create_query──────────────────────────────────┐
│ testFunc │            0 │                0 │          │ CREATE FUNCTION testFunc AS (a, b) -> (a   b) │
└──────────┴──────────────┴──────────────────┴──────────┴───────────────────────────────────────────────┘

1 rows in set. Elapsed: 0.003 sec. Processed 1.06 thousand rows, 46.30 KB (304.53 thousand rows/s., 13.24 MB/s.)

好了,今天就分享到这里吧,PR在此:

https://github.com/ClickHouse/ClickHouse/pull/23978

原创不易,如果这篇文章对你有帮助,欢迎 点赞、转发、在看 三连击

0 人点赞