You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL自定义变长文本类型异常:数据截断或对齐问题求助

问题分析与解决

你的自定义类型出现数据截断/对齐问题,核心原因是结构体定义错误——额外添加的int32 length字段破坏了PostgreSQL变长类型(varlena)的内存布局。

PostgreSQL的变长类型本身通过头部的VARHDRSZ(通常为4字节)存储数据总长度,无需在自定义结构体中重复定义长度字段。你额外增加的length字段会占用4字节内存,导致实际数据的存储位置偏移,最终读取时指向错误的内存区域,引发截断或乱码。

修正后的代码

结构体定义

typedef struct Hierarchy
{
    char path[FLEXIBLE_ARRAY_MEMBER];
} Hierarchy;

输入/输出函数

PG_FUNCTION_INFO_V1(hierarchy_in);
PG_FUNCTION_INFO_V1(hierarchy_out);

typedef struct Hierarchy
{
    char path[FLEXIBLE_ARRAY_MEMBER];
} Hierarchy;


Datum
hierarchy_in(PG_FUNCTION_ARGS)
{
    char *input_str = PG_GETARG_CSTRING(0);
    int32 input_len = strlen(input_str);
    Hierarchy *result;

    // 分配内存:VARHDR头部 + 数据长度
    result = (Hierarchy *)palloc(VARHDRSZ + input_len);
    // 设置总长度(头部+数据)
    SET_VARSIZE(result, VARHDRSZ + input_len);
    // 复制数据到柔性数组(VARHDR之后的区域)
    memcpy(result->path, input_str, input_len);

    PG_RETURN_POINTER(result);
}

Datum
hierarchy_out(PG_FUNCTION_ARGS)
{
    Hierarchy *input = (Hierarchy *)PG_GETARG_POINTER(0);
    char *result;
    int32 input_len = VARSIZE(input) - VARHDRSZ;

    // 复制指定长度字节并自动添加字符串终止符
    result = pnstrdup(input->path, input_len);

    PG_RETURN_CSTRING(result);
}

关键修正点

  1. 移除冗余的length字段:避免与PostgreSQL内置的varlena头部长度冲突,确保数据存储位置对齐。
  2. 替换strncpy为memcpy:memcpy语义更清晰,适合处理固定长度的字节数据,避免strncpy自动补0的潜在问题。
  3. 内存与长度严格匹配:palloc分配的内存大小、SET_VARSIZE设置的总长度完全对应,保证数据完整存储。

重新编译扩展并执行测试用例,数据即可正常显示,不会再出现截断或对齐问题。

内容的提问来源于stack exchange,提问作者Christopher Aliotta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 21:58:09