Ada dua kesalahan dalam kode Anda:
-
Anda mencoba mengirim data biner, tetapi Anda tidak memberi tahu
PQexecParams
jenis apa itu.Itu tidak bisa bekerja. Kurangnya informasi jenis, PostgreSQL akan menggunakan jenis
unknown
dan memperlakukannya sebagai string. Itu berarti representasi biner Anda akan diumpankan kefloat8in
fungsi yang mengubah string menjadi nilai presisi ganda, yang akan gagal total. Ini mungkin yang Anda amati.Anda harus menggunakan parameter keempat dengan
Oid[]
yang berisi 701 (atauFLOAT8OID
jika Anda lebih suka menggunakan#define
PostgreSQL , tetapi Anda harus#include <postgres.h>
dan<catalog/pg_type.h>
untuk itu). -
Anda keliru berasumsi bahwa representasi biner PostgreSQL dari
double precision
type adalah format biner untukdouble
sedang digunakan di mesin klien Anda.Ini mungkin tidak sengaja bekerja jika program Anda berjalan pada big-endian mesin, karena hampir setiap arsitektur saat ini menggunakan nomor floating point IEEE .
Jika Anda membaca kode sumber, Anda akan menemukan bahwa format biner over-the-wire PostgreSQL didefinisikan dalam
pq_sendfloat8
disrc/backend/libpq/pqformat.c
, yang memanggilpq_sendint64
, yang mengubah nilai 8-byte menjadi urutan byte jaringan (yang sama dengan representasi big-endian).
Jadi, Anda harus mendefinisikan fungsi konversi yang mirip dengan ini:
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);
}
Maka kode Anda akan terlihat seperti ini:
Oid types[1];
double converted;
...
types[0] = FLOAT8OID;
to_nbo(value, &converted);
values[0] = (char *)&converted;
Tapi terus terang, akan jauh lebih mudah menggunakan representasi teks. Itu akan membuat kode Anda independen dari internal PostgreSQL dan mungkin tidak jauh lebih lambat.
Tidak terlihat seperti itu, tetapi jika double precision
nilai ditarik dari tabel PostgreSQL di tempat lain, Anda dapat mengatur extra_float_digits
= 3
sehingga Anda dijamin tidak akan kehilangan presisi saat nilai dikonversi ke representasi string..