Er zijn twee fouten in uw code:
-
U probeert binaire gegevens te verzenden, maar u vertelt
PQexecParams
niet welk type het is.Dat kan niet werken. Bij gebrek aan type-informatie gebruikt PostgreSQL het type
unknown
en behandel het als een string. Dat betekent dat uw binaire representatie wordt ingevoerd in defloat8in
functie die tekenreeksen converteert naar dubbele precisiewaarden, die vreselijk zullen mislukken. Dit is waarschijnlijk wat je waarneemt.U moet een vierde parameter gebruiken met een
Oid[]
die 701 (ofFLOAT8OID
bevat) als je liever PostgreSQL's#define
gebruikt , maar je moet#include <postgres.h>
en<catalog/pg_type.h>
daarvoor). -
U neemt ten onrechte aan dat PostgreSQL's binaire representatie van de
double precision
type is het binaire formaat voordouble
in gebruik op uw clientcomputer.Dit kan per ongeluk werken als je programma draait op een big-endian machine, aangezien vrijwel elke architectuur tegenwoordig IEEE floating point getallen gebruikt .
Als je de broncode leest, zul je zien dat het over-the-wire binaire formaat van PostgreSQL is gedefinieerd in
pq_sendfloat8
insrc/backend/libpq/pqformat.c
, diepq_sendint64
. aanroept , die de 8-byte-waarde converteert naar netwerkbytevolgorde (wat hetzelfde is als big-endian-representatie).
U zou dus een conversiefunctie moeten definiëren die lijkt op deze:
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);
}
Dan zou je code er als volgt uit kunnen zien:
Oid types[1];
double converted;
...
types[0] = FLOAT8OID;
to_nbo(value, &converted);
values[0] = (char *)&converted;
Maar eerlijk gezegd zou het veel gemakkelijker zijn om de tekstrepresentatie te gebruiken. Dat maakt je code onafhankelijk van PostgreSQL internals en is waarschijnlijk niet zo veel langzamer.
Het lijkt er niet op, maar als de double precision
waarden uit een PostgreSQL-tabel ergens anders worden gehaald, kunt u extra_float_digits
= 3
zodat u gegarandeerd geen precisie verliest wanneer de waarden worden geconverteerd naar hun tekenreeksweergave.