技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> MySQL --> 教你写MySQL UDF

教你写MySQL UDF

浏览:2024次  出处信息

第一次听说UDF是,一片懵懂。还被一个半桶水的培训师忽悠说是存储函数即是UDF。现在想来真是匪夷所思,害人不浅。


从名字上可以得知UDF(user define function)为用户自定义函数。UDF在一定程度上可以使得普通用户定制自己的MySQL函数库,减少对内建函数的依赖。UDF 的功能还是非常强大的。


各类技术人员都可以开发相应的UDF。

管理员可以开发一些与系统交互的UDF。而开发人员可将常用功能用UDF替代存储函数,这样可以大幅提高执行速度和效率。



这篇BLOG的目的想给希望编写UDF的读者提供一些帮助,但读者应该根据自己的需要添加某些具体函数。

现在直入话题,MySQL手册上确实提供了有关MySQL UDF的一些规则。读者可以参考链接

咱们分4步骤创建一个UDF:

  1. 编写代码
  2. 编译
  3. 安装
  4. 使用

下面给出一个简单的UDF。其作用就是往error日志里面写入语句。为了做这个实验,我们将使用如下平台:

  • OS:OpenSolaris,
  • DB:MySQL 5.1.39
  • C compiler: Sun C

实例代码如下:

以下是代码片段:
/* You owed me when you copy this code without informing dingze.zhu@gmail.com
* It’s owned by mysqlsystems.com
*/ 
#if defined(_WIN32)

#define DLLEXP __declspec(dllexport)
#else
#define DLLEXP
#endif

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <mysql.h>
#define LIBVERSION “mysqlsystems_udf_log version 0.1 beta”
#define ERR_ARG “Hiro tells you: Exactly one argument expected!”
#define ERR_MEM “Out of memory!”
#ifdef  __cplusplus
extern “C” {
#endif
/**
* mysqlsystems_udf_log
*/
DLLEXP
my_bool mysqlsystems_udf_log_init(
UDF_INIT *initid
,    UDF_ARGS *args
,    char *message
){
return 0;
}
DLLEXP
void mysqlsystems_udf_log_deinit(
UDF_INIT *initid
){}
DLLEXP
char* mysqlsystems_udf_log(
UDF_INIT *initid
,    UDF_ARGS *args
,    char* result
,    unsigned long* length
,    char *is_null
,    char *error
){
*length = strlen(LIBVERSION);
return LIBVERSION;
}
/**
* another one : log2error
*/
DLLEXP
my_bool log2error_init(
UDF_INIT *initid
,    UDF_ARGS *args
,    char *message
){
if(args->arg_count==1){
//alloc mem for format pattern:
// “%s0.xxxx\n”
// where xxxx is the max
// 7 = length of %s0.\n + trailing \0
if(!(initid->ptr = (char *)malloc(7 + 4))){
strcpy(message, ERR_MEM);
return 1;
}
args->arg_type[0] = STRING_RESULT;
initid->maybe_null = 0;
} else {
strcpy(message, ERR_ARG);
return 1;
}
return 0;
}
DLLEXP
void log2error_deinit(
UDF_INIT *initid
){
if(initid->ptr)
{
fflush(stderr);
free(initid->ptr);
}
}
DLLEXP
my_ulonglong log2error(
UDF_INIT *initid
,    UDF_ARGS *args
,    char *is_null
,    char *error
){
int numDigits;
char *fmt;
*is_null = 0;
if(args->args[0]==NULL){
fprintf(stderr, “NULL\n”);
} else {
fmt = (char *)initid->ptr;
memcpy(fmt, “%0.”, 3);
sprintf(fmt+3, “%d”, args->lengths[0]<=9998? args->lengths[0]: 9998);
numDigits = strlen(fmt + 4);
memcpy(fmt + 4 + numDigits, “s\n\0″, 3);
fprintf(stderr, fmt, args->args[0]);
}
return 0;
}
#ifdef  __cplusplus
}
#endif

编写完毕代码后,需要将源代码编译成动态库.so文件。随后将动态库拷贝到MySQL安装目录的lib/plugin下。(在那里我们还可以找到Innodb的动态库文件)

根据你使用的OS、MySQL等环境。可能有所出入。在本实验中,使用如下

cc -I/user/local/mysql/include -shared -o mysqlsystems_udf_log.so mysqlsystems_udf_log.c

下图是安装和使用的过程:

install_udf2

查看MySQL的error日志:

error_log

网友可以看到,在error log第22号,出现了我们输入的 hello world字样。

建议继续学习:

  1. 不定参数的应用 function(fmt, …)    (阅读:3928)
  2. 函数式编程    (阅读:3596)
  3. JavaScript的5种调用函数的方法    (阅读:3476)
  4. 为 MySQL 增加 HTTP/REST 客户端:MySQL UDF 函数 mysql-udf-http 1.0 发布    (阅读:3043)
  5. C 语言中统一的函数指针    (阅读:2976)
  6. C语言函数实现的另类方法    (阅读:2836)
  7. 关于在函数调用时传递string引用的必要性    (阅读:2774)
  8. 深入理解PHP之匿名函数    (阅读:2556)
  9. MySQL 内部函数简介    (阅读:2391)
  10. PHP中htmlentities()和htmlspecialchars()这两个函数的区别    (阅读:2386)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1