Re: improper call to spi_printtup ???

From: "Darko Prenosil" <Darko(dot)Prenosil(at)finteh(dot)hr>
To: "Tom Lane" <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: improper call to spi_printtup ???
Date: 2004-06-28 20:53:32
Message-ID: 000a01c45d52$2a4edf50$f096bfd5@darko
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Here is the source, but now when You mentioned SPI state, I see that I put
SPI_finish stupidly after SRF_RETURN_NEXT(funcctx, result);
Could that be my problem ?

Regards !

PG_FUNCTION_INFO_V1(check_view);
Datum
check_view(PG_FUNCTION_ARGS)
{
FuncCallContext *funcctx;
MemoryContext oldcontext;
int spiRet=0;
PQExpBuffer queryBuff;
void *plan=0;
char *schemaName = 0;
char *viewName = 0;
int ret = -1;

uint call_cntr;
uint max_calls;
TupleTableSlot *slot;
AttInMetadata *attinmeta;

typedef struct sqlPlanInfo{
SPITupleTable* result;
List* targetList;
} sqlPlanInfo;

if ( SRF_IS_FIRSTCALL()){

schemaName = GET_STR(PG_GETARG_TEXT_P(0));
viewName = GET_STR(PG_GETARG_TEXT_P(1));
queryBuff = createPQExpBuffer();

if (schemaName == NULL)
elog(ERROR, "schemaName not set");

if (viewName == NULL)
elog(ERROR, "viewName not set");

if (_SPI_connected >=0){
elog(NOTICE, "ALREADY CONNECTED");
spiRet = _SPI_connected;
}else{
if ((spiRet = SPI_connect()) < 0)
elog(ERROR, "rlog: SPI_connect returned %d", spiRet);
}

funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);

printfPQExpBuffer(queryBuff,
"SELECT definition"
" FROM pg_views WHERE schemaname='%s' "
" AND viewname ='%s';",schemaName,viewName
);

ret = SPI_exec(queryBuff->data,1);
if (ret == SPI_OK_SELECT){
if ( SPI_processed > 0 ){
TupleDesc tupdesc = SPI_tuptable->tupdesc;
printfPQExpBuffer(
queryBuff,
"%s",
SPI_getvalue(SPI_tuptable->vals[0],tupdesc,1)
);
}else{
elog(ERROR, "Unexisting view %s.%s", schemaName,viewName );
}
}else{
elog(ERROR, "Error executing %s", queryBuff->data );
}

plan = SPI_prepare(queryBuff->data, 0, 0);
if (!plan)
elog(ERROR, "Unable to create plan for %s", queryBuff->data );

ret = SPI_execp(plan,0, 0, 0);

if (ret < 0){
elog(ERROR, "Error executing %s", queryBuff->data );
}else{
List *raw_parsetree_list=pg_parse_query(queryBuff->data);
Node *parsetree = (Node *) lfirst(raw_parsetree_list);
List *query_list = pg_analyze_and_rewrite(parsetree,0,0);
Query *queryTree = (Query *) lfirst(query_list);
sqlPlanInfo* inf = (sqlPlanInfo*) palloc(sizeof(sqlPlanInfo));

inf->result = SPI_tuptable;
inf->targetList = queryTree->targetList;
funcctx->max_calls = inf->result->tupdesc->natts;

/*
* Generate attribute metadata needed later to produce tuples
*/
TupleDesc tupdescRes;
tupdescRes = CreateTemplateTupleDesc(18, false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 1, "attrelid",OIDOID, -1, 0,
false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 2, "attname",NAMEOID, -1, 0,
false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 3, "atttypid",OIDOID, -1, 0,
false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 4, "attstattarget",
INT4OID, -1, 0, false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 5, "attlen",INT2OID, -1, 0,
false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 6, "attnum",INT2OID, -1, 0,
false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 7, "attndims",INT4OID, -1, 0,
false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 8, "attcacheoff",INT4OID, -1,
0, false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 9, "atttypmod", INT4OID, -1,
0, false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 10, "attbyval",BOOLOID, -1,
0, false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 11, "attstorage",CHAROID, -1,
0, false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 12, "attisset", BOOLOID, -1,
0, false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 13, "attalign",CHAROID, -1,
0, false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 14, "attnotnull",BOOLOID, -1,
0, false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 15, "atthasdef", BOOLOID, -1,
0, false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 16,
"attisdropped",BOOLOID, -1, 0, false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 17, "attislocal",BOOLOID, -1,
0, false);
TupleDescInitEntry(tupdescRes, (AttrNumber) 18,
"attinhcount",INT4OID, -1, 0, false);

slot = TupleDescGetSlot(tupdescRes);
funcctx->slot = slot;
attinmeta = TupleDescGetAttInMetadata(tupdescRes);
funcctx->attinmeta = attinmeta;
funcctx->user_fctx = inf;
}

MemoryContextSwitchTo(oldcontext);
}

funcctx = SRF_PERCALL_SETUP();
call_cntr = funcctx->call_cntr;
max_calls = funcctx->max_calls;
slot = funcctx->slot;
sqlPlanInfo* inf = (sqlPlanInfo*)funcctx->user_fctx;

if (call_cntr >= funcctx->max_calls)
SRF_RETURN_DONE(funcctx);

/* Do we have a non-resjunk tlist item? */
while (inf->targetList && ((TargetEntry *)
lfirst(inf->targetList))->resdom->resjunk)
inf->targetList = lnext(inf->targetList);

char **values;
HeapTuple tuple;
Datum result;
values = (char **) palloc(18 * sizeof(char *));

if (inf->targetList){
Resdom *res = ((TargetEntry *) lfirst(inf->targetList))->resdom;
inf->result->tupdesc->attrs[call_cntr]->attrelid = res->resorigtbl;
inf->result->tupdesc->attrs[call_cntr]->attnum = res->resorigcol;
inf->targetList = lnext(inf->targetList);
}

int cols=0;
for (cols=0; cols<18;cols++){
values[cols] = (char *) palloc(256);
}

sprintf(values[0], "%i", inf->result->tupdesc->attrs[call_cntr]->attrelid);
sprintf(values[1], "%s",
inf->result->tupdesc->attrs[call_cntr]->attname.data);
sprintf(values[2],"%i",inf->result->tupdesc->attrs[call_cntr]->atttypid);

sprintf(values[3],"%i",inf->result->tupdesc->attrs[call_cntr]->attstattarget
);
sprintf(values[4],"%i",inf->result->tupdesc->attrs[call_cntr]->attlen);
sprintf(values[5],"%i",inf->result->tupdesc->attrs[call_cntr]->attnum);
sprintf(values[6],"%i",inf->result->tupdesc->attrs[call_cntr]->attndims);

sprintf(values[7],"%i",inf->result->tupdesc->attrs[call_cntr]->attcacheoff);
sprintf(values[8],"%i",inf->result->tupdesc->attrs[call_cntr]->atttypmod);
sprintf(values[9],"%i",inf->result->tupdesc->attrs[call_cntr]->attbyval);

sprintf(values[10],"%c",inf->result->tupdesc->attrs[call_cntr]->attstorage);
sprintf(values[11],"%i",inf->result->tupdesc->attrs[call_cntr]->attisset);
sprintf(values[12],"%c",inf->result->tupdesc->attrs[call_cntr]->attalign);

sprintf(values[13],"%i",inf->result->tupdesc->attrs[call_cntr]->attnotnull);
sprintf(values[14],"%i",inf->result->tupdesc->attrs[call_cntr]->atthasdef);

sprintf(values[15],"%i",inf->result->tupdesc->attrs[call_cntr]->attisdropped
);

sprintf(values[16],"%i",inf->result->tupdesc->attrs[call_cntr]->attislocal);

sprintf(values[17],"%i",inf->result->tupdesc->attrs[call_cntr]->attinhcount)
;

/* build a tuple */
tuple = BuildTupleFromCStrings(funcctx->attinmeta, values);
/* make the tuple into a datum */
result = TupleGetDatum(slot, tuple);
SRF_RETURN_NEXT(funcctx, result);

SPI_finish();
}

----- Original Message -----
From: "Tom Lane" <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: "Darko Prenosil" <darko(dot)prenosil(at)finteh(dot)hr>
Cc: <pgsql-hackers(at)postgresql(dot)org>
Sent: Monday, June 28, 2004 9:39 PM
Subject: Re: [HACKERS] improper call to spi_printtup ???

> Darko Prenosil <darko(dot)prenosil(at)finteh(dot)hr> writes:
> > Anyone knows what I'm doing wrong ?
>
> Well, when you didn't show us the text of the function, no.
>
> However, a reasonable bet would be that you used SPI inside the function
> and did not use it correctly, leaving the SPI state corrupted when
> control got back to plpgsql.
>
> regards, tom lane
>
> ---------------------------(end of broadcast)---------------------------
> TIP 7: don't forget to increase your free space map settings
>

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Jeff Keller 2004-06-28 22:59:11 Capacity Planning: Repost from pgsql-admin
Previous Message Marc Röttig 2004-06-28 20:50:53 Survey: "Motivation of Free/Open Source Software (F/OSS) Developers"