Estaba yo con mis cosas, y repasando la lista de correo de harbour, leí que alguien ponía una función, llamada OrdWildSeek
Buscando más información sobre dicha función, me percaté enseguida, que haciendo un poco de malabares y con un indice CUSTOM, y sin apenas esfuerzos, podemos quitar nuestros SET FILTER, que por su utilidad estaban, pero que por su ineficacia no lo usaba prácticamente nadie.
Cada vez que he tenido que usar un LIKE en SQL, pasa por mi memoria el SET FILTER ;-)
¿ Y cual es la idea ? El idea es usar un sub-indice a partir del índice activo.
¿ Y como funciona ?
Pues a grandes rasgos y para que todo el mundo lo entienda;
- SET FILTER TO , recurre TODO la DBF en busca de coincidencias.
Ah!! y lo bonito que es ver que en el filtro hay solo 2 coincidencias separadas entre si por 200MB, el salto de un registro a otro es de "reír por no llorar" ;-)
- OrWildSeek, recurre el FICHERO NTX ACTIVO, y nos va diciendo que registro cumple con el patrón que pasamos, y ahí es donde entramos nosotros con nuestro indices CUSTOMS
Ahora lo que más nos gusta, el código fuente.
Imagina que tenemos una tabla de clientes, y tenemos varios indices, y el 4, la expresión es nombre+apellidos.
Ahora, queremos obtener el nombre de SARAH. Pero no solo los que comienzan con SARAH, eso lo podemos solucionar rápidamente con un SCOPE, si no, que forme parte de él, como;
- ANGIE SARAH LOWE
- SARAH CARMONA
- JULIA SARAH SMITH
Eso se consigue , pasando el patrón "*"+Cadena+"?"
cNombre := "SARAH"
fast_filter( "*"+ alltrim( cNombre ) + "?", 4, 22, 28 )
Browse()
Ahora, ya estaría el filtro activado basado en subindices.
/*
Sustituto de SET FILTER
cExpr
Expresion a buscar que forme parte del indice, podemos
poner *Texto? , para buscar palabra que forme parte
nOrder
Sobre que indice activo vamos a recorrer la lista.
Por defecto es el indice activo.
nRow, nCol
Posicion fila,columna para mostrar progreso. Se ejecuta en
un hilo aparte
Return: Indice anterior
*/
function fast_filter( cExpr, nOrder, nRow, nCol )
local PantaAnt := savescreen(0,0,MaxRow(),MaxCol())
Local p := hb_threadStart( @Pajaritos(), nRow, nCol )
Local nIndice := OrdNumber()
DEFAULT nOrder TO OrdNumber()
set order to nOrder
INDEX ON &(IndexKey()) TAG _TEMP_ TO tHarbourt ;
CUSTOM ADDITIVE MEMORY
set order to nOrder
go top
DO WHILE OrdWildSeek( cExpr, .T. )
OrdKeyAdd( "_TEMP_" )
ENDDO
OrdSetFocus( "_TEMP_" )
hb_threadTerminateAll()
restscreen(0 ,0 ,MaxRow(), MaxCol(), PantaAnt)
return nIndice
PROCEDURE Pajaritos( nRow, nCol )
Local pajarito := "|",n := 0
DEFAULT nRow := MaxRow(), nCol := 1
DO WHILE .T.
do case
case n = 1
pajarito = "|"
case n = 2
pajarito = "/"
case n = 3
pajarito = "-"
case n = 4
pajarito = "\"
Otherwise
n := 0
end case
DispOutAt( nRow, nCol, "Generando Consulta....[ " + pajarito +" ]" ) //, "GR+/N" )
ThreadSleep( 500 )
n++
ENDDO
RETURN
Creo que la función es muy simple y no necesita más explicación, el código habla por si mismo.
Lo único es que se crea un hilo para mostrar que se está haciendo alguna cosa.
Lo ideal sería que la función OrdWildSeek tuviese un codeblock para hacer llamada e ir mostrando un progreso, pero al no tenerlo, lo he ejecutado en un hilo aparte.
He de decir que me sorprende la velocidad, eso si, siempre teniendo en cuenta la cantidad de información a recorrer, avisados estáis.
Espero que os guste ;-)
No hay comentarios:
Publicar un comentario