コードには2つのエラーがあります:
-
バイナリデータを送信しようとしていますが、
PQexecParamsに通知していません どのタイプか。それはうまくいきません。タイプ情報が不足しているため、PostgreSQLはタイプ
unknownを使用します 文字列として扱います。つまり、バイナリ表現はfloat8inに送られます。 文字列を倍精度値に変換する関数。これはひどく失敗します。これはおそらくあなたが観察していることです。Oid[]で4番目のパラメータを使用する必要があります 701(またはFLOAT8OIDPostgreSQLの#defineを使用したい場合 、ただし、#include <postgres.h>を実行する必要があります および<catalog/pg_type.h>そのために)。 -
PostgreSQLの
double precisionのバイナリ表現を誤って想定しています typeは、doubleのバイナリ形式です。 クライアントマシンで使用中です。プログラムが
ビッグエンディアン で実行されている場合、これは誤って機能する可能性があります。 最近のほぼすべてのアーキテクチャで IEEE浮動小数点数 が使用されているためです。 。 ソースコードを読むと、PostgreSQLの有線バイナリ形式が
pq_sendfloat8で定義されていないことがわかります。src/backend/libpq/pqformat.c内 、pq_sendint64を呼び出します 、8バイト値をネットワークバイトオーダーに変換します(これはビッグエンディアン表現と同じです)。
したがって、次のような変換関数を定義する必要があります。
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);
}
その場合、コードは次のようになります。
Oid types[1];
double converted;
...
types[0] = FLOAT8OID;
to_nbo(value, &converted);
values[0] = (char *)&converted;
しかし率直に言って、テキスト表現を使用する方がはるかに簡単です。これにより、コードがPostgreSQLの内部から独立し、おそらくそれほど遅くなることはありません。
見た目は違いますが、double precisionの場合 値は別の場所のPostgreSQLテーブルから取得されます。extra_float_digits
= 3 値が文字列表現に変換されるときに精度が失われないことが保証されます。