mysql udf介绍_Mysql UDF
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相关推荐
- mysql udf编译_MySql UDF 调用外部程序和系统命令
1.mysql利用mysqludf的一个mysql插件可以实现调用外部程序和系统命令 2.安装说明: 2.1查询mysql插件路径: 在mysql里查询mysql插件目录的路径:show variab ...
- mysql mysqladmin 介绍_Mysql—mysqladmin 命令详解
mysqladmin是一个执行管理操作的客户端程序.它可以用来检查服务器的配置和当前状态.创建和删除数据库等. mysqladmin工具的使用格式:mysqladmin [option] comman ...
- mysql 主从复制介绍_MySQL 主从复制介绍
一.MySQL 主从复制简介 (1) MySQL 主从复制通过逻辑的 binlog 日志复制到要同步的服务器本地,然后由本地的线程读取日志里面的 SQL 语句,重新应用到 MySQL 数据库中 (2) ...
- MySQL社区介绍_mysql社区服务器
{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],&q ...
- mysql事物介绍_MySQL事务介绍
从事务理论的角度来说,可以把事务分为以下几种类型: 扁平事务类型(Flat Transaction) 带有保存点的扁平事务(Flat Transaction with Savepoints) 链事务( ...
- mysql的udf功能_mySql的UDF是什么
CRUD:添删改查 UDF是mysql的一个拓展接口,UDF(Userdefined function)可翻译为用户自定义函数,这个是用来拓展Mysql的技术手段. 1 MySQL简介 MySQL是最 ...
- mysql udf 源码_Windows上的MySQL UDF开发_mysql
曾以为Windows版本的mysql存在不能使用UDF的BUG诸提交了一个bug报告.不过 似乎发现是我搞错了,MySQL的技术支持人员给了非常完美的解答,同大家分享 一下.下边是原文回复
- mysql 查看 udf_MySQL的UDF
最近用到MySQL的UDF, 查了一下相关文献, 对用户用户实现function和Aggregate function的方法做个介绍. 快速编写一个MySQL UDF 为了能够快速了解UDF(user ...
- Mysql数据库提权——UDF提权
实验原理:UDF可以理解为MySQL的函数库,可以利用UDF定义创建函数(其中包括了执行系统命令的函数),要想利用udf, 必须上传udf.dll作为udf的执行 ...
最新文章
- 用NiceTool在微信浏览器中下载APP
- 基于 FPGA 的数字抢答器设计
- Spring Security 用户登录实战
- PHP Linux安装
- 小户型吊顶的注意事项有哪些
- matlab 信道模拟 差错概率,移动信道差错序列的分布概率模拟法及门限电平的讨论...
- python程序-怎么用手机编写Python程序?
- VM上安装Redhat无法选包
- oracle startup open ora 03113,oracle宕机,startup报错ora03113
- matlab矩阵转置函数
- 【爬虫专栏17】多线程爬双色球
- SegNet 论文解析
- [JZOJ4940]前鬼后鬼的守护/[JZOJ4623]搬运干草捆
- 使用Python实现批量PPT转图片,格式支持PNG、JPG,转后图片后批量重命名
- Android Dialog之间的层级设置(WindowManager.LayoutParams)
- 几款笔记软件的使用感受
- SVN强制编写注释才能提交,提交中不允许删除文件操作。
- 1131 拯救大兵瑞恩(单源最短路径扩展-拆点(dp))
- 「优知学院」淘宝架构的前世今生(下)
- jquery控制table的行显示和隐藏