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

使用libpq更新PostgreSQL表时遇ERROR: insufficient data left in message错误

使用libpq更新PostgreSQL表时出现"insufficient data left in message"错误

问题详情

执行PostgreSQL表更新操作时触发如下错误:

ERROR: insufficient data left in message

用相同参数编写示例代码后仍出现相同错误,PQerrorMessage(res)返回上述错误,状态码为PGRES_FATAL_ERROR。目前插入和查询语句可正常执行。

示例代码

std::string sQuery("update client_backlog_period set starttime = $1, endtime = $2, unavailable = $3 where periodid = $4");

int nElem = 4;

timestamp start_time = 736260060000000, end_time = 736260900000000;
short nUnavailable = 0;
long nPeriodid = 1;

start_time = boost::endian::native_to_big(start_time);
end_time = boost::endian::native_to_big(end_time);
nUnavailable = boost::endian::native_to_big(nUnavailable);
nPeriodid = boost::endian::native_to_big(nPeriodid);

const char* paramValues[4] = { (char*)&start_time, (char*)&end_time, (char*)&nUnavailable, (char*)&nPeriodid};
Oid paramTypes[4] = { TIMESTAMPOID, TIMESTAMPOID, INT2OID , INT8OID };

int paramLengths[4] = { sizeof(start_time), sizeof(end_time),sizeof(nUnavailable), sizeof(nPeriodid) };
int paramFormats[4] = { 1,1,1,1 };
PGresult* res = PQexecParams(db.m_pPGConn,
        sQuery.c_str(),
        nElem,
        paramTypes,
        paramValues,
        paramLengths,
        paramFormats,
        1
    );

ExecStatusType status = PQresultStatus(res);
if (status != PGRES_COMMAND_OK)
{
    std::cerr << "\nUpdate Query failed, Error: " << PQerrorMessage(res) << ",status: " << status << std::endl;
    PQclear(res);
}

表结构

表client_backlog_period字段信息:

  • periodid: bigint(主键)
  • clientid: integer
  • starttime: timestamp without time zone
  • endtime: timestamp without time zone
  • unavailable: smallint

问题原因及修复方案

该错误核心原因是参数类型/长度与PostgreSQL期望不匹配,导致数据库解析消息时数据不足。结合代码和表结构,问题集中在以下两点:

1. periodid的类型长度不匹配

表中periodid是bigint类型,对应libpq的INT8OID需要8字节数据,但代码中使用的long类型在Windows等平台下仅为4字节,sizeof(nPeriodid)返回4,远小于PostgreSQL要求的8字节,直接导致消息数据不足。

2. (可选)自定义timestamp类型的长度验证

PostgreSQL的timestamp without time zone二进制格式为8字节大端int64,需确保你的自定义timestamp类型是8字节的整数类型(如int64_t),否则也会出现长度不匹配问题。

修复步骤

  • 将nPeriodid的类型改为int64_t或long long,确保是8字节:
    int64_t nPeriodid = 1;
    
  • 确认自定义timestamp类型为8字节,若不是则调整定义:
    using timestamp = int64_t;
    
  • 打印验证参数长度,确保符合要求:
    std::cout << "start_time size: " << sizeof(start_time) << std::endl; // 应输出8
    std::cout << "nPeriodid size: " << sizeof(nPeriodid) << std::endl; // 应输出8
    

内容的提问来源于stack exchange,提问作者Rakesh Mehta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 04:50:03