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" <[EMAIL PROTECTED]>
To: "Darko Prenosil" <[EMAIL PROTECTED]>
Cc: <[EMAIL PROTECTED]>
Sent: Monday, June 28, 2004 9:39 PM
Subject: Re: [HACKERS] improper call to spi_printtup ???


> Darko Prenosil <[EMAIL PROTECTED]> 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
>


---------------------------(end of broadcast)---------------------------
TIP 3: if posting/reading through Usenet, please send an appropriate
      subscribe-nomail command to [EMAIL PROTECTED] so that your
      message can get through to the mailing list cleanly

Reply via email to