sql >> データベース >  >> RDS >> PostgreSQL

libpqを使用してテーブルに浮動小数点数を挿入する

    コードには2つのエラーがあります:

    • バイナリデータを送信しようとしていますが、PQexecParamsに通知していません どのタイプか。

      それはうまくいきません。タイプ情報が不足しているため、PostgreSQLはタイプunknownを使用します 文字列として扱います。つまり、バイナリ表現はfloat8inに送られます。 文字列を倍精度値に変換する関数。これはひどく失敗します。これはおそらくあなたが観察していることです。

      Oid[]で4番目のパラメータを使用する必要があります 701(またはFLOAT8OID PostgreSQLの#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 *)&in;
        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 値が文字列表現に変換されるときに精度が失われないことが保証されます。




    1. mysqlは同じnow()で複数の列を更新します

    2. トランザクションとして多くのSQLクエリを実行するにはどうすればよいですか?

    3. mysql親に関する子行の総数を見つける方法

    4. Linuxサーバー上のMySQLデータベースを自動的にバックアップします