Há dois erros no seu código:
-
Você está tentando enviar dados binários, mas não informaPQexecParams
que tipo é.
Isso não pode funcionar. Na falta de informações de tipo, o PostgreSQL usará o tipounknown
e tratá-lo como string. Isso significa que sua representação binária será alimentada nofloat8in
funçã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 (ouFLOAT8OID
se você preferir usar o#define
do 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 precision
type é o formato binário paradouble
em 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_sendfloat8
emsrc/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.