Hay dos errores en su código:
-
Está intentando enviar datos binarios, pero no le dice a
PQexecParams
de qué tipo es.Eso no puede funcionar. Al carecer de información de tipo, PostgreSQL utilizará el tipo
unknown
y trátelo como una cadena. Eso significa que su representación binaria se alimentará alfloat8in
función que convierte cadenas en valores de doble precisión, lo que fallará horriblemente. Esto es probablemente lo que estás observando.Tendrá que usar un cuarto parámetro con un
Oid[]
que contiene 701 (oFLOAT8OID
si prefiere usar#define
de PostgreSQL , pero tendría que#include <postgres.h>
y<catalog/pg_type.h>
por eso). -
Asumes erróneamente que la representación binaria de PostgreSQL de la
double precision
type es el formato binario paradouble
en uso en su máquina cliente.Esto podría funcionar accidentalmente si su programa se ejecuta en un big-endian máquina, ya que prácticamente todas las arquitecturas en estos días usan números de coma flotante IEEE .
Si lee el código fuente, encontrará que el formato binario over-the-wire de PostgreSQL está definido en
pq_sendfloat8
ensrc/backend/libpq/pqformat.c
, que llama apq_sendint64
, que convierte el valor de 8 bytes en orden de bytes de red (que es lo mismo que la representación big-endian).
Entonces tendría que definir una función de conversión similar 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);
}
Entonces su código podría verse así:
Oid types[1];
double converted;
...
types[0] = FLOAT8OID;
to_nbo(value, &converted);
values[0] = (char *)&converted;
Pero, francamente, sería mucho más fácil usar la representación de texto. Eso hará que su código sea independiente de las partes internas de PostgreSQL y probablemente no sea mucho más lento.
No lo parece, pero si la double precision
los valores se extraen de una tabla de PostgreSQL en otro lugar, puede configurar extra_float_digits
= 3
para que tenga la garantía de no perder precisión cuando los valores se conviertan a su representación de cadena..