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
Update a la nueva version de Sqlite3
Nuevas implementaciones para Harbour.
No me habia dado tiempo todavia de abordar ciertas características de la version 3.3, cuando WenCheng me informó de una nueva versión.
Actualicé mi versión y miré por encima que es lo que habían metido de nuevo.
Bien, en el CVS de T-Gtk ya esta el servidor 3.4, o en la respectiva web de sqlite.
La novedad es que ahora podemos controlar mejor el commit y el rollback, y ya he realizado este fin de semana los wrappers para los usuarios de Harbour.
Asi , por ejemplo, para controlar los commits o los rollback, simplemente con ;
sqlite3_commit_hook( db, {|| Commit_Hook() } )
Además, si devolvemos .F., hará un rollback.
Y , para dar información sobre el rollback, esta funcion;
sqlite3_rollback_hook( db, {||Qout( "Rollback...") } )
Además, en esta actualización se a portado más funciones, en especial la función sqlite3_get_table().
El funcionamiento es un pelin diferente a la wrapper original,
pues nos bajo Harbour nos va a devolver el array completo de la sentencia, quedando asi;
aResult := sqlite3_get_table( db, cSql, @nRow, @nCol, @cError, lHeader )
aResult
El resultado puede ser un array multidimensional o unidimensional, o un array vacio si no ya datos que cumplan la condición de la
sentencia.
db
->es la db abierta.
cSql
-> es la sentencia, "Select * from test;"
nRow, nCol
-> nos informa de las filas y columnas,
cError
-> Informa si hubo error o NIL.
lHeader
-> Este es por que me intuyo que los programadores van
a estar peleando de si o no, asi que dejamos preparados para
que escojan lo que quieran.
Sqlite, por defecto, devuelve el array con el header al inicio,
nosotros podemos coger el array devuelto con él o sin él.
En fin, haber si termino cuanto antes las funciones, para empezar ya al desarrollo de la clase o las distintas clases, porque seguramente se harán varias para manejarlo de diferente manera.
Implementacion libre para Harbour sobre BD Sqlite3.
Hace bastante tiempo que no posteo por aqui. Una de las razones principales es que estado un pelín liado con la salud, y me a sido imposible haber seguido publicando.
Bueno, a lo que íbamos.
Estoy implementando una nueva versión libre de las librerias de acceso a Sqlite3 a través de [x]Harbour.
Algunos todavian me dicen como es que sigo dando código libre a la comunidad de xBase, que más que comunidad, parece una reunión de los 4 vecinos mal avenidos, pero en fin, y siempre contesto, que ni yo lo sé ;-), quizás ¿ para ayudar a otros ? Vete tú a saber.
El trabajo parte inicialmente en el estudio de la implementación sobre la version 2.X de Sqlite , realizada por Alejandro de Garate,
si bien, la versión 2 y 3 han cambiado, su trabajo hizo que cogiera con ganas el portar la nueva versión.
Además quiero agraceder a WenCheng Liao, ( si no me 'liao' ese es el apellido ) desde Taiwan, el haberme pasado una versión suya, y llegar a un acuerdo en liberar partes de su trabajo como GPL.
Si bien he estado mirando ambos código, el mio es un pelín diferente, porque parto de la idea, que un wrapper, debe o debería ser lo más parecido al original.
Despué ya haremos funciones que realicen determinadas tareas, para facilitar mejor el acceso a los datos o la recuperación de los mismos, pero eso será en la segunda fase.
El hacer también el wrapper lo más puro al origen, y portarlo simplemente a Harbour, sin GUI de por medio, facilita que todo programador de Harbour pueda usarlo sin problemas, no dependiendo de que si programa con objetos, con clases, con funciones, o con chimpances rodeados de teclados rosas...
simplemente, funcionará.
Actualmente esta en version ALPHA 0.2, la 0.1 simplemente abria,
ejecutaba una instruccion, y se cerraba.
La 0.2, ya es posible recuperar los datos, saber el tipo, las cantidad de filas de la select, etc..., bueno, lo que se supone
que debe hacer una 0.2 ;-)
El código fuente esta dividido en 2:
- El servidor , un fichero .c y .h, que lo podeis coger, o bien desde
http://www-sqlite.org o si eres usuarios de T-Gtk lo tienes ya disponibles en /src/sqlite3
Esto es simplemente el servidor.
- La librería de acceso al Sqlite3 para Harbour.
Como gente interesada en esta librería , le importará 3 pimientos T-Gtk, no vamos a castigarles con bajarse un montón de codigo fuente inútil, para ello he creado un nuevo módulo llamado sqlite3 en T-Gtk, aparte de nuestra GUI favorita.
Los datos de conexión a través del CVS son:
cvs -z3 -d:pserver:anonymous@t-gtk.cvs.sourceforge.net:/cvsroot/t-gtk co -P sqlite3
Si usais tortoiseCVS o similar, al final os debería quedar una linea similar a la descrita arriba, si usas GNU/Linux, escribe simplemente esa linea en la linea de comandos y obtendras automaticamente un directorio en tu home , p.e. /home/rafa/sqlite3.
Faltan unas pocas funciones más, y el siguiente plan será crear funciones más productivas y crear las clases, que usar objetos nos simplificará mejor las cosas ;-)
Ah! Se me olvidaba... los makefiles son para los usuarios de T-Gtk, por favor, createlos para tu sistema, no me dió tiempo a probar con otros.
Saludos.
Rafa Carmona