Guia completa de Lazarus + Zeos + Firebird

Iniciado por daragor, Ago 02, 2022, 07:59 AM

Tema anterior - Siguiente tema

daragor



En este post vamos a hacer una guía paso a paso de lo que sería el desarrollo de una aplicación creada con el IDE Lazarus (lenguaje Free Pascal) (clone de Delphi gratuito y open source), el complemento Zeos para la conectividad con la base de datos y el poderoso administrador Firebird ya sea para trabajar de manera embebida o en local.

Lo primero será descargar un programa IBExpert, en su version gratuita (uso personal) desde la Web Oficial
Esta versión de ibexpert nos será suficiente para el tutorial. Instalamos.

Ahora nos toca descargar e instalar Firebird, en la versión indicada para nuestro S.O., en este caso usamos Windows 7 32bits
Vamos a la web oficial y entramos en la sección Downloads, Server Packages, en este momento está la versión 2.5.x de la plataforma, elegimos el instalador e instalamos.



Aquí vamos a hacer una sola aclaración para poder comenzar con firebrid pero si quieren más detalles, tutoriales, guías, etc., les recomiendo esta página que esta muy muy desarrollada y en español: https://firebird21.wordpress.com

Firebird, tiene varias arquitecturas: SuperServer, Classic y SuperClassic y en la instalación nos pregunta cual queremos usar, esto tiene que ver con las cantidad de usuarios que van a trabajar (mono - multi), después de leer un poco, elegimos superserver para windows. Si quieren conocer más en detalle les dejo el link correspondiente: Diferencias entre SuperServer, Classic y SuperClassic
Otras opciones importantes que vamos a tildar en el instalación son:
- Usar el Guardián, Instalar applet del panel de control y copiar la libreria al directorio System y copiar la librería gds32.dll
- Destildamos Iniciar Firebird automáticamente con el inicio de windows.

Bueno, ahora, cada vez que necesitemos correr el servidor firebird de manera local, ejecutamos el applet (icono) del panel de control y clickeamos en "Start", "Stop" para detenerlo. Si quieren pueden hacer un acceso directo al escritorio.



* Firebird usa el lenguaje SQL para sus consultas

Ahora vamos a crear una base de datos firebird para nuestro programa en lazarus. La idea que se me ocurre es una agenda de contactos, basica solo para ver un ejemplo de altas, bajas, modificaciones de registros y consultas generales y con algunos filtros.

Corremos el servidor, abrimos IBExpert y creamos una nueva BD. Desde el menú DataBase -> Create DataBase
Como vemos en la ventana, configuramos:



Server: Local
Database: hacemos clic en el icono navegador con forma de carpeta y en el directorio correspondiente vamos a indicar un nombre, en nuestro caso le llamamos basedatos.fbd
Username: SYSDBA / Password: masterkey (son los que vienen por defecto)
Charsert: UTF-8

Presionamos OK y se nos abrirá la ventana de Registro de BD, en este caso solamente seleccionamos la Server Versión: Firebird 2.5 y luego clickeamos el boton "Register", Listo aparece al costado izquierdo en la lista Database Explorer (bases de datos registradas y creadas). Desde allí, haciendo doble click en el nombre nos conectamos. En el submenú "Tables" hacemos click derecho y "New Table"

Ahora vamos darle un nombre y armamos el esquema, con los campos correspondientes:
ID = integer
APENOM = varchar(65)
TELEFONO = varchar(25)
DIRECC = varchar(80)
EMAIL = varchar(40)



Una vez configurada, compilamos la tabla con el rayo amarillo del menú (se ve en la imagen el cursor), Nos aparece una ventana y presionamos el botón "Commit", Listo la tabla está creada, registrada y aparece listada en el explorador de la izquierda. Esto es básico! tanto en los datos como en los tipos de campos, si desean más info deben investigar, ya que firebird no es el propósito del tutorial. Por ejemplo el campo ID podría ser autoincremental (con un generador) pero en este caso no lo vamos a usar.

Ahora vamos a Lazarus y comenzamos a programar!
Aclaro nuevamente que no vamos a detallar todos los pasos ya que el tutorial trata sobre otros conceptos no sobre usar lazarus o instalar un complemento como zeoslib, suponemos que ya esta instalado correctamente.

Continua...

daragor

Creamos un nuevo Proyecto -> Aplicación

Ya contamos con le unidad y el formulario principal, les coloco el nombre main y f_main respectivamente.

En el formulario principal vamos a agregar unos objetos zeos como se ve en la siguiente imagen:



Encontramos:
- TZConnection el cual realiza la conexión con la base de datos, le llamaremos conex
- ZQuery1 y ZQuery2 dos objetos del tipo query uno para listar y otro para ejecutar consultas SQL = los llamaremos qlista y qexe
- TDataSource1 este es de lazarus y se utiliza para almacenar datos de la consulta = lo llamaremos datos

* qlista lo usaremos para los SELECT y qexe para los INSERT, UPDATE, DETELTE, etc.
Bueno procedemos a configurar, primero el conex: les dejo una imagen para ser más gráfico con los propiedades del objeto



Connected: false (por ahora)
Database: localizamos el archivo con el directorio completo creado previamente (basedatos.fbd)
Hostname: localhost por ahora será con el servidor corriendo en windows
Password: masterkey
Protocol: Firebird-2.5
User: SYSDBA

SI tenemos el servidor firebird corriendo podemos settear el Connected en "true" y debería conectarse a la BD correctamente, si legamos aquí vamos por buen camino, ya que tenemos un objeto en lazarus conectado con una base de datos firebird.

En esta primera parte de lazarus vamos a trabajar de esta manera, una vez terminada la aplicación, lo pasaremos a firebird embebido.

Ahora configuramos los querys:
Ambos querys -> Connection: conex (objeto de conexion)
En qlista aparte debe configurarse lo siguiente: DataSource: datos



Y el DataSource debe llevar como Dataset: qlista



En palabras simples los que hacemos es: darle acceso a los 2 querys a la base de datos indicándole que conexión usar, luego al datasource lo linkeamos con qlista para almacenar los resultados de manera tal que los tendremos disponibles para trabajar y/o mostrarlos en pantalla, por último vamos a agregar una instrucción más al qlista, que será la sentencia SQL que tomará todos los datos de la tabla Contactos. Un Select básico, quiero aclarar que para el tutorial voy a usar comando sql básicos, sin transacciones, ni commits, rollbacks, etc. inyección directa!

Este comando, al activar qlista traerá todos los contactos de la base de datos y vamos a mostrarlos en un DBGrid, para eso lo seleccionamos del menu de lazarus y lo agregamos en el formulario con el nombre "lista". En la configuración del DBGird indicaremos en DataSource: datos (configurado anteriormente con el resultado de qlista)

Aquí vamos a tener contacto por primera vez con los campos de una tabla en la BD:
1. Activamos el qlista desde las propiedades, Active: true (no debe dar error ni freezar lazarus, debe estar conectado conex)
2. Vamos a ingresar en la propiedad Columns del DBGird y se nos abre una ventana donde Añadiremos los Campos que vamos a mostrar, indicando principalmente: el FieldName (que se toma de la tabla) para cada columna agregada, ver la imágen, también hay otras opciones interesantes de diseño y presentación que podremos ver en otro momento. Veremos en la grilla los campos de la tabla.





Luego pueden configurar algunas otras opciones del DBGird, a modo de personalización:
dgColumnMove: false; dgEditing: false; dgRowSelect: true; Scrollbars: ssVertical; la fuente, el tamaño, los colores, etc. etc. etc.

Para terminar esta parte del tutorial vamos a hacer 2 cosas, primero desactivamos el qlista (Active: false) desde el formulario y lo vamos a activar desde el Evento -> OnActivate del formulario:



Luego, guardamos todos los cambios, compilamos y ejecutamos el proyecto, todo debe marchar bien... obviamente aun no tenemos ningún contacto cargado.

Continua...

daragor

#2
En este punto pueden insertar un TDBNavigator para trabajar con la BD, yo voy a hacerlo de forma manual.
Dicho esto, lo siguiente que hice fue agregar algunos objetos necesarios al formulario como se ve en la imágen de abajo. Detallo:

4 TLabeledEdit: para ingresar los datos, en las propiedades destaco los nombres: t_apenom, t_tel, t_dire, t_mail, los captions, el maxlength de cada uno correspondientes a lo que configuramos en la tabla (65,25,40 y 80) campos varchar. El resto corre por cuenta de uds.

5 TBitBtn: son botones con la capacidad de agregarle un icono, que luego lo voy a hacer. Cada botón tiene su nombre (b_nvo, b_mod, b_elim, b_graba, b_imp) y será usado para el ABM (altas, bajas y modificaciones) un botón "Guardar" y uno "Imprimir" centrados en pantalla. No estoy pensando mucho en el diseño la verdad.



Seguido vamos a deshabilitar el botón Guardar (enabled: false) y voy a settear las cajas de texto en readonly: true;

Ahora vamos a proceder a Crear un Nuevo Contacto, ya cada uno maneja su programación de forma personal, lo que voy a mostrar es lo que uso con cada botón para ejecutar las consultas SQL. Por ejemplo yo creo un procedimiento para habilitar y deshabilitar los campos de texto y los botones correspondientes a cada acción. Otro para controlar los campos obligatorios antes de Guardar, etc.

Tengo hasta el momento creadas 2 variables en la Unidad
  OP: char;      {Tipo de operacion SQL}
  cid: integer;  {Variable ID usuario}

Botón NUEVO:
Recordemos que no hemos configurado en la tabla un autoincrement para el ID del contacto, así que vamos a crearlo, posterior vamos a hacer el INSERT del nuevo usuario en la tabla y por ultimo refrescamos la consulta qlista para ver los cambios.
procedure Tf_main.b_nvoClick(Sender: TObject);
begin
  // ID DE CONTACTO
  qexe.Active:= false;
  qexe.SQL.Clear;
  qexe.SQL.Text:= 'SELECT id FROM contactos ORDER BY id ASC';
  qexe.Open;
  // Inicializo la variable
  cid:= 1;
  if not qexe.IsEmpty then
  begin
    qexe.Last;   {Ultimo}
    cid:= qexe.FieldByName('id').Value + 1;
  end;
  // ----------------------
  cnro.Caption:= inttostr(cid);
  OP:= 'A';      {Operacion = ALTA}
  habdes();      {Habilita/Deshabilita}
  t_apenom.SetFocus;
end;

Con esto ya podemos llenar los datos, previo control de "vacios", y Guardar el nuevo contacto en la tabla. El guardar lo haremos en 2 partes, por que nos faltará el MODIFICAR...

Botón GUARDAR 1:
procedure Tf_main.b_guardaClick(Sender: TObject);
begin
  // Uso el mismo objeto query para trabajar
  qexe.Active:= false;
  qexe.SQL.Clear;
  if OP = 'A' then    {NUEVO}
  begin
    qexe.SQL.Text:= 'INSERT INTO contactos(id,apenom,telefono,direcc,email)'+
    'VALUES(:ID,:AN,:TE,:DI,:EM)';
    qexe.ParamByName('ID').AsInteger:= cid;
  end;
  {Parametros Generales}
  qexe.ParamByName('AN').AsString:= trim(t_apenom.Text);
  qexe.ParamByName('TE').AsString:= trim(t_tel.Text);
  qexe.ParamByName('DI').AsString:= trim(t_dire.Text);
  qexe.ParamByName('EM').AsString:= trim(t_mail.Text);
  qexe.ExecSQL;
  // LISTO!
  qlista.Refresh;
  habdes();
  cnro.Caption:= '...';
end;



* Para los comandos de la consulta SQL uso siempre parametros, para mi la mejor forma de no cometer errores ya que el mismo lenguaje se encarga de settear los formatos correctos.

Ahora vamos a programa el botón Modificar, el cual tomará los datos del contacto seleccionado del listado.

Botón MODIFICAR:
procedure Tf_main.b_modClick(Sender: TObject);
begin
  // Primero habilito objetos
  habdes();
  // Muestro los datos en los textbox
  t_apenom.Text:= qlista.FieldByName('apenom').Text;
  t_tel.Text:= qlista.FieldByName('telefono').Text;
  t_dire.Text:= qlista.FieldByName('direcc').Text;
  t_mail.Text:= qlista.FieldByName('email').Text;
  // ----------------------
  cid:= qlista.FieldByName('id').Value;
  cnro.Caption:= inttostr(cid);
  OP:= 'M';      {Operacion = MODIFICA}
  t_apenom.SetFocus;
end;

Y agregamos, editamos, el botón Guardar con los nuevo códigos

Botón GUARDAR 2:
procedure Tf_main.b_guardaClick(Sender: TObject);
var
  msje: string;
begin
  // Uso el mismo objeto query para trabajar
  qexe.Active:= false;
  qexe.SQL.Clear;
  if OP = 'A' then    {NUEVO}
  begin
    qexe.SQL.Text:= 'INSERT INTO contactos(id,apenom,telefono,direcc,email)'+
    'VALUES(:ID,:AN,:TE,:DI,:EM)';
    msje:= 'Contacto Cargado Correctamente!';
  end else begin      {MODIFICA}
    qexe.SQL.Text:= 'UPDATE contactos SET apenom=:AN,telefono=:TE,direcc=:DI,'+
    'email=:EM WHERE id=:ID';
    msje:= 'Contacto Modificado Correctamente!';
  end;
  {Parametros Generales}
  qexe.ParamByName('ID').AsInteger:= cid;
  qexe.ParamByName('AN').AsString:= trim(t_apenom.Text);
  qexe.ParamByName('TE').AsString:= trim(t_tel.Text);
  qexe.ParamByName('DI').AsString:= trim(t_dire.Text);
  qexe.ParamByName('EM').AsString:= trim(t_mail.Text);
  qexe.ExecSQL;
  // LISTO!
  qlista.Refresh;
  habdes();
  cnro.Caption:= '...';
  showmessage(msje);
end;



He modificado la sentancia SQL, ya que el parametro ID también es compartido por ambas. (ver if - else) también he agregado un mensaje de aviso de la acción realizada.

Pueden ver en IBExpert como la tabla se va llenando, desde la pestaña "DATA"



Por último en esta parte ABM del tutorial voy a terminar con el botón Eliminar... Agrego una pregunta de seguridad y elimino de la tabla.

Botón ELIMINAR:
procedure Tf_main.b_elimClick(Sender: TObject);
begin
  if not qlista.IsEmpty then
  begin
    //*Pregunta de Seguridad?
    if MessageDlg('ATENCION!!','Está seguro que desea ELIMINAR este Contacto'+#13+
    'de la Base de Datos? Este proceso es Irreversible!'+#13+#13+
    '- '+uppercase(qlista.FieldByName('apenom').Text),
    mtConfirmation,[mbYes, mbNo],0) = mrYes then
    begin
      qexe.Active:= false; qexe.SQL.Clear;
      qexe.SQL.Text:= 'DELETE FROM contactos WHERE id=:ID';
      qexe.ParamByName('ID').AsInteger:= qlista.FieldByName('id').Value;
      qexe.ExecSQL;
      qlista.Refresh;
    end;
  end;
end;



Listo! Como te fue con el ABM? Continua...

daragor

En esta parte del tutorial vamos a crear un filtro por palabras, tipo buscador.

1. Filtro por palabras: en este caso insertamos un TLabeledEdit llamado "xpal", configuramos el diseño y en el evento OnChange, programamos lo siguiente:
procedure Tf_main.xpalChange(Sender: TObject);
var
  fpal: string;
begin
  if (xpal.Text <> '') then
  begin
   fpal:= uppercase(trim(xpal.Text));         {Tomo letra x letra}
   qlista.Active:= true; qlista.SQL.Clear;
   qlista.SQL.Text:= 'SELECT * FROM contactos WHERE apenom CONTAINING :PAL ORDER BY apenom ASC';
   qlista.ParamByName('PAL').AsString:= fpal;
   qlista.Open;
   ccan.Caption:= inttostr(qlista.RecordCount);
  end else todos(); {Sin Filtro x Palabra}
end;
* CONTAINING funciona con firebird y no es CaseSensitive, hay otras posibilidades como LIKE.

Si se fijan, en el "else" tenemos un proceso llamado: todos(); Lo que pasa es que he quitado la instrucción SQL que le había puesto al "qlista", osea que lo dejé en blanco, y he creado el proceso todos() para listar todos los contactos, lo dejo más abajo. Entonces cambian algunas cosas, como ser el qlista.Active:= true; en el FormActivate del formulario, esto no va a funcionar xq ya no hay instrucción SQL predefinida, entonces lo que debemos hacer es cambiar esta instrucción por: todos();

procedure Tf_main.todos();
begin
  qlista.Active:= true; qlista.SQL.Clear;
  qlista.SQL.Text:= 'SELECT * FROM contactos ORDER BY apenom ASC';
  qlista.Open;
  ccan.Caption:= inttostr(qlista.RecordCount);
end;

Una vez hecho esto podemos probar el filtro, otras cosas que agregué fue un contador en el titulo de la lista llamado ccan que al pasar el resultado del query a str (es un integer con recordcount) muestra la cantidad de contactos (registros) cargados en la tabla. A medida que vamos intertando palabras se va a ir filtrando la lista, si no hay palabras muestra todos.

Sin Filtro: 10 contactos


Filtrados:




Ahora vamos a configurar firebird embebido para que el programa trabaje de manera independiente:

Primero vamos a colocar los archivos necesarios en la carpeta donde creamos la BD, los archivos son:



Segundo: en el objeto "conex" configuramos connected: false; Database: vacio; Hostname: vacio; (ver imágen)



Por último vamos a modificar el FormActivate del main programando un "Try" de conexión, si conecta ejecutamos el proceso "todos()" y estamos listos para trabajar de forma portable, sino saldrá un mensaje de error.
procedure Tf_main.FormActivate(Sender: TObject);
begin
  {Conecta a la Base de edatos}
  conex.HostName:= ''; {Local: localhost, Embebido: ''}
  conex.Database:= ExtractFilePath(Application.EXEName)+'data\BASEDATOS.FDB';
  conex.LibLocation:= ExtractFilePath(Application.EXEName)+'data\fbclient.dll';
  try
    conex.Connect;
    todos();
  except
    showmessage('No se pudo conectar con la Base de Datos!'+#13
    +'El sistema se cerrará, contacte con el soporte técnico.'+#13
    +'Web: www.webscom.com.ar');
    close();
  end;
end;

Detenemos el servidor, Compilamos y Ejecutamos el programa, todo debería marchar bien.. tanto desde lazarus como desde la carpeta.
Una vez que este funcionando pueden usar el programa desde la carpeta esté donde esté, escritorio, pendrive, otra unidad, etc.

Eso fue todo en esta guía, hay muchas cosas más por hacer pero será en otros posteos! saludos y espero sus comentarios tanto para consultar lo hecho como para mejorarlo. Voy a dejar la descarga del ejecutable con los fuentes a su disposición.