2010-10-25 33 views
9

sau hàng giờ tài liệu/bảng/danh sách gửi thư và không có tiến bộ nào tôi có thể hỏi bạn: Làm cách nào để 'mã hóa' dữ liệu của tôi để sử dụng nó cho việc vận chuyển nhị phân bằng cách sử dụng libpq's PQexecParams(.)?libpq của PostgreSQL: Mã hóa cho truyền tải nhị phân ARRAY [] - dữ liệu?

biến đơn giản chỉ là để về cuối lớn:

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 

và như thế này cũng tăng gấp đôi, int, vv ...

Nhưng làm thế nào về mảng?

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)); 

Có ví dụ nào về chuyển dữ liệu ARRAY ở định dạng nhị phân của PostgreSQL không? Các mã trong backend/utils/adt/ không giúp tôi nhiều (ngoại trừ bây giờ tôi biết có một ARRAYTYPE, nhưng không phải là cách để sử dụng chúng) :-(

tôi chỉ cần một hàm char* to_PQbin(float [] input, int length) cho đi để paramValues[.] ...

Thanks a lot, Tebas

PS: cách đề nghị chuyển đổi biến đơn giản (chứ không phải htobe32(.) của tôi) là gì

Trả lời

4

ccuter đã được đề cập, bạn cần tạo API của riêng mình. Đoạn mã sau trích xuất mảng 1 chiều của int4 bỏ qua bất kỳ giá trị NULL nào.

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

Dường như thư viện có tên là libpqtypes giúp loại chuyển đổi này.

3

http://git.postgresql.org/gitweb?p=postgresql.git;a=blob;f=src/include/utils/array.h;h=7f7e744cb12bc872f628f90dad99dfdf074eb314;hb=master mô tả định dạng nhị phân Postgres cho mảng Khi chúng ta. ing libpq, bỏ qua phần vl_len_. Ví dụ, một một mảng của 4 số nguyên sẽ trông như thế:

0x00000001 0x00000000 0x00000017 0x00000004 0x00000001 0x00000004 0x00000004 0x00000004 0x00000004

Đây có OID 1007 (INT4ARRAYOID). Số nguyên đầu tiên là 1 thứ nguyên, số nguyên thứ hai không có bitmap NULL (vì vậy không có giá trị nào của mảng là NULL), số nguyên thứ ba là OID của các phần tử (23, INT4OID), số nguyên thứ tư là kích thước thứ nhất lớn như thế nào (4), số nguyên thứ năm là chỉ số bắt đầu của thứ nguyên đầu tiên. Sau đó là dữ liệu mảng thô, theo thứ tự tuần tự, mỗi phần tử được đặt trước bởi độ dài của nó (4 byte cho mỗi số nguyên).

Các vấn đề liên quan