Der er to fejl i din kode:
-
Du forsøger at sende binære data, men du fortæller ikke
PQexecParams
hvilken type det er.Det kan ikke fungere. Manglende typeoplysninger vil PostgreSQL bruge typen
unknown
og behandle det som snor. Det betyder, at din binære repræsentation vil blive ført tilfloat8in
funktion, der konverterer strenge til dobbelte præcisionsværdier, hvilket vil fejle frygteligt. Det er sandsynligvis det, du observerer.Du bliver nødt til at bruge en fjerde parameter med en
Oid[]
der indeholder 701 (ellerFLOAT8OID
hvis du hellere vil bruge PostgreSQL's#define
, men du skal#include <postgres.h>
og<catalog/pg_type.h>
for det). -
Du antager fejlagtigt, at PostgreSQL's binære repræsentation af
double precision
type er det binære format fordouble
i brug på din klientmaskine.Dette virker muligvis ved et uheld, hvis dit program kører på en big-endian maskine, da stort set alle arkitekturer i disse dage bruger IEEE flydende kommatal .
Hvis du læser kildekoden, vil du opdage, at PostgreSQL's over-the-wire binære format er defineret i
pq_sendfloat8
isrc/backend/libpq/pqformat.c
, som kalderpq_sendint64
, som konverterer 8-byte-værdien til netværksbyte-rækkefølge (hvilket er det samme som big-endian-repræsentation).
Så du bliver nødt til at definere en konverteringsfunktion, der ligner denne:
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);
}
Så kunne din kode se sådan ud:
Oid types[1];
double converted;
...
types[0] = FLOAT8OID;
to_nbo(value, &converted);
values[0] = (char *)&converted;
Men ærligt talt ville det være meget nemmere at bruge tekstgengivelsen. Det vil gøre din kode uafhængig af PostgreSQL internals og er sandsynligvis ikke så meget langsommere.
Det ser ikke sådan ud, men hvis double precision
værdier hentes fra en PostgreSQL-tabel et andet sted, kan du indstille extra_float_digits
= 3
så du er garanteret ikke at miste nogen præcision, når værdierne konverteres til deres strengrepræsentation.