Re: SPI_connect

From: Yessica Brinkmann <yessica(dot)brinkmann(at)gmail(dot)com>
To: Enrique Herrera Noya <enrique(dot)herreranoya(at)gmail(dot)com>
Cc: folarte(at)peoplecall(dot)com, Postgres Español <pgsql-es-ayuda(at)postgresql(dot)org>
Subject: Re: SPI_connect
Date: 2019-09-17 23:16:55
Message-ID: CABrYqSNSqrTVO4Mu2+9rSY0QUNaAL96kEbUOixO+FhnNJWi7-A@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-es-ayuda

Si me pueden ayudar por favor por lo menos para poder encontrar el log de
Postgresql, para ir buscando el error. La versión de Postgresql que tengo
es la 8.3.23. Uso versión debido a que sólo con esta versión me funciona el
Index Adviser.
Saludos cordiales,
Yessica

El mar., 17 sept. 2019 15:19, Yessica Brinkmann <yessica(dot)brinkmann(at)gmail(dot)com>
escribió:

> Buenas tardes,
> Estuve haciendo algunas verificaciones y lastimosamente pude darme cuenta
> de que luego de ejecutar el Index Adviser básicamente no me aparece nada en
> el directorio /var/log/postgresql, es decir dicho directorio aparece vacío,
> sin ningún archivo. Realmente veo que dicho directorio existe, sin embargo
> luego de levantar el servidor Postgresql y ejecutar el Index Adviser me
> aparece vacío, no hay allí ningún archivo de log. No sé a qué se deberá
> esto realmente. Como les comentaba, no soy buena usando Linux, pero me veo
> obligada a usarlo.
> Por otro lado, hice un diagrama de la estructura del Index Adviser, que es
> simplemente un gráfico explicativo de lo que dice el readme del Index
> Adviser. Adjunto a este mail como documento .pdf, para que no sea
> muy pesado, ya que según me habían dicho las imágenes son muy pesadas para
> anexarlas a los mails.
> Finalmente, copio el código fuente de la función que contiene el Insert
> que funciona con el SPI_connect(), y a continuación, las dos funciones que
> yo estoy intentando escribir, que tienen Selects, y con las cuales obtengo
> el SPI_ERROR_CONNECT.
> Saludos cordiales,
> Yessica
> /**
> * save_advice
> * for every candidate insert an entry into IND_ADV_TABL
> */
> static void
> save_advice( List* candidates )
> {
> StringInfoData query; /* string for Query */
> StringInfoData cols; /* string for Columns */
> Oid advise_oid;
> ListCell *cell;
>
> elog( DEBUG3, "IND ADV: save_advice: ENTER" );
>
> Assert( list_length(candidates) != 0 );
>
> /*
> * Minimal check: check that IND_ADV_TABL is at least visible to us. There
> * are a lot more checks we should do in order to not let the INSERT fail,
> * like permissions, datatype mis-match, etc., but we leave those checks
> * upto the executor.
> */
>
> /* find a relation named IND_ADV_TABL on the search path */
> advise_oid = RelnameGetRelid( IND_ADV_TABL );
>
> if (advise_oid != InvalidOid)
> {
> #if 1
> Relation advise_rel = relation_open(advise_oid, AccessShareLock);
>
> if (advise_rel->rd_rel->relkind != RELKIND_RELATION
> && advise_rel->rd_rel->relkind != RELKIND_VIEW)
> {
> relation_close(advise_rel, AccessShareLock);
>
> /* FIXME: add errdetail() and/or errcontext() calls here. */
> ereport(ERROR,
> (errcode(ERRCODE_WRONG_OBJECT_TYPE),
> errmsg( IND_ADV_ERROR_NTV )));
> }
>
> relation_close(advise_rel, AccessShareLock);
> #else
> /*
> * heap_open() makes sure that the oid does not represent an INDEX or a
> * COMPOSITE type, else it will raise an ERROR, which is exactly what we
> * want. The comments above heap_open() ask the caller not to assume any
> * storage since the returned relation may be a VIEW; but we don't mind,
> * since the user may have defined some rules on it to make the INSERTs
> * work smoothly! If not, we leave it upto the executor to raise ERROR.
> */
> PG_TRY();
> {
> heap_close(heap_open(advise_oid, AccessShareLock), AccessShareLock);
> }
> PG_CATCH();
> {
> errmsg( IND_ADV_ERROR_NTV );
> PG_RE_THROW();
> }
> PG_END_TRY();
> #endif
> }
> else
> {
> /* FIXME: add errdetail() and/or errcontext() calls here. */
> ereport(ERROR,
> (errcode(ERRCODE_UNDEFINED_TABLE),
> errmsg( IND_ADV_ERROR_NE )));
> }
>
> initStringInfo( &query );
> initStringInfo( &cols );
>
> foreach( cell, candidates )
> {
> int i;
> IndexCandidate* idxcd = (IndexCandidate*)lfirst( cell );
>
> if( !idxcd->idxused )
> continue;
>
> /* pfree() the memory allocated for the previous candidate. FIXME: Avoid
> * meddling with the internals of a StringInfo, and try to use an API.
> */
> if( cols.len > 0 )
> {
> pfree( cols.data );
> cols.data = NULL;
> }
>
> initStringInfo( &cols );
>
> for (i = 0; i < idxcd->ncols; ++i)
> appendStringInfo( &cols, "%s%d", (i>0?",":""), idxcd->varattno[i]);
>
> /* FIXME: Mention the column names explicitly after the table name. */
> appendStringInfo( &query, "insert into \""IND_ADV_TABL"\" values"
> "( %d, array[%s], %f, %d, %d, now());",
> idxcd->reloid,
> cols.data,
> idxcd->benefit,
> idxcd->pages * BLCKSZ/1024, /* in KBs */
> MyProcPid );
> } /* foreach cell in candidates */
>
> if( query.len > 0 ) /* if we generated any SQL */
> {
> if( SPI_connect() == SPI_OK_CONNECT )
> {
> if( SPI_execute( query.data, false, 0 ) != SPI_OK_INSERT )
> elog( WARNING, "IND ADV: SPI_execute failed while saving advice." );
>
> if( SPI_finish() != SPI_OK_FINISH )
> elog( WARNING, "IND ADV: SPI_finish failed while saving advice." );
> }
> else
> elog( WARNING, "IND ADV: SPI_connect failed while saving advice." );
> }
>
> /* TODO: Propose to -hackers to introduce API to free a StringInfoData . */
> if ( query.len > 0 )
> pfree( query.data );
>
> if ( cols.len > 0 )
> pfree( cols.data );
>
> elog( DEBUG3, "IND ADV: save_advice: EXIT" );
> }
>
>
> /**
> * get_distinct
> * for every candidate get an entry into IndexCandidate
> */
> static void
> get_ndistinct( List* candidates )
> {
> int proc;
> StringInfoData query; /* string for Query */
> StringInfoData cols; /* string for Columns */
> Oid advise_oid;
> ListCell *cell;
>
> SPITupleTable *SPI_tuptable;
>
> TupleDesc tupdesc;
>
>
> elog( DEBUG3, "IND ADV: get_distinct: ENTER" );
>
> Assert( list_length(candidates) != 0 );
>
> /*
> * Minimal check: check that IND_ADV_TABL is at least visible to us. There
> * are a lot more checks we should do in order to not let the INSERT fail,
> * like permissions, datatype mis-match, etc., but we leave those checks
> * upto the executor.
> */
>
> /* find a relation named IND_ADV_TABL on the search path */
> advise_oid = RelnameGetRelid( IND_ADV_TABL );
>
> if (advise_oid != InvalidOid)
> {
> #if 1
> Relation advise_rel = relation_open(advise_oid, AccessShareLock);
>
> if (advise_rel->rd_rel->relkind != RELKIND_RELATION
> && advise_rel->rd_rel->relkind != RELKIND_VIEW)
> {
> relation_close(advise_rel, AccessShareLock);
>
> /* FIXME: add errdetail() and/or errcontext() calls here. */
> ereport(ERROR,
> (errcode(ERRCODE_WRONG_OBJECT_TYPE),
> errmsg( IND_ADV_ERROR_NTV )));
> }
>
> relation_close(advise_rel, AccessShareLock);
> #else
> /*
> * heap_open() makes sure that the oid does not represent an INDEX or a
> * COMPOSITE type, else it will raise an ERROR, which is exactly what we
> * want. The comments above heap_open() ask the caller not to assume any
> * storage since the returned relation may be a VIEW; but we don't mind,
> * since the user may have defined some rules on it to make the INSERTs
> * work smoothly! If not, we leave it upto the executor to raise ERROR.
> */
> PG_TRY();
> {
> heap_close(heap_open(advise_oid, AccessShareLock), AccessShareLock);
> }
> PG_CATCH();
> {
> errmsg( IND_ADV_ERROR_NTV );
> PG_RE_THROW();
> }
> PG_END_TRY();
> #endif
> }
> else
> {
> /* FIXME: add errdetail() and/or errcontext() calls here. */
> ereport(ERROR,
> (errcode(ERRCODE_UNDEFINED_TABLE),
> errmsg( IND_ADV_ERROR_NE )));
> }
>
> initStringInfo( &query );
> initStringInfo( &cols );
>
> foreach( cell, candidates ) /* foreach cell in candidates */
> {
> int i;
> IndexCandidate* idxcd = (IndexCandidate*)lfirst( cell );
> get_columnnames(idxcd);
>
> if( !idxcd->idxused )
> continue;
>
> /* pfree() the memory allocated for the previous candidate. FIXME: Avoid
> * meddling with the internals of a StringInfo, and try to use an API.
> */
> if( cols.len > 0 )
> {
> pfree( cols.data );
> cols.data = NULL;
> }
>
>
> appendStringInfo( &query, "select n_distintic from pg_stats where ");
>
> for (i = 0; i < idxcd->ncols; ++i)
> {
>
> appendStringInfo( &cols, "attname=%s%d", (i>0?"OR":""),
> idxcd->varattnombres[i]);
>
>
> }/* foreach col in varattno*/
>
>
> /* FIXME: Mention the column names explicitly after the table name. */
> appendStringInfo( &query, "%s;", cols.data);
>
> elog(INFO,"QUERY:%s", query.data);
> elog(INFO,"LONGITUD:%d", query.len);
>
>
> if( query.len > 0 ) /* if we generated any SQL */
> {
> if( SPI_connect() == SPI_OK_CONNECT )
> {
>
> if( SPI_execute( query.data, true, 0 ) != SPI_OK_SELECT )
> elog( WARNING, "IND ADV: SPI_execute failed while select." );
>
> else /* SPI_OK_SELECT*/
> {
>
> proc=SPI_processed;
> tupdesc=SPI_tuptable->tupdesc;
> SPITupleTable *tuptable=SPI_tuptable;
> char buf[8192];
> int i,j;
> for(j=0;j<proc;j++)
> {
> /*cada fila*/
> HeapTuple tuple=tuptable->vals[j];
> for (i=0,buf[0]=0;i<tupdesc->natts;i++)
> {
> /* cada columna de cada fila*/
> char *data;
> data=SPI_getvalue(tuple,tupdesc,i);
> /* falta imprimir data y guardar el dato correspondiente en la estructura
> del índice*/
> snprintf(buf+strlen(buf),sizeof(buf)-strlen(buf),"%s
> %s",data,(i==tupdesc->natts)?"": "|");
> }
>
> elog(INFO,"EXECQ:%s",buf);
> strcpy(idxcd->ndistinct,buf);
>
> }
>
> }
>
> if( SPI_finish() != SPI_OK_FINISH )
> elog( WARNING, "IND ADV: SPI_finish failed while select." );
> }
> else /* SPI_connect() != SPI_OK_CONNECT*/
> elog( WARNING, "IND ADV: SPI_connect failed while select." );
> }
>
> /* TODO: Propose to -hackers to introduce API to free a StringInfoData . */
> if ( query.len > 0 )
> pfree( query.data );
>
>
> } /* foreach cell in candidates */
>
>
> elog( DEBUG3, "IND ADV: select: EXIT" );
> }
>
>
> static void
> get_columnnames( IndexCandidate* idx )
> {
> int proc;
> StringInfoData query; /* string for Query */
> StringInfoData cols; /* string for Columns */
> Oid advise_oid;
> ListCell *cell;
>
> SPITupleTable *SPI_tuptable;
>
> TupleDesc tupdesc;
>
>
> elog( DEBUG3, "IND ADV: get_column_names: ENTER" );
>
>
>
>
> initStringInfo( &query );
> initStringInfo( &cols );
>
>
>
>
>
> int i;
> IndexCandidate* idxcd = idx;
>
>
>
> /* pfree() the memory allocated for the previous candidate. FIXME: Avoid
> * meddling with the internals of a StringInfo, and try to use an API.
> */
> if( cols.len > 0 )
> {
> pfree( cols.data );
> cols.data = NULL;
> } /*IF col.len>0*/
>
>
>
>
> appendStringInfo( &query, "select a.attname from pg_class c,pg_attribute a
> where c.oid=%d AND a.attrelid = c.oid AND ", idxcd->reloid);
>
> for (i = 0; i < idxcd->ncols; ++i)
> {
>
> appendStringInfo( &cols, "a.attnum=%s%d", (i>0?"AND":""),
> idxcd->varattno[i]);
>
>
> }/* foreach col in varattno*/
>
>
> /* FIXME: Mention the column names explicitly after the table name. */
> appendStringInfo( &query, "%s;", cols.data);
>
> elog(INFO,"QUERY:%s", query.data);
> elog(INFO,"LONGITUD:%d", query.len);
>
> if( query.len > 0 ) /* if we generated any SQL */
> {
> if( SPI_connect() == SPI_OK_CONNECT )
> {
>
> if( SPI_execute( query.data, true, 0 ) != SPI_OK_SELECT )
> elog( WARNING, "IND ADV: SPI_execute failed while select." );
>
> else /* ok*/
> {
>
> proc=SPI_processed;
> tupdesc=SPI_tuptable->tupdesc;
> SPITupleTable *tuptable=SPI_tuptable;
> char buf[8192];
> int i,j;
> for(j=0;j<proc;j++)
> {
> /*cada fila*/
> HeapTuple tuple=tuptable->vals[j];
> for (i=0,buf[0]=0;i<tupdesc->natts;i++)
> {
> /* cada columna de cada fila*/
> char *data;
> data=SPI_getvalue(tuple,tupdesc,i);
> idxcd->varattnombres[i]=data;
>
> } /* (i=0,buf[0]=0;i<tupdesc->natts;i++)*/
>
>
> }/* (j=0;j<proc;j++)*/
>
> }/*else ok*/
>
>
>
> if( SPI_finish() != SPI_OK_FINISH )
> elog( WARNING, "IND ADV: SPI_finish failed while select." );
>
> } /*if( SPI_connect() == SPI_OK_CONNECT )*/
>
>
> else
> elog( WARNING, "IND ADV: SPI_connect failed while select." );
>
>
> } /*if( query.len > 0 )*/
>
> /* TODO: Propose to -hackers to introduce API to free a StringInfoData . */
> if ( query.len > 0 )
> pfree( query.data );
>
>
>
>
>
>
> elog( DEBUG3, "IND ADV: select: EXIT" );
> }
>
> El mar., 17 sept. 2019 a las 11:41, Yessica Brinkmann (<
> yessica(dot)brinkmann(at)gmail(dot)com>) escribió:
>
>> Muchas gracias a todos por sus respuestas. Voy a estar haciendo las
>> verificaciones con el log, y enviando lo que me pidieron. Y también voy a
>> enviar parte del código fuente, para que se pueda ver el Insert que
>> funciona, y los Selects que quiero hacer.
>> Saludos cordiales,
>> Yessica
>>
>>
>> El mar., 17 sept. 2019 9:57, Enrique Herrera Noya <
>> enrique(dot)herreranoya(at)gmail(dot)com> escribió:
>>
>>>
>>>
>>> El mar., 17 de sep. de 2019 10:20, Yessica Brinkmann <
>>> yessica(dot)brinkmann(at)gmail(dot)com> escribió:
>>>
>>>> El código fuente del SPI_connect ()? Si, estuve mirando. Pero sólo daba
>>>> errores por error en la pila por lo que entendí. O sea, no encontré nada
>>>> concreto de las posibles razones para un spi_error_connect.
>>>> Saludos cordiales,
>>>> Yessica
>>>>
>>>
>>> Podrías hacer un diagrama, para entender la infraestructura como la
>>> tienes estructurada,
>>> De esa forma podremos ir acotando, cuál es el punto de falla,. Y de
>>> acuerdo a eso ver LOG, Y saber que buscar
>>>
>>>
>>>
>>>
>>>
>>>>
>>>> El mar., 17 sept. 2019 9:14, Enrique Herrera Noya <
>>>> enrique(dot)herreranoya(at)gmail(dot)com> escribió:
>>>>
>>>>> miraste el código fuente?
>>>>> ahí hay información que dejan los programadores...
>>>>>
>>>>>
>>>>>
>>>>> El mar., 17 de sep. de 2019 a la(s) 09:49, Yessica Brinkmann (
>>>>> yessica(dot)brinkmann(at)gmail(dot)com) escribió:
>>>>>
>>>>>> No, realmente no creo que el error se deba a que se realiza "fuera
>>>>>> del servidor". Permite realizar el Insert.
>>>>>> Realmente justamente esa es mi pregunta... Si alguien conoce por qué
>>>>>> podría dar error el SPI_connect (), o los motivos posibles para obtener un
>>>>>> spi_error_connect con dicha función.
>>>>>> Saludos cordiales,
>>>>>> Yessica
>>>>>>
>>>>>> El mar., 17 sept. 2019 8:37, Enrique Herrera Noya <
>>>>>> enrique(dot)herreranoya(at)gmail(dot)com> escribió:
>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> El mar., 17 de sep. de 2019 a la(s) 08:52, Francisco Olarte (
>>>>>>> folarte(at)peoplecall(dot)com) escribió:
>>>>>>>
>>>>>>>> Yessica:
>>>>>>>>
>>>>>>>> On Tue, Sep 17, 2019 at 12:40 PM Yessica Brinkmann
>>>>>>>> <yessica(dot)brinkmann(at)gmail(dot)com> wrote:
>>>>>>>> > Cuando digo en un programa me refiero a un programa en lenguaje C
>>>>>>>> que se conecta al servidor Postgresql.
>>>>>>>>
>>>>>>>> Veamos, lenguaje aparte ( que aqui no importa, es el ABI simplemente
>>>>>>>> ), no se si me he hecho entender.
>>>>>>>>
>>>>>>>> SPI quiere decir Server Programming Interface. Se usa para programar
>>>>>>>> dentro del server, como si estuvieras haciendo las funciones en
>>>>>>>> sql, o
>>>>>>>> pl-sql. Es decir, para codigo que esta ejecutando en el server, no
>>>>>>>> para "programas", que normalmente se usa para cosas que ejecutan
>>>>>>>> FUERA
>>>>>>>> del server y se hacen con la libpq, p.e., en C. De hecho no conectas
>>>>>>>> con el servidor, la propia descripcion de la funcion dice
>>>>>>>> "SPI_connect
>>>>>>>> opens a connection from a C function invocation to the SPI manager.
>>>>>>>> You must call this function if you want to execute commands through
>>>>>>>> SPI. Some utility SPI functions can be called from unconnected C
>>>>>>>> functions.", conectas con el manager, tienes que estar ya dentro del
>>>>>>>> servidor ( por eso la funcion no tiene ningun parametro que diga
>>>>>>>> donde
>>>>>>>> esta el servidor ).
>>>>>>>>
>>>>>>>
>>>>>>> entonces de acuerdo a eso, SPI_connect () daría error cuando se
>>>>>>> intenta usar desde "fuera" del servidor?
>>>>>>> siendo así , por que deja realizar INSERT según indica Yessica?
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>>
>>>>>>>> > Pasa que estoy haciendo unas modificaciones al Index Adviser de
>>>>>>>> Gurget como tesis de la Universidad, y para eso es.
>>>>>>>> > El SPI_connect () se usa en dicho programa y funciona, para hacer
>>>>>>>> un Insert. Yo estoy procurando de hacer Selects, pero supongo que debería
>>>>>>>> funcionar igual.
>>>>>>>> > Realmente no entiendo por qué me aparecería el spi_error_connect
>>>>>>>>
>>>>>>>> He intentado buscar el I.A. de G, en jujel sin exito. No se si es un
>>>>>>>> programa / coleccion de o es un conjunto de funciones que se carga.
>>>>>>>> Suponiendo que sea una extension, es raro que esa funcion de
>>>>>>>> errores.
>>>>>>>> ¿ Te has asegurado de que no llamas dos veces ? ¿ Has mirado el log
>>>>>>>> del servidor a ver si dice algo ?
>>>>>>>>
>>>>>>>> Francisco Olarte.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> > Saludos cordiales,
>>>>>>>> > Yessica
>>>>>>>> >
>>>>>>>> > El mar., 17 sept. 2019 6:08, Francisco Olarte <
>>>>>>>> folarte(at)peoplecall(dot)com> escribió:
>>>>>>>> >>
>>>>>>>> >> Yessica:
>>>>>>>> >>
>>>>>>>> >> On Tue, Sep 17, 2019 at 11:39 AM Yessica Brinkmann
>>>>>>>> >> <yessica(dot)brinkmann(at)gmail(dot)com> wrote:
>>>>>>>> >> > Quisiera hacer una consulta al grupo por favor.
>>>>>>>> >> > Alguien ha usado SPI_connect() para conectarse a Postgresql
>>>>>>>> desde un programa?
>>>>>>>> >> > Saben por si acaso en qué casos da error?
>>>>>>>> >> > Me está dando error spi_error_connect desde un programa en C y
>>>>>>>> no comprendo exactamente a qué se pueden deber los errores.
>>>>>>>> >> > Disculpen la consulta pero es que hay muy poco información
>>>>>>>> sobre el tema en Internet y muy pocos ejemplos. Prácticamente sólo está la
>>>>>>>> documentación sobre el tema.
>>>>>>>> >>
>>>>>>>> >> Yo no la he usado, pero si que se que las SPI* son para ejecutar
>>>>>>>> cosas
>>>>>>>> >> desde una extension cargada en el servidor, desde una funcion que
>>>>>>>> >> pones en una dll o similar y cargas en el servidor, como el
>>>>>>>> postgis y
>>>>>>>> >> similares.
>>>>>>>> >>
>>>>>>>> >> Cuando dices "en un programa" te refieres a eso o te refieres a
>>>>>>>> un
>>>>>>>> >> programa distinto, que se conecta al servidor ?
>>>>>>>> >>
>>>>>>>> >> Frnacisco Olarte.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> visita
>>>>>>> http://www.plataformavecinal.cl
>>>>>>> http://www.plataformaconstituyente.cl
>>>>>>> http://www.partidopirata.cl
>>>>>>> --
>>>>>>> <http://www.partidopirata.cl>
>>>>>>>
>>>>>>
>>>>>
>>>>> --
>>>>> visita
>>>>> http://www.plataformavecinal.cl
>>>>> http://www.plataformaconstituyente.cl
>>>>> http://www.partidopirata.cl
>>>>> --
>>>>> <http://www.partidopirata.cl>
>>>>>
>>>>

In response to

Responses

Browse pgsql-es-ayuda by date

  From Date Subject
Next Message Yessica Brinkmann 2019-09-18 00:50:07 Re: SPI_connect
Previous Message Emanuel Calvo 2019-09-17 21:12:56 Re: PgBouncer con varias aplicaciones Java