Implementación de sqlite3_progress_handler()
Bueno, acabo de terminar un nueva funcion, que creo que es bastante interesante,
sobre todo para los que programan con GUIs.
Dicha funcion es sqlite3_progress_handler()
¿ Y que hace dicha funcion que la hace tan especial ?
Pues una cosa que los amantes de los While les encantará , el poder hacer determinadas tareas cada X tiempo.
Imagina que realizamos un consulta del tipo "SELECT * FROM TEST", y que
contiene nada mas ni nada menos que 1 millon de registros.
A tu aplicacion no tardará en decir "I,m sorry, not respondo....", aunque realmente, si que esta trabajando, pero como no tiene manera de comunicarse con la GUIs para decirselo, pues... pasan estas cosas.
La solución es bien sencilla utilizando dicha función;
Sqlite3_Progress_Handler( db, Time, bCodeblock )
Donde
db
--> Db a usar
time
--> No es el tiempo propiamente dicho si no , es por cada N de opcodes de la
maquina virtual de Sqlite3. ( No preguntes que es, realmente no tengo ni
idea )
bCodeblock
--> Que es lo que queremos hacer, por ejemplo, hacer un SysRefresh() cada
cierto TIME.
Además, desde aqui, vamos a poder controlar si cancelamos o no la sentencia actual, permitiendo por ejemplo, cancelar la operacion de consulta.
Si devolvemos .F., continuará haciendo el trabajo.
Si devolvemos .T., cancelará lo que estaba haciendo.
Por ejemplo imagina este código;
#define TIME_CANCEL 4
static nSeconds
Function test()
nSeconds := Seconds()
Sqlite3_Progress_Handler( db, 50, {|| Cancel_Time() } )
for x := 1 to 100
sqlite3_exec( db, 'insert into test (nombre) values ( "pepe"
)',@cError )
next
function cancel_time()
if ( Seconds() - nSeconds >= TIME_CANCEL )
return .T.
endif
SysRefresh() // Dile a las Guis que espavilen..
return .F.
Con esto , cuando llegue el tiempo a 4 segundos, ya no va a permitir meter
más insert en la tabla.
( Esto por supuesto es un caso de experimentación, no tiene ningún sentido.)
Pero, bueno, ilustra como podemos cambiar, a traves de un boton por ejemplo,
el estado de la variable, para poder cancelar la operacion que se esta
llevando a cabo.
De todas maneras, el for continuaria, lo cual es incorrecto, porque estaria
no haciendo nada. Una version mejor seria;
#define SQLITE_INTERRUPT 9 /* Operation terminated by
sqlite3_interrupt()*/
for x := 1 to 100
nResult := sqlite3_exec( db, 'insert into test (nombre) values (
"pepe"
)',@cError )
if nResult = SQLITE_INTERRUPT
? "Se termino en " + Str( x, 3 )
EXIT
endif
next
En fin, espero que entendáis que es lo que se realiza y lo bien que nos puede ir
para hacer muchas cosas en los 'tiempos' muertos ;-)
Saludos
Rafa Carmona