10

何時間ものドキュメント/ボード/メーリングリストの後、私はあなたに尋ねるかもしれませんPQexecParams(.).

単純な変数は、ビッグ エンディアン順になっています。

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.12345678901234567890; // 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

このように、double、int なども ...

しかし、ARRAY はどうですか?

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

ARRAY データを PostgreSQL のバイナリ形式で転送する実際の例はありますか? のコードbackend/utils/adt/はあまり役に立ちません (ただし、ARRAYTYPE があることはわかっていますが、それらの使用方法はわかりません) :-(

char* to_PQbin(float [] input, int length)渡す関数が必要なだけですparamValues[.]...

どうもありがとう、テバス

PS: 単純な変数 ( my ではなくhtobe32(.)) を変換する推奨される方法は何ですか?

4

3 に答える 3

11

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 つの整数の配列は次のようになります。

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

これには OID 1007 (INT4ARRAYOID) があります。最初の整数は 1 次元、2 番目の整数は非 NULL ビットマップ (配列の値はどれも NULL ではない)、3 番目の整数は要素の OID (23、INT4OID)、4 番目の整数は最初の次元の大きさです。 (4)、5 番目の整数は、最初の次元の開始インデックスです。その後、生の配列データが順番に並べられ、各要素の前にその長さ (整数ごとに 4 バイト) が付けられます。

于 2011-01-28T20:19:40.183 に答える
5

ccuter既に述べたように、独自の API を作成する必要があります。int4次のコードは、NULL 値を無視して の1 次元配列を抽出します。

#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という名前のライブラリもあるようです。

于 2011-07-12T13:22:07.587 に答える