sql >> Database >  >> RDS >> PostgreSQL

Maak een kopie van de interne C-functie van PostgreSQL en laad deze als een door de gebruiker gedefinieerde functie

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.




  1. PostgreSQL uitvoeren met Amazon RDS

  2. Redundante externe sleutels opslaan om joins te voorkomen

  3. HBase-tabel exporteren naar mysql

  4. Verplaats knoop in geneste set