SRF's + SPI - Mailing list pgsql-hackers

From Eric B.Ridge
Subject SRF's + SPI
Date
Msg-id da7c7eb07f7d2f295e53b936ecf07983@tcdi.com
Whole thread Raw
Responses Re: SRF's + SPI  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers
With pg v7.4.7 I've written an SRF that uses SPI to return the results 
of a query.  It's one of those functions that works perfectly for me in 
development but randomly crashes in production.  Thus far I've been 
unable to reproduce the crash.  The problem is surely in my code.  And 
before I dig into debugging the hard stuff I would love a sanity check 
to verify that I'm using SPI_connect()/SPI_finish() correctly within 
the context of the SRF.

The backtrace from a core dump:
(gdb) bt
#0  0x0820ee29 in pfree ()
#1  0x08204a18 in end_MultiFuncCall ()
#2  0x4cee0f99 in my_src (fcinfo=0xbfffccd0) at foo.c:93
#3  0x0811058b in ExecMakeTableFunctionResult ()
#4  0x08750c78 in ?? ()
#5  0x00004000 in ?? ()
#6  0xbfffccac in ?? ()
#7  0xbfffcd88 in ?? ()

And the code at foo.c:93SRF_RETURN_DONE(funcctx);

I'm wondering if I'm using SPI incorrectly.  In the past I've had 
issues with incorrectly using SPI (esp with recursion), and I'm not 
entirely sure how it should work with SRF's.  Like I said, everything 
usually works without problems, but from time to time it crashes.  
Below is the basic outline of my code.

Any input will be greatly appreciated.

thanks!

eric

------------------------------
Datum my_srf (PG_FUNCTION_ARGS) {FuncCallContext    *funcctx;
        if (SRF_IS_FIRSTCALL()) {            MemoryContext oldcontext;    char *query;
    if(PG_ARGISNULL(0))        SRF_RETURN_DONE(NULL);  /* nothing to expand when arg[0] is null */
    funcctx = SRF_FIRSTCALL_INIT();
                oldcontext = 
MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
    query = < function call to build a query string >;
    SPI_connect();    if (SPI_exec(query, 0) != SPI_OK_SELECT)        elog(ERROR, "unable to execute fulltext query");
    funcctx->slot = TupleDescGetSlot(SPI_tuptable->tupdesc);    funcctx->attinmeta =
TupleDescGetAttInMetadata(SPI_tuptable->tupdesc);   funcctx->user_fctx = SPI_tuptable;    funcctx->call_cntr = 0;
funcctx->max_calls= SPI_processed;
 
                 MemoryContextSwitchTo(oldcontext);        }
funcctx = SRF_PERCALL_SETUP();
        if (funcctx->call_cntr < funcctx->max_calls) {    SPITupleTable *tuptable = (SPITupleTable *)
funcctx->user_fctx;   HeapTuple tuple;    Datum result;
 
    tuple = tuptable->vals[funcctx->call_cntr];    result = TupleGetDatum(funcctx->slot, tuple);
    SRF_RETURN_NEXT(funcctx, result);        } else {    SPI_finish();
line_93:                SRF_RETURN_DONE(funcctx);  /** XXX: CRASH HERE **/}
PG_RETURN_NULL();
}



pgsql-hackers by date:

Previous
From: "Andrew Dunstan"
Date:
Subject: Re: ARC patent
Next
From: "Mark Woodward"
Date:
Subject: Re: ARC patent