Det finns två fel i din kod:
-
Du försöker skicka binär data, men du berättar inte för
PQexecParams
vilken typ det är.Det kan inte fungera. I brist på typinformation kommer PostgreSQL att använda typen
unknown
och behandla det som ett snöre. Det betyder att din binära representation kommer att matas tillfloat8in
funktion som omvandlar strängar till dubbla precisionsvärden, vilket kommer att misslyckas fruktansvärt. Detta är förmodligen vad du observerar.Du måste använda en fjärde parameter med en
Oid[]
som innehåller 701 (ellerFLOAT8OID
om du hellre vill använda PostgreSQL:s#define
, men du måste#include <postgres.h>
och<catalog/pg_type.h>
för det). -
Du antar felaktigt att PostgreSQL:s binära representation av
double precision
typ är det binära formatet fördouble
som används på din klientdator.Detta kan fungera av misstag om ditt program körs på en big-endian maskin, eftersom praktiskt taget alla arkitekturer nuförtiden använder IEEE-flyttal .
Om du läser källkoden kommer du att upptäcka att PostgreSQL:s binära format över tråden är definierat i
pq_sendfloat8
isrc/backend/libpq/pqformat.c
, som anroparpq_sendint64
, som konverterar 8-byte-värdet till nätverksbyteordning (vilket är samma som big-endian-representation).
Så du måste definiera en konverteringsfunktion som liknar denna:
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);
}
Då kan din kod se ut så här:
Oid types[1];
double converted;
...
types[0] = FLOAT8OID;
to_nbo(value, &converted);
values[0] = (char *)&converted;
Men ärligt talat skulle det vara mycket lättare att använda textrepresentationen. Det kommer att göra din kod oberoende av PostgreSQL-interna funktioner och är förmodligen inte så mycket långsammare.
Det ser inte ut som det, men om double precision
värden hämtas från en PostgreSQL-tabell någon annanstans kan du ställa in extra_float_digits
= 3
så att du garanterat inte förlorar någon precision när värdena konverteras till deras strängrepresentation.