linux下使用Eclipse创建mysql UDF(用户自定义函数)

来源:互联网 发布:android 修改mac地址 编辑:程序博客网 时间:2024/05/22 05:08

一 Mysql UDF:
为了在mysql中使用UDF,必须要动态链接库。
UDF通常需要用C/C++编写,如果要编写一个名为dist的UDF,那么需要定义如下的C/C++方法:
●dist() (必选)。这个方法的返回值就是UDF的结果。SQL数据类型和C/C++类型之间的对应关系是:varchar char *;INTEGER long long;REAL double;DECIMAL char *等。
●dist_init() (可选)。dist()对应的初始化方法。该方法通常用来检查dist()方法的参数(或者进行参数类型的转换),分配内存,指定返回值的最大长度等。
●dist_deinit() (可选)。dist()对应的清理方法。在这个方法中应该释放之前分配的内存。
生成动态链接库:
在linux下可以用eclips + CDT + G++
首先下载ECLIPS:
http://download.actuatechina.com/eclipse/technology/epp/downloads/release/galileo/SR2/eclipse-jee-galileo-SR2-linux-gtk.tar.gz
然后下载CDT:
http://mirrors.fe.up.pt/pub/eclipse//tools/cdt/releases/galileo/dist/cdt-master-6.0.2.zip
解压,复制features,plugins里面的文件到eclipse相应的目录下。
这样就可以使用eclipse开发C/C++程序了。
File->New->Project,如下图:
 
选择C++ Project,Next,如下图
 
填入Project name: dist, 左侧选择Share Library->Empty Project,右侧选择Linux GCC, 点击Finish
复制mysql里面的include文件件到dist工程目录下.然后Project->Properties出现下图:
 
左侧C/C++ General->Paths and Symbols,中间选择 GNU C++,然后Add include文件夹。
在dist项目中加入源文件,share.cc:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <math.h>
#include "mysql.h"
///////////////////////////////////////////////////
extern "C" {
    //
    my_bool dist_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
double dist(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args, char *is_null, char *error __attribute__((unused)));
}
my_bool dist_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
    uint i;
    if(args->arg_count != 4)
    {
        return -1;
    }
    for (i = 0; i < args->arg_count; i++)
        args->arg_type[i] = REAL_RESULT;
    initid->maybe_null = 1; /* The result may be null */
    return 0;
}

double dist(UDF_INIT *initid __attribute__((unused)), UDF_ARGS *args,
char *is_null, char *error __attribute__((unused)))
{
    int i;
    for(i=0; i<4; i++)
    {
        if(args->args[i] == NULL)
        {
            *is_null = 1;
            return 0.0;
        }
    }
    double lat1 = *((double*) args->args[0]);
    double lng1 = *((double*) args->args[1]);
    double lat2 = *((double*) args->args[2]);
    double lng2 = *((double*) args->args[3]);
    double radLat1 = M_PI*lat1/180.0;
    double radLat2 = M_PI*lat2/180.0;
    double a = radLat1 - radLat2;
    double b = M_PI*lng1/180.0 - M_PI*lng2/180.0;
double s = 2 * asin(sqrt(pow(sin(a/2),2) +
cos(radLat1)*cos(radLat2)*pow(sin(b/2),2)));
    s = s * 6371.01;
    return s;

Build Project 就可以生成动态连接库:libGetDistanceSo.so
注:在32位操作系统下声称的动态链接库在64位下面可能会出现这样的错误:wrong ELF class: ELFCLASS32。这样可以把工程放到64位的操作系统下进行编译:命令如下:
g++ -I/home/nkwangtong/GetDistanceSo/include -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"share.d" -MT"share.d" -o"share.o" "share.cc" -fPIC
g++ -shared -o"libGetDistanceSo.so"  ./share.o
拷贝libGetDistanceSo.so到usr/lib/mysql/plugin下,如果没有该目录就新建。
进入mysql shell
mysql -uroot -proot -Dracestorage
创建UDF dist:
CREATE FUNCTION dist RETURNS REAL SONAME "libGetDistanceSo.so";
测试:
select dist(latitude,longitude,45,63) from locations;
搞定!

二 MonetDB Create function:
在monetDB中创建UDF比较容易;
按如下操作进行即可:
create function dist(lat1 double,lng1 double,lat2 double,lng2 double) returns double
begin
declare radLat1 double;
declare radLat2 double;
declare a double;
declare b double;
declare s double;
set radLat1=3.1415926*lat1/180.0;
set radLat2=3.1415926*lat2/180.0;
set a=radLat1-radLat2;
set b=3.1415926*lng1/180.0-3.1415926*lng2/180.0;
set s=2*asin(sqrt(sin(a/2)*sin(a/2)+cos(radLat1)*cos(radLat2)*sin(b/2)*sin(b/2)));
return 6371.01*s;
end;


搞定!