please! SPI_finish is strange

Started by 서기석over 18 years ago2 messagesgeneral
Jump to latest
#1서기석
akbar@korea.com

<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>&nbsp;</P>
<P>when I <STRONG>uncomment</STRONG> <STRONG><FONT color=#0000ff>code(1)</FONT></STRONG>, and compile, and, run query</P>
<P>&nbsp;</P>
<P>d_cppschool=&gt;</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>&nbsp;</P>
<P>and I get result :</P>
<P>&nbsp;</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 :&nbsp; <STRONG>psql process die !!</STRONG></P>
<P>&nbsp;</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>&nbsp;</P>
<P><STRONG>code(1) is "::SPI_finish()" </STRONG></P>
<P><STRONG><BR>Thank for your&nbsp;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&#39; 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&amp;to_email=pgsql-general@postgresql.org__________________________________________________________________________________________________________________________&quot; width="1" border="0" height="1">

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: 서기석 (#1)
Re: please! SPI_finish is strange

"=?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