c
  • postgresql
  • libpq
  • 2009-08-19 4 views 1 likes 
    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

    libpq에 형식이 무엇인지 알려주지 않으므로 32 비트 정수로 전달 된 다음 64 비트로 변환됩니다.

    매개 변수의 int8 (20 임)에 대한 oid를 사용하여 paramTypes에 대한 배열을 지정하십시오.

    +0

    그것은 :: int8 캐스트에서 결정할 수 있어야합니다. 또한 엔디안을 뒤집는 것은 오류를 제거 할뿐만 아니라 실제로 올바른 삽입을 초래하기 때문에 확실히 엔디안 문제입니다. – Edward

    +0

    아, 알겠습니다. 나는 그것을 생각해야했다 :) –

    1

    좋아요, 리틀 엔디안 (즉, x86) 64 비트 부호있는 정수가 빅 엔디안 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; 
    
    } 
    

     관련 문제

    • 관련 문제 없음^_^