Há dois erros no seu código:
-
Você está tentando enviar dados binários, mas não informaPQexecParamsque tipo é.
Isso não pode funcionar. Na falta de informações de tipo, o PostgreSQL usará o tipounknowne tratá-lo como string. Isso significa que sua representação binária será alimentada nofloat8infunção que converte strings em valores de precisão dupla, que falharão horrivelmente. Provavelmente é isso que você está observando.
Você terá que usar um quarto parâmetro com umOid[]que contém 701 (ouFLOAT8OIDse você preferir usar o#definedo PostgreSQL , mas você teria que#include <postgres.h>e<catalog/pg_type.h>por isso).
-
Você erroneamente assume que a representação binária do PostgreSQL dadouble precisiontype é o formato binário paradoubleem uso em sua máquina cliente.
Isso pode funcionar acidentalmente se seu programa estiver sendo executado em um big-endian máquina, já que praticamente todas as arquiteturas atualmente usam números de ponto flutuante IEEE .
Se você ler o código-fonte, verá que o formato binário over-the-wire do PostgreSQL está definido empq_sendfloat8emsrc/backend/libpq/pqformat.c, que chamapq_sendint64, que converte o valor de 8 bytes em ordem de bytes de rede (que é o mesmo que representação big-endian).
Então você teria que definir uma função de conversão semelhante a esta:
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);
}
Então seu código pode ficar assim:
Oid types[1];
double converted;
...
types[0] = FLOAT8OID;
to_nbo(value, &converted);
values[0] = (char *)&converted;
Mas, francamente, seria muito mais fácil usar a representação de texto. Isso tornará seu código independente dos componentes internos do PostgreSQL e provavelmente não será muito mais lento.
Não parece, mas se a
double precision os valores são extraídos de uma tabela PostgreSQL em outro lugar, você pode definir extra_float_digits
= 3 para que você tenha a garantia de não perder nenhuma precisão quando os valores forem convertidos em sua representação de string.