please! SPI_finish is strange
<style> BODY { background-color: #ffffff;} BODY, TD, TH { color: black; font-family: 占쏙옙占쏙옙; font-size: 12px; } TD { border: 0px} P { margin: 0px; } </style><P>this source is strange,</P>
<P> </P>
<P>when I <STRONG>uncomment</STRONG> <STRONG><FONT color=#0000ff>code(1)</FONT></STRONG>, and compile, and, run query</P>
<P> </P>
<P>d_cppschool=></P>
<P>SELECT * FROM UC_ExecWithNo('SELECT I_IDNum,I_UserID FROM DI_ID',10,10,3) as T(T1 int,T2 bigint,T3 CHAR(20))</P>
<P> </P>
<P>and I get result :</P>
<P> </P><XMP>WARNING: transaction left non-empty SPI stack Hint: Check for missing "SPI_finish" calls.
t1 | t2 | t3
----+----+----------------------
10 | 0 | nullid
13 | 2 | admin
16 | 1 | test
(3 rows)"
</XMP>
<P>but when I <STRONG>comment</STRONG> <STRONG><FONT color=#0000ff>code(1)</FONT></STRONG>, and compile, and, run the query</P>
<P>and I get the strange result : <STRONG>psql process die !!</STRONG></P>
<P> </P>
<P>I Don't know why.</P>
<P>Please help me to solve the problem.(Sorry, I'm not good at english speeking)</P>
<P> </P>
<P><STRONG>code(1) is "::SPI_finish()" </STRONG></P>
<P><STRONG><BR>Thank for your advices in advance.</STRONG></P>
<P><BR>The Detail is below : </P>
<P></P><XMP> 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)</XMP><XMP> SRF_RETURN_DONE(pFuncCTX);
}
//endif
}
//end Datum uc_execwithno(PG_FUNCTION_ARGS)
</XMP><br><br><table width=100% cellpadding=0 cellspacing=0 border=0><tr><td background='http://mbox10.korea.com/include_css/hanaro/dot.gif' style='height: 1px; margin: 0 0 0 0;background-repeat: repeat-x;' ></td></tr></table>
<img src="http://mbox10.korea.com/mail/PutAck.jsp?ack_args=c2VudF9maWxlPWFrYmFyQGtvcmVhLmNvbS8uU2VudC8xMTg3MjI5NDE0OTA0LjExOTAzLmtvcmVhJnNlbmRfZGF0ZT0yMDA3MDgxNjEwNTY1NCZzdWJqZWN0PXBsZWFzZSEgU1BJX2ZpbmlzaCBpcyBzdHJhbmdl&to_email=pgsql-general@postgresql.org__________________________________________________________________________________________________________________________" width="1" border="0" height="1">
"=?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