MySQL实现大整数相加的udf

前提,大整数保存为varchar, char暂时还不行,还需改进

bigint.h头文件

#include

#include

#include

 

#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

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;icount;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

{

charstr_temp[N+1];

intt=0;

for(j=0;j

{

if(j

elsestr_temp[j]=str[t++];

}

for(j=0;j

len=strlen(str);

}

for(j=0;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

 

#include

#include

#include

#include

 

 

extern "C"{

 

typedef unsignedlong long ulonglong;

typedef long longlonglong;

// Use the standardmysql dev headers.

#include

#include

 

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(as);

    initid->maybe_null = 1;

    return 0;

}

 

void

udf_sum_samp_deinit(UDF_INIT*const initid)

{

    agg_state *const as =reinterpret_cast(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(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(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(initid->ptr);

    strcpy(static_cast(as->rbuf),list_to_string(as->sum));

    //std::cerr << "the result:" << static_cast(as->rbuf) << "\n";

    strcpy(result,static_cast(as->rbuf));

    *length=strlen(result);

    return static_cast(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实现大整数相加的udf_第1张图片

  • select udf_sum_samp(value) from bigint_demo_char;

MySQL实现大整数相加的udf_第2张图片

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

MySQL实现大整数相加的udf_第3张图片

你可能感兴趣的:(Linux)