De reden dat de psql-client vraagt of je opnieuw verbinding wilt maken, is omdat de backend segfaulting vertoont, zoals in de opmerkingen staat.
Het zou mogelijk zijn om een core dump van zo'n crash te verzamelen en deze te onderzoeken met een debugger (bijv. gdb) om erachter te komen waar hij precies crasht. Mijn beste gok is echter dat het crasht omdat je een groot bestand hebt genomen dat is geschreven als een kerncomponent van postgresql, het afzonderlijk hebt gecompileerd en hebt geprobeerd het in te laden als een uitbreidingsmodule.
Het bestand numeric.c bevat een groot aantal functies, statische variabelen en datastructuren, waarvan u er slechts één probeert te dupliceren. Al deze functies, variabelen, enz. bestaan al in het actieve postgresql-systeem. Wanneer u uw versie van numeric.c compileert en laadt, zal de nieuwe functie die u toevoegt, verwijzen naar de functies en variabelen in uw bibliotheek in plaats van die in het hoofdprogramma van postgresql te gebruiken. Het verwijst waarschijnlijk naar datastructuren die niet correct zijn geïnitialiseerd, waardoor het crasht.
Ik raad je aan te beginnen met een leeg bestand en alleen de functie int2_avg_accum van numeric.c te kopiëren (hernoemd zoals je hebt gedaan). Als die functie andere functies in postgresql aanroept, of naar variabelen verwijst, gebruikt hij de functies en variabelen in het hoofdbinaire postgresql-bestand, wat je wilt. U kunt #inclusief de originele numeric.h om de verklaringen van alle externe functies te krijgen.
Er zijn enkele andere verschillen tussen hoe de functie wordt gedefinieerd als een interne functie en hoe deze moet worden gedefinieerd wanneer deze wordt geladen als een dynamisch geladen module:
-
U moest specificeren dat u V1-aanroepconventie gebruikt door de macro toe te voegen:
PG_FUNCTION_INFO_V1(int2_avg_accum2);
Als dit ontbreekt, veroorzaakt dit ook segfaults omdat postgresql de aanroepconventies van versie 0 aanneemt, wat niet overeenkomt met de functiedefinitie!
-
Zoals je hebt aangegeven, moet je de PG_MODOULE_MAGIC toevoegen.
Het volledige bestand, dat voor mij werkte, is:
#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);
}
Samengesteld met:
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
Ik gebruikte Postgresql 9.2 op Centos 6. Mogelijk moet je je paden aanpassen aan je instellingen.