Skip site navigation (1) Skip section navigation (2)

SRF's + SPI

From: Eric B(dot)Ridge <ebr(at)tcdi(dot)com>
To: pgsql-hackers(at)postgresql(dot)org
Subject: SRF's + SPI
Date: 2005-04-01 18:25:21
Message-ID: da7c7eb07f7d2f295e53b936ecf07983@tcdi.com (view raw or flat)
Thread:
Lists: 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:93
	SRF_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();
}


Responses

pgsql-hackers by date

Next:From: Mark WoodwardDate: 2005-04-01 18:50:35
Subject: Re: ARC patent
Previous:From: Andrew DunstanDate: 2005-04-01 17:11:39
Subject: Re: ARC patent

Privacy Policy | About PostgreSQL
Copyright © 1996-2014 The PostgreSQL Global Development Group