Lý do ứng dụng khách psql hỏi bạn có muốn kết nối lại hay không là vì chương trình phụ trợ đang mặc định, theo các nhận xét.
Có thể thu thập một kết xuất cốt lõi từ một sự cố như vậy và kiểm tra nó bằng trình gỡ lỗi (ví dụ:gdb) để tìm ra chính xác nơi nó đang gặp sự cố. Tuy nhiên, dự đoán tốt nhất của tôi là nó bị lỗi vì bạn đã lấy một tệp lớn được viết để làm thành phần cốt lõi của postgresql, biên dịch nó thành một cách riêng biệt và cố gắng tải nó vào dưới dạng một mô-đun mở rộng.
Tệp numeric.c chứa một số lượng lớn các hàm, biến tĩnh và cấu trúc dữ liệu mà bạn chỉ đang cố gắng sao chép một trong số đó. Tất cả các hàm, biến, v.v. này đã tồn tại trong hệ thống postgresql đang chạy. Khi bạn biên dịch phiên bản numeric.c của mình và tải nó, hàm mới bạn đang thêm sẽ tham chiếu đến các hàm và biến trong thư viện của bạn thay vì sử dụng chúng trong chương trình postgresql chính. Nó có thể đang tham chiếu đến cấu trúc dữ liệu không được khởi tạo đúng cách, khiến nó gặp sự cố.
Tôi khuyên bạn nên bắt đầu với một tệp trống và chỉ sao chép trong hàm int2_avg_accum từ numeric.c (đã đổi tên như bạn đã thực hiện). Nếu hàm đó đang gọi các hàm khác trong postgresql hoặc các biến tham chiếu, nó sẽ sử dụng các hàm và biến trong nhị phân postgresql chính, đó là những gì bạn muốn. Bạn có thể #include numeric.h ban đầu để nhận khai báo của tất cả các hàm bên ngoài.
Có một số khác biệt khác giữa cách hàm được định nghĩa như một hàm bên trong và cách nó cần được xác định khi được tải dưới dạng mô-đun được tải động:
-
Bạn cần xác định rằng bạn đang sử dụng quy ước gọi V1 bằng cách thêm macro:
PG_FUNCTION_INFO_V1 (int2_avg_accum2);
Nếu thiếu điều này cũng sẽ gây ra giá trị mặc định vì postgresql sẽ giả sử các quy ước gọi phiên bản 0, không khớp với định nghĩa hàm!
-
Như bạn đã chỉ ra, bạn phải bao gồm PG_MODOULE_MAGIC.
Tệp hoàn chỉnh, phù hợp với tôi, là:
#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);
}
Tổng hợp với:
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
Tôi đang sử dụng Postgresql 9.2 trên Centos 6. Bạn có thể cần phải điều chỉnh đường dẫn theo thiết lập của mình.