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

PostgreSQL内部C関数のコピーを作成し、ユーザー定義関数としてロードします

    コメントに従って、psqlクライアントが再接続するかどうかを尋ねる理由は、バックエンドがセグフォールトしているためです。

    このようなクラッシュからコアダンプを収集し、デバッガー(gdbなど)で調べて、クラッシュしている場所を正確に見つけることができます。ただし、postgresqlのコアコンポーネントとして書き込まれた大きなファイルを取得し、個別にコンパイルして、拡張モジュールとしてロードしようとしたため、クラッシュしていると推測されます。

    ファイルnumeric.cには、膨大な数の関数、静的変数、およびデータ構造が含まれていますが、そのうちの1つだけを複製しようとしています。これらの関数、変数などはすべて、実行中のpostgresqlシステムにすでに存在します。あなたがnumeric.cのバージョンをコンパイルしてそれをロードするとき、あなたが追加する新しい関数は、メインのpostgresqlプログラムでそれらを使用する代わりに、あなたのライブラリーの関数と変数を参照するでしょう。正しく初期化されていないデータ構造を参照している可能性があり、クラッシュを引き起こしています。

    空のファイルから始めて、numeric.cからint2_avg_accum関数のみをコピーすることをお勧めします(これまでと同じように名前を変更しました)。その関数がpostgresql内の他の関数を呼び出している場合、または変数を参照している場合は、メインのpostgresqlバイナリ内の関数と変数を使用します。これは必要なものです。元のnumeric.hを#includeして、すべての外部関数の宣言を取得できます。

    関数を内部関数として定義する方法と、動的にロードされるモジュールとしてロードするときに定義する必要がある方法には、他にもいくつかの違いがあります。

    • マクロを追加して、V1呼び出し規約を使用していることを指定する必要がありました:

      PG_FUNCTION_INFO_V1(int2_avg_accum2);

      欠落している場合、postgresqlは関数定義と一致しないバージョン0の呼び出し規約を想定するため、これもsegfaultsを引き起こします!

    • あなたが示したように、PG_MODOULE_MAGICを含める必要があります。

    私のために働いた完全なファイルは次のとおりです:

    #include "postgres.h"
    #include "fmgr.h"
    #include "utils/array.h"
    
    #ifdef PG_MODULE_MAGIC
    PG_MODULE_MAGIC;
    #endif
    
    typedef struct Int8TransTypeData
    {
        int64       count;
        int64       sum;
    } Int8TransTypeData;
    
    PG_FUNCTION_INFO_V1(int2_avg_accum2);
    
    Datum
    int2_avg_accum2(PG_FUNCTION_ARGS)
    {
        ArrayType  *transarray;
        int16       newval = PG_GETARG_INT16(1);
        Int8TransTypeData *transdata;
    
        /*
         * If we're invoked as an aggregate, we can cheat and modify our first
         * parameter in-place to reduce palloc overhead. Otherwise we need to make
         * a copy of it before scribbling on it.
         */
        if (AggCheckCallContext(fcinfo, NULL))
            transarray = PG_GETARG_ARRAYTYPE_P(0);
        else
            transarray = PG_GETARG_ARRAYTYPE_P_COPY(0);
    
        if (ARR_HASNULL(transarray) ||
            ARR_SIZE(transarray) != ARR_OVERHEAD_NONULLS(1) + sizeof(Int8TransTypeData))
            elog(ERROR, "expected 2-element int8 array");
    
        transdata = (Int8TransTypeData *) ARR_DATA_PTR(transarray);
        transdata->count++;
        transdata->sum += newval;
    
        PG_RETURN_ARRAYTYPE_P(transarray);
    }
    

    コンパイル済み:

    gcc -I/usr/pgsql-9.2/include/server -fPIC -c my_avg_accum.c
    gcc -shared -o my_avg_accum.so my_avg_accum.o
    

    Centos6でPostgresql9.2を使用していました。セットアップに応じてパスを調整する必要がある場合があります。




    1. 1つのgroup-byからのSQL2つの基準

    2. 自動インクリメントを2番目の列に挿入します

    3. eclipselinkJTAシーケンス接続プールを構成する方法

    4. SQLデータ操作言語