Mysql UDF (User-Defined Function Interface),可以用于Mysql功能扩展。

一般来说使用C/C++实现。

这里实现一个名字为fx_msg的function.

主要功能是开启一个线程进行监听sockt连接,

当调用此函数时将指定的消息发送到socket连接上.

select FX_MSG(CMD[,PARM1,PARM2...]);

初始化 FX_MSG 监听环境

CMD:INIT PARM:int MAX_Conn , int PORT

关闭所有连接,关才监听

CMD:CLOSE

查看当前连接Client信息

CMD:LISTCLIENT

查看当前版本信息

CMD:VERSION

还设想了一些功能,懒得做了。。。

.....

布置开发环境.

不喜欢 M$ 的 VC (也是不太会用)(-:

还是用eclipse习惯。哈哈。。。。

呵呵,操作系统还是比较习惯用XP.....

eclipse 3.3 CDT 用来起还是相当不

错(-: . 不过它只是一个编辑器,

不具备编译功能。

download cygwin 做为cygwin编译器.

注意安装的时候要 选中 开发工具中

的 gcc / g++ 等。

要做mysql的UDF当然需要mysql的一些

头文件 ,去mysql.com下载mysql的原

码包。 解开,里面有个include目录。

使用这个就可以了。

不过我使用的时候里面有几个和mysql

版本号相关的预编译宏编译不过,不知道

为啥了,手动处理一下。该删的删,该改

的改。

闲话少说,动手:

A. eclipse 新建一个Shared Library工程 。

呵呵,别建搞错了。默认可不是这个(-:

B.选择工具链:Cygwin GCC

C.Project Properties中把mysql的include包含进来

原代码://data_struct.h

//***********************************************

#ifndef DATASTRUCT_H_

#define DATASTRUCT_H_

/**

* client connection infomation

*/

typedef struct client{

long sock_fd ;

char *ip ;

long port ;

struct client *next;

}Client,*ClientPtr;

typedef struct {

ClientPtr g_client;

long g_sockFD ;

int INITOK ;

} Status;

#endif /*DATASTRUCT_H_*/

fxmsg.h

//*********************************************

#include "mysql.h"

#include

#include

#include

#include

#include

#include

#include

#include

#include "data_struct.h"

#ifndef FXMSG_H_

#define FXMSG_H_

#define BOOL_TRUE 100

#define BOOL_FALSE 200

int initCheck(UDF_INIT *initid, UDF_ARGS *args, char *message);

int sendCheck(UDF_INIT *initid, UDF_ARGS *args, char *message);

int doInit(UDF_INIT *initid, UDF_ARGS *args, char *message);

int closeCheck(UDF_INIT *initid, UDF_ARGS *args, char *message);

int doClose(UDF_INIT *initid, UDF_ARGS *args, char *message);

void fxlog(char *c);

Status g_status;

#endif /*FXMSG_H_*/

cmd_close.c

//************************************

#include "fxmsg.h"

int closeCheck(UDF_INIT *initid, UDF_ARGS *args, char *message){

if(args->arg_count !=1){

strcpy(message,"ERROR. ERR Parameter! Eg: select fx_msg('CLOSE');");

return BOOL_FALSE;

}

if( BOOL_FALSE == g_status.INITOK ){

strcpy(message,"ERROR. INITOK is false.");

return BOOL_FALSE;

}

return BOOL_TRUE;

}

int doClose(UDF_INIT *initid, UDF_ARGS *args, char *message){

ClientPtr temp ;

while(g_status.g_client!=NULL){

temp = g_status.g_client;

g_status.g_client = g_status.g_client->next;

char buf[200];

sprintf(buf," close connection [fd:%ld] ip:%s:%ld",temp->sock_fd,temp->ip,temp->port);

fxlog(buf);

close(temp->sock_fd);

free(temp);

}

char buf[200];

sprintf(buf," close g_sockFD ! [fd:%ld] ",g_status.g_sockFD);

fxlog(buf);

close(g_status.g_sockFD);

g_status.INITOK = BOOL_FALSE;

char buf2[200];

sprintf(buf2," INITOK:%d ",g_status.INITOK);

fxlog(buf2);

return BOOL_TRUE;

}

cmd_init.c

//*******************************

#include "fxmsg.h"

int initCheck(UDF_INIT *initid, UDF_ARGS *args, char *message){

if(args->arg_count !=3 || args->arg_type[1]!=INT_RESULT || args->arg_type[2]!=INT_RESULT){

strcpy(message,"ERROR. ERR Parameter! Eg: select fx_msg('INIT',10,20000);");

return BOOL_FALSE;

}

if( BOOL_TRUE == g_status.INITOK ){

strcpy(message,"ERROR. Already INIT OK.");

return BOOL_FALSE;

}

return BOOL_TRUE;

}

void *accepter(void *sockfd);

int initServer(int port , int listenQueueLength);

int doInit(UDF_INIT *initid, UDF_ARGS *args, char *message){

const long port = *((long long*) args->args[2]);

char logBuffer[200];

sprintf(logBuffer,"listenPort:%ld",port);

fxlog(logBuffer);

g_status.g_sockFD = initServer(port , 10);

if(g_status.g_sockFD == -1){

strcpy(message,"InitServer ERR!");

return BOOL_FALSE;

}

pthread_t tid;

pthread_create(&tid,NULL,(void*)&accepter,NULL);

return BOOL_TRUE;

}

void *accepter(void *sockfd){

while( 1 ){

struct sockaddr_in info;

int buf_size = sizeof(struct sockaddr_in);

int fd = accept(g_status.g_sockFD,(struct sockaddr *)&info, &buf_size);

char logbuf[100];

sprintf(logbuf,"accept return -> fd:%d,g_sockFD:%ld",fd,g_status.g_sockFD);

fxlog(logbuf);

if(fd<0){

fxlog("************* because fd<0 so accepter end!************");

return (void*)-1;

}

ClientPtr temp = (ClientPtr)malloc(sizeof(Client));

if(!temp){

fxlog("malloc result adder is 0");

close(fd);

return (void*)-1;

}

temp->sock_fd = fd;

temp->port=info.sin_port;

temp->ip=inet_ntoa(info.sin_addr);

if(g_status.g_client == NULL){

g_status.g_client = temp;

temp->next = NULL;

}else{

temp->next = g_status.g_client;

g_status.g_client = temp;

}

}

}

/**

* 初始化服务器,绑定监听端口,开始监听

* RET socket 描述符 / -1出错

*/

int initServer(int port , int listenQueueLength){

int sock_fd=0;

if((sock_fd = socket(AF_INET,SOCK_STREAM,0)) == -1){

return -1;

}

/**

* 设定监听协议、端口等

*/

struct sockaddr_in servaddr;

servaddr.sin_family = AF_INET;

servaddr.sin_port = htons(port);

servaddr.sin_addr.s_addr = htons(INADDR_ANY);

/**

* 绑定监听端口

*/

if( bind(sock_fd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == -1){

return -1;

}

/**

* 监听

*/

if( listen(sock_fd,listenQueueLength) == -1){

return -1;

}

return sock_fd;

}

cmd_send.c

//*****************************

#include "fxmsg.h"

int sendCheck(UDF_INIT *initid, UDF_ARGS *args, char *message){

if(args->arg_count !=2){

strcpy(message,"ERROR. ERR Parameter! Eg: select fx_msg('SEND','a message');");

return 1;

}

if(args->arg_type[0]!=STRING_RESULT || args->arg_type[1]!=STRING_RESULT){

strcpy(message,"ERROR. ERR Parameter! Eg: select fx_msg('SEND','a message');");

return 1;

}

return 0;

}

//fxmsg.c

//********************************

#include "mysql.h"

#include "fxmsg.h"

my_bool fx_msg_init(UDF_INIT *initid, UDF_ARGS *args, char *message){

/**

* parm is null;

*/

if(args->arg_count == 0){

strcpy(message,"ERROR. NO Parameter! Eg: select fx_msg(CMD[,p1,p2...]);");

return 1;

}

if(args->arg_type[0]!=STRING_RESULT){

strcpy(message,"ERROR. Type of CMD is String!");

return 1;

}

const char *CMD = args->args[0];

/**

* INIT CHECK

*/

if( strcmp(CMD,"INIT") == 0 ){

fxlog("INIT...");

pthread_mutex_t INIT_LOCK=PTHREAD_MUTEX_INITIALIZER;

if(pthread_mutex_lock(&INIT_LOCK)!=0){

strcpy(message,"ERROR. lock INIT_LOCK Err!");

return 1;

}

if(initCheck(initid, args, message) == BOOL_FALSE){

pthread_mutex_unlock(&INIT_LOCK);

return 1;

}

int ret = doInit(initid, args, message) ;

char buf1[100];

sprintf(buf1,"INITOK:%d",g_status.INITOK);

fxlog(buf1);

g_status.INITOK = BOOL_TRUE;

char buf2[100];

sprintf(buf2,"INITOK:%d",g_status.INITOK);

fxlog(buf2);

pthread_mutex_unlock(&INIT_LOCK);

if(ret == BOOL_TRUE){

return 0;

}else{

return 1;

}

}

else if( strcmp(CMD,"CLOSE") == 0 ){

fxlog("CLOSE...");

if(closeCheck(initid, args, message) == BOOL_FALSE ){

return 1;

}

doClose(initid, args, message);

return 0;

}

else if( strcmp(CMD,"SEND") == 0 ){

fxlog("SEND...");

return sendCheck(initid, args, message);

}

else if( strcmp(CMD,"LISTCLIENT") == 0){

fxlog("LISTCLIENT...");

}

else if( strcmp(CMD,"VERSION") == 0){

fxlog("VERSION...");

}

else{

strcpy(message,"ERROR. Unknow CMD!");

return 1;

}

initid->max_length=255;

initid->maybe_null=1;

return 0;

}

char *fx_msg(UDF_INIT *initid, UDF_ARGS *args, char *result,unsigned long *length, char *is_null, char *error){

const char *CMD = args->args[0];

if( strcmp(CMD,"INIT") == 0 ){

*length=strlen("OK");

memcpy(result,"OK",*length);

return result;

}

else if( strcmp(CMD,"CLOSE") == 0 ){

*length=strlen("OK");

memcpy(result,"OK",*length);

return result;

}

else if( strcmp(CMD,"SEND") == 0 ){

fxlog("SEND....1...");

const char *msg=args->args[1];

int msgLen = strlen(msg);

ClientPtr temp = g_status.g_client;

while(temp != NULL){

fxlog("SEND....2...");

long sendbyte = send(temp->sock_fd,msg,msgLen,0);

char senBuf[2000];

sprintf(senBuf,"send message to %ld [%ld bytes]!",temp->sock_fd,sendbyte);

if(sendbyte == -1){

strcat(senBuf," Send Message Err!");

}

fxlog(senBuf);

temp = temp->next;

}

fxlog("SEND....3...");

memcpy(result,msg,(size_t)msgLen);

*length=msgLen;

return result;

}

else if( strcmp(CMD,"LISTCLIENT") == 0){

char buf[1000];

sprintf(buf,"==========ClientList========/n");

ClientPtr temp = g_status.g_client;

while(temp != NULL){

char xbuf[100];

sprintf(xbuf,"fd:%ld ip:%s port:%ld/n",temp->sock_fd,temp->ip,temp->port);

strcat(buf,xbuf);

temp=temp->next;

}

*length = strlen(buf);

char *resbuf = (char*)malloc(*length);

initid->ptr = resbuf;

strcpy(resbuf,buf);

result = resbuf;

return result;

}

else if( strcmp(CMD,"VERSION") == 0 ){

char *ver = "FX_MSG_VER:100010";

*length=strlen(ver);

memcpy(result,ver,*length);

return result;

}

*is_null = 1;

return 0;

}

void fx_msg_deinit(UDF_INIT *initid){

if(initid->ptr != NULL){

free(initid->ptr);

}

}

//tools.c

//******************************

#include

#include

#include

void fxlog(char *c){

char *buf = (char*)malloc(strlen(c)+1);

strcpy(buf,c);

fprintf(stdout,buf);

fprintf(stdout,"/n");

fflush(stdout);

free(buf);

}

时间紧任务急,大概的功能可能实现了.

以上 代码在

root@fes-middle01 so]# gcc --version

gcc (GCC) 3.4.6

20060404 (Red Hat 3.4.6-3)

Copyright (C) 2006 Free Software Foundation,

Inc.

This is free software; see the source for copying conditions. There is NO

warranty; not even for MERCHANTABILITY or FITNESS FOR A

PARTICULAR PURPOSE.

[root@fes-middle01 mysql]# bin/mysql -uroot -pskywest

Welcome to the MySQL

monitor. Commands end with ; or /g.

Your MySQL connection id is 3 to

server version: 5.0.22-max

中编译运行通过.

编译方法:

gcc -I. -O0 -g3 -Wall -c -fmessage-length=0 -ofxmsg.o

fxmsg.c

gcc -I. -O0 -g3 -Wall -c -fmessage-length=0 -ocmd_close.o

cmd_close.c

gcc -I. -O0 -g3 -Wall -c -fmessage-length=0 -ocmd_init.o

cmd_init.c

gcc -I. -O0 -g3 -Wall -c -fmessage-length=0 -ocmd_send.o

cmd_send.c

gcc -I. -O0 -g3 -Wall -c -fmessage-length=0 -otools.o

tools.c

gcc -shared -oFXMSG.so fxmsg.o cmd_send.o cmd_init.o cmd_close.o

tools.o

将生成的so文件放到 /usr/lib中

cp FXMSG.so /usr/lib

建立 fx_msg function.

CREATE FUNCTION fx_msg RETURNS STRING SONAME ;

FXMSG.so;

删除时候用:

DROP FUNCTION fx_msg;

mysql udf介绍_Mysql UDF相关推荐

  1. mysql udf编译_MySql UDF 调用外部程序和系统命令

    1.mysql利用mysqludf的一个mysql插件可以实现调用外部程序和系统命令 2.安装说明: 2.1查询mysql插件路径: 在mysql里查询mysql插件目录的路径:show variab ...

  2. mysql mysqladmin 介绍_Mysql—mysqladmin 命令详解

    mysqladmin是一个执行管理操作的客户端程序.它可以用来检查服务器的配置和当前状态.创建和删除数据库等. mysqladmin工具的使用格式:mysqladmin [option] comman ...

  3. mysql 主从复制介绍_MySQL 主从复制介绍

    一.MySQL 主从复制简介 (1) MySQL 主从复制通过逻辑的 binlog 日志复制到要同步的服务器本地,然后由本地的线程读取日志里面的 SQL 语句,重新应用到 MySQL 数据库中 (2) ...

  4. MySQL社区介绍_mysql社区服务器

    {"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],&q ...

  5. mysql事物介绍_MySQL事务介绍

    从事务理论的角度来说,可以把事务分为以下几种类型: 扁平事务类型(Flat Transaction) 带有保存点的扁平事务(Flat Transaction with Savepoints) 链事务( ...

  6. mysql的udf功能_mySql的UDF是什么

    CRUD:添删改查 UDF是mysql的一个拓展接口,UDF(Userdefined function)可翻译为用户自定义函数,这个是用来拓展Mysql的技术手段. 1 MySQL简介 MySQL是最 ...

  7. mysql udf 源码_Windows上的MySQL UDF开发_mysql

    曾以为Windows版本的mysql存在不能使用UDF的BUG诸提交了一个bug报告.不过 似乎发现是我搞错了,MySQL的技术支持人员给了非常完美的解答,同大家分享 一下.下边是原文回复

  8. mysql 查看 udf_MySQL的UDF

    最近用到MySQL的UDF, 查了一下相关文献, 对用户用户实现function和Aggregate function的方法做个介绍. 快速编写一个MySQL UDF 为了能够快速了解UDF(user ...

  9. Mysql数据库提权——UDF提权

    实验原理:UDF可以理解为MySQL的函数库,可以利用UDF定义创建函数(其中包括了执行系统命令的函数),要想利用udf,                    必须上传udf.dll作为udf的执行 ...

最新文章

  1. 用NiceTool在微信浏览器中下载APP
  2. 基于 FPGA 的数字抢答器设计
  3. Spring Security 用户登录实战
  4. PHP Linux安装
  5. 小户型吊顶的注意事项有哪些
  6. matlab 信道模拟 差错概率,移动信道差错序列的分布概率模拟法及门限电平的讨论...
  7. python程序-怎么用手机编写Python程序?
  8. VM上安装Redhat无法选包
  9. oracle startup open ora 03113,oracle宕机,startup报错ora03113
  10. matlab矩阵转置函数
  11. 【爬虫专栏17】多线程爬双色球
  12. SegNet 论文解析
  13. [JZOJ4940]前鬼后鬼的守护/[JZOJ4623]搬运干草捆
  14. 使用Python实现批量PPT转图片,格式支持PNG、JPG,转后图片后批量重命名
  15. Android Dialog之间的层级设置(WindowManager.LayoutParams)
  16. 几款笔记软件的使用感受
  17. SVN强制编写注释才能提交,提交中不允许删除文件操作。
  18. 1131 拯救大兵瑞恩(单源最短路径扩展-拆点(dp))
  19. 「优知学院」淘宝架构的前世今生(下)
  20. jquery控制table的行显示和隐藏

热门文章

  1. 步进电机脱机状态实质
  2. vijos P1009 清帝之惑之康熙
  3. 关于ftp出现425错误
  4. java的多线程机制_Java多线程开发(一)| 基本的线程机制
  5. 格式化电脑硬盘后数据能恢复吗?
  6. 一种signal 5 (SIGTRAP), code 1 (TRAP_BRKPT)的原因
  7. 恐怖黎明修改器|恐怖黎明十四项修改器小斧头版下载 v1.4最新版
  8. 图文 | 海岸TDM平台部署架构
  9. 微信小程序首页图片本地缓存
  10. Spring boot实现Activemq死信队列