2009-08-19 52 views
1

我试图插入一些整数到Postgres表中使用以下几个简单的代码。PostgreSQL libpq发送整数作为二进制时出现“整数超出范围”错误

#include <libpq-fe.h> 
#include <stdio.h> 
#include <stdint.h> 

int main() { 
    int64_t i = 0; 
    PGconn * connection = PQconnectdb("dbname='babyfood'"); 
    if(!connection || PQstatus(connection) != CONNECTION_OK) 
    return 1; 
    printf("Number: "); 
    scanf("%d", &i); 

    char * params[1]; 
    int param_lengths[1]; 
    int param_formats[1]; 
    param_lengths[0] = sizeof(i); 
    param_formats[0] = 1; 
    params[0] = (char*)&i; 
    PGresult * res = PQexecParams(connection, 
            "INSERT INTO intlist VALUES ($1::int8)", 
            1, 
            NULL, 
            params, 
            param_lengths, 
            param_formats, 
            0); 
    printf("%s\n", PQresultErrorMessage(res)); 
    PQclear(res); 
    PQfinish(connection); 
    return 0; 
} 

我得到如下结果:

 
Number:55 
ERROR: integer out of range 
 
Number:1 
ERROR: integer out of range 

我敢肯定的int64_t总会适合在任何理智的平台的8字节整数。我究竟做错了什么?

回答

3

相反的:

params[0] = (char*)&i; 

你应该使用:

#include <endian.h> 
/* ... */ 
int64_t const i_big_endian = htobe64(i); 
params[0] = (char*)&i_big_endian; 

一个htobe64功能将开启小端字节序,什么事都不做在大端。

抛弃您的flip_endian函数,因为它会使您的程序与PowerPC,Alpha,Motorola,SPARC,IA64等大端/双端计算机不兼容。即使您的程序不期望在它们上运行这是一种糟糕的风格,缓慢且容易出错。

-1

我认为它已经越过了32位int,然后被转换为64位,因为你没有告诉libpq格式是什么。

尝试为paramTypes指定一个数组,使用参数的int8(即20)的oid。

+0

它应该能够从:: int8转换中确定。此外,这绝对是一个endian问题,因为翻转endian不仅会摆脱错误,而且实际上会导致正确的插入。 – Edward 2009-08-19 21:01:44

+0

啊,我明白了。我应该想到这一点:) – 2009-08-20 08:38:02

1

好吧,它似乎是一个endian问题,它仍然不能很好地解释它,因为64位有序符号(即x86)有符号整数应该适合大端64位整数,反之亦然,他们只会被损坏。然而,交换整数的端点会产生正确的值。交换是与下面的函数:

int64_t flip_endian(int64_t endi) { 
    char* bytearray; 
    char swap; 
    int64_t orig = endi; 
    int i; 

    bytearray = (char*)&orig; 

    for(i = 0; i < sizeof(orig)/2; ++i) { 
    swap = bytearray[i]; 
    bytearray[i] = bytearray[ sizeof(orig) - i - 1 ]; 
    bytearray[ sizeof(orig) - i - 1 ] = swap; 
    } 

    return orig; 

} 
相关问题