前提,大整数保存为varchar, char暂时还不行,还需改进
bigint.h头文件
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define N 4
#ifdef __cplusplus
extern "C"{
#endif
typedef structbigint_node
{
intvalue; // four bitsbetween 0000 and 9999
structbigint_node *preview;
structbigint_node *next;
}*BigInt_Node;
typedef structbigint_list
{
BigInt_Nodefirst;
intcount; // the length ofBigInt_Node
//intflag; // the sign flag, 0represent plus, 1 represent minus.--Have not considered it at present.
}*BigInt_List;
BigInt_Listbigint_init();
BigInt_Listbigint_mov(BigInt_List b);
BigInt_Listbigint_mov_value(int value);
BigInt_Liststring_to_list(char *s);
char*list_to_string(BigInt_List list);
BigInt_Listbigint_add(BigInt_List a, BigInt_List b);
#ifdef __cplusplus
}
#endif
bigint.c源代码
#include"bigint.h"
/*
bigintinitialization
*/
BigInt_Listbigint_init()
{
BigInt_Listlist=(BigInt_List)(malloc(sizeof(struct bigint_list)));
list->first= NULL;
list->count= 0;
//list->flag= 0;
returnlist;
}
/*
a=b;
*/
BigInt_Listbigint_mov(BigInt_List b)
{
BigInt_Lista=bigint_init();
BigInt_Nodenode = b->first;
inti;
for(i = 0; i < b->count; i++)
{
BigInt_Nodetemp = (BigInt_Node)malloc(sizeof(struct bigint_node));
temp->value= node->value;
if(a->first == NULL)
{
a->first= temp;
temp->preview= temp;
temp->next= temp;
}
else
{
BigInt_Nodelast = a->first->preview;
last->next= temp;
temp->preview= last;
temp->next= a->first;
a->first->preview= temp;
}
node= node->next;
}
a->count=b->count;
returna;
}
/*
mova value to list
*/
BigInt_Listbigint_mov_value(int value)
{
BigInt_Listlist=bigint_init();
BigInt_Nodenode = (BigInt_Node)malloc(sizeof(struct bigint_node));
node->value= value;
node->preview= node;
node->next= node;
list->count= 1;
list->first= node;
returnlist;
}
/*
* input: char *s
* output: BigInt_List
*/
BigInt_Liststring_to_list(char *s)
{
BigInt_Listlist=bigint_init();
inti,k=N-1,len=strlen(s);
charstr[N+1];
for(i=len-1;i>=-1;i--)
{
if(k==-1)
{
BigInt_Nodenode=(BigInt_Node)malloc(sizeof(struct bigint_node));
node->value=atoi(str);
if(list->first==NULL)
{
list->first=node;
node->preview=node;
node->next=node;
}
else
{
list->first->preview->next=node;
node->preview=list->first->preview;
node->next=list->first;
list->first->preview=node;
list->first=node;
}
list->count++;
if(i==-1)break; // end
k=N-1;
}
if(i<k){k=i; str[k+1]='\0';}
str[k--]=s[i];
}
returnlist;
}
/*
input:BigInt_List
output:char *
*/
char*list_to_string(BigInt_List list)
{
char*s=(char *)malloc(256);
inti,j,k=0;
BigInt_Nodenode=list->first;
for(i=0;i<list->count;i++)
{
charstr[N+1];
sprintf(str,"%d",node->value);
intlen=strlen(str);
//if the length is less N(=4) bits, then supplement enough by '0', and do notconsider the first one for it's MSB.
if(i!=0&& len<N)
{
charstr_temp[N+1];
intt=0;
for(j=0;j<N;j++)
{
if(j<N-len) str_temp[j]='0';
elsestr_temp[j]=str[t++];
}
for(j=0;j<N;j++)str[j]=str_temp[j];
len=strlen(str);
}
for(j=0;j<len;j++)
{
s[k++]=str[j];
}
node=node->next;
}
s[k]='\0';
returns;
}
/*
* c=a+b
*/
BigInt_Listbigint_add(BigInt_List a, BigInt_List b)
{
inti, carry = 0;
BigInt_Listc=bigint_mov(a);
//from end to begin
BigInt_Nodenode_a = c->first->preview;
BigInt_Nodenode_b = b->first->preview;
for(i = 0; i < c->count && i < b->count; i++)
{
intvalue=node_a->value + node_b->value + carry;
if(value<10000)carry=0;
else
{
value-=10000;
carry=1;
}
node_a->value=value;
node_a= node_a->preview;
node_b= node_b->preview;
}
//if c(also a) has more
while(i < c->count && carry>0)
{
intvalue = node_a->value + carry;
if(value < 10000) carry = 0;
else
{
value-=10000;
carry= 1;
}
node_a->value=value;
node_a= node_a->preview;
i++;
}
//if b has more
while(i < b->count)
{
intvalue = node_b->value + carry;
if(value < 10000) carry = 0;
else
{
value-= 10000;
carry= 1;
}
BigInt_Nodenode=(BigInt_Node)malloc(sizeof(struct bigint_node));
node->value=value;
c->first->preview->next=node;
node->preview=c->first->preview;
node->next=c->first;
c->first->preview=node;
c->first=node;
c->count++;
node_b= node_b->preview;
i++;
}
if(carry == 1)
{
BigInt_Nodenode = (BigInt_Node)malloc(sizeof(struct bigint_node));
node->value= carry;
c->first->preview->next= node;
node->preview= c->first->preview;
node->next= c->first;
c->first->preview= node;
c->first= node;
c->count++;
}
if(c->count > 1)
{
while(c->first->value == 0)
{
c->first->preview->next= c->first->next;
c->first->next->preview= c->first->preview;
c->first= c->first->next;
c->count--;
if(c->count == 1)
{
break;
}
}
}
returnc;
}
编译成动态库g++ -shared -fPIC -o libbigint.so bigint.c
将生成的.so文件放入/usr/lib目录下
udf文件udf_sum_samp.cc
#define DEBUG 1
#include<memory>
#include<string.h>
#include<stdint.h>
#include<iostream>
#include<bigint.h>
extern "C"{
typedef unsignedlong long ulonglong;
typedef long longlonglong;
// Use the standardmysql dev headers.
#include<mysql.h>
#include<ctype.h>
my_bool udf_sum_samp_init(UDF_INIT *const initid,UDF_ARGS *const args,
char *constmessage);
void udf_sum_samp_deinit(UDF_INIT *constinitid);
void udf_sum_samp_clear(UDF_INIT *constinitid, char *const is_null,
char *const error);
my_bool udf_sum_samp_add(UDF_INIT *const initid,UDF_ARGS *const args,
char *const is_null,char *const error);
char * udf_sum_samp(UDF_INIT *const initid,UDF_ARGS *const args,
char *const result,unsigned long *const length,
char *const is_null, char*const error);
} /* extern"C" */
struct agg_state {
BigInt_List sum;
void *rbuf;
};
my_bool
udf_sum_samp_init(UDF_INIT*const initid, UDF_ARGS *const args,
char *const message)
{
if (args->arg_count != 1 ||
args->arg_type[0] != STRING_RESULT)
{
strcpy(message, "Usage:udf_sum_samp(string value)");
return 1;
}
agg_state *const as = new agg_state();
as->rbuf = malloc(256);
initid->ptr = reinterpret_cast<char*>(as);
initid->maybe_null = 1;
return 0;
}
void
udf_sum_samp_deinit(UDF_INIT*const initid)
{
agg_state *const as =reinterpret_cast<agg_state *>(initid->ptr);
free(as->rbuf);
delete as;
}
void
udf_sum_samp_clear(UDF_INIT*const initid, char *const is_null, char *const error)
{
agg_state *const as =reinterpret_cast<agg_state *>(initid->ptr);
as->sum = bigint_mov_value(0);
}
my_bool
udf_sum_samp_add(UDF_INIT*const initid, UDF_ARGS *const args,
char *const is_null, char*const error)
{
agg_state *const as =reinterpret_cast<agg_state *>(initid->ptr);
//
BigInt_List e;
if (NULL == args->args[0]) {
e = bigint_mov_value(0);
} else {
e = string_to_list(args->args[0]);
}
//std::cerr << "the value ofargs " << args->args[0] << "\n";
//std::cerr << "the value oflist_to_string " << list_to_string(e) << "\n";
as->sum=bigint_add(as->sum,e);
//std::cerr << "sum so far" << as->sum << "\n";
memset(args->args[0],0,strlen(args->args[0]));
return true;
}
char *
udf_sum_samp(UDF_INIT*const initid, UDF_ARGS *const args, char *const result,
unsigned long *const length, char*const is_null, char *const error)
{
agg_state *const as =reinterpret_cast<agg_state *>(initid->ptr);
strcpy(static_cast<char*>(as->rbuf),list_to_string(as->sum));
//std::cerr << "the result:" << static_cast<char *>(as->rbuf) << "\n";
strcpy(result,static_cast<char*>(as->rbuf));
*length=strlen(result);
return static_cast<char*>(as->rbuf);
}
将udf文件编译成动态库 g++ -shared -fPIC -I /usr/include/mysql/ udf_sum_samp.cc-o udf_sum_samp.so -lbigint
将生成的.so放入mysql/plugin下,sudo cp udf_sum_samp.so/usr/lib/mysql/plugin
进入mysql,mysql -u root -p
- 创建数据库 create database test;
- 使用该数据库 use test;
- 创建表 ---flag暂时还没用上
- create table bigint_demo_char(id int primary key auto_increment, value char(20), flag int);
- create table bigint_demo_varchar(id int primary key auto_increment, value varchar(20), flag int);
- 插入测试数据
- insert into bigint_demo_char(value,flag) values('34',0)
- insert into bigint_demo_char(value,flag) values('5',0)
- insert into bigint_demo_char(value,flag) values('1',0)
- insert into bigint_demo_char(value,flag) values('225',0)
- insert into bigint_demo_varchar(value,flag) values('34',0)
- insert into bigint_demo_varchar(value,flag) values('5',0)
- insert into bigint_demo_varchar(value,flag) values('1',0)
- insert into bigint_demo_varchar(value,flag) values('225',0)
- 创建udf
- create aggregate function soname udf_sum_samp returns string soname 'udf_sum_samp.so';
- 使用该udf
- select udf_sum_samp(value) from bigint_demo_varchar;
- select udf_sum_samp(value) from bigint_demo_char;
udf代码中注释掉输出语句,可以把一些结果输出到mysql的错误日志中,默认是在/var/log/error.log