利用DeepSeek采用hugeint转字符串函数完善luadbi-duckdb的decimal处理

用如下函数替换原有同名函数,弥补了原函数不能处理非常大的HUGEINT值的缺陷。让DeepSeek利用已有hugeint转换的字符串,结合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_t
            int_value = *(int8_t*)data;
            break;
        case DUCKDB_TYPE_SMALLINT: // int16_t
            int_value = *(int16_t*)data;
            break;
        case DUCKDB_TYPE_INTEGER: // int32_t
            int_value = *(int32_t*)data;
            break;
        case DUCKDB_TYPE_BIGINT: // int64_t
            int_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) {
            int_value = *(int64_t*)data;
            break;

            
        } else {
            // 对于非常大的HUGEINT值,用hugeint返回的字符串
            int128_t u128a = ((int128_t)UINT64_MAX + 1) * huge_val.upper + huge_val.lower;
            char a[100];
            int128_to_string_safe(u128a, a, sizeof(a));

            if (scale == 0) {

                snprintf(buffer, buffer_size, "%s", a);
            } else {
                    size_t len = strlen(a);
    
                if (scale >= len) {
                    // 小数位数大于等于数字总长度,需要在前面补0
                    // 例如: "123" scale=5 -> "0.00123"
                    snprintf(buffer, buffer_size, "0.%0*s%s", 
                            scale - len, "0", 
                            a);
                } else {
                    // 正常情况,在合适位置插入小数点
                    // 例如: "12345" scale=2 -> "123.45"
                    size_t decimal_pos = len - scale;
        
                    // 复制整数部分
                    strncpy(buffer, a, decimal_pos);
                    // 添加小数点
                    buffer[decimal_pos] = '.';
                    // 复制小数部分
                    strncpy(buffer + decimal_pos + 1, a + decimal_pos, scale);
                    // 添加结束符
                    buffer[len + 1] = '\0';
                }
            }
            }
    }
            return;
        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^scale
        uint64_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);
    }
}

这样改造以后,就可以处理各种大小的decimal数据了,与duckdb的输出一致。

复制代码
root@66d4e20ec1d7:/par/luadbi# lua ../duck.lua
-15
2025-09-25 12:26:55.123456
-1234567890123456789012345
-12345678900020250922.12345
root@66d4e20ec1d7:/par/luadbi# ../duckdb141 lua_duckdb -c "from table_1"
┌───────┬────────────────────────────┬────────────────────────────┬─────────────────────────────┐
│  id   │          column1           │          column2           │           column3           │
│ int32 │         timestamp          │           int128           │        decimal(34,5)        │
├───────┼────────────────────────────┼────────────────────────────┼─────────────────────────────┤
│  -15  │ 2025-09-25 12:26:55.123456 │ -1234567890123456789012345 │ -12345678900020250922.12345 │
└───────┴────────────────────────────┴────────────────────────────┴─────────────────────────────┘

root@66d4e20ec1d7:/par/luadbi# lua ../duck.lua
-15
2025-09-25 12:26:55.123456
-1234567890123456789012345
-345.00000
root@66d4e20ec1d7:/par/luadbi# ../duckdb141 lua_duckdb -c "from table_1"
┌───────┬────────────────────────────┬────────────────────────────┬───────────────┐
│  id   │          column1           │          column2           │    column3    │
│ int32 │         timestamp          │           int128           │ decimal(34,5) │
├───────┼────────────────────────────┼────────────────────────────┼───────────────┤
│  -15  │ 2025-09-25 12:26:55.123456 │ -1234567890123456789012345 │  -345.00000   │
└───────┴────────────────────────────┴────────────────────────────┴───────────────┘

root@66d4e20ec1d7:/par/luadbi# lua ../duck.lua
-15
2025-09-25 12:26:55.123456
-1234567890123456789012345
-12345678900.03450
root@66d4e20ec1d7:/par/luadbi# ../duckdb141 lua_duckdb -c "from table_1"
┌───────┬────────────────────────────┬────────────────────────────┬────────────────────┐
│  id   │          column1           │          column2           │      column3       │
│ int32 │         timestamp          │           int128           │   decimal(34,5)    │
├───────┼────────────────────────────┼────────────────────────────┼────────────────────┤
│  -15  │ 2025-09-25 12:26:55.123456 │ -1234567890123456789012345 │ -12345678900.03450 │
└───────┴────────────────────────────┴────────────────────────────┴────────────────────┘

测试脚本如下

lua 复制代码
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, '-1234567890123456789012345'::hugeint  column2,'-12345678900.0345'::decimal(34,5) column3 ;" )
statement:execute()

statement = assert(dbd:prepare( "select * from table_1 where id = $1;" ))
statement:execute( -15 )

for row in statement:rows(true) do
         print(row['id'])
	 print(row['column1'])
	 print(row['column2'])
	 print(row['column3'])

end
相关推荐
银发控、7 小时前
MySQL联合索引
数据库·mysql
予枫的编程笔记7 小时前
【MySQL修炼篇】从踩坑到精通:事务隔离级别的3大异常(脏读/幻读/不可重复读)解决方案
数据库·mysql·后端开发·数据库事务·事务隔离级别·rr级别·脏读幻读不可重复读
一起养小猫9 小时前
Flutter for OpenHarmony 实战:记账应用数据统计与可视化
开发语言·jvm·数据库·flutter·信息可视化·harmonyos
世界尽头与你9 小时前
(修复方案)CVE-2023-22047: Oracle PeopleSoft Enterprise PeopleTools 未授权访问漏洞
数据库·安全·oracle·渗透测试
韩立学长9 小时前
【开题答辩实录分享】以《智能大学宿舍管理系统的设计与实现》为例进行选题答辩实录分享
数据库·spring boot·后端
Henry Zhu1239 小时前
数据库(五):反规范化
数据库
Mr_Xuhhh10 小时前
MySQL函数详解:日期、字符串、数学及其他常用函数
java·数据库·sql
he___H10 小时前
Redis高级数据类型
数据库·redis·缓存
霖霖总总11 小时前
[小技巧60]深入解析 MySQL Online DDL:MySQL Online DDL、pt-osc 与 gh-ost 机制与最佳实践
数据库·mysql
爱学习的阿磊11 小时前
使用PyTorch构建你的第一个神经网络
jvm·数据库·python