Page 1 of 1

Problemas indice

PostPosted: Fri Nov 28, 2008 1:04 pm
by diegopolverelli
Hola. Tengo una aplicacion que usa un indice que se compone de 3 campos caracter de 5, 16 y 10 de largo cada uno. Antes utilizaba un
locate e igualaba cada campo de la base con una variable; ahora hago un indice, y busco las 3 variables concatenadas.

El problema es que a veces, con el indice, se producen errores; no me encuentra un registro que existe, y me genera un duplicado (si no encuentra, lo da de alta). Probe muchisimas variantes de carga (muchos items, un solo item, etc.) pero en principio funciona bien con el locate y con el indice, pero cuando pongo el programa en produccion, la version con indice, una de 15 falla, y el del locate no.

Obviamente tengo funcionando el del locate, pero como se imaginaran, la performance del mismo, especialmente cuando trabajo en red, es peor.

¿se les ocurre que puede estar pasando? el indice esta armado de manera correcta; la prueba está en que funciona bien en muchas oportunidades. En fin, espero me puedan orientar. Ya no se por donde buscar. Gracias. Atte.

PostPosted: Fri Nov 28, 2008 2:01 pm
by karinha
Muestra algo en la pratica, porfa.

Saludos.

ejemplo

PostPosted: Fri Nov 28, 2008 2:37 pm
by diegopolverelli
tengo una tabla st_stock indexada por
deposito+st_codigoart+st_lote (en in indice permamente)

hago un movimiento, tengo 10 productos que salen de stock:

hago un while, y segun el producto, lote y deposito de donde salen,
busco en la tabla st_stock y resto o sumo en un campo CANTIDAD. Si no esta el registro, agrego en st_stock un registro nuevo.
Si esa busqueda la hago asi:
loca for st_stock->coddep=xcoddep .and. st_stock->art_codig=xart_codig .and. st_stock->lote=xlote, y pongo el programa en produccion, funciona todo de 10... ahora, si uso el indice del cual hablo en los primeros renglones, tambien funciona bien, pero no siempre... a veces no me encuentra un registro que existe, y por ende, al agregar, me duplica un registro.

Es rarisimo. Trabajo en red contra un server, con fwh 803... en fin Gracias...!!!

PostPosted: Fri Nov 28, 2008 3:16 pm
by karinha
Porque usas LOCATE en vez de DBSEEK()??

al agregar, me duplica un registro.

Esto és en una ALTERACION? Trabas el registro antes con RLOCK()?


Saludos.

PostPosted: Fri Nov 28, 2008 3:35 pm
by diegopolverelli
yo hago

seek xcoddep+xartcodig+xlote
if !eof()

modifico el reg

else

agrego el registro

endif


de esa menera funciona, pero a veces el seek falla, entra por el else, a pesar de existir la combinacion coddep+artcodig+lote, y me da de alta algo que ya existe.

si en lugar del seek uso locate (abro la base sin indexar incluso), no falla nunca. Rarisimo...

PostPosted: Fri Nov 28, 2008 3:49 pm
by Armando Picon
LOCATE trabaja bien porque ubica la cadena que buscas sin importar el tamaño del campo... Cuando utilizas el índice, el mecanismo de búsqueda es ubicar el valor de tu cadena "con el mismo largo".

Mi sugerencia es que hagas una sentencia como esta, para crear tu índice:

INDEX ON PADL(Libros->Epoca,LEN(Libros->Epoca))+ ;
PADL(Libros->Orden,LEN(Libros->Orden))+ ;
PADL(Libros->numlibro,LEN(Libros->numlibro)) ;
TAG "LIBRO1" TO "LIBROS.CDX"

Como puedes ver en este índice se puede buscar el valor de tu variable + los espacios necesarios para completar el ancho del campo correspondiente...

PostPosted: Fri Nov 28, 2008 4:02 pm
by diegopolverelli
yo no uso .cdx

igualmente tengo indices sin usar esto del Len y demas, y funcionan bien; Antes del Seek pongo set softseek off y creo que funciona bien. ¿no tienen conocimiento de algun error aleatorio que se verifique con los indices?

ademas, el locate, si hago:

loca for st->cod=xcod1 .and. st->lote=xlote1

y tengo en st->lote, por ej, a001 y a0012, puede darse que me actualice mal: si xlote1=a001, quisas el locate me de .t. en a0012

¿o no? en fin. Gracias. Atte.

PostPosted: Fri Nov 28, 2008 4:10 pm
by Ruben D. Fernandez
Diego:
Prueba a poner antes del segundo dBseek(lo_que_buscas) un dbgotop().

Saludos

Ruben Fernandez.

PostPosted: Fri Nov 28, 2008 4:13 pm
by karinha
xlote1=a001, quisas el locate me de .t. en a0012


mira se no hay una cadena en blanco e retira los blancos con ALLTRIM().

OTRA:

locate for st->cod==xcod1 .and. st->lote==xlote1 //-> Intente asi.

Saludos.

PostPosted: Fri Nov 28, 2008 4:17 pm
by Armando Picon
No necesitas usar el CDX, lo puse solo como ejemplo. Locate te va ha ubicar a001 correctamente si fue introducido primero antes que a0012... en caso contrario SIEMPRE se va ha colocar sobre a0012 porque ya contiene la cadena "a001". En Clipper ese fenómeno no ocurría. Por eso es que empece a utilizar PADL(alias->campo1, LEN(alias->campo1)) con la ventaja adicional que, sin importar las variaciones de la longitud del campo, puedo reindexar... y hasta el presente me funciona al 100%

diegopolverelli wrote:yo no uso .cdx

igualmente tengo indices sin usar esto del Len y demas, y funcionan bien; Antes del Seek pongo set softseek off y creo que funciona bien. ¿no tienen conocimiento de algun error aleatorio que se verifique con los indices?

ademas, el locate, si hago:

loca for st->cod=xcod1 .and. st->lote=xlote1

y tengo en st->lote, por ej, a001 y a0012, puede darse que me actualice mal: si xlote1=a001, quisas el locate me de .t. en a0012

¿o no? en fin. Gracias. Atte.

PostPosted: Fri Nov 28, 2008 5:24 pm
by Carlos Mora
Armando,

hacer un PADL(alias->campo1, LEN(alias->campo1)) no tiene sentido en el índice. Hay que hacerlo en la clave, al hacer el seek:

Seek PADL( cVar1, LEN(alias->campo1))+PADL( cVar2, LEN(alias->campo2))+PADL( cVar3, LEN(alias->campo3))

Ahí si tiene sentido. SIEMPRE campo1 tiene una longitud Len(campo1), es una identidad, no cambia nada.

Un saludo,

Carlos.

PostPosted: Fri Nov 28, 2008 8:32 pm
by Armando Picon
Carlos

Si tiene y muchísimo... mi preferencia es construir el indice con el PAD ya que en adelante no tengo que preocuparme de estar revisando en que parte del codigo, que podrían ser muchísima líneas, debo estar revisando para que no se vaya algo que luego no me devuelva el dato que busco con el Seek o Dbseek... (claro que utilizo rutinas que crean los índices al inicio y mantengo abierto las bases). Por otra parte mis variables de búsqueda las construyo, por ejemplo, vCampo1 := SPACE(LEN(Campo1)) y así sucesivamente de forma tal, que aunque por razones insospechadas tenga que modificar la losngitud del campo, no tengo que realizar ajuste alguno a mi código.

No hace mucho, enfrenté un problema con código parecido a lo que indicas en tu respuesta (realizar un adecuación de codigo contable para pasar de 6 dígitos de cuenta a 8 dígitos) y la verdad que fue horroroso el trabajo... tuve que trabajar a pérdida por que la revisión y modificación de código de terceros es peor que tortura china...!!!


Carlos Mora wrote:Armando,

hacer un PADL(alias->campo1, LEN(alias->campo1)) no tiene sentido en el índice. Hay que hacerlo en la clave, al hacer el seek:

Seek PADL( cVar1, LEN(alias->campo1))+PADL( cVar2, LEN(alias->campo2))+PADL( cVar3, LEN(alias->campo3))

Ahí si tiene sentido. SIEMPRE campo1 tiene una longitud Len(campo1), es una identidad, no cambia nada.

Un saludo,

Carlos.

PostPosted: Sun Nov 30, 2008 3:14 am
by FranciscoA
diegopolverelli wrote:yo hago

seek xcoddep+xartcodig+xlote
if !eof()

modifico el reg

else

agrego el registro

endif


de esa menera funciona, pero a veces el seek falla, entra por el else, a pesar de existir la combinacion coddep+artcodig+lote, y me da de alta algo que ya existe.

si en lugar del seek uso locate (abro la base sin indexar incluso), no falla nunca. Rarisimo...



Prueba de esta manera:

seek xcoddep+xartcodig+xlote
if Found() // en vez de !eof()
modifico el reg
else
agrego el registro
endif


O, asi:

if dbseek( xcoddep+xartcodig+xlote )
modifico el reg
else
agrego el registro
endif

PostPosted: Mon Dec 01, 2008 2:47 pm
by Carlos Mora
Hola Armando,

Armando Picon wrote:Si tiene y muchísimo...

realmente no me imagino donde podria tener algo que ver, por más que le doy vueltas, no se me ocurre como puede llegar a fallar.

¿Podrías enviarme una dbf con un ejemplo donde:

Code: Select all  Expand view
PADL(alias->campo1, LEN(alias->campo1)) <> alias->campo1


?
En lo que me dices del codigo contable cambiado de 6 a 8, si has cambiado un campo y no has reindexado evidentemente te saldrá mal. Y de hecho Harbour, a diferencia del Clipper, no acepta claves de longitud variable, por lo que usar el indice con las claves a 6 probablemente te hubiese resultado en un 'Corruption detected'. Por ejmplo usar claves variables como alltrim(nombre) falla en harbour en cuanto una clave no tien el mismo largo que la del registro 1.

Respecto de lo valores en blanco, siempre uso el registro fantasma del Eof() como base para los registros en blanco, es algo muy seguro. De hecho hace poco Manu Expósito puso una clase buffer, que es muy parecida a la que uso, y no he tenido nunca problemas.

Un saludo,

Carlos.