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

利用DeepSeek辅助修改luadbi-duckdb读取DuckDB decimal数据类型

DuckDB的decimal数据类型在duckdb.h的定义如下,

//! DECIMAL is composed of a width and a scale.
//! Their value is stored in a HUGEINT.
typedef struct {uint8_t width;uint8_t scale;duckdb_hugeint value;
} duckdb_decimal;

但实际上value的类型是变化的,通常的方法无法正确读取,参考https://github.com/duckdb/duckdb/issues/10986 回帖的方法

var logicalType = duckdb_vector_get_column_type(vector);
byte scale = duckdb_decimal_scale(logicalType);
var type = duckdb_decimal_internal_type(logicalType);
var data = duckdb_vector_get_data(vector);
//cast data to either short, int, long or hugeint depending on the type variable above and divide it by 10 to the power of scale
If it helps you can find C# version here: https://github.com/Giorgi/DuckDB.NET/blob/8520bf5005d9309f762ef61d71412d60d24ca32c/DuckDB.NET.Data/Internal/Reader/DecimalVectorDataReader.cs#L43

让DeepSeek编写函数,根据输入的数据类型输出decimal(width,scale,data,type)的c字符串,当type==1,data是指向int8_t的指针,type==2,指向int16_t, type==3,指向int32_t,type==4,指向int64_t,输出结果是 *data / (10^scale),同时小数点后保留scale位的c字符串
他给出的代码如下:

// 将decimal数据转换为字符串
void decimal_to_string_format(uint8_t width, uint8_t scale, void* data, int type, char* buffer, size_t buffer_size) {if (data == NULL || buffer == NULL || buffer_size == 0) {return;}// 根据类型获取整数值int64_t int_value = 0;switch (type) {case DUCKDB_TYPE_TINYINT: // int8_tint_value = *(int8_t*)data;break;case DUCKDB_TYPE_SMALLINT: // int16_tint_value = *(int16_t*)data;break;case DUCKDB_TYPE_INTEGER: // int32_tint_value = *(int32_t*)data;break;case DUCKDB_TYPE_BIGINT: // int64_tint_value = *(int64_t*)data;break;case DUCKDB_TYPE_HUGEINT: // int128_t{duckdb_hugeint huge_val = *(duckdb_hugeint*)data;// 简化处理:如果upper为0,只使用lower部分if (huge_val.upper == 0) {// 直接使用lower部分uint64_t value = huge_val.lower;int is_negative = (huge_val.upper < 0); // 检查符号if (scale == 0) {snprintf(buffer, buffer_size, "%s%lu", is_negative ? "-" : "", value);} else {uint64_t divisor = 1;for (int i = 0; i < scale; i++) {divisor *= 10;}uint64_t integer_part = value / divisor;uint64_t fractional_part = value % divisor;char format[32];snprintf(format, sizeof(format), "%%s%%lu.%%0%dlu", scale);snprintf(buffer, buffer_size, format, is_negative ? "-" : "", integer_part, fractional_part);}} else {// 对于非常大的HUGEINT值,使用简化表示if (scale == 0) {snprintf(buffer, buffer_size, "%s%ld%09lu", huge_val.upper < 0 ? "-" : "", huge_val.upper < 0 ? -huge_val.upper : huge_val.upper,huge_val.lower);} else {// 对于有小数位的大数,输出简化信息snprintf(buffer, buffer_size, "hugeint[upper=%ld,lower=%lu,scale=%d]", huge_val.upper, huge_val.lower, scale);}}return;}break;default:// 无效类型snprintf(buffer, buffer_size, "decimal(%d,%d,invalid_type,%d)", width, scale, type);return;}// 处理负号int is_negative = (int_value < 0);uint64_t abs_value = is_negative ? (uint64_t)(-int_value) : (uint64_t)int_value;if (scale == 0) {// 整数情况,直接输出snprintf(buffer, buffer_size, "%s%lu", is_negative ? "-" : "", abs_value);} else {// 计算10^scaleuint64_t divisor = 1;for (int i = 0; i < scale; i++) {divisor *= 10;}// 分离整数部分和小数部分uint64_t integer_part = abs_value / divisor;uint64_t fractional_part = abs_value % divisor;// 构建格式字符串,确保小数部分有正确的位数(前导零)char format[32];snprintf(format, sizeof(format), "%%s%%lu.%%0%dlu", scale);// 格式化输出snprintf(buffer, buffer_size, format, is_negative ? "-" : "", integer_part, fractional_part);}
}

再自行在函数statement_fetch_impl中添加:

				case DUCKDB_TYPE_DECIMAL:{duckdb_logical_type logicalType = duckdb_vector_get_column_type(col1);
uint8_t width = duckdb_decimal_width(logicalType);
uint8_t scale = duckdb_decimal_scale(logicalType);
duckdb_type type = duckdb_decimal_internal_type(logicalType);
void* data = duckdb_vector_get_data(col1);
char decimal_str[100];
decimal_to_string_format(width, scale, data, type, decimal_str, sizeof(decimal_str) );
duckdb_string_t str= convert_to_duckdb_string(decimal_str);if (named_columns) {LDB_PUSH_ATTRIB_STRING( str );} else {LDB_PUSH_ARRAY_STRING(i + 1, str);}}break;	

编译和运行

oot@6ae32a5ffcde:/par/luadbi-0.7.5# luarocks make luadbi-duckdb-scm-0.rockspec --pack-binary-rock DUCKDB_DIR=/par/141 DUCKDB_INCDIR=/par/141Packed: /par/luadbi-0.7.5/luadbi-duckdb-scm-0.linux-x86_64.rockroot@6ae32a5ffcde:/par/luadbi-0.7.5# luarocks install luadbi-duckdb-scm-0.linux-x86_64.rock --forceluadbi-duckdb scm-0 is now installed in /usr/local (license: MIT/X11)root@6ae32a5ffcde:/par/luadbi-0.7.5# lua /par/duckdtpath.lua
[123456789012345.79000]15
2025-09-25 12:26:55.123456
123456789012345.79000
2025-09-23root@6ae32a5ffcde:/par/luadbi-0.7.5# lua /par/duckdtpath.lua
[hugeint[upper=6,lower=12776324570088369304,scale=5]]15
2025-09-25 12:26:55.123456
hugeint[upper=6,lower=12776324570088369304,scale=5]
2025-09-23root@6ae32a5ffcde:/par/luadbi-0.7.5# lua /par/duckdtpath.lua
[hugeint[upper=-1,lower=6101065172474972616,scale=5]]15
2025-09-25 12:26:55.123456
hugeint[upper=-1,lower=6101065172474972616,scale=5]
2025-09-23

对于hugeint高位不为0的情况,简化了处理。
测试脚本如下

DBI = require "DBI"dbd, err = DBI.Connect( 'DuckDB', 'lua_duckdb', 'dbuser', 'password' )
assert(dbd, err)dbd:autocommit(true)
statement = dbd:prepare( "create or replace table table_1 as select 15 id, timestamp'2025-09-25 12:26:55.123456' column1,-123456789012345.79::decimal(38, 5) column2,date'2025-09-23' column3 ;" )
statement:execute()statement = assert(dbd:prepare( "select * from table_1 where id = $1;" ))
statement:execute( 15 )for row in statement:rows(true) doprint(row['id'])print(row['column1'])print(row['column2'])print(row['column3'])end
http://www.dtcms.com/a/561053.html

相关文章:

  • 深圳网站设计网站制作深圳网站建设推进
  • 电力电子技术 第十三章——PWM逆变器
  • 网站建设方案应该怎么写wordpress用户评论图片
  • xtuoj 2021
  • 数据科学每日总结--Day8--数据挖掘
  • 达梦DEM监控工具部署
  • 机器学习实践项目(二)- 房价预测 - 认识数据
  • 李宁运动服网站建设规划书网站内链少改怎么做
  • 安装JDK安装GIT安装IDEA
  • 定制报表系统设计与实现
  • 最具价值的网站建设商业策划公司十大公司
  • 网站开发设计公东莞智通人才招聘网官网
  • 【BFS 解决FloodFill 算法】3. 岛屿的最⼤⾯积(medium)
  • 【JUnit实战3_23】 第十四章:JUnit 5 扩展模型(Extension API)实战(上)
  • python_study--week3
  • 【Excalidraw】简洁好看的超轻量级画图白板
  • 手写Autosar架构的CAN通讯协议栈2(CanIf模块详解-上)
  • 【Agentic RL 专题】三、深入浅出强化学习算法 TRPO 和PPO
  • 中国最好的建站公司毕业设计模板
  • 《算法通关指南:数据结构和算法篇 --- 栈相关算法题》--- 1. 【模板】栈,2.有效的括号
  • 高效管理搜索历史:Vue持久化实践
  • html网站架设目录和文章wordpress
  • Rust 编程语言基础知识全面介绍
  • 洛龙区网站制作建设费用做网站一般用什么语言
  • 计算机网络---基础诊断ping
  • 13.2.2.Nginx
  • java后端学习经验分享(大三进大厂版)
  • 好用的镜像源
  • 做网站的经验有什么好的加盟店项目
  • linux-shell-基础与变量和运算符-1