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.brinkm...@gmail.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.herreran...@gmail.com> escribió: > >> >> >> El mar., 17 de sep. de 2019 10:20, Yessica Brinkmann < >> yessica.brinkm...@gmail.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.herreran...@gmail.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.brinkm...@gmail.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.herreran...@gmail.com> escribió: >>>>> >>>>>> >>>>>> >>>>>> El mar., 17 de sep. de 2019 a la(s) 08:52, Francisco Olarte ( >>>>>> fola...@peoplecall.com) escribió: >>>>>> >>>>>>> Yessica: >>>>>>> >>>>>>> On Tue, Sep 17, 2019 at 12:40 PM Yessica Brinkmann >>>>>>> <yessica.brinkm...@gmail.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 < >>>>>>> fola...@peoplecall.com> escribió: >>>>>>> >> >>>>>>> >> Yessica: >>>>>>> >> >>>>>>> >> On Tue, Sep 17, 2019 at 11:39 AM Yessica Brinkmann >>>>>>> >> <yessica.brinkm...@gmail.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> >>>> >>>
gráfico - index - adviser.pdf
Description: Adobe PDF document