PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Buat salinan fungsi C internal PostgreSQL dan muat sebagai fungsi yang ditentukan pengguna

Alasan klien psql menanyakan apakah Anda ingin menyambung kembali adalah karena backend segfaulting, sesuai dengan komentar.

Dimungkinkan untuk mengumpulkan dump inti dari crash seperti itu dan memeriksanya dengan debugger (mis. gdb) untuk mengetahui dengan tepat di mana ia mogok. Namun, tebakan terbaik saya adalah itu mogok karena Anda telah mengambil file besar yang ditulis sebagai komponen inti dari postgresql, mengompilasinya secara terpisah, dan mencoba memuatnya sebagai modul ekstensi.

File numeric.c berisi sejumlah besar fungsi, variabel statis, dan struktur data, di mana Anda mencoba untuk menduplikasi hanya satu. Semua fungsi, variabel, dll ini sudah ada di sistem postgresql yang sedang berjalan. Saat Anda mengkompilasi versi numeric.c dan memuatnya, fungsi baru yang Anda tambahkan akan merujuk fungsi dan variabel di perpustakaan Anda alih-alih menggunakan yang ada di program postgresql utama. Ini mungkin merujuk pada struktur data yang tidak diinisialisasi dengan benar, yang menyebabkannya mogok.

Saya sarankan Anda memulai dengan file kosong dan menyalin hanya fungsi int2_avg_accum dari numeric.c (diganti namanya seperti yang telah Anda lakukan). Jika fungsi itu memanggil fungsi lain di postgresql, atau variabel referensi, itu akan menggunakan fungsi dan variabel dalam biner postgresql utama, yang Anda inginkan. Anda dapat #menyertakan numeric.h asli untuk mendapatkan deklarasi semua fungsi eksternal.

Ada beberapa perbedaan lain antara bagaimana fungsi didefinisikan sebagai fungsi internal dan bagaimana fungsi itu perlu didefinisikan saat dimuat sebagai modul yang dimuat secara dinamis:

  • Anda perlu menentukan bahwa Anda menggunakan konvensi pemanggilan V1 dengan menambahkan makro:

    PG_FUNCTION_INFO_V1(int2_avg_accum2);

    Jika tidak ada, ini juga akan menyebabkan segfault karena postgresql akan mengasumsikan konvensi pemanggilan versi 0, yang tidak cocok dengan definisi fungsi!

  • Seperti yang Anda tunjukkan, Anda harus menyertakan PG_MODOULE_MAGIC.

File lengkap, yang berhasil untuk saya, adalah:

#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);
}

Disusun dengan:

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

Saya menggunakan Postgresql 9.2 di Centos 6. Anda mungkin perlu menyesuaikan jalur Anda sesuai dengan pengaturan Anda.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Bagaimana cara memulai kembali penghitungan id pada tabel di PostgreSQL setelah menghapus beberapa data sebelumnya?

  2. CASCADE DELETE sekali saja

  3. sqlalchemy beberapa kunci asing ke tabel yang sama

  4. org.postgresql.util.PSQLException:ERROR:tidak dapat membuat serial akses karena dependensi baca/tulis di antara transaksi

  5. pgAdmin III :Tidak ada server yang muncul