MySQL实现大整数相加的udf

前提,大整数保存为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

进入mysqlmysql -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;

计算机生成了可选文字:mysql> select from btgtnt_demo_varchar; 1 udf 265 row in set (0.00 sec)

  • select udf_sum_samp(value) from bigint_demo_char;

计算机生成了可选文字:mysql> select from btgtnt_demo_char; 1 row in set (0.00 sec)

udf代码中注释掉输出语句,可以把一些结果输出到mysql的错误日志中,默认是在/var/log/error.log

计算机生成了可选文字:the the the the the the the the the the the the the the the the the the value value value value value value value value of of of of of of of of args args args args result: 265 value of args value of list value of args value of list value of args value of list value of args value of list result: 34 34 5 1 225 225 34 _to_strtng 34eeeeeeeeeeeeeeee 5 _to_strtng seeeeeeeeeeeeeeee 1 _to_strtng leeeeeeeeeeeeeeee 225 to string 2250000000000000000

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值