背景:select count(*) from table;
上述count是mysql内部的方法,但是毕竟是mysql自己定义的,有时候不能满足我们自己的需求,所以mysql对外提供了这样的接口,允许用户自己定义相应的功能函数;
开发UDF需要使用c/c++,我使用的是c++,IDE是vc++6.0,然后呢编写UDF需要MYSQL提供的文件头,当然你要是用c++编写过访问mysql数据库的程序的话,这个就不是问题;这几个文件头是my_alloc.h,my_global.h,my_list.h,mysql.h,mysql_com.h,mysql_time.h,mysql_version.h,typelib.h;这几个头文件可以从你安装的mysql数据库服务器的include文件夹下找到,当然要是你安装mysql的时候没有选择安装开发包的话,那么你就找不到这个文件夹,所以你就是个悲剧,从网上下相应的头文件,结果没吓到自己想要的,反而下下来一些恶意软件,我也没有安装,所以我很悲剧的把数据库搞崩了,然后重新安装了一个完整版的;
好的,打开vc++新建一个win2动态链接库工程;
在新建一个source file;
考入如下简单代码做测试,当然别忘了在工程下考上上面提到的几个头文件;
// Encode.cpp : Defines the entry point for the DLL
application.
//
#include "winsock2.h"
#include "mysql.h"
using namespace std;
#define SAFE_DELETE(p) if(p!=NULL){delete p;p=NULL;}
#define CDLLEXPORT extern "C" __declspec(dllexport)
typedef __int64 longlong;
typedef unsigned long ulong;
CDLLEXPORT my_bool saas_init(UDF_INIT *initid, UDF_ARGS *args,
char *message)
{
longlong* i = new longlong; // 建立变量
*i = 0; //
设初值 //指针变量中保存为一个字符指针
//确认你不会遇到类型问题
initid->ptr = (char*)i;
if(args->arg_count!=1)
//参数个数为1
{
strcpy(message,"args count
wrong");
return 1;
}
if(args->arg_type[0]!=REAL_RESULT&&args->arg_type[0]!=INT_RESULT)
//参数类别为整型或double
{
strcpy(message,"args
wrong"); return 1;
}
return 0;
}
CDLLEXPORT void saas_deinit(UDF_INIT *initid)
{
delete
(longlong*)initid->ptr;
}
CDLLEXPORT __int64 saas(UDF_INIT *initid, UDF_ARGS *args,char
*is_null, char *error)
{
longlong int_val;
if(args->arg_type[0]==INT_RESULT)
{
int_val = *((longlong*)
args->args[0]);
}
return int_val+5;
}
很好,现在你可以生成一个动态链库了,将其考到你的mysql安装目录下的bin目录,当然这里其实只要考到系统路径下都是可以找到的;
然后需要在mysql中注册你定义的函数;
CREATE [AGGREGATE] FUNCTION function_name RETURNS {STRING|INTEGER|REAL}
SONAME shared_library_name
DROP FUNCTION function_name
第一句的意思是创建一个聚合或者是非聚合的函数,sql中调用的名称是function_name,返回类型是{STRING|INTEGER|REAL}其中的一种,然后shared_library_name是你生成的动态链接库的名称,貌似但是还没有确定的是你的函数名和上述的源代码中的方法必须一致,这点不用怀疑,另外貌似动态链接库的,名称也得喝函数的名称一致;
创建成功后会从mysql服务器的mysql数据库的func表中找到对应的一条记录的添加,;如果想要删除这个自定义函数那么就用第二条语句删之;
至于上述的代码运行时没有问题,但关键是其中的参数是怎么一个情况,在此不做过多介绍,可参考
记录下我需要的信息:
说明主函数xxx()。注意返回值和参数会有所不同,这取决于你说明的SQL函数xxx()在CREATE FUNCTION声明中返回的是STRING,INTEGER类型还是REAL类型示:
对于STRING 型函数:
char *xxx(UDF_INIT *initid, UDF_ARGS *args,
char *result, unsigned long *length,
char *is_null, char *error);
对于INTEGER型函数:
long long xxx(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error);
对于REAL型函数:
double xxx(UDF_INIT *initid, UDF_ARGS *args,
char *is_null, char *error);
对主函数的每次调用,args->args 包含为每个当前处理的行传递的实际参量。
如下使用参量i的函数:
给一个STRING_RESULT
型的参量作为一个字符串加一个长度,可以允许所有二进制数或任意长度的数处理。字符串内容作为args->args[i]
而字符串长度为args->lengths[i]。你不能采用null结尾的字符串。
对一个INT_RESULT型的参量,你必须转换args->args[i] 为一个long long
值:
longlong int_val;
int_val = *((longlong*) args->args[i]);
对一个REAL_RESULT型参量,你必须转换args->args[i]为一个双精度值:
double real_val;
real_val = *((double*) args->args[i]);
unsigned long *lengths
对初始化函数,lengths数列表示对每个参量的最大字符串长度。你不要改变它。对主函数的每次调用,lengths包含了对当前处理行传递的任何字符串
参量的实际长度。对于INT_RESULT 或 REAL_RESULT类型的参量,lengths
仍包含参量的最大长度(对初始化函数)。
好的,到此为止!
下面是上述定义的函数的注册操作和相应的删除过程,上述定义的函数仅仅是一个简单的对结果加5的操作,可从下面的操作具体看出;
Enter password: ****
Welcome to the MySQL monitor. Commands end with ;
or \g.
Your MySQL connection id is 13
Server version: 5.2.3-falcon-alpha-community-nt MySQL Community
Server (GPL)
Type 'help;' or '\h' for help. Type '\c' to clear the
buffer.
mysql> use saas
Database changed
mysql> --with-mysqld-ldflags=-rdynamic
mysql> CREATE FUNCTION saas RETURNS INTEGER SONAME
'saas.dll';
Query OK, 0 rows affected (0.02 sec)
mysql> select appid from dataobjects;
+-------+
| appid |
+-------+
| 1 |
| 1 |
+-------+
2 rows in set (0.02 sec)
mysql> select saas(appid) from dataobjects;
+-------------+
| saas(appid) |
+-------------+
| 6 |
| 6 |
+-------------+
2 rows in set (0.00 sec)
mysql> drop function saas;
Query OK, 0 rows affected (0.00 sec)
mysql>