Teb*_*bas 9 c c++ postgresql libpq
几个小时的文件/委员会/邮件列表并且没有进展我可能会问你:我如何'编码'我的数据用于使用libpq进行二进制传输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
Run Code Online (Sandbox Code Playgroud)
并且像这样也是double,int等...
但ARRAYs怎么样?
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));
Run Code Online (Sandbox Code Playgroud)
有没有以PostgreSQL的二进制格式传输ARRAY数据的工作示例?代码对backend/utils/adt/我没什么帮助(除了我现在知道有一个ARRAYTYPE,但不是如何使用它们):-(
我只需要一个函数char* to_PQbin(float [] input, int length)传递给paramValues[.]...
非常感谢,Tebas
PS:转换简单变量(而不是我的htobe32(.))的建议方法是什么?
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维,第二个整数是没有NULL位图(因此没有数组的值是NULL),第三个整数是元素的OID(23,INT4OID),第四个整数是第一个维度有多大(4),第五个整数是第一个维度的起始索引.之后是原始数组数据,按顺序排列,每个元素以其长度为前缀(每个整数为4个字节).
小智 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;
}
Run Code Online (Sandbox Code Playgroud)
似乎还有一个名为libpqtypes的库可以帮助进行这种转换.