martes, 26 de mayo de 2009

Acceder a MySQL con una Aplicacion simple:

Hola amigos,,,
Aqui os dejo un ejemplo simple de como acceder a una base de datos de MySQL y hacer un Browse,,, con TWBrowse.... luego veremos como hacer la Altas, Bajas y Reportes, pero eso si, utilizando pura sentencia SQL,,,

# include "fivewin.ch"
Static oWnd, oMySQl, oDBase, lConecta, lOkDb
//----------------------------------------------------------------------------------------Function Main()
local cHost, cUser, cPass, lOk, nPortlocal cDbName
lOk := .f.
lConecta := lOkDb := .f.
//-------parametros de entrada-------------------------------------//
cHost := "localhost" // en modo local
cUser := "pruebas" // usuario
cPass := "pruebas" // password
cDbName := "pruebas" // nombre de la base de datos
nPort := "3306"
//--------aqui nos conectamos al servidor--------------------------
ConectaMySQL(cHost, cUser, cPass, nPort)
If !lConecta
MsgInfo( "No Hay Conexión Con El Servidor " + cHost "" )
Return(.f.)
EndIf

oDBase := AbreDbMySQL(oMySQL, oDBase, cDbName)
If !lOkDb
MsgInfo( "No Se Puede Crear la Base De Datos " + cDbName + CHR(34), "" )
Return(.f.)
EndIF

DEFINE WINDOW oWnd
ACTIVATE WINDOW oWnd MAXIMIZED ;
ON INIT AMB(oWnd, oMySQL, oDBase) // siempre envio los handles,,,,,
Return(nil)
//--------------------------------------------------------------------
Function ConectaMySQL(cHost, cUser, cPass, nPuerto )
oMySQL := TMySQLServer():New(cHost, cUser, cPass, nPuerto)
IF oMySQL:NetErr()
lConecta := .f.
ELse
lConecta := .t.
EndIF
Return(lConecta)
//---------------------------------------------------------------------
Function AbreDbMySQL(oMySQL, oDBase, cDbName)
cDBName := AllTrim(cDbName)
oMySQL:Query( "CREATE DATABASE IF NOT EXISTS " + cDBName )
oDBase := oMySQL:SelectDB( cDBName )
IF oMySQL:NetErr()
lOkDb := .f.
Else
lOkDb := .t.
EndIF
Return(oDBase)

//-------esta funcion puede estar en otro prg---------------------
Function AMB(oWnd, oMySQL, oDBase)
local oSalir, oNuevo, oModif, oImpri, oElimi, tCargalocal oDlg, oLbx, oDatos, eDatos, oOrden
local nOrden, oAlgo, lAlgolocal aCol, oBrw, cQuery, nCont, nLen, aListaaCol := ARRAY(2)

cQuery := "SELECT * FROM kardex WHERE cod_producto = '20071121223230' ORDER BY num_movimiento LIMIT 500"
oDatos := oMySQL:Query(cQuery , .t. )
If oDatos:RecCount() == 0 && si no tiene datos...
oDatos:End()
MsgInfo("No hay registros")
Return(Nil)
EndIf

DEFINE DIALOG oDlg ; RESOURCE "PRODUCTOSTW" ; TITLE "FWH + HARBOUR + TMySQL + MySQL"

REDEFINE LISTBOX oLbx ;
FIELDS STR(MyCampo(oDatos, "ingreso"),12,2), ;
STR(MyCampo(oDatos, "egreso"),12,2), ;
STR(MyCampo(oDatos, "saldo"),12,2) ;
HEADERS "Campo1", ;
"Campo2", ;
"Campo3" ;
SIZES 150, 150, 150 ;
ID 200 OF oDlg
MySetbrowse(oLbx, oDatos ) // importante para la navegacion

ACTIVATE DIALOG oDlg CENTER //ON INIT createxb( oDatos, oDlg )
Return(nil)
*/
//----esta funcion permite manejar las tablas aun sin datos---------------
Function MyCampo(oBjeto, nCampo, nEnt, nDec)
local cCampo, cRet, nCol, nCont, cField, nPos
If VALTYPE(nCampo) = "C" // vino el nombre de un campo
nCampo := ALLTRIM(nCampo)
nPos := oBjeto:FieldPos(nCampo)
If nPos = 0 // no existe en campo en mencion
Msginfo("No Existe el Campo Indicado <" + nCampo + ">", "Error")
Return("")
EndIf
Else
nPos := nCampo
EndIf

DO CASE
CASE oBjeto:FieldType(nPos) = "N"
cCampo := 0
CASE oBjeto:FieldType(nPos) = "C"
cCampo := ""
CASE oBjeto:FieldType(nPos) = "L"
cCampo := ".f."
CASE oBjeto:FieldType(nPos) = "D"
cCampo := CTOD(" / / /")
OTHER cCampo := ""
ENDCASE

If oBjeto:RecCount() = 0
Return(cCampo)
EndIF
IF oBjeto:FieldType(nPos) = "U"
Return(cCampo)
EndIf
cCampo := oBjeto:FieldGet(nPos)
Return(cCampo)

Script de compilación de la LIB TMySQL

Bueno amigos,

Retomando la escritura.

Pues resulta que ayudando al amigo Dutch, hemos descubierto que las lib de TMySQL deben de estar en la posición siguiente para poder utilizar sin errores o GPF la lib mencionada.

SCRIPT Erróneo
ECHO %CC_LIB%\c0w32.obj + > b32.bc
ECHO %ARCHIVO%.obj, + >> b32.bc
ECHO xh%ARCHIVO%.exe, + >> b32.bc
ECHO %ARCHIVO%.map, + >> b32.bc
ECHO %FWH_LIB%\fivehc.lib + >> b32.bc
ECHO %FWH_LIB%\fivehx.lib + >> b32.bc
<< aquí el error >>
ECHO Y:\TSuperLib\TMySql\LIB\mysql.lib + >> b32.bc
ECHO Y:\TSuperLib\TMySql\LIB\libmysql.lib + >> b32.bc
<< termina error >>
ECHO %CC_LIB%\cw32.lib + >> b32.bc
ECHO %CC_LIB%\Import32.lib + >> b32.bc
ECHO %CC_LIB%\PSDK\msimg32.lib + >> b32.bc
ECHO %XC_LIB%\pcrepos.lib + >> b32.bc
rem La LIB FMSTAT.LIB es para sacar la estadistica de memoria
rem quitar si no se quiere
ECHO %XC_LIB%\ct.lib + >> b32.bc
ECHO %XC_LIB%\rtl.lib + >> b32.bc
ECHO %XC_LIB%\vm.lib + >> b32.bc
ECHO %XC_LIB%\gtgui.lib + >> b32.bc
ECHO %XC_LIB%\lang.lib + >> b32.bc
ECHO %XC_LIB%\macro.lib + >> b32.bc
ECHO %XC_LIB%\debug.lib + >> b32.bc
ECHO %XC_LIB%\common.lib + >> b32.bc
ECHO %XC_LIB%\pp.lib + >> b32.bc
ECHO %XC_LIB%\rdd.lib + >> b32.bc
ECHO %XC_LIB%\tip.lib + >> b32.bc
rem Poner el controlador o controladores que se vayan a usar
ECHO %XC_LIB%\dbfntx.lib + >> b32.bc
ECHO %XC_LIB%\dbfcdx.lib + >> b32.bc
ECHO %XC_LIB%\hsx.lib + >> b32.bc
ECHO %XC_LIB%\hbsix.lib + >> b32.bc
ECHO %XC_LIB%\dbffpt.lib >> b32.bc

SCRIPT Correcto
ECHO %CC_LIB%\c0w32.obj + > b32.bc
ECHO %ARCHIVO%.obj, + >> b32.bc
ECHO xh%ARCHIVO%.exe, + >> b32.bc
ECHO %ARCHIVO%.map, + >> b32.bc
<< aquí la corrección o lo correcto >>
ECHO Y:\TSuperLib\TMySql\LIB\mysql.lib + >> b32.bc
ECHO Y:\TSuperLib\TMySql\LIB\libmysql.lib + >> b32.bc
<< termina error >>
ECHO %FWH_LIB%\fivehc.lib + >> b32.bc
ECHO %FWH_LIB%\fivehx.lib + >> b32.bc
ECHO %CC_LIB%\cw32.lib + >> b32.bc
ECHO %CC_LIB%\Import32.lib + >> b32.bc
ECHO %CC_LIB%\PSDK\msimg32.lib + >> b32.bc
ECHO %XC_LIB%\pcrepos.lib + >> b32.bc
rem La LIB FMSTAT.LIB es para sacar la estadistica de memoria
rem quitar si no se quiere
ECHO %XC_LIB%\ct.lib + >> b32.bc
ECHO %XC_LIB%\rtl.lib + >> b32.bc
ECHO %XC_LIB%\vm.lib + >> b32.bc
ECHO %XC_LIB%\gtgui.lib + >> b32.bc
ECHO %XC_LIB%\lang.lib + >> b32.bc
ECHO %XC_LIB%\macro.lib + >> b32.bc
ECHO %XC_LIB%\debug.lib + >> b32.bc
ECHO %XC_LIB%\common.lib + >> b32.bc
ECHO %XC_LIB%\pp.lib + >> b32.bc
ECHO %XC_LIB%\rdd.lib + >> b32.bc
ECHO %XC_LIB%\tip.lib + >> b32.bc
rem Poner el controlador o controladores que se vayan a usar
ECHO %XC_LIB%\dbfntx.lib + >> b32.bc
ECHO %XC_LIB%\dbfcdx.lib + >> b32.bc
ECHO %XC_LIB%\hsx.lib + >> b32.bc
ECHO %XC_LIB%\hbsix.lib + >> b32.bc
ECHO %XC_LIB%\dbffpt.lib >> b32.bc

Entonces la nota sería, las lib de tmysql deben de ir exactamente al inicio donde se incluyen las LIB forzosamente. Si se hiciera de la manera incorrecta pues saldrían errores aleatorios y GPF.

Saludos

martes, 7 de abril de 2009

SQL como SQL

Hola amigos,Veamos, empezaremos por el principio:
Luego de batallar con las DBFs desde 1986 (full Clipper), en diciembre del 2006, por una cuestion de orgullo, decidi entrar de lleno al manejo de MySQL, vi un par de opciones, opte por una libreria que no usaba ODBC, la verdad es que tuve que batallar casi solo con el tema
del manejo de las tablas,,,,
20 años pensando en DBF, conociendolas al reves y al derecho, los tiempos cambian y las tecnologias tambien,,,
En el foro se dio mucha importancia en una momento a SQLWIN, pero el ultimo post es de feb2009, ADO la usa algunos seguidores, pero,,,, SQL se debe usar como SQL,,,
Utilizar MySQL como si tubieran tablas DBF, me parece usar un formula 1 con llantas de bicicleta, no desmerezco las DBFs, me dieron mucho, pero la potencia de SQL es otra cosa,,,
TMySQL me parece una muy buena libreria (fuentes abiertas) para acceder a MySQL, empeze con unas pruebas basicas, "INSERT, UPDATE, DELETE,SELECT,CREATE,DROP,ALTER" ups,,, ya estaba con todo el MySQL encima,,,
Pues es eso mismo, el poder de cada sentencia de MySQL o SQL en general es fabuloso, ademas la curva de aprendizaje en corta, basicamente con lo que tiene TMySQL se pueden hacer aplicaciones comerciales estupendas,,, ya mismo estoy desarrollando una app para Hoteles, y de momento todo funciona ok, incluso ya se resolvio el manejo de los "store procedure" (gracias William) entre otras cosillas, pero basicamente TMySQL debe ser potenciada, afinada y formar parte integral de la comunidad Fivewin.
Amigos lectores, animense a entra al mundo SQL, y TMySQL es la mejor opcion para MySQL, recuerden, las fuentes estan disponibles, y claro, estoy a vuestra disposicion para cualquier consulta a nivel de MySQL,,, si no tengo la respuesta, tendre el numero de telefono del que la sabe...
Salu2
Willi Quintana

martes, 24 de marzo de 2009

TMySql y la creación de Contenedores y Tablas

Quiubo espero estemos bien,

He notado que muchos compañeros que se han animado a probar esta fabulosa clase han tenido el problema o por lo menos la duda de como crear tablas y base de datos.

Muchos prefieren el modo xBase otros prefieren la manera SQL directa.

Veremos la manera xBase primero, Veremos como iniciar la conexión de igual manera..

#include "fivewin.ch"

STATIC oCon

FUNCTION main()
MSGRun( "Conectando a server-sql, espere...", "INCOS - wmormar", ;
{|| oCon := TMYsqlServer():new( "localhost", "root", "123", 3306)} )
IF oCon:lError
? "Se ha generado un error, no hay conexión, verifique..."
RETURN NIL
ENDIF

IF oCon:DBExist( "tutor" )
MSGRun( "Creando contenedor, espere...",, {|| oCon:DBCreate( "tutor")} )
ENDIF

oCon:SelectDB( "tutor" )
IF oCon:lError
? "No se pudo seleccionar el contenedor..."
RETURN NIL
ENDIF

// Aquí llamaremos a la creación de la tabla tipo xbase
createxbase()

// Aquí llamaremos a la creación de la tabla SQL directa
createsqldirecta()

oCon:end()

RETURN NIL

STATIC FUNCION createxbase()
LOCAL aTabla := {}

aadd( aTabla, { "clave" , "C", 10, 0} )
aadd( aTabla, { "nombre" , "C", 40, 0} )
aadd( aTabla, { "otro" , "N", 5, 0} )
aadd( aTabla, { "otromas" , "N", 6, 2} )

// Sintaxis de :createtable()
// CreateTable( cTable, aStruct, cPrimaryKey, cUniqueKey, cAuto)
IF !oCon:createtable( "modoxbase", aTabla, "clave" )
? "No pudo crear la tabla, verifique..."
ENDIF

RETURN NIL

STATIC FUNCION createsqldirecta()
LOCAL cQuery

cQuery := [CREATE IF EXISTS modosql( ]
cQuery += [clave varchar(10) DEFAULT "wmormar", ]
cQuery += [nombre varchar(40) DEFAULT "william morales", ]
cQuery += [otro int(5) DEFAULT 0, ]
cQuery += [otromas decimal(6,2) DEFAULT 0.00, ]
cQuery += [PRIMARY KEY ("clave") ]
oCon:Query( cQuery )

IF oCon:lError
? "No se pudo crear la tabla, verifique..."
ENDIF

RETURN NIL

Bueno, pasamos a explicarlo.

En la primera función (la principal) hacemos la respectiva conexión al serveidor mysql, el cual está alojado en la misma maquina donde estamos codificando (localhost).

Ahí lo que hacemos, es tener una variable Estática oCon, la cual será visible en todo el PRG, está contendrá la conexión al servidor.

Con la data lError (oCon:lError), verificamos que se esté aceptando nuestras operaciones en el servidor, es decir, que lo que estemos haciendo sean correctas.

También verificamos que el Contenedor (base de datos) exista, eso lo hacemos con: oCon:DBExist( "tutor" )

Si el contenedor no existe, pues lo creamos, esto lo hacemos con: oCon:DBCreate( "tutor" )

Después lo colocamos en uso o activo. Debemos recordar siempre que es necesario, de hecho es una regla, que para hacer cualquier tipo de consulta, debemos de colocar en uso o activo un Contenedor. Es una regla de oro.

Ya teniendo todo esto colocado, podremos hacer lo que queramos en el servidor. Por ejemplo: INSERT, UPDATE, DELETE, ETC.

Recordemos cerrar la conexión del server antes de cerrar nuestra aplicación: oCon:end()

Bueno, pasamos a la función que crea la tabla en "modoxbase". Creamos una variable tipo Array de igual manera que lo hacemos para crear una DBF. La llenamos con la estructura a crear.

Ya llenada la estructura usamos el método: CreateTable( cTable, aStruct, cPrimaryKey, cUniqueKey, cAuto) de la siguiente manera:
oCon:createtable( "modoxbase", aTabla, "clave" )

En este caso la tabla se llamará "modoxbase", conteniendo la estructura colocada en el Array e indicando que tendrá una Primary Key "clave". Si se dan cuenta es el mismo nombre que nuestra primera columna (antes le llamamos campo). Después vodificamos para que nos indique si se creó o no.

Bueno, en nuestra ultima funcion de esta entrada, estamos viendo como podemos de igual manera crear una tabla, desde sentencias SQL directas. Y vamos con lo que sigue.

En una variable local hemos incluido el código totalmente SQL, éste indica como se llamará nuestra tabla, y la misma sentencia tambien verifica si la tabla existe o no, asi que el SERVER mysql se encarga de verificar la existencia de la tabla y actua según la condición expresada, así mismo también verificamos que la sentencia se haya ejecutada con un condicional.

Espero sea de ayuda esta breve explicación, nos leemos en la próxima.

Saludos

sábado, 14 de marzo de 2009

Y proseguimos...

Como está dividida la tmysql.

Bueno, está dividida en 4 clases.
TMySqlServer()
Está es la clase principal y la que se encarga de hacer la conexión y
el respectivo query (consulta)

TMySqlQuery()
Aquí se procesa la consulta y se asignan los registros para manejo tipo xBase
Está clase es para su uso cuando mandamos un SELECT con una varias tabla.
Lo que llamamos un SET RELATION en SQL se llama INNER JOIN, INNER LEFT

TMySqlTable()
Hace exactamente lo mismo que el TMySqlQuery(), pero con la particularidad de
que solo maneja una tabla.

TMySqlRow()
Aquí hace el manejo de los registros (que en SQL están definidas como FILAS)
Graba en Hashes o Array la fila actual.

Hasta aquí debemos de tener un poco claro que hace cada clase.

Les comento que hago mi mejor esfuerzo para poder explicarlo, cuando charlo con algún amigo, comentamos sin problemas, pero cuando tengo que teclearlo, siempre me trabo.

Saludos

Continuamos...

Hasta ahora, debemos de crear nuestra LIB sin problema alguno.

Aunque las dudas que esperaba no se han hecho visibles, asumo que todo va en orden hasta ahora.

Ha sido poco, pero creo que sustancioso.

Uno de los problemas que en lo personal me encontré al iniciar fue y más que problema fue el hecho de pensar si mis aplicaciones terminadas iban a funcionar o no. Les comento que "casi" todas las herramientas que están circulando funcionan, unas mas otras menos, pero todas funcionan, o por lo menos la mayoría, decir todas representa una gran responsabilidad. Pero, les comento que hagan las pruebas necesarias con todas las herramientas que puedan, desde luego si todavía no han decidido cual usar. Aunque a lo largo del tiempo que he venido siguiendo varias herramientas me he convencido totalmente que no hay mejor herramienta que la que le podamos usar el provecho máximo, eso si, sin minimizar o criticar ninguna.

En el próximo artículo-comentario, veremos una descripción de las datas y métodos mas importantes de la TMySql.

Saludos

lunes, 23 de febrero de 2009

Comentarios ADO-TMYSQL

Conversación entre Armando y un servidor.

Armando dice:
Epa, paisano
Estas despierto ?
!! [INCOS] william morales dice:
quiubo mi estimado
Armando dice:
Saludando a las estrellas !
!! [INCOS] william morales dice:
gracias amigo
igualmente
wmormar.blogspot.com
ahi mi blog y estoy escribiendo sobre la tmysql
haz leido algo?
Armando dice:
Claro, no me lo pierdo
Quiero tener otra altenativa
!! [INCOS] william morales dice:
hoy me toco escribir
Armando dice:
Sip, ya lo vi
Perooooooo
Resulta que en la carpeta donde tengo instalado el servidor no hay carpeta de INCLUDES
O sera que no la veo ?
!! [INCOS] william morales dice:
eso depende de como hayas instalado el server
Armando dice:
Ok ok
Puede ser ahi el problema
!! [INCOS] william morales dice:
preo puedo colgar los includes
Armando dice:
Pero deben coincidir con la versión que tengo instalada de MySql, no ?
!! [INCOS] william morales dice:
no necesariamente
pero de preferencia, desde luego
Armando dice:
Ok
Si no recuerdo mal, instale MySql como SERVER y creo que debería ser como DEVELOPER
Sera cierto ?
!! [INCOS] william morales dice:
asi es
Armando dice:
Bueno, al menos ya se donde esta mi falla
ahora, sería mucha molestia si pasas los INLCUDE ?
!! [INCOS] william morales dice:
dja colgarlo al blog
para que los demás lo tengan
Armando dice:
Ok, gracias
!! [INCOS] william morales dice:
que te parece?
Armando dice:
Como te decia, a mi me parece excelente tener otra alternativa
No me cierro a que todo sea ADO
!! [INCOS] william morales dice:
yo he usado tmysql, ADO no le tomo cariño aun
pero no lo descarto
Armando dice:
Tengo otra pregun tonta
Usando la TMySql al hacer una SELECT que se crea ?
!! [INCOS] william morales dice:
algo como un recordset
Armando dice:
Me explico, con ADO se crea un record set (Tabla)
Pero si entiendo bien es un ARRAY, cierto ?
!! [INCOS] william morales dice:
solo el registro
lo demás no
es el recordset
Armando dice:
No me queda claro, disculpa master
!! [INCOS] william morales dice:
bueno, hay dois formas
puedes usar la forma de arreglo
y la forma del recordset
Armando dice:
Ok ok
Fijate que tambien en ADO tienes ambas posibilidades
Hasta ahi vamos bien
Volviendo al tema, por ejemplo, yo ya estoy acostumbrado al record set
usando la TMySql lo puedo seguir trabajando igual ?
!! [INCOS] william morales dice:
cambia un poco
como cargas los datos desde ADO?
Armando dice:
Como cargo los datos al Browse ?
O te refieres al SELECT ?
!! [INCOS] william morales dice:
por ejemplo yo hago lo sigguiente
oQry := oCon:Query( "SELEC * FROM CLIENTES" )
cClave := oQry:fieldget( "clave" )
cNombre := oQry:fieldget( "nombre" )
como lo haces tu en ADFO?
Armando dice:
Ahhh
Es parecido
oRsFol: Source := "SELECT " +;
"* " +;
"FROM " +;
"folfac"

Luego
oRsFol: Open()

Con esto ya tengo creado el Record set
!! [INCOS] william morales dice:
oQry := oCon:Query( "SELEC * FROM CLIENTES" )
aqui ya tengo creado el recordset
Armando dice:
Y luego para referirme a un campo en particular lo hago así
oRsHdr:Fields("CLI_NOM"):Value)
Y como defines una columna en un TXbrowse ?
!! [INCOS] william morales dice:
acá
cClave := oQry:fieldget( "clave" =
como ADO
asignas el nombre del campo
Armando dice:
Pues es muy parecido
Desde luego cambia pero no es cosa del otro mundo
!! [INCOS] william morales dice:
claro, claro
Armando dice:
Otras dudas, puedo ?
!! [INCOS] william morales dice:
claro
Armando dice:
Descargue la LIB de las contribuciones
Revisando un poco veo que esta muy abandonada
Creo que la ultima revisión es del 2006
No hay problema con eso ?
Sera que la abandonaron o tal vez ya esta en su punto ?
!! [INCOS] william morales dice:
nones
ha sido modificada por Walter
hay una version por ahi
Armando dice:
Okas
Bueno, mira
Yo te voy a seguir
Te repito siempre es bueno tener otra alternativa, no me cierro
!! [INCOS] william morales dice:
perfecto
autrizas colocar esta conversación en el blog?
Armando dice:
No te hago más preguntas para no adelantarnos al blog
por supuesto
!! [INCOS] william morales dice:
okas, okas
la proxima semana, haremos un miniproyecto
espero me de tiempo
porque esta semana, andaré un poco ocupado
Armando dice:
Ok, no hay urgencia, al menos por mi, jeje
!! [INCOS] william morales dice:
okas, okas
veré la audicnecia amigo
aunque dejame decirte que tengo casi 250 visits desde el inicio del blog
y dos seguidores logueados
Armando dice:
Mira, ya por ahi alguien lo dijo
La mayoria solo lee
Pocos son los que tienen iniciativa para interactuar
!! [INCOS] william morales dice:
asi es, lo tengo claro
solo que espero se anime mas gente
Armando dice:
Así que no te desanimes si no ves mucha respuesta
!! [INCOS] william morales dice:
faltaba info y me decidi a aportar una poca
Armando dice:
Cuando menos yo te voy a seguir
Y estaré molestando con pregun-tontas, jejeje
!! [INCOS] william morales dice:
eso me reconforta y anima amigo
aun asi fuese uno, espero seguir hasta donde la fuerza me acompañe
jjejjejjejjejje
Armando dice:
ok, éxito
!! [INCOS] william morales dice:
saludfos amigo, por aqui sigo aun
Armando dice:
=mente, bytes


Conversación autorizada por Armando.

Saludos
William Morales