1.什么是UDF
UDF顾名思义,就是User defined Function,用户定义函数。我们知道,MySQL本身支持很多内建的函数,此外还可以通过创建存储方法来定义函数。UDF为用户提供了一种更高效的方式来创建函数。
UDF与普通函数类似,有参数,也有输出。分为两种类型:单次调用型和聚集函数。前者能够针对每一行数据进行处理,后者则用于处理Group By这样的情况。
2.为什么用UDF
既然MySQL本身提供了大量的函数,并且也支持定义函数,为什么我们还需要UDF呢?这主要基于以下几点:
1)UDF的兼容性很好,这得益于MySQL的UDF基本上没有变动
2)比存储方法具有更高的执行效率,并支持聚集函数
3)相比修改代码增加函数,更加方便简单
当然UDF也是有缺点的,这是因为UDF也处于mysqld的内存空间中,不谨慎的内存使用很容易导致mysqld crash掉。
3.如何编写UDF
UDF的API包括
name_init():
在执行SQL之前会被调用,主要做一些初始化的工作,比如分配后续用到的内存、初始化变量、检查参数是否合法等。
name_deinit()
在执行完SQL后调用,大多用于内存清理等工作。init和deinit这两个函数都是可选的
name()
UDF的主要处理函数,当为单次调用型时,可以处理每一行的数据;当为聚集函数时,则返回Group by后的聚集结果。
name_add()
在每个分组中每行调用
name_clear()
在每个分组之后调用
为了便于理解,这里给出两种UDF类型的API调用图:

下面将就上述几个API进行详细的讲解:
1). name_init
原型:
my_boolname_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
UDF_INIT结构体如下:
字段
|
类型
|
描述
|
maybe_null
|
my_bool
|
如果为1表示该UDF可以返回NULL
|
decimals
|
unsigned int
|
返回值为实数时,表示精度,范围0~30
|
max_length
|
unsigned long
|
返回值最大允许的长度
|
ptr
|
char*
|
额外的指针,我们可以在这里分配内存。通过initd传递给其他API
|
const_item
|
my_bool
|
为1表示函数总是返回相同的值
|
extension
|
void*
|
用于扩展?
|
UDF_ARGS结构体如下:
字段
|
类型
|
描述
|
arg_count
|
unsigned int
|
参数个数
|
arg_type
|
enum Item_result*
|
参数类型数组,记录每一个参数的类型,可以是STRING_RESULT、REAL_RESULT、INT_RESULT以及DECIMAL_RESULT
|
args
|
char **
|
同样是一个数组,用于存储实际数据。
STRING_RESULT与DECIMAL_RESULT类型为char*,INT_RESULT类型为long long*,REAL_RESULT类型为double*,或者一个NULL指针
|
lengths
|
unsigned long*
|
数组,用于存储每一个参数的长度
|
maybe_null
|
char *
|
该数组用于表明每个参数是否可以为NULL,例如
|
attributes
|
char **
|
每个参数的名字
|
attribute_lengths
|
unsigned long*
|
每个参数名字的长度
|
extension
|
void*
|
用于扩展?
|
Message:用于打印错误信息,该指针本身提供长度为MYSQL_ERRMSG_SIZE,来存储信息;
2).name_deinit
原型:
void name_deinit(UDF_INIT*initid)
该函数会进行一些内存释放和清理的工作,在之前我们提到initid->ptr,我们可以在该区域·进行内存的动态分配,这里就可以直接进行内存释放。
3).name()
原型:针对不同的返回值类型,有不同的函数原型:
返回值类型
|
函数原型
|
STRING or DECIMAL
|
char *name(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error)
|
INTEGER
|
long long name(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
|
REAL
|
double name(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
|
当返回值为STRING类型时,参数result开辟一个buffer来存储返回值,但不超过766字节,在length参数中存储了字符串的长度。
每个函数原型还包括了is_null和error参数,当*is_null被设置为1时,返回值为NULL,设置*error为1,表明发生了错误。
4).name_add()和name_clear()
原型:
void name_add(UDF_INIT *initid, UDF_ARGS *args, char *is_null,char *error)
void name_clear(UDF_INIT *initid, char *is_null, char *error)
对于聚合类型的UDF,name_addd和name_clear会被反复调用。
4. 两个例子
下面将举两个简单的例子,一个单次调用型函数,一个聚集类型函数,来描述写一个UDF的过程。
1)接受一个参数,并返回该参数的值
//初始化
//清理操作
//主函数
2)接受一个浮点数类型的参数,并对每个分组进行求和
//清理、释放在init函数中分配的内存
//每一行都会调用到该函数
//每个分组完成后,返回结果
//在进行下一个分组前调用,设置initid->ptr指向的值为0,以便下一次分组统计
3) Mysql-udf-http是一个开源的UDF,可以利用HTTP协议进行REST操作。什么是REST操作呢?REST是一种web service架构风格,其实现基于HTTP协议的四种方法:POST、GET、PUT以及DELETE操作,在mysql-udf-http里分别对应的函数是http_post、http_get()、http_put()、http_delete()。
源码下载:http://curl.haxx.se/download/curl-7.21.1.tar.gz
./configure–prefix={mysql安装目录} –with-mysql=/usr/local/webserver/mysql/bin/mysql_config
Make&& make install
该UDF的实现原理比较简单,主要使用libcurl库函数来实现http协议通信,总共三百多行代码。这里有使用和介绍http://blog.s135.com/mysql-udf-http/
有些比较有趣的功能:
例如,我们可以通过GET方法获取微博中的个人信息,其中1821798401为用户ID
selecthttp_get('http://api.t.sina.com.cn/statuses/user_timeline/1821798401.json?count=1&source=1561596835')
UDF具有非常高的自由度,你可以编写你任何想要实现的功能函数,甚至可以引用MySQL内核的代码和变量。
当然,UDF也有着局限性,如下:
a)在mysql库下必须有func表,并且在‑‑skip‑grant‑tables开启的情况下,UDF会被禁止;
b)当UDF挂掉时,有可能会导致mysqld crash掉;
c)所有的UDF的函数必须是线程安全的,如果非要用全局变量,需要加互斥,尽量在name_init中分配资源,并在name_deinit中释放
d)需要有insert权限
转载请注明作者:印风
分享到:
相关推荐
C语言因其高效和接近硬件的特性,被广泛用于编写MySQL UDF。开发过程包括以下几个步骤: 1. **设计函数接口**:定义UDF的输入参数和返回类型,以及可能的错误状态。 2. **编写函数实现**:在C代码中实现具体的功能...
1. **UDF(User Defined Function)**:MySQL UDF 允许开发者用 C/C++ 编写函数,然后在 SQL 查询语句中调用这些函数,以满足特定的数据处理需求。这极大地提高了 MySQL 的灵活性和功能性。 2. **HTTP 请求**:HTTP...
2. **编程语言**:多数数据库系统支持用不同的编程语言(如C, C++, Java等)来编写UDF。你需要确保数据库系统支持你选择的语言,并且正确配置了相应的接口。 3. **函数签名**:每个UDF都有输入参数(如果有的话)和...
1. **UDF编译与注入**:首先,你需要编写或找到一个能够执行系统命令或者具有恶意行为的UDF库,如`UDF.dll`。这个动态链接库文件包含自定义函数的实现。然后,通过SQL注入或其他手段,将这个UDF注入到MySQL服务器的...
- **安全性和性能**:编写UDF时,应考虑安全性和性能。确保函数是线程安全的,并优化代码以减少计算时间。 - **安装和卸载**:UDF可以通过`CREATE FUNCTION`和`DROP FUNCTION` SQL语句在MySQL中安装和卸载。编译后...
- UDF的错误处理:在编写UDF时,应妥善处理可能出现的错误,避免因异常导致数据库服务崩溃。 - UDF版本兼容性:不同版本的MySQL可能对UDF接口有所改动,确保UDF与目标MySQL版本兼容。 通过深入理解MySQL UDF的...
MySQL UDF允许用户编写C或C++代码,将其编译成动态链接库(.so文件),然后在MySQL服务器中加载,使得这些自定义函数可以在SQL查询中被调用。UDF可以处理各种数据类型,包括数值、字符串、日期和时间等,极大地丰富...
- **定义**:MySQL UDF 允许开发者编写自己的函数,将其集成到 MySQL 查询中,扩展其内置函数库。 - **类型**:UDFs 分为整数、字符串、时间和二进制四种类型。 - **作用**:通过 UDF,MySQL 可以调用外部程序或...
总结来说,这个压缩包提供了跨平台的MySQL UDF C语言源码,可以帮助开发者深入了解MySQL的扩展机制,学习如何编写和集成自定义函数,以满足特定的数据库操作需求。通过这个实践,你可以提升对MySQL底层机制的理解,...
这个项目是用C语言编写的,因为MySQL的UDF接口主要支持C和C++。C语言是一种底层编程语言,能够直接与操作系统交互,因此适合实现这样的低级功能。开发人员通常会使用C来编写数据库的扩展,以确保高效性和兼容性。 ...
UDF(User Defined Function)的原理是,MySQL允许用户编写C语言的库,并将其加载到服务器中,作为新的内置函数使用。这些函数可以执行原本MySQL不支持的操作,或者增强已有的功能。UDF分为两种类型:存储过程和函数...
在MySQL中,UDF(User Defined Function)是开发者可以编写并集成到数据库服务器中的代码模块,它们可以是C、C++或其他支持的语言编写的。这种功能使得MySQL能够执行原本不包含在标准SQL语句中的特定操作,例如这里...
`lib_mysqludf_sys`库由一系列C语言编写的共享库组成,这些库包含了一系列系统调用函数,如执行shell命令、读取文件内容等。这使得数据库管理员和开发人员可以在执行SQL查询时直接与操作系统交互,从而实现一些...
在标题和描述中提到的"UDF 源项, udf源项编程问题, C, C++源码",我们可以推断这是一个关于使用C或C++语言编写UDF源代码的问题集,可能包含了示例、代码片段和解决常见编程问题的方案。 在数据库系统中,UDF主要...
在编写UDF时,必须遵循MySQL UDF接口的规定。例如,`http_post_init`函数必须返回`my_bool`类型的值,如果初始化成功,则返回0,否则返回1。如果主函数(`http_post`)的返回值为1,MySQL将停止执行。 在实现...
UDF手册2020可能包含了关于如何在C和C++编程语言中编写UDF的详细指南,这些函数可以被数据库系统调用。C和C++作为底层语言,提供了高效的性能和灵活的控制,是创建UDF的理想选择,特别是对于需要高性能计算或者与...
Hive 自定义 UDF 编写函数 本文主要讲解了 Hive 中自定义 UDF 函数的编写方法,包括创建 UDF 类、实现自定义函数逻辑、编译和打包 UDF jar 包、上传至 Hive 服务器并注册自定义函数。 一、创建 UDF 类 为了实现...
UDF在数据库系统中的作用在于,当内置的函数无法满足特定业务需求时,开发人员可以通过编写自己的函数来处理数据。在SQL中,UDF可以与查询语句一起使用,提供更灵活的数据处理能力。UDF分为两种类型:过程化UDF和...
UDF允许开发者编写C或C++代码,创建新的函数供SQL查询使用。在这个JSON插件中,UDF可能是用来处理和解析JSON文档的关键组件,提供了标准函数集之外的额外功能。 文件"lib_mysqludf_json.so"是一个动态链接库,它是...