Thread: please! SPI_finish is strange

please! SPI_finish is strange

From
"서기석"
Date:

this source is strange,

 

when I uncomment code(1), and compile, and, run query

 

d_cppschool=>

SELECT * FROM UC_ExecWithNo('SELECT I_IDNum,I_UserID FROM DI_ID',10,10,3) as T(T1 int,T2 bigint,T3 CHAR(20))

 

and I get result :

 

WARNING: transaction left non-empty SPI stack Hint: Check for missing "SPI_finish" calls.t1 | t2 | t3 ----+----+----------------------10 | 0 | nullid13 | 2 | admin16 | 1 | test(3 rows)"

but when I comment code(1), and compile, and, run the query

and I get the strange result :  psql process die !!

 

I Don't know why.

Please help me to solve the problem.(Sorry, I'm not good at english speeking)

 

code(1) is "::SPI_finish()"


Thank for your advices in advance.


The Detail is below :

PG_FUNCTION_INFO_V1(uc_execwithno); // add no field to table Datum uc_execwithno(PG_FUNCTION_ARGS) { class CMyData // context { public: SPITupleTable* GP_TupleTable; int /********/ GI_FieldCount; int /********/ GI_StartNum ; CMyData() { GP_TupleTable=0; GI_FieldCount=0; GI_StartNum =0; } //end CMyData() }; //end class CMyData if(GB_DoShowInfoLog==true) elog(INFO, "UC_ExecWithNo Start"); //endif text* pQuery_T=PG_GETARG_TEXT_P(0); int AI_LimitCnt=PG_GETARG_INT32 (1); int AI_StartNum=PG_GETARG_INT32 (2); int AI_SkipNum =PG_GETARG_INT32 (3); int VI_AttCnt =0; CMyData* pCMyData =0; TupleDesc pTupleDesc ; SPITupleTable* pTupleTable; TupleDesc TupDescNew ; MemoryContext OldContext ; AttInMetadata* pAttInMeta ; FuncCallContext* pFuncCTX ; if (SRF_IS_FIRSTCALL()) { char* AP_Query=NsPgsql::NewAlloc(pQuery_T); int VI_Result=0; int VI_RowCnt=0; pFuncCTX = SRF_FIRSTCALL_INIT(); OldContext = ::MemoryContextSwitchTo(pFuncCTX->multi_call_memory_ctx); if ((VI_Result = ::SPI_connect()) < 0) { /* internal error */ elog(ERROR, "internal error : ISPI_connect returned =%d", VI_Result); SRF_RETURN_DONE(pFuncCTX); } //endif VI_Result=::SPI_execute(AP_Query,true/*AB_DoReadOnly*/,AI_LimitCnt); VI_RowCnt=::SPI_processed ; pfree(AP_Query); if(VI_Result!=SPI_OK_SELECT || VI_RowCnt<1) { ::SPI_finish(); SRF_RETURN_DONE(pFuncCTX); } else { pFuncCTX->max_calls=VI_RowCnt ; pTupleTable = ::SPI_tuptable; pTupleDesc = ::SPI_tuptable->tupdesc; VI_AttCnt=pTupleDesc->natts; } //endif TupDescNew = ::CreateTemplateTupleDesc(VI_AttCnt+1, false/*bool hasoid*/); ::TupleDescInitEntry(TupDescNew, 1/*attnum*/, "no"/*attname*/, INT4OID/*oidtypeid*/,-1/*typmod*/, 0/*attdim*/); FormData_pg_attribute* pFormDataAtt; for(int i=1;i<=VI_AttCnt;++i) { pFormDataAtt=pTupleDesc->attrs[i-1]; // cf) char* SPI_fname(TupleDesc rowdesc, int colnumber) ::TupleDescInitEntry(TupDescNew, (AttrNumber)(i+1), SPI_fname(pTupleDesc,i), pFormDataAtt->atttypid,pFormDataAtt->atttypmod, pFormDataAtt->attndims); } //endfor // generate attribute metadata needed later to produce tuples from raw pAttInMeta = ::TupleDescGetAttInMetadata(TupDescNew); pFuncCTX->attinmeta = pAttInMeta; /* Save spi data for use across calls */ CMyData* pCMyData=(CMyData*)palloc(sizeof(CMyData)); pCMyData->GP_TupleTable=pTupleTable ; pCMyData->GI_FieldCount=VI_AttCnt ; pCMyData->GI_StartNum =AI_StartNum ; pFuncCTX->user_fctx=pCMyData ; ::MemoryContextSwitchTo(OldContext); } //end if (SRF_IS_FIRSTCALL()) pFuncCTX = SRF_PERCALL_SETUP(); pAttInMeta = pFuncCTX->attinmeta; pCMyData =(CMyData*)(pFuncCTX->user_fctx); VI_AttCnt =pCMyData->GI_FieldCount; pTupleTable =pCMyData->GP_TupleTable; AI_StartNum =pCMyData->GI_StartNum ; pTupleDesc =pTupleTable->tupdesc ; pCMyData->GI_StartNum += AI_SkipNum ; if (pFuncCTX->call_cntr < pFuncCTX->max_calls) { if(GB_DoShowInfoLog==true) elog(INFO, "UC_ExecWithNo Call Num=%d",pFuncCTX->call_cntr); //endif char** ppValues ; HeapTuple TupleNewObj ; Datum DatumResult ; const int CI_IntAllocLen=12; ppValues = (char **)palloc((VI_AttCnt+1) * sizeof(char *)); ppValues[0] = (char *) palloc(CI_IntAllocLen * sizeof(char)); ::snprintf(ppValues[0], CI_IntAllocLen, "%d", AI_StartNum); HeapTuple TupleObj = pTupleTable->vals[pFuncCTX->call_cntr]; for(int i=1;i<=VI_AttCnt;++i) { ppValues[i]=::SPI_getvalue(TupleObj, pTupleDesc, i); } //endfor TupleNewObj = BuildTupleFromCStrings(pAttInMeta, ppValues); /* build a tuple */ DatumResult = HeapTupleGetDatum(TupleNewObj); /* make the tuple into a datum */ pfree(ppValues[0]); pfree(ppValues); ::SPI_freetuple(TupleObj); SRF_RETURN_NEXT(pFuncCTX, DatumResult); } else { pfree(pCMyData); // ::SPI_finish(); // code(1) SRF_RETURN_DONE(pFuncCTX); } //endif } //end Datum uc_execwithno(PG_FUNCTION_ARGS)

Re: please! SPI_finish is strange

From
Tom Lane
Date:
"=?EUC-KR?B?vK2x4ryu?="<akbar@korea.com> writes:
> <P>Please help me to solve the problem.(Sorry, I'm not good at english speeking)</P>

This code has no chance of working --- you cannot hold an SPI context
open across multiple calls to an SRF.  Run the SPI query to completion
during the FIRSTCALL setup, and stash the results someplace safe.

            regards, tom lane