Jam*_*Jam 3 c postgresql libpq
我正在使用libpq. 我收到此错误INSERT failed: ERROR: insufficient data left in message。
这是我的代码库中的相应片段:
printf ("Enter write parameter_value");
scanf("%f", ¶meter_value);
char *stm = "INSERT INTO write_reg_set (parameter_value) VALUES ($1::double precision)";
int nparam = 1;
//set the values to use
const char *values[1] = {(char *)¶meter_value};
//calculate the lengths of each of the values
int lengths[1] = {sizeof(parameter_value)};
//state which parameters are binary
int binary[1] = {1};
PGresult *res = PQexecParams(conn,
stm,
nparam, //number of parameters
NULL, //ignore the Oid field
values, //values to substitute $1 and $2 and so on
lengths, //the lengths, in bytes, of each of the parameter values
binary, //whether the values are binary or not
0); //we want the result in text format
if (PQresultStatus(res) != PGRES_COMMAND_OK) {
fprintf(stderr, "INSERT failed: %s", PQerrorMessage(conn));
exit_nicely(conn,res);
}
PQclear(res);
Run Code Online (Sandbox Code Playgroud)
您的代码中有两个错误:
您正在尝试发送二进制数据,但您不知道PQexecParams它是哪种类型。
那行不通。缺少类型信息,PostgreSQL 将使用该类型unknown并将其视为字符串。这意味着您的二进制表示将被馈送到float8in将字符串转换为双精度值的函数,这将非常失败。这可能是你正在观察的。
你将不得不使用与第四个参数Oid[]包含701(或者FLOAT8OID,如果你宁愿使用PostgreSQL的#define,但你必须#include <postgres.h>和<catalog/pg_type.h>该)。
您错误地认为 PostgreSQL 的二进制表示double precision类型是double在您的客户端机器上使用的二进制格式。
如果您的程序在大端机器上运行,这可能会意外地工作,因为如今几乎所有架构都使用IEEE 浮点数。
如果您阅读源代码,您会发现 PostgreSQL 的在线二进制格式定义在pq_sendfloat8中src/backend/libpq/pqformat.c,它调用pq_sendint64,将 8 字节值转换为网络字节顺序(与 big-endian 表示相同) .
所以你必须定义一个类似于这样的转换函数:
static void to_nbo(double in, double *out) {
uint64_t *i = (uint64_t *)∈
uint32_t *r = (uint32_t *)out;
/* convert input to network byte order */
r[0] = htonl((uint32_t)((*i) >> 32));
r[1] = htonl((uint32_t)*i);
}
Run Code Online (Sandbox Code Playgroud)
那么您的代码可能如下所示:
Oid types[1];
double converted;
...
types[0] = FLOAT8OID;
to_nbo(value, &converted);
values[0] = (char *)&converted;
Run Code Online (Sandbox Code Playgroud)
但坦率地说,使用文本表示会容易得多。这将使您的代码独立于 PostgreSQL 内部结构,并且可能不会那么慢。
它看起来不像,但是如果double precision值是从其他地方的 PostgreSQL 表中提取的,您可以进行设置,以便保证在将值转换为其字符串表示时不会丢失任何精度。extra_float_digits= 3