2010-10-25 7 views
9

después de horas de documentaciones/tableros/listas de correo y sin progreso Puedo pedirte: ¿Cómo 'codifico' mis datos para usarlos en el transporte binario usando libpq's PQexecParams(.)?Libpq de PostgreSQL: Codificación para el transporte binario de ARRAY [] - ¿datos?

Las variables simples son sólo con el fin big endian:

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 

y como esto también doble, int, etc ...

Pero, ¿cómo acerca de las matrices?

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

¿Hay algún ejemplo de trabajo de transferencia de datos ARRAY en formato binario de PostgreSQL? El código en backend/utils/adt/ no me ayuda mucho (excepto que ahora se que hay un ArrayType, pero no cómo usarlos) :-(

Sólo necesito una función char* to_PQbin(float [] input, int length) para pasar a paramValues[.] ...

Muchas gracias, Tebas

PS: ¿Cuál es la forma sugerida de conversión de variables simples (en lugar de mi htobe32(.))

Respuesta

4

Como ccuter ya mencionado, necesita crear su propia API. El siguiente código extrae una matriz de 1 dimensión de int4 ignorando los valores 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; 
} 

También parece ser una biblioteca llamada libpqtypes que ayuda para este tipo de conversión.

3

http://git.postgresql.org/gitweb?p=postgresql.git;a=blob;f=src/include/utils/array.h;h=7f7e744cb12bc872f628f90dad99dfdf074eb314;hb=master describe el formato binario de Postgres para matrices nosotros cuando. ing libpq, omite la porción vl_len_. Por ejemplo, un una matriz de 4 números enteros se vería así:

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

Esto tiene OID 1007 (INT4ARRAYOID). El primer entero es 1 dimensión, el segundo entero no es mapa de bits NULL (por lo que ninguno de los valores de la matriz son NULL), el tercer entero es el OID de los elementos (23, INT4OID), el cuarto entero es qué tan grande es la primera dimensión (4), el quinto entero es el índice inicial de la primera dimensión. Después de eso, están los datos de la matriz en bruto, en orden secuencial, cada elemento prefijado por su longitud (4 bytes para cada entero).

Cuestiones relacionadas