2010-10-25 90 views
9

幾小時的文件/董事會/郵件列表並且沒有任何進展我可能會問你:如何使用libpq的PQexecParams(.)對我的數據進行「編碼」以用於二進制傳輸?PostgreSQL的libpq:ARRAY []的二進制傳輸的編碼 - 數據?

簡單的變量只是在大尾序:

PGconn *conn; 
PGresult *res; 
char *paramValues[1]; 
int paramLengths[1]; 
int paramFormats[1]; 

conn = PQconnectdb(CONNINFO); 

// -- (1) -- send a float value 
float val_f = 0.123456789; // float precision: ~7 decimal digits 
// alloc some memory & write float (in big endian) into 
paramValues[0] = (char *) malloc(sizeof(val_f)); 
*((uint32_t*) paramValues[0]) = htobe32(*((uint32_t*) &val_f)); // host to big endian 

paramLengths[0] = sizeof(val_f); 
paramFormats[0] = 1; // binary 

res = PQexecParams(conn, "SELECT $1::real ;", // 
     1, // number parameters 
     NULL, // let the backend deduce param type 
     paramValues, // 
     paramLengths, // 
     paramFormats, // 
     0); // return text 
printf("sent float: %s \n", PQgetvalue(res, 0, 0)); 
// --> sent float: 0.123457 

和這樣也雙,INT,等等

但如何對數組?

float vals_f[] = {1.23, 9.87}; 
    // alloc some memory 
    paramValues[0] = (char *) malloc(sizeof(float) * 2); 

// ???? paramValues[0] = ?????? 

    paramLengths[0] = sizeof(float) * 2; 
    paramFormats[0] = 1; // binary 


    res = PQexecParams(conn, "SELECT $1::real[] ;", // 
      1, // number parameters 
      NULL, // let the backend deduce param type 
      paramValues, // 
      paramLengths, // 
      paramFormats, // 
      0); // return text 
    printf("sent float array: %s \n", PQgetvalue(res, 0, 0)); 

有任何工作的例子,在PostgreSQL的二進制格式轉換ARRAY數據? 在backend/utils/adt/代碼不幫我多(除了現在我知道有一個數組類型,但不知道如何使用它們):-(

我只是需要一個功能char* to_PQbin(float [] input, int length)傳遞到paramValues[.] ...

非常感謝, Tebas

PS:什麼是將簡單的變量(而不是我的htobe32(.))的建議方式

回答

4

由於ccuter已經提到,您需要創建自己的API。以下代碼提取int4的一維數組忽略任何NULL值。

#define INT4OID 23 

/*! Structure of array header to determine array type */ 
struct array_int4 { 
    int32_t ndim; /* Number of dimensions */ 
    int32_t _ign; /* offset for data, removed by libpq */ 
    Oid elemtype; /* type of element in the array */ 

    /* First dimension */ 
    int32_t size; /* Number of elements */ 
    int32_t index; /* Index of first element */ 
    int32_t first_value; /* Beginning of integer data */ 
}; 

static int extract_int4_array (char *raw_array, 
           int32_t **values, 
           int *num_values) { 
    /* Array information header */ 
    struct array_int4 *array = (struct array_int4 *) raw_array; 
    /* Pointer to traverse int array */ 
    int32_t *p_value = &(array->first_value); 
    /* int value in host byte order */ 
    int32_t hval; 

    /* Check if we have a 1-dimensional INT4 array */ 
    if (ntohl(array->ndim) != 1 
    || ntohl(array->elemtype) != INT4OID) { 
    return -1; 
    } 
    /* Number of elements including NULLs */ 
    int array_elements = ntohl (array->size); 

    *num_values = 0; 
    /* Get size of array */ 
    for (int i=0; i<array_elements; ++i) { 
    /* Check size to see if this is a NULL value */ 
    hval = ntohl (*p_value); 
    if (hval != -1) { 
     ++p_value; 
     (*num_values) += 1; 
    } 

    ++p_value; 
    } 
    *values = malloc (*num_values * sizeof **values); 

    /* Fill output int array. Skip every other value as it contains the size of 
    * the element */ 
    *num_values = 0; /* Use num_values as the index of the output array */ 
    p_value = &(array->first_value); 
    for (int i=0; i<array_elements; ++i) { 
    /* Check size to see if this is a NULL value */ 
    hval = ntohl (*p_value); 
    if (hval != -1) { 
     ++p_value; 
    (*values)[*num_values] = ntohl (*p_value); 
     (*num_values) += 1; 
    } 

    ++p_value; 
    } 

    return 0; 
} 

似乎還有一個名爲libpqtypes的庫,可以幫助進行這種轉換。

3

http://git.postgresql.org/gitweb?p=postgresql.git;a=blob;f=src/include/utils/array.h;h=7f7e744cb12bc872f628f90dad99dfdf074eb314;hb=master描述的Postgres的二進制格式數組時我們。在libpq中,省略vl_len_部分。例如,4個整數的陣列看起來像:

00000001 00000000 0x00000017 0x00000004 00000001 0x00000004 0x00000004 0x00000004 0x00000004

這具有OID 1007(INT4ARRAYOID)。第一個整數是1維,第二個整數不是NULL位圖(因此沒有數組的值是NULL),第三個整數是元素的OID(23,INT4OID),第四個整數是第一個維度有多大(4)中,第五個整數是第一維的起始索引。之後是原始數組數據,按順序排列,每個元素以其長度爲前綴(每個整數4個字節)。