Причината, поради която psql клиентът ви пита дали желаете да се свържете отново, е, че бекендът е segfaulting, според коментарите.
Би било възможно да се събере дъмп на ядрото от такъв срив и да се изследва с дебъгер (напр. gdb), за да се установи точно къде се срива. Най-доброто ми предположение обаче е, че се срива, защото сте взели голям файл, написан като основен компонент на postgresql, компилирали сте го отделно и сте се опитали да го заредите като модул за разширение.
Файлът numeric.c съдържа огромен брой функции, статични променливи и структури от данни, от които се опитвате да дублирате само една. Всички тези функции, променливи и т.н. вече съществуват в работещата система postgresql. Когато компилирате вашата версия на numeric.c и я заредите, новата функция, която добавяте, ще препраща към функциите и променливите във вашата библиотека, вместо да използва тези в основната програма postgresql. Вероятно препраща към структури от данни, които не са правилно инициализирани, което води до срив.
Препоръчвам ви да започнете с празен файл и да копирате само функцията int2_avg_accum от numeric.c (преименувана, както сте направили). Ако тази функция извиква други функции в postgresql или препраща към променливи, тя ще използва функциите и променливите в основния двоичен файл на postgresql, което е, което искате. Можете да #включите оригиналния numeric.h, за да получите декларациите на всички външни функции.
Има някои други разлики между това как функцията е дефинирана като вътрешна функция и как трябва да бъде дефинирана, когато се зарежда като динамично зареден модул:
-
Трябваше да посочите, че използвате конвенция за извикване V1, като добавите макроса:
PG_FUNCTION_INFO_V1(int2_avg_accum2);
Ако липсва, това също ще причини segfaults, тъй като postgresql ще приеме конвенции за извикване версия 0, което не отговаря на дефиницията на функцията!
-
Както посочихте, трябва да включите 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
Използвах Postgresql 9.2 на Centos 6. Може да се наложи да коригирате пътищата си според вашата настройка.