利用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
相关推荐
无敌最俊朗@2 小时前
Qt 开发终极坑点手册图表版本
数据库
老衲提灯找美女3 小时前
MySQL数据库基础操作:
数据库·mysql·oracle
轻舟客丶3 小时前
ORA-03113的解决方案
数据库·经验分享·笔记·oracle
ヾChen3 小时前
头歌MySQL——复杂查询
数据库·物联网·学习·mysql·头歌
上下翻飞的屁3 小时前
jdbcTemplate执行sql后数据库字段没有更新问题解决
java·数据库·sql
悦光阴3 小时前
SQL Server 并发控制:Fabric Warehouse只支持快照隔离
大数据·运维·数据库·fabric
谅望者3 小时前
SQL子查询完全指南:从零掌握嵌套查询的三种用法与最佳实践
数据库·sql·数据库开发·子查询
Mr.Lee jack4 小时前
【CUDA 编程思想】FwdKvcacheMla 算子详细数据流程讲解
deepseek
武子康4 小时前
AI研究-121 DeepSeek-OCR 研究路线:无限上下文、跨模态抽取、未来创意点、项目创意点
人工智能·深度学习·机器学习·ai·ocr·deepseek·deepseek-ocr