Sei sulla pagina 1di 6

D:\Utiles\Motores\SQLite\PRUEBAS-ODBC\Ejemplo-VFP-accesando-SQLite-con-ODBC.prg Jueves, 04 de Julio del 2013 10:32 p.m.

** Ejemplo-VFP-accesando-SQLite-con-ODBC.prg
** Jul-2013
** jhernancanom-at-hotmail-dot-com

*-- Author: Jesús Hernán Cano Martínez


*-- Este es un ejemplo de acceso a una base de datos SQLite, en este caso utilizando ODBC.
*
*-- Nota: Es el segundo de varios documentos para accesar tanto este motor como otros
*
*-- Parámetros: Este ejemplo no usa parámetros
*
*-- Ejemplo de llamada: desde la ventana de comandos de VFP (o IDE compatible),
* o desde un .EXE ya compilado, ejecuta lo sgte:
* do "Ejemplo-VFP-accesando-SQLite-con-ODBC.prg"
* (puede cambiar el nombre a este ejemplo si gusta)
*
*-- Requirimientos:
* Este ejemplo consta de varios archivos, todos incluidos en el .zip que usted descargó.
* Esos archivos son:
* 1. Ejemplo-VFP-accesando-SQLite-con-ODBC.prg
* 2. registry.vcx + registry.vct + registry.h
* 3. sqlite3odbc.dll
* 4. sqlitedb.db
*
*--********************************************************************************************
*-- Recomendación:
* Con el fin de probar adecuadamente este procedimiento, y cualq otro que quieras escribir,
* te recomiendo que abras la base de datos con un administrador de bases de datos.
* En mi caso tengo estos siete (la mayoría portables):
*
* SQLite Studio: muy bien!!! seleccionado y recomendado de mi parte a ustedes
* (pero puedes usar el que uses, si te acostumbraste a otro)
*
* SQLite Admin : muy bien!!! (pero ya me está fallando: no me volvió a abrir NorthWind.sqlite)
* éste tiene el logo original de SQLite
* SQLiteMan : bien "Describe table" [PortableApps]
*
* Descarté los sgtes:
*
*x SQLite Database Browser: no muestra la estructura completa [PortableApps]
*x Database Browser: requiere ODBC [PortableApps]
*x HeidiSQL: requiere ODBC [PortableApps]
*x EasySQLite2: parece que es para SQLite2.
*
* El hecho de descartarlos por requerir de ODBC es por que los otros no necesitan del
* motor (o lo habilitan por sí solos), y el ejemplo está registrando y des-regidtrando
* el ODBC. El sgte paso será (2) conocer un "motor portable" como MariaDB (y proba-
* blemente MySQL) y luego (3) ODBC, pero haciendo la instalación del ODBC del motor
* desde VFP, para de esta forma requerir menos recursos (con "recursos" me refiero a
* no necesitar instalar nada más que la app)
*
* Pero claro antes de ello será optimizar y socializar la info que este ejemplo nos

-1-
D:\Utiles\Motores\SQLite\PRUEBAS-ODBC\Ejemplo-VFP-accesando-SQLite-con-ODBC.prg Jueves, 04 de Julio del 2013 10:32 p.m.

* permita descubrir sobre SQLite y VFP.


*
* Nos vemos en el foro!!!
*
*--********************************************************************************************

************************************************************************************************
****************** PROCEDURE MAIN **************************************************************
************************************************************************************************

** Primera parte: Registrando el ODBC de SQLite

if .not.Registrar()
= MessageBox ( "No se pudo registrar SQLite3ODBC.dll " +chr(13)+chr(13);
+ "No puedo continuar" )
return
endif
CLEAR
close databases

** Segunda parte: Inicializando una conexión con SQLite ODBC


** y a la vez nos conectamos a la base de datos

** De acuerdo al ejemplo "combo-(SQLite)" --se adjunta-- necesitamos lo sgte


** que encontramos en el formulario test_cbsearch.scx
** (ahí hay algo con respecto a _Screen.nConnectionHandleAsync, que entiendo que es
** algo como "Conexión Asincrónica", pero por no haber documentación, no lo uso aquí)

** Indicamos cuál es la base de datos que queremos abrir


local M.cDB
M.cDB = addbs(curdir())+"sqlitedb.db" &&"northwind.sqlite"

local lnHandle as Integer, laError(1)


*-- Usando SQL pass-through, sin DSN
*lnHandle = SQLSTRINGCONNECT ( [DRIVER=SQLite3 ODBC Driver;Database=northwind.sqlite;] )
lnHandle = SQLSTRINGCONNECT ( [DRIVER=SQLite3 ODBC Driver;Database=]+M.cDB+[;] )

IF lnHandle > 0

** en el ejemplo más sencillo para usar esta metodología (el ejemplo_SPT_sql,prg, de


** Luis María Guayán) no está lo sgte, pero sé que son propiedades que --al configurar
** el ODBC de forma interactiva-- se usan; por lo tanto me gusta más hacerlo por aquí
** por código; quizá se puedan dar sus valores en la misma cadena de conexión que se le
** entrega a SQLSTRINGCONNECT, pero hagámoslo como sabemos que funciona (como lo vemos
** en el ejemplo combo-(SQLite) )
CURSORSETPROP("FetchSize",20,0)
CURSORSETPROP("FetchAsNeeded",.t.,0)

*SQLSETPROP(lnHandle,"Asynchronous",.t.)
** si no se comentariza la anterior instrucción aparece: "Invalid call issued while
** executing a SQLEXEC() sequence" al cerrar el Browse

-2-
D:\Utiles\Motores\SQLite\PRUEBAS-ODBC\Ejemplo-VFP-accesando-SQLite-con-ODBC.prg Jueves, 04 de Julio del 2013 10:32 p.m.

** Ojalá pudiera detectar la versión de SQLite o de su ODBC, sólo por


** saberlo didácticamente...

local M.cSQL

** detectemos la versión de SQLite


M.cSQL = "SELECT sqlite_version() AS 'SQLite Version';"
if SQLEXEC(lnHandle, M.cSQL, 'MiCursor') > 0
MessageBox( 'SQLite_Version: '+tran(sqlite_version), 0, '--', 5000 ) && muestra 3
BROWSE nomodify title 'Visualizando la version de SQLite'
&& muestra 3.6.23.1 dentro del memo
** el SQLiteAdmin me devuelve 3.5.1 muy bien visible
endif

** Tercera parte: Ejecutamos una operación (un comando SQL) sobre la base de datos SQLite3
*************
** vamos a visualizar los datos de una de las tablas
M.cSQL = "SELECT * FROM customers"

**=SQLEXEC(lnHandle, [SELECT * FROM Employees], 'MiCursor') && WHERE EmpleadoId = 1


if SQLEXEC(lnHandle, M.cSQL, 'MiCursor') > 0
if .t.
BROWSE nomodify title 'Visualizando los datos de Customers'
else
** una forma más elegante de hacer un BROWSE
** (lástima que dependa de la vble lBrowseSetup)
private oBrowse, lBrowseSetup
lBrowseSetup=.F.
wait window [Visualizando datos...] nowait
BROWSE NAME oBrowse WHEN BrowseSetup() title 'Visualizando los datos de Customers'
oBrowse = .null.
wait clear
endif
endif
**
** Aquí realizamos operaciones sobre el cursor y/o sobre la bdatos remota
** según la necesidad, utilizando el lenguaje SQL
** Quiero profundizar sobre lenguaje SQL de manera que pueda detectar qué instrucciones
** son standard y cuáles no, es decir detectar lo básico del SQL92 (¿así se llama?).
** Así se podría generar una clase adecuadamente standard para cualq motor.
** Pero éso sería en otro momento. Completemos lo básico......
**
ELSE
= AERROR(laError)
*' Deal with the error further
= MESSAGEBOX('No nos pudimos conectar a: ' +chr(13)+M.cDB+ chr(13)+chr(13);
+'Motivo: ' +laError(2), 48, 'Aviso')
return .f.
ENDIF

** Buenos ya tenemos nuestros datos en VFP-----------------------------

-3-
D:\Utiles\Motores\SQLite\PRUEBAS-ODBC\Ejemplo-VFP-accesando-SQLite-con-ODBC.prg Jueves, 04 de Julio del 2013 10:32 p.m.

** ¿Terminamos?

** Comparando con el primer ejemplo símil-RecordSet, allá completamos más de 500


** (quinientas) líneas, pero aquí llevamos sólo 150 (cien) (con comentarios).

** =========================================================================================
** De forma didáctica veamos cómo capturamos la estructura de una de las tablas
**
** Con AFIELDS sobre el cursor de VFP obtenemos la estructura
** o también con COPY STRUCTURE EXTENDED
** ¿y qué más?
** voy a hacerlo con 'copy structure extended'...

** Cuarta parte: Veamos la estructura de uno de los archivos de datos (una de la tablas)

select MiCursor
if file('_MiCursor_.dbf')
erase _MiCursor_.*
endif
copy structure extended to _MiCursor_
use _MiCursor_ in 0 exclusive
select _MiCursor_
if .f.
browse nomodify title "Estructura segun 'copy structure extended' - Employees"
else
** una forma más elegante de hacer un BROWSE
** (lástima que dependa de la vble lBrowseSetup)
private oBrowse, lBrowseSetup
lBrowseSetup=.F.
*wait window [Visualizando datos...] nowait
BROWSE NAME oBrowse WHEN BrowseSetup() title "Estructura segun ;
'copy structure extended' - Employees" &&NOWAIT
oBrowse = .null.
wait clear
endif
use in _MiCursor_
erase _MiCursor_.*

** ==========================================================================================

** Quinta parte: Desconexión


*' Finish everything
if SQLDISCONNECT(lnHandle)>0
** desconectado---Ok!!
else
=MessageBox('Error al cerrar conexión',0,'--',5000)
endif

** Sexta parte: Limpiamos el sistema operativo, des-registrando las DLL que registramos al
** inicio nosotros mismos

wait window 'Desregistrando...' timeout 2&&nowait noclear &&

-4-
D:\Utiles\Motores\SQLite\PRUEBAS-ODBC\Ejemplo-VFP-accesando-SQLite-con-ODBC.prg Jueves, 04 de Julio del 2013 10:32 p.m.

if !Registrar('U')
= MessageBox ( "No se pudo des-registrar SQLite3ODBC.dll " +chr(13)+chr(13) +;
"Pero podemos continuar..." )
endif
wait clear
************************************************************************************************
****************** ENDPROC MAIN ****************************************************************
************************************************************************************************

** De acuerdo al ejemplo "combo-(SQLite)" --se adjunta-- necesitamos registrar sólo una DLL:
** SQLite3ODBC.dll para activar el ODBC de SQLite en nuestras app
** (así nos evitamos tener que hacer una instalación adicional --la del ODBC--)
** (parece que con SQLite también nos evitamos hacer la instalación adicional del motor)
** Veamos...
function Registrar(M.pDes)
if pcount()=0
LOCAL oReg as registry OF 'registry'
oReg = NEWOBJECT('registry','registry')
local M.nRet
* This routine sets a registry key setting
M.nRet = oReg.SetRegKey('Driver','sqlite3odbc.dll',;
'Software\ODBC\ODBC.INI\generic_SQLite_ODBC',-2147483647,.t.)
if M.nRet<>0
=MessageBox('Error en SetRegKey'+chr(13)+transform(M.nRet),0,'Error en SetRegKey')
endif
clear class registry
clear classlib registry
return (M.nRet=0)
endif

if pcount()=1 and M.pDes=='U'


wait window 'Desregistrando' nowait noclear
LOCAL oReg as registry OF 'registry'

** la sgte instrucción se requiere, pues de lo contrario oReg.DeleteKey fallará


** pues no encuentra la función del API
DECLARE Integer RegDeleteKey IN Win32API Integer nHKey, String @cSubKey

oReg = NEWOBJECT('registry','registry')
local M.nRet
* This routine deletes a Registry Key
M.nRet = oReg.DeleteKey(-2147483647,'Software\ODBC\ODBC.INI\generic_SQLite_ODBC')
if M.nRet<>0
=MessageBox(M.nRet,0,'Error en DeleteKey')
endif
clear class registry
clear classlib registry
return (M.nRet=0)
** el "des-registro" se hace al finalizar la app; si no se puede
** des-registrar, realmente no hay problema... ¿cierto?
endif
wait window '¿Qué pasó?' &&nowait noclear

-5-
D:\Utiles\Motores\SQLite\PRUEBAS-ODBC\Ejemplo-VFP-accesando-SQLite-con-ODBC.prg Jueves, 04 de Julio del 2013 10:32 p.m.

** si llegó hasta aquí, sí hay problema... sólo se ejecuta sin parámetro (para registrar)
** o con el parámetro U (para des-registrar)...
return .f.

*----------------------------------------
** Es una idea interesante para visualizar datos y no me aguanté presentárselas
** obtenida de Internet, pero no recuerdo la fuente (la buscaré)
PROCEDURE BrowseSetup
IF NOT lBrowseSetup
WITH oBrowse AS GRID
.LEFT = 50
.TOP = 50

**** Row coloring ------------------------------


* Only works good with no index:
*.SETALL("DynamicBackColor","IIF(RECNO() % 2 = 0, 16777215, 16777088)","Column")
* This one works much better
.SETALL("DynamicBackColor","IIF(oBrowse.ActiveRow%2=0,16777215,16777088)","Column")

*** Fix the first column -----


.LOCKCOLUMNS = 1
.Columns(1).DynamicBackColor= ""
.Columns(1).BackColor = RGB(255,255,168)

.AUTOFIT()
.HIGHLIGHTSTYLE= 2
.ALLOWCELLSELECTION = .F.
.HIGHLIGHTBACKCOLOR = RGB(255,128,64)
.HIGHLIGHTFORECOLOR = RGB(0,0,0)
.Refresh

ENDWITH
lBrowseSetup = .T.
ENDIF
*----------------------------------------
return
ENDPROC

**

-6-

Potrebbero piacerti anche