2009-08-19 61 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; 

} 
相關問題