2009-08-19 10 views
1

Ich versuche einige Integer in eine Postgres-Tabelle mit dem folgenden etwas einfachen Code einzufügen.PostgreSQL libpq "Integer out of range" -Fehler beim Senden von Integer als binär

#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; 
} 

ich folgende Ergebnisse:

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

Ich bin mir ziemlich sicher, dass ein int64_t wird in einer 8-Byte-Ganzzahl auf jeder vernünftige Plattform immer fit. Was mache ich falsch?

Antwort

3

Statt:

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

sollten Sie verwenden:

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

A htobe64 Funktion endianness auf Little-Endian-Schalter, und nichts tun auf Big-Endian.

Ditch Ihre flip_endian Funktion, da es Ihr Programm inkompatibel mit Big-Endian/Bi-Endian Computer, wie PowerPC, Alpha, Motorola, SPARC, IA64 usw. machen würde. Auch wenn Ihr Programm nicht erwartet, auf ihnen ausgeführt werden Es ist ein schlechter Stil, langsam und fehleranfällig.

-1

Ich denke, es wird als 32-Bit-Int übergeben und wird dann auf 64-Bit geworfen, weil Sie libpq nicht sagen, was das Format ist.

Versuchen Sie, ein Array für paramTypes mit der oid für int8 (20) für den Parameter anzugeben.

+0

Es soll in der Lage sein, das aus der :: int8 Besetzung zu bestimmen. Außerdem ist es definitiv ein Endian-Problem, da das Umdrehen des Endian nicht nur den Fehler beseitigt, sondern tatsächlich zu korrekten Einfügungen führt. – Edward

+0

Ah, ich verstehe. Ich hätte daran denken sollen :) –

1

In Ordnung, es scheint, dass es ein Endian-Problem ist, das es immer noch nicht recht erklärt, da ein Little-Endian (dh x86) 64-Bit-Ganzzahl mit Vorzeichen in eine Big-Endian-64-Bit-Ganzzahl passen sollte und umgekehrt, sie würden nur verdorben werden. Der Austausch des Endian auf die ganze Zahl ergibt jedoch den richtigen Wert. Swapping wird mit folgenden Funktion getan:

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; 

}