1 de noviembre de 2008

Soluciones SSH con FoxPro

Hace poco se presentó el desafío de conectarme a través de Hamachi a un servidor, y por esa misma conexión crear una aplicación que pueda correr a través de SSH.

Por supuesto lo primero que pensé es hacerlo en VFP, pero la conexión SSH en Windows no permite levantar interfaces gráficas, así que las solución fue FPD (FoxPro para DOS) y VFP (Visual FoxPro).

Aquí les presento la solución.

Por defecto FPD no provee un medio para hacer conexión a SQL, hay una librería FLL que anda dando vuelta por ahí, pero con SQL Express 2005 es un verdadero problema. La solución, como siempre en FoxPro, es mas sencilla de lo que parece.

Lo primero que hice es crear una App en VFP que haga las consultas a SQL, algo así:
PARAMETERS lcinifile,ltabla
_screen.Visible= .F. 
SET RESOURCE  OFF
PUBLIC lc_con
SET ECHO OFF
SET TALK OFF
SET SAFETY OFF 
SET NOTIFY OFF 
SET default TO (JUSTPATH(SYS(16,0)))
lcpath = JUSTPATH(SYS(16,0))
lcpathini = lcpath + "\" + lcinifile
SQLSETPROP(0,"DispLogin",3)
lc_con=SQLCONNECT("localdb","miuser","mipass")
if m.lc_con < 0
  nopc = MESSAGEBOX("No se pudo conectar via DSN, talvez ODBC no este configurado",0+48,"Error")
ELSE
  lcselect=LeerIni('consulta','lselect',lcpathini) 
  lctipo=leerini('consulta','tipo',lcpathini)
  DO case
    CASE ALLTRIM(UPPER(lctipo)) = "SELECT"
      m.nresult = SQLEXEC(m.lc_con,lcselect,ltabla)
      SELECT (ltabla)
      ltabla = JUSTPATH(SYS(16,0)) + "\" ltabla + ".dbf"
      COPY TO (ltabla) TYPE FOX2X 
    CASE ALLTRIM(UPPER(lctipo)) = "INSERT"
      m.nresult = SQLEXEC(m.lc_con,lcselect)
    CASE ALLTRIM(UPPER(lctipo)) = "UPDATE"
      m.nresult = SQLEXEC(m.lc_con,lcselect)
    CASE ALLTRIM(UPPER(lctipo)) = "DELETE"
      m.nresult = SQLEXEC(m.lc_con,lcselect)
    CASE ALLTRIM(UPPER(LCTIPO)) = "STORE"
      mc_select(lctipo,lcselect,ltabla)
      SELECT (ltabla)
      ltabla = JUSTPATH(SYS(16,0)) + "\" ltabla + ".dbf"
      COPY TO (ltabla) TYPE FOX2X 
  ENDCASE 
ENDIF 
El procedimiento LeerIni lo pueden encontrar en este mismo portal. Es un procedimiento para leer archivos .INI y el mc_select no es mas que un procedimiento donde esta la variable m.nresult simplificado para pasarles parámetros.

Bueno ... esta aplicación recibe dos parámetros lcIniFile y lTabla, donde lcIniFile es el archivo .INI que debe tener las siguientes claves este archivo .INI lo arma FPD) por ej:
[CONSULTA]
LSELECT=select * from Vista_Vehiculo_Grupo ORDER BY codigo_interno
tipo=select
Y lTabla es el nombre de tabla que quieren crear.

En una App en FPD 2.6 hay que armar el siguiente procedimiento en un PRG con nombre mcSelect (usen el que mas les guste)
 parameter lctipo,lcselect,lccursor,lcini
 lcini=lcini+".ini"
 SET TEXTMERGE ON
 SET TEXTMERGE TO (lcini) NOSHOW
 \[CONSULTA]
 \LSELECT=<<LCSELECT>>
 \tipo=<<lctipo>>
 SET TEXTMERGE OFF
 SET TEXTMERGE TO
 lcmacro1="run odbcvfp.exe "+lcini+" "+lcCursor
 &lcmacro1
Esta rutina recibe lctipo,lcselect,lccursor,lcini

Donde:
lctipo es el tipo de Sql Statement que desean hacer SELECT, INSERT,UPDATE,DELETE o EXEC en este ultimo uso STORE.

lcselect es el Sql Statement que le pasan.

lccursor es la tabla que desean obtener

lcini el archivo .INI que desean armar para que odbcvfp ejecute la consulta

Una vez que recibe los parametros arma un archivo .INI ejecuta odbcvfp (visto mas arriba) que arma el cursor que necesitamos o simplemente ejecuta la consulta

Eso es todo ... ahora para que FPD pueda hacer una consulta a un servidor SQL habria que hacer asi
lc_select1="select * from personal order by nombre"   && armo la consulta
do mcselect with "insert",lc_insert2,"tPer","bal5"   && ejecuto la consulta
*esto arma la tabla tPer 
use tPer in 0
select tper
browse
Y listo ... FPD ahora puede hacer consultas a un cualquier servidor a través de ODBC!!! desde acá usen su imaginación !!!


Saludos

Carlos Emilio