please! SPI_finish is strange - Mailing list pgsql-general

From 서기석
Subject please! SPI_finish is strange
Date
Msg-id 1187229419451076.0.outsmtp04@outsmtp04
Whole thread Raw
Responses Re: please! SPI_finish is strange  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-general

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)

pgsql-general by date:

Previous
From: "Trevor Talbot"
Date:
Subject: Re: Writing most code in Stored Procedures
Next
From: "D. Dante Lorenso"
Date:
Subject: Re: SELECT ... FOR UPDATE performance costs? alternatives?