当前位置: 首页 > news >正文

利用DeepSeek编写Duckdb的C插件实现大数运算

在C插件模板的基础上, 将一个调用openssl中的大数运算函数示例发给他,第一次给出的代码编译通过,但是执行出错,问题出在DuckDB对字符串做了特殊处理,短的内联,长的存地址,他不了解,将文档中的正确例子给他,就输出了如下代码:

#include "duckdb_extension.h"
#include <string.h>
#include <stdlib.h>
// 声明BN函数(来自OpenSSL)
//extern "C" {typedef struct bignum_st BIGNUM;typedef struct bn_ctx_st BN_CTX;BIGNUM* BN_new();void BN_free(BIGNUM*);int BN_dec2bn(BIGNUM**, const char*);char* BN_bn2dec(const BIGNUM*);int BN_add(BIGNUM*, const BIGNUM*, const BIGNUM*);int BN_mul(BIGNUM*, const BIGNUM*, const BIGNUM*, BN_CTX*);BN_CTX* BN_CTX_new();void BN_CTX_free(BN_CTX*);void free(void*);
//}DUCKDB_EXTENSION_EXTERN// 从duckdb_string_t提取C字符串
static char* extract_string(duckdb_string_t str) {char* result = NULL;if (duckdb_string_is_inlined(str)) {result = duckdb_malloc(str.value.inlined.length + 1);memcpy(result, str.value.inlined.inlined, str.value.inlined.length);result[str.value.inlined.length] = '\0';} else {result = duckdb_malloc(str.value.pointer.length + 1);memcpy(result, str.value.pointer.ptr, str.value.pointer.length);result[str.value.pointer.length] = '\0';}return result;
}// 设置duckdb_string_t为C字符串
static void set_string(duckdb_string_t* str, const char* cstr) {size_t len = strlen(cstr);if (len <= 12) { // 内联字符串最大长度str->value.inlined.length = len;memcpy(str->value.inlined.inlined, cstr, len);str->value.inlined.inlined[len] = '\0';} else {char* ptr = duckdb_malloc(len + 1);memcpy(ptr, cstr, len);ptr[len] = '\0';str->value.pointer.ptr = ptr;str->value.pointer.length = len;}
}// 标量函数:大数加法
static void BNAddFunction(duckdb_function_info info, duckdb_data_chunk input, duckdb_vector output) {idx_t input_size = duckdb_data_chunk_get_size(input);duckdb_vector a_vec = duckdb_data_chunk_get_vector(input, 0);duckdb_vector b_vec = duckdb_data_chunk_get_vector(input, 1);// 获取字符串向量数据duckdb_string_t* a_data = (duckdb_string_t*)duckdb_vector_get_data(a_vec);duckdb_string_t* b_data = (duckdb_string_t*)duckdb_vector_get_data(b_vec);duckdb_string_t* result_data = (duckdb_string_t*)duckdb_vector_get_data(output);// 获取有效性位图uint64_t* a_validity = duckdb_vector_get_validity(a_vec);uint64_t* b_validity = duckdb_vector_get_validity(b_vec);BN_CTX* ctx = BN_CTX_new();if (!ctx) return;for (idx_t row = 0; row < input_size; row++) {if ((a_validity && !duckdb_validity_row_is_valid(a_validity, row)) ||(b_validity && !duckdb_validity_row_is_valid(b_validity, row))) {// 如果有NULL值,结果设为NULLduckdb_vector_ensure_validity_writable(output);uint64_t* result_validity = duckdb_vector_get_validity(output);duckdb_validity_set_row_invalid(result_validity, row);continue;}BIGNUM* a = BN_new();BIGNUM* b = BN_new();BIGNUM* result = BN_new();char* a_str = NULL;char* b_str = NULL;char* res_str = NULL;if (!a || !b || !result) {if (a) BN_free(a);if (b) BN_free(b);if (result) BN_free(result);continue;}// 提取输入字符串a_str = extract_string(a_data[row]);b_str = extract_string(b_data[row]);// 将字符串转换为大数if (!BN_dec2bn(&a, a_str) || !BN_dec2bn(&b, b_str)) {duckdb_free(a_str);duckdb_free(b_str);BN_free(a);BN_free(b);BN_free(result);continue;}// 执行加法if (!BN_add(result, a, b)) {duckdb_free(a_str);duckdb_free(b_str);BN_free(a);BN_free(b);BN_free(result);continue;}// 将结果转换为字符串res_str = BN_bn2dec(result);set_string(&result_data[row], res_str);free(res_str);duckdb_free(a_str);duckdb_free(b_str);BN_free(a);BN_free(b);BN_free(result);}BN_CTX_free(ctx);
}// 标量函数:大数乘法
static void BNMultiplyFunction(duckdb_function_info info, duckdb_data_chunk input, duckdb_vector output) {idx_t input_size = duckdb_data_chunk_get_size(input);duckdb_vector a_vec = duckdb_data_chunk_get_vector(input, 0);duckdb_vector b_vec = duckdb_data_chunk_get_vector(input, 1);duckdb_string_t* a_data = (duckdb_string_t*)duckdb_vector_get_data(a_vec);duckdb_string_t* b_data = (duckdb_string_t*)duckdb_vector_get_data(b_vec);duckdb_string_t* result_data = (duckdb_string_t*)duckdb_vector_get_data(output);uint64_t* a_validity = duckdb_vector_get_validity(a_vec);uint64_t* b_validity = duckdb_vector_get_validity(b_vec);BN_CTX* ctx = BN_CTX_new();if (!ctx) return;for (idx_t row = 0; row < input_size; row++) {if ((a_validity && !duckdb_validity_row_is_valid(a_validity, row)) ||(b_validity && !duckdb_validity_row_is_valid(b_validity, row))) {duckdb_vector_ensure_validity_writable(output);uint64_t* result_validity = duckdb_vector_get_validity(output);duckdb_validity_set_row_invalid(result_validity, row);continue;}BIGNUM* a = BN_new();BIGNUM* b = BN_new();BIGNUM* result = BN_new();char* a_str = NULL;char* b_str = NULL;char* res_str = NULL;if (!a || !b || !result) {if (a) BN_free(a);if (b) BN_free(b);if (result) BN_free(result);continue;}a_str = extract_string(a_data[row]);b_str = extract_string(b_data[row]);if (!BN_dec2bn(&a, a_str) || !BN_dec2bn(&b, b_str)) {duckdb_free(a_str);duckdb_free(b_str);BN_free(a);BN_free(b);BN_free(result);continue;}// 执行乘法if (!BN_mul(result, a, b, ctx)) {duckdb_free(a_str);duckdb_free(b_str);BN_free(a);BN_free(b);BN_free(result);continue;}res_str = BN_bn2dec(result);set_string(&result_data[row], res_str);free(res_str);duckdb_free(a_str);duckdb_free(b_str);BN_free(a);BN_free(b);BN_free(result);}BN_CTX_free(ctx);
}// 注册函数
void RegisterBNFunctions(duckdb_connection connection) {// 注册大数加法函数duckdb_scalar_function add_func = duckdb_create_scalar_function();duckdb_scalar_function_set_name(add_func, "bn_add");duckdb_logical_type varchar_type = duckdb_create_logical_type(DUCKDB_TYPE_VARCHAR);duckdb_scalar_function_add_parameter(add_func, varchar_type);duckdb_scalar_function_add_parameter(add_func, varchar_type);duckdb_scalar_function_set_return_type(add_func, varchar_type);duckdb_scalar_function_set_function(add_func, BNAddFunction);duckdb_register_scalar_function(connection, add_func);duckdb_destroy_scalar_function(&add_func);// 注册大数乘法函数duckdb_scalar_function mul_func = duckdb_create_scalar_function();duckdb_scalar_function_set_name(mul_func, "bn_multiply");duckdb_scalar_function_add_parameter(mul_func, varchar_type);duckdb_scalar_function_add_parameter(mul_func, varchar_type);duckdb_scalar_function_set_return_type(mul_func, varchar_type);duckdb_scalar_function_set_function(mul_func, BNMultiplyFunction);duckdb_register_scalar_function(connection, mul_func);duckdb_destroy_scalar_function(&mul_func);duckdb_destroy_logical_type(&varchar_type);
}

将RegisterBNFunctions函数的声明加入add_numbers.h

void RegisterBNFunctions(duckdb_connection connection);

再在capi_quack.c中增加对它的调用

    RegisterBNFunctions(connection);

重新编译和加工就可以加载使用了。可见,它像模板一样正确处理了NULL。注意,编译动态库时需要加-lssl -lcrypto选项动态链接openssl库。还要注意load命令后跟绝对路径的插件文件名。

root@6ae32a5ffcde:/par/extension-template-c-main/src# gcc -fPIC -shared -o libtest2.so *.c -I include -I ../duckdb_capi -lssl -lcrypto
root@6ae32a5ffcde:/par/extension-template-c-main/src# python3 ../../appendmetadata.py -l libtest2.so -n add -dv v1.2.0  --duckdb-platform linux_amd64 --extension-version 0.1
Creating extension binary:- Input file: libtest2.so- Output file: add.duckdb_extension- Metadata:- FIELD8 (unused)            = EMPTY- FIELD7 (unused)            = EMPTY- FIELD6 (unused)            = EMPTY- FIELD5 (abi_type)          = C_STRUCT- FIELD4 (extension_version) = 0.1- FIELD3 (duckdb_version)    = v1.2.0- FIELD2 (duckdb_platform)   = linux_amd64- FIELD1 (header signature)  = 4 (special value to identify a duckdb extension)
root@6ae32a5ffcde:/par/extension-template-c-main/src# /par/duckdb140 -unsigned
DuckDB v1.4.0 (Andium) b8a06e4a22
Enter ".help" for usage hints.
D load '/par/extension-template-c-main/src/add.duckdb_extension';
D select bn_add('123456780','123999999');
┌──────────────────────────────────┐
│ bn_add('123456780', '123999999') │
│             varchar              │
├──────────────────────────────────┤
│ 247456779                        │
└──────────────────────────────────┘
D select bn_add('123456780123456780','123999999'),bn_multiply('12345678901234567890','123999999');
┌───────────────────────────────────────────┬──────────────────────────────────────────────────┐
│ bn_add('123456780123456780', '123999999') │ bn_multiply('12345678901234567890', '123999999') │
│                  varchar                  │                     varchar                      │
├───────────────────────────────────────────┼──────────────────────────────────────────────────┤
│ 1234567802474567791530864171407407517125432110                     │
└───────────────────────────────────────────┴──────────────────────────────────────────────────┘
D with t as(select '12345678' a,NULL::varchar b union all select '123456780123456780','123999999' union all select NULL,'123999999')select a,b,bn_multiply(a,b) from t;
┌────────────────────┬───────────┬────────────────────────────┐
│         a          │     b     │     bn_multiply(a, b)      │
│      varchar       │  varchar  │          varchar           │
├────────────────────┼───────────┼────────────────────────────┤
│ 12345678           │ NULL      │ NULL                       │
│ 12345678012345678012399999915308640611851860596543220 │
│ NULL               │ 123999999 │ NULL                       │
└────────────────────┴───────────┴────────────────────────────┘
http://www.dtcms.com/a/396876.html

相关文章:

  • 微信上浏览自己做的网站吗自己做电商网站
  • 佛山网站设计模板sem竞价托管公司
  • 网站蜘蛛屏蔽怎样恢复吐鲁番市网站建设
  • 成都设计电商网站wordpress的slider
  • 如何做网站写手wordpress上传主题错误
  • 网站排名优化查询阳江招聘网最新招聘找工作
  • 网站站外优化深圳 网页制作
  • 如何设计网站的主菜单企业做网站的痛点有哪些
  • 域名不变 网站改版vs做网站开发吗
  • 莱钢建设网站优秀排版设计网站
  • 展示型网站和官网wordpress置顶文章 图标
  • 怎么做网站跳转嘉兴有能做网站优化
  • 鄂尔多斯网站网站建设新的seo网站优化排名 网站
  • 通辽网站网站建设济南百度推广公司电话
  • 泰安网站制作排行网站如何做二级栏目
  • 南浔区住房城乡建设局网站网页制作报价单
  • 佛山新网站制作渠道网页源代码搜索关键字
  • 易班班级网站建设展示PPT做网站开发需要的笔记本配置
  • 网络引流推广怎么做南阳网站推广优化公司
  • 浙江城乡建设网站证件查询空间网站
  • 邳州网站开发北京优化互联网公司
  • 网站推广员是什么商城网站开发文档
  • 佛山外贸网站建设平台网站空间支持下载但不能下载文件
  • 中国住房和城乡建设部网站6广西营销型网站公司
  • 网站建设 书wordpress 缓存 自适应
  • 专门做微信公众号的网站wordpress模板增加文章
  • 建设银行网站登录不上去中国铁建最新消息
  • wordpress怎么搬站品牌名称
  • 引用网站资料怎么注明销售课程培训视频教程
  • 企维多类似网站山东省建设官方网站