Una comparativa entre algunes bases de dades a Ubuntu

Des del punt de vista del desenvolupador. Entorn Ubuntu Lucid Lynx 10.04.

He considerat les següents bases de dades:

Bases de dades d’aplicació:
OpenOffice.org Base – HyperSonic DB (OpenOffice.org 3.2)
SQLite: el motor SQLite passa per ser el més eficient de tots per a bases de dades d’aplicació. Se’l compara amb el motor JET de l’Access. És la base de dades que s’amaga darrera de Kexi, l’aplicació de gestió de bases de dades de la suite KOffice de KDE.
dBase: el vell format .DBF dBase.

Servidors:
MySQL: El Servidor SQL que primer et ve al cap.
FireBird: La versió OpenSource de InterBase de Borland. Versions de servidor, d’aplicació i embedded. Molt escalable.
PostgreSQL: El més antic dels servidors SQL OpenSource. GLOM, una eina de desenvolupament senzill d’aplicacions de bases de dades, està basat en PostgreSQL.

I també he considerat les següents eines de desenvolupament:

OpenOffice.org Basic (OOoBasic)
Gambas2
Lazarus
PHP
java

Per què aquestes eines de desenvolupament i aquestes bases de dades? docs perquè, a priori, em semblen les que em donaran una major productivitat a l’hora de desenvolupar aplicacions.
En el concepte de major productivitat incloc la facilitat d’instal·lació, disponibilitat d’eines gràfiques de configuració, disponibilitat d’entorns de desenvolupament…

Això fa que, per exemple, no hagi considerat Python o C/C++ al no disposar d’entorns RAD (Rapid Application Development) lliures per a aquests llenguatges. Gambas2, Lazarus i OOoBasic, en canvi, sí que en disposen.

PHP i Java els he considerat per que són els dos llenguatges de servidor per a desenvolupar aplicacions web. Per a Java i per a PHP es disposa d’IDEs prou bons i complets (i pesats), com Eclipse o NetBeans.

El resum de la situació és el següent:

PostgresSQL  (Versió 8.4)
Accessible sense problemes amb Gambas2,  OpenOffice.org , Lazarus, PHP i Java

Firebird
Accessible sense problemes amb Gambas2, Lazarus i PHP (no he provat l’accés amb java)
no funciona driver JDBC de FireBird amb OpenOffice
no funciona driver ODBC de EasySoft amb OpenOffice
no funciona driver ODBC de FireBird amb OpenOffice
Conclusió: no disponible fàcilment sobre OpenOffice

SQLite2
Accessible sense problemes amb OpenOffice (driver ODBC),  Gambas2, Lazarus (però no és pot tenir simultàniament els controls de SQLite 2 i SQLite3),  PHP (no he provat l’accés amb java)

SQLite3
Accessible sense problemes amb OpenOffice (driver ODBC),  Gambas2, Lazarus (però no és pot tenir simultàniament els controls de SQLite 2 i SQLite3) .
Problemes per instal·lat PHP5-Sqlite3 amb Lucid Lynx. Sembla que es pot fer funcionar, amb versions anteriors ho feia! però per alguna rao, a la Lucid Lynx no es disposa del paquet (per què?). No he provat d’accedir-hi amb Java.

OpenOffice.org Base
Es tracta d’una HyperSOnic DB i, per tant, és accessible per aplicacions java amb JDBC.
No s’hi pot accedir (de forma útil) des  de Gambas2, Lazarus ni PHP. Realment a OpenOfficer.org Base només s’hi pot accedir bé amb… OpenOffice.org. Base.
Ara bé, en el món java, la HyperSonic és una molt bona tria (òptima) quan cal una base de dades d’aplicació.

dBase3
Sense problemes d’accés amb Gambas2, Lazarus, OpenOffice (nadiu) i Java. No funciona amb PHP però podria funcionar. En la Ubuntu Lucid Lynx aquest suport, per alguna raó, no està disponible (cal pensar que s’hi pot afegir)

MySQL
Sense problemes d’accés amb Gambas2, OpenOffice, PHP i Java.  Lazarus només suporta correctament fins 5.0. Però a la Lucid Lynx la versió del repositori és la 5.1!

Tinc, doncs, algun criteri addicional a l’hora de fer estimacions d’esforç al planificar desenvolupaments amb aquestes eines lliures.

OpenOffice.org i PostgreSQL

Hi han diverses alternatives per atacar amb OpenOffice una base de dades PostgreSQL. Potser les més evidents son 1. Utilitzar SDBC, els drivers nadius d’OpenOffice; 2. utilitzar JDBC

1. El Driver SDBC per accedir a PostgresSQL des de l’OpenOffice. Es pot descarregar des del Centre de Programari de l’Ubuntu, o des de http://dba.openoffice.org/drivers/postgresql/postgresql-sdbc-0.7.6a.zip. Aquesta és la versió que cal per a la versió d’OpenOffice 3.2

2. Driver JDBC per a PostgreSQL. Des del Centre de Programari de L’Ubuntu. Els jar queden ubicats a /usr/share/java.
Aquesta ubicació és el lloc escaient per a deixar les llibreries java per aplicacions "de sistema". Per exemple, aquí es troba el driver d’HyperSonic DB que fa servir OpenOffice Base.

He instal·lat el driver SDBC des del Centre de Programari. En arrencar l’OpenOffice Base i anar a "Connectar amb una base de dades existent" m’ha aparegut el tipus "Postgres", Bé!

L’he triat. Em demana la URL. Hi poso el següent:
host=localhost port=5432 dbname=proves

El format de la cadena és nom1=valor1 nom2=valor2…  amb les parelles nom=valor separades per espais i sense cometes envoltant al "valor". Ho remarco perquè el format no té res a veure amb el típic de les connexions JDBC a les que estic més acostumat.

Indico login i password i, sense fer res més, funciona i em connecto a la BD. Puc accedir a les taules de la BD proves i a les taules de l’esquema public. El login i lo password també es poden posar a la cadena. En el meu cas quedaria així:

host=localhost port=5432 user=postgres password=masterkey dbname=proves

Però, pel que es veu, l’OpenOffice3.2 ignora que ja disposa del password i me’l torna  demanar. És un bug? de fet, no m’està malament que me’l demani.

Com accedir a PostgreSQL (o MySQL, o FireBird) amb Lazarus

Tanco la serie de "com accedir a una base de dades del tipus xxxx amb Lazarus" amb el post d’avui, en el que desenvolupo una aplicació que accedeix a una taula d’una base de dades del tipus PostgreSQL.

L’entorn és Ubuntu Lucid Lynx 10.04. Amb el Centre de Programari de l’Ubuntu m’he instal·lat  PostgreSQL 8.4 i PgAdmin III. Que pel poc que he vist, és una molt bona eina d’administració i de consulta i força intuitiva.

El primer pas ha estat canviar el password de l’usuari postgres. Per això he fet des d’un terminal

sudo -u postgres psql postgres

i, a continuació, dins de la consola de sql

\password postgres

La barra de l’inici és important. Li indico el nou password: per exemple, "masterkey". (consulteu l’ajuda al setup de PostgreSQl a Ubuntu).

Un cop fet  això, amb pgAdmin ja podré registrar el servidor Localhost i crear-hi una nova base de dades que anomenaré ‘proves’. A proves, dins l’esquema public, hi creo una taula taula1, amb les mateixes columnes que en posts anteriors:  id (numèrica i PK), valor (text) i traducció (text).

Puc fer servir pgAdmin per a informar amb dades la taula.

I ara creo l’aplicació amb Lazarus. Idèntica a la del post  accedir amb Lazarus a SQLite. Amb un parell de diferències. En aquesta ocasió, els components d’accés seran uns altres:

Poso un component de Connexió a Postgres del tipus TPQConnection (objecte PQConnection1)
Un objecte TSQLTransaction (SQLTranasaction1) i un TSQLQuery (SQLQuery1) i els connecto entre ells.
En particular:
PQConnection1. UserName: postgres
PQConnection1.password: masterkey
PQConnection1.hostname: localhost
PQConnection1.databasename: proves
PQConnection1.transaction: SQLTransaction1

SQLTransaction1. Database: PQConnection1

SQLQuery1.database: PQConnection1
SQLQuery1.transaction: SQLTransaction1
SQLQuery1.SQL: select id,valor,traduccio from taula

La resta és un camp memo i tres botons Carregar (Button1Click), Netejar (Button2Click) i Sortir (Button3Click).

El codi del form és:

unit unProvaPostgres01;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, pqconnection, sqldb, FileUtil, LResources, Forms, Controls,
  Graphics, Dialogs, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Memo1: TMemo;
    PQConnection1: TPQConnection;
    SQLQuery1: TSQLQuery;
    SQLTransaction1: TSQLTransaction;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  sId, sValor, sTraduccio, sLinea: String;
begin
  (* obre connexions a la BD *)
  PQConnection1.Open;
  SQLQuery1.Open;

  (* itera a través de la BD *)
  SQLQuery1.First;
  while not SQLQuery1.EOF do begin
    sId := SQLQuery1.FieldByName(‘id’).AsString;
    sValor := SQLQuery1.FieldByName(‘valor’).AsString;
    sTraduccio := SQLQuery1.FieldByName(‘traduccio’).AsString;
    sLinea := sId + ‘; ‘ + sValor + ‘; ‘ + sTraduccio;
    Memo1.Append(sLinea);
    SQLQuery1.Next;
  end;

  // tanca la query
  SQLQuery1.Close;
  PQConnection1.Close;

end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Memo1.Clear;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  Application.Terminate;
end;

initialization
  {$I unprovapostgres01.lrs}
end.

EL codi anterior funciona exactament igual amb bases de dades del tipus FireBird / InterBase, o amb Bases de dades del tipus MySQL (si més no, fins a la 5.0), només que canviant el component TPQConnection per un TIBConnection per a les FireBird/InterBase, o per un TMySQL40Connection per a les MySQL4.0, TMySQL41Connection per a MySQL4.1 o TMySQL50Connection per a les MySQL50.

Amb les bases de dades del tipus MySQL 5.1 el control de connexió disponible amb Lazarus SqlDB funciona a mitges. No tanca bé. Suposo que es podria buscar algun control alternatiu, però cal trobar-lo. És una mala notícia perquè la versió de MySQL del repositori de programari d’Ubuntu per a Lucid és la 5.1

En tot cas, aquest és el HelloWorld de la connexió de Lazarus a Postgres (i a FireBird i fins a les MySQL 5.0).

OpenOffice.org Basic: Form per accedir a una BD registrada

En el post anterior accedia a una base de dades a través d’una macro i un diàleg. Ara accediré a la base de dades registrada posant la interfase d’usuari en un formulari.
Depenent de l’aplicació, Write, Draw, Impress, Calc o Base, hi hauran algunes diferències petites.

En cas de triar Write, Draw, Impress o Calc, poso els controls directament sobre el document.
En cas de triar Base, he de crear un objecte de formulari de la base de dades. I sobre aquest objecte poso els controls.

Visualitzo la paleta controls de formulari i la paleta de disseny de formulari. Si no els tinc actius, faig Visualitza-Barres d’eines i activo Controls de FormulariDisseny del Formulari.

Em poso en mode de disseny (fent clic al botó mode disseny de la paleta de disseny de formulari).

Poso un camp de text: Fent clic amb botó de la dreta sobre el camp, obro la finestra de propietats del control. AL control li poso el nom TextMostrar i indico que és multilínea
Poso tres botons. els anomeno BotoCarregar, BotoNetejar i BotoSortir i respectivament tenen les etiquetes "Carregar", "Netejar" i "Sortir".

Li dono nom al Formulari. Ara que ja tinc controls sobre el document, el botó formulari (situat a la paleta de disseny del formulari) ja estarà actiu. Faig clic i s’obre la finestra de propietats del formulari i li en dic FormulariProves1

Creo el codi. Com sempre això es fa amb Eines->Macros->Organitza les macros->OpenOffice.org BASIC.  En aquest cas, associo el codi de les macros al document  Writer, Calc, Draw o Impress segons el cas. Es dir: el codi de les macros es guarda en el fitxer del document.

Si hagués triat fer-lo a  "les meves macros" / Standard, la macro es guardaria a la carpeta de macros del meu directori home. En el meu cas, OpenOffice.org 3.2 sobre Ubuntu 10.04 Lucid Lynx, a la carpeta/home/albert/.openoffice.org/3/user/basic/Standard

El codi de les macros per a Writer, Draw, Impress i Base és en tots els casos el mateix:

REM  *****  BASIC  *****

‘ variables globals
‘ La DrawPage
Dim dpDrawPage As Object
‘ El Formulari
Dim Formulari As Object
‘ El camp de text
Dim TextMostrar As Object

Sub Main
    AccedeixBD
End Sub

Sub AccedeixBD
    ‘ obre la base de dades actual i fa una inserció de dades
    Dim Context
    Dim DB
    Dim Conn
    Dim Stmt
    Dim Result
    Dim strSQL As String
    Dim sText as String
   
    ‘ BasicLibraries.loadLibrary("XrayTool")
    ‘ crea el context de BD
    Context=CreateUnoService("com.sun.star.sdb.DatabaseContext")
  
    ‘obté la BD
    DB=Context.getByName("proves-sqlite-01")
     
    ‘ obté la connexió
    Conn=DB.getConnection("","")
   
    ‘ crea una statement
    Stmt=Conn.createStatement()

    ‘ crea string amb query
    strSQL="SELECT * FROM Taula1"

    ‘ executa i obté a un ResultSet
    Result=Stmt.executeQuery(strSQL)
   
    ‘ neteja la text box   
    Neteja()
   
    sText = TextMostrar.Text()
    While Result.next()       
        sText = sText & "id: " & Result.getInt(1) & "; valor: " & Result.getString(2) & chr(13)
    Wend
    TextMostrar.Text = sText
   
    ‘ tanca la connexió
    Conn.close
   
End Sub

Sub Neteja
    ‘ obté la DrawPage, el component en el que es dibuixen els controls
    dpDrawPage = ThisComponent.getDrawPage
    ‘ un cop té la drawPage, obté el formulari per nom
    Formulari = dpDrawPage.Forms.getByName("FormulariProves1")
    ‘ i del formulari, obté el control, també per nom
    TextMostrar = Formulari.getByName("TextMostrar")
    ‘ fa servir els mètodes i propietats del component.
    TextMostrar.Text=""
End sub

Sub Sortir
    ‘ Amb Close(True) tanca l’aplicació
    ThisComponent.Close(true)
End sub

Associo
procediment AccedeixBD a BotoCarregar
procediment Netejar a BotoNetejar
procediment Sortir al botó BotoSortir

Per a calc, cal tenir en compte que un mateix document pot tenir moltes fulles i que cada fulla pot tenir un formulari.  Aleshores, com he posat els components a la primera fulla, cal fer aquest tractament diferent

    ‘ obté la DrawPage, el component en el que es dibuixen els controls
    ‘ en el cas del writer, draw, impress i base, directament de ThisComponent,
    ‘ en cas de calc, cal primer obtenir la
sheet
    dpDrawPage = ThisComponent.Sheets.getByIndex(0).getDrawPage
    ‘ la resta és igual
    ‘ un cop té la drawPage, obté el formulari per nom
    Formulari = dpDrawPage.Forms.getByName("FormulariProves1")
    ‘ i del formulari, obté el control, també per nom
    TextMostrar = Formulari.getByName("TextMostrar")
    ‘ fa servir els mètodes i propietats del component.
    TextMostrar.Text=""

És dir, per a Writer, Draw, Impress i Base obtinc DrawPage (la capa de presentació de l’OpenOffice.org, per entendre’ns) directament del ThisComponent

dpDrawPage = ThisComponent.getDrawPage

En cas de Calc, hi ha una capa intermitja, la col·lecció de fulles. N’he de fer servir la primera que és on he posat els controls.

dpDrawPage = ThisComponent.Sheets.getByIndex(0).getDrawPage


Finalment, com tancar l’aplicació des d’una macro:

ThisComponent.Close(true)

Vet aquí el HelloWorld dels formularis amb OpenOffice.org

OpenOffice.org Basic: Macro i diàleg per accedir a una BD registrada

Aquest post segueix l’estil dels dos anteriors: es tracta d’accedir a una base de dades que tingui registrada a l’OpenOffice amb una macro i un diàleg genèrics. És dir, es tracta d’una macro i un dialeg que es podran invocar des de qualsevol de les aplicacions de la suite: calc, writer, draw, base o impress.

El fet de registrar la base de dades a l’OpenOffice em permet fer abstracció del mètode d’accés. Totes les bases de dades registrades s’accedeixen igual.

Per registrar una base de dades, o bé la creo amb OpenOffice.org Base, o bé aprofito una d’existent (i que reconegui OOo Base) i, en ambdós casos, marco el checkbox de registrar-la.

Un cop tinc la base de dades registrada aquesta passa a ser una base de dades del Base i ja no m’he de preocupar del que hi hagi per sota (o, si més no, no me n’he de preocupar gaire!).

Una informació interessant és saber quines són les bases de dades registrades i quin són els seus noms de registre. Això ho podem saber mirant Eines->Opcions->OpenOffice.org Base->Bases de Dades, que ens mostra la llista de noms de registre de les  bases de dades registrades i el path fins el fitxer .odb corresponent a cada base de dades.

Amb OpenOffice.org Basic (OOoBasic, d’ara endavant, per a fer-ho més curt), podem obtenir la llista de noms de registre amb un procediment com aquest:

sub ObteLListaBDRegistrades
    ‘ variables
    Dim Noms
   
    ‘ obté el context de base de dades
    Context=CreateUnoService("com.sun.star.sdb.DatabaseContext")

    ‘ obté la col·lecció d’elements
    Noms = Context.getElementNames()
   
    ‘ itera a través de la llista de bases de dades registrades
    For i = 0 To UBound(Noms())
      MsgBox Noms(i)
    Next i
end sub

El que faré ara és crear una interfase d’usuari similar a la dels posts anteriors, és dir, tres botons: Obtenir, Netejar i Sortir
Obtenir: Carregarà les dades de la taula en una camp de text multi-línia
Netejar: esborrarà el camp de text
Sortir: en aquest cas, tancarà el diàleg.

Ara bé una pregunta interessant: On creo aquesta interfase? en realitat, amb OpenOffice.org puc arribar a posar botons, etiquetes, camps de text i elements d’interfase gràfica d’usuari a molts llocs:
En Calc, Writer, Draw i Impress, al mateix document
En Base, a formularis de base de dades
En totes les aplicacions: en els diàlegs

triar posar els controls en el document o en diàlegs ha de seguir criteris funcionals: per exemple, si el que estem fent és un full de càlcul en el que ens interessa executar una macro que afecta a cel·les del full, o que ha de conèixer l’estructura del full, aleshores té sentit emplaçar al mateix document els controls.

Si, en canvi, estem creant una macro d’utilitat general, és dir, una macro que posariem al menú general que comparteixen les aplicacions d’OpenOffice, aleshores té sentit posar els controls en un diàleg.

Per facilitat, aquí posaré la interfase gràfica en un diàleg, i invocaré la macro que l’obre des del menú principal.

Per a crear un diàleg he de fer: Eines->Macros->Organitza els diàlegs, en "Els meus diàlegs"-"Standard" en creo un de nou fent click al botó de mateix nom. Al nou Dialeg li en dic Dialog1

Afegeixo un camp de text gran i els botons, per exemple com en la imatge:

Ara creo el codi.  El posaré al "Module1" de "Standard" de "Les meves macros" (els valors per defecte!)
Em calen:

Un parell de variables globals (sí, ja se que podria fer-ho millor).
‘ variables globals
‘ variables per al diàleg
‘ Dlg apunta al diàleg
‘ Ctl apunta al textbox
Dim Dlg As Object
Dim Ctl As Object

1. el procediment  que obre el diàleg i que invocaré des del menú principal

sub ObrirDialeg   
    ‘ carrega la llibraria de diàlegs estandard
    DialogLibraries.LoadLibrary("Standard")
   
    ‘ carrega el Diàleg "Dialog1"
    Dlg = CreateUnoDialog(DialogLibraries.Standard.Dialog1)
   
    ‘ i el mostra
    Dlg.Execute()
end sub

2. la càrrega de les dades en la textbox. Els comentaris del codi són prou explicatius.
Sub AccedeixBD
    ‘ obre la base de dades actual i fa una inserció de dades
    Dim Context
    Dim DB
    Dim Conn
    Dim Stmt
    Dim Result
    Dim strSQL As String
   
    ‘ crea el context de BD
    Context=CreateUnoService("com.sun.star.sdb.DatabaseContext")
  
    ‘obté la BD. He de posar el nom de registre de la base de dades que vull tractar
    ‘ DB=Context.getByName("proves-dbase")
    DB=Context.getByName("proves-sqlite-01")
     
    ‘ obté la connexió. En aquest cas, una SQLite, no calen logins/passowrds
    Conn=DB.getConnection("","")
   
    ‘ crea una statement
    Stmt=Conn.createStatement()

    ‘ crea string amb query
    strSQL="SELECT * FROM Taula1"

    ‘ executa i obté a un ResultSet
    Result=Stmt.executeQuery(strSQL)
   
    ‘ neteja la text box (i, de pas, inicialitza Ctl per aque apunti al textbox) 
    Neteja()
   
    While Result.next()
        REM for now, let us just use the getString() method to get the
        REM columns. Note that they are being accessed by index       
        Ctl.text = Ctl.text & "id: " & Result.getInt(1) & "; valor: " & Result.getString(2) & chr(13)
    Wend
   
    ‘ tanca la connexió
    Conn.close
   
End Sub

3. la neteja de la text box
Sub Neteja
    Ctl = Dlg.getControl("TextField1")
    Ctl.text = ""
End sub

4. el tancament del diàleg
Sub Sortir
    Dlg.endExecute()
End sub

Aleshores només cal associar
al botó ExecutaMacro, el procediment ‘AccedeixBD’
al botó Netejar, el procediment ‘Neteja’
al botó Sortir, el procediment ‘Sortir’

Com? en l’editor de diàlegs fem doble clic a cada botó  i en la pestanya esdeveniments trio "En prémer el botó del ratolí" i li associo el mètode  corresponent

Queda, finalment, obrir el diàleg des del menú principal:

Eines->Personalitza premo el botó ‘Nou’, indico el nom del nou Menú, per exemple "Les meves macros" i premo el botó D’acord.
Tornem-hi:
Eines->Personalitza, sel·lecciono a la llista desplegable el nou menú que to just he creat. Ara premo el botó afegeix i trio el procediment  ObrirDialeg. Per a trobar-lo he sel·leccionar en la caixa de Categoria: Macros de l’OpenOffice.Org-> Les meves macros->Standard->Module1 i en la caixa Ordre:ObrirDialeg. Premo D’acord.
Finalment, faig un altre cop:
Eines->Personalitza, sel·lecciono "les meves macros" a la llista desplegable de menú; a la llista de contingut sel·lecciono "ObrirDialeg" i premo el botó "Modifica" i Canvia el nom. Poso "Exemple de diàleg". Premo d’acord.

Encara podem dir si volem que aquest menú sigui per a document actual o per a tots els documents del tipus de l’aplicació actual. Ho fariem amb Eines-Personalitza. i triant l’opció de Desa a document actual o a OpenOffice.org aplicació.

Com accedir a SQLite amb Lazarus

Aquest post és una rèplica de l’anterior, però canviant d’eina RAD. En aquest cas faig servir Lazarus que és una IDE d’aspecte similar al Delphi.

Lazarus funciona com una IDE de desenvolupament ràpid basat en components que fa servir el llenguatge Free Pascal (mireu també el site oficial)

Lazarus i Free Pascal es poden instal·lar directament des del  Centre de Programari de l’Ubuntu (jo faig servir una Ubuntu 10.04 – Lucid Lynx).

Tanmateix, amb la instal·lació per defecte, el component de connexió al SQLite  ve precarregat però no està activat. Cal anar a Package – Paquets instal·lats i allà triar en la caixa de paquets disponibles (la de la dreta) el paquet sqlite3laz 0.4 i prémer  el botó per desar i remuntar l’IDE. Amb això disposaré a la pestanya Data Access d’un component DataSet de connexió a bases de dades del tipus SQLite3. Podria triar un component de connexió a bases  de dades SQLite2, però no semblen conviure bé.

El que faré serà el mateix que en el post anterior:

Creo una base de dades SQLite 3. Aquest cop puc fer servir SQLite Database Browser, per exemple o bé la el client  en mode text (a la consola escriu sqlite3, si només poso sqlite se m’activa el client d’SQLite2).

Creo una taula taula1, amb tres camps: id (integer i PK), valor (varchar de 20) i traducció (varchar de 20)

Pel que he vist, Es necessari que el fitxer de base de dades tingui permisos 777. A més també cal que tingui permisos de lectura i escriptura la carpeta on s’ubica el fitxer de base de dades.

A continuació creo un formulari al que incorporo un SQLite3Dataset i un Datasource.
A les propietats del dataset indico:
Filename:  /home/albert/databases/sqlite3/prova-sqlite2/prova2.db3
TableName: taula1 (que és el mateix que posar a la propietat SQL: Select * from taula1;
i activo

Al Datasource li poso a la propietat Dataset el nom del component SQLite3Dataset

A continuació completo el formulari amb els botons Mostrar, Netejar i Sortir i un camp memo (que és l’equivalent a la textbox multilinea del VB). El funcionament dels botons es:
Mostrar: carrega les dades de la taula i les mostra al camp memo.
Netejar: esborra el camp memo.
Sortir: atura l’aplicació.

Per exemple, una cosa així:

El codi de la unitat queda de la següent forma:

unit unProvaSQLite3_03;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Sqlite3DS, db, odbcconn, sqldb, sqlite3conn, FileUtil,
  LResources, Forms, Controls, Graphics, Dialogs, DbCtrls, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Datasource1: TDatasource;
    Memo1: TMemo;
    Sqlite3Dataset1: TSqlite3Dataset;
    Sqlite3Dataset1id: TLongintField;
    Sqlite3Dataset1traduccio: TMemoField;
    Sqlite3Dataset1valor: TMemoField;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
  Form1: TForm1;

implementation

{ TForm1 }

procedure TForm1.Button3Click(Sender: TObject);
begin
  Application.Terminate;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  { ShowMessage(‘esborra’); }
  Memo1.Clear;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  sId,sValor,sTraduccio: String;
  sLinea: String;
begin
  Sqlite3Dataset1.Open;
  Sqlite3Dataset1.First;
  while not Sqlite3Dataset1.EOF do begin
    sId := Sqlite3Dataset1id.AsString;
    sValor := Sqlite3Dataset1valor.AsString;
    sTraduccio := Sqlite3Dataset1traduccio.AsString;

    sLinea := sId  + ‘; ‘ + sValor + ‘; ‘ + sTraduccio;
    Memo1.Append(sLinea);
    Sqlite3Dataset1.Next;
  end;
 
Sqlite3Dataset1.Close;
end;

initialization
  {$I unprovasqlite3_03.lrs}

end.

El més interessant és el mètode del botó mostrar (el procedure TForm1.Button1Click)

Obrim el dataset
Sqlite3Dataset1.Open;

anem al primer element del dataset
Sqlite3Dataset1.First;

mentre no arribem a la fi del dataset fem
while not Sqlite3Dataset1.EOF do begin

agafaem els valors dels camps de la fila actual del dataset. A diferència del Gambas, cada camp del dataset ha de tenir un objecte que el representi explícitament. El valor es torna com cadena per a facilitar-ne el tractament però hi han mètodes específics per aretornar int, long…
    sId := Sqlite3Dataset1id.AsString;

    sValor := Sqlite3Dataset1valor.AsString;

    sTraduccio := Sqlite3Dataset1traduccio.AsString;

formata una línia per mostrar amb els valors dels camps
sLinea := sId  + ‘; ‘ + sValor + ‘; ‘ + sTraduccio;

afegeix la línia al camp memo
Memo1.Append(sLinea);

avança a la següent fila del dataset
Sqlite3Dataset1.Next;

I quan ha recorregut tot el dataset, el tanca.
Sqlite3Dataset1.Close;

Aquest és el HelloWorld de Lazarus + SQLite.

Com accedir a SQLlite amb Gambas

Gambas és un llenguatge Basic per a Linux. El més interessant és que ens proporciona un entorn RAD (Rapid Application Development) de l’estil del Visual Basic prou eficient.

Qualsevol aplicació professional acaba atacant a una base de dades. Una opció interessant a Linux és fer servir SQLite.

La combinació de Gambas i SQLite és, doncs, una possibilitat a tenir en compte a l’hora de desenvolupar aplicacions sobre Linux.

Com utilitzar Gambas i SQLite conjuntament? faré un experiment

Primer de tot crearé una base de dades de SQLite, en aquet cas, d’SQLite2 (podria ser SQLite3)
La base de dades tindrà una taula taula1, amb dues columnes: ID (integer, clau primària) i VALOR (text)

Per a crear la DB podem fer servir la utilitat Gambas2 DB Manager que es proporciona juntament amb la instal·lació de Gambas.

També podria fer servir el client en mode text de SQLite.

Informo algunes dades de prova a taula1

Al Gambas:

Creo un formulari amb una textbox i tres botons (Obtenir, Netejar i Sortir)
Obtenir: mostra el contingut de la taula1
Netejar: esborra la textbox
Sortir: acaba l’aplicació.

Per exemple, alguna cosa així:

El codi BASIC seria el següent:

‘ Gambas class file
PRIVATE conConnexio AS Connection
PRIVATE trTaulaResultats AS Result
 
PUBLIC SUB _new()
  ‘ res
END

PUBLIC SUB Form_Open()
  ‘ res
END

PUBLIC SUB Button1_Click()
  PRINT ("[Button1_Click] Connecta")
  conConnexio = NEW Connection
  conConnexio.Type = "sqlite2"
  conConnexio.Host = "/home/albert/databases/sqlite2"
  conConnexio.Name = "proves.db"
  TRY conConnexio.Open()
  IF ERROR THEN
    Message.Error("Error al connectar amb la base de dades.")
    conConnexio = NULL
  ELSE
    trTaulaResultats = conConnexio.Exec("Select * from taula1")
    Neteja
    WHILE trTaulaResultats.Available
        MostrarCamps
        trTaulaResultats.MoveNext
    WEND
   
conConnexio.Close()
  END IF
END

PUBLIC SUB Button2_Click()
  FMain.Close()
  STOP EVENT
END

PUBLIC SUB Button3_Click()
  Neteja
END

PUBLIC SUB MostrarCamps()
  TextArea1.text = TextArea1.text & "id: " & trTaulaResultats["id"] & "; valor: " & trTaulaResultats["valor"] & Chr(13)
END

PUBLIC SUB Neteja()
  TextArea1.text = ""
END

No hi ha pèrdua possible:

   crea un objecte de connexió
  conConnexio = NEW Connection

  indica que és una connexió del tipus SQLite2, podria ser d’altres: SQLite3, MySQL, Postgres, FireBird…

  conConnexio.Type = "sqlite2"

  indica l’ubicació de la BD a obrir

  conConnexio.Host = "/home/albert/databases/sqlite2"

  conConnexio.Name = "proves.db"

  i obre la connexió. Fixem-nos com obre la connexió dins d’un TRY.

  TRY conConnexio.Open()

  Si hi ha un error, ho indica;

  IF ERROR THEN

    Message.Error("Error al connectar amb la base de dades.")

    conConnexio = NULL

  ELSE
    …

  i si no, mostra les dades:
   Obté el resultset (fent servir terminologia java), dataset (delphi) o recordset (VB).
    trTaulaResultats = conConnexio.Exec("Select * from taula1")
   
   mentres tingui files per mostrar disponibles (available)
    WHILE trTaulaResultats.Available

   mostra la fila
        MostrarCamps

   avança fins la següent fila
        trTaulaResultats.MoveNext
    WEND

    quan ha recorregut tot el conjunt de resultats, tanca la connexió
    conConnexio.Close()

Per mostrar els resultats recupera el valor de cada columna per nom, els concatena amb una mica de format i afegeix un salt de línea amb Chr(13). tot plegat ho afegeix al contingut preexistent a la textbox

TextArea1.text
= TextArea1.text & "id: " & trTaulaResultats["id"] & ";
valor: " & trTaulaResultats["valor"] & Chr(13)

Aquest seria el HelloWorld!  de Gambas2+SQLite.

Com combinar correspondència amb OpenOffice

Aquesta és una de les tasques bàsiques d’ofimatica.  De forma general es tracta de combinar el contingut d’una base de dades, amb un text de plantilla, i enviar el text combinat a les adreces indicades.

Amb OpenOffice.org això es pot fer de forma molt fàcil utilitzant Base per a guardar la taula amb les dades a combinar i Writer per a fer la plantilla. Si el que volem fer són etiquetes, podem utilitzar l’assistent específic disponible.

Per a fer una combinació des de zero, per exemple per enviar una carta personalitzada per correu electrònic seguiríem els següets passos:

1. Primer de tot, hem de tenir configurat el SMTP d’enviament de correu que farà servir l’OpenOffice: Eines->Opcions-OpenOffice.org Writer->Adreça electrònica de la combinació. Degut al caràcter "universal" del GMail, aquesta seria l’opció que em vindria de gust fer servir però l’OpenOffice (si més no a la versió 3.2 sobre Ubuntu) no tracta bé les connexions segures de GMail, així que el descarto.
Faré servir una altre servidor SMTP: el del meu proveïdor d’accés a Internet és una bona tria, però molts proveïdors de correu gratuit proporcionen servidors SMTP.
Posarem a
Nom: el nostre nom
Adreça electrónica: l’adreça de correu sota la que s’enviaran els missatges
Paràmetres del servidor
Nom del servidor: smtp.elmeuservidor.com (aquí posarem el host)
Port: Si no fa servir SSL és 25, SI va sobre SSL, serà 465
marcar o desmarcar "Utilitza una connexió segura (SSL)" segons correspongui
Clic al botó Autenticació del servidor i indicarem el nom d’usuari i la contrasenya.

En acabar, puc provar les connexions. Quan tot està OK segueixo endavant

2. El següent NO es fa servir en les combinacions de correspondència. Sinó quan se li demana a l’OpenOffice que envii un document per correu. Es tracta de configurar el client de correu per defecte:  a Eines->opcions->Internet->Correu electrònic. En el meu cas, faig servir thunderbird i hi tinc posat: /usr/bin/thunderbird

3. A continuació, amb OpenOffice Base, faig una nova base de dades i, molt important, la registro. Al registrar-la OpenOffice "coneixerà" i posarà a disposició de totes les aplicacions la nova base de dades.
Afegeixo una taula d’adreces. La taula d’adreces podria tenir, per exemple, les següents columnes.
nom:  nom per l’emaling
direccio: carrer, núm. pis i porta.
cp: codi postal
poblacio: poble o ciutat
email: adreça d’enviament

i informo la taula amb algunes dades

4. Amb OpenOffice Writer faig la plantilla. Escric el text que m’interessa (per exemple una carta presentant un producte) i insereixo els camps variables que es correspondran amb els de la taula d’adreces. Això ho faré amb Insereix->Camps->Altres…
Apareix la llista de les bases de dades registrades. Trio la base de dades que he creat i registrat abans. Es desplega la llista de taules d’aquesta base de dades. Trio la taula d’adreces i se’m desplega la llista de camps.

5. Ara es tan senzill com triar el camp que vulguem de la llista de camps i  prémer el botó Insereix. En el document del writer, al lloc on es trobi el cursor, apareixerà el camp remarcat en gris. Fins que no la tanqui, la finestra d’inserció de camps restarà oberta. Per tant puc situar-me allà on vulgui del document writer i triar camps de la llista. Repeteixo fins haver col·locat tots els camps als llocs que em semblen adequats de la plantilla. En aquest moment ja tinc una plantilla amb camps vinculats a la base de
dades.

6. El següent pas és executar l’auxiliar de combinació de correu. Eines->Auxiliar de combinació de correu

pas 1. Li dic que faci servir el document actual de plantilla.
pas 2. Trio entre combinació tipus correu electrònic o del tipus carta (per facilitat, trio tipus correu electrònic)
pas 3
a). Si he triat tipus carta, hauré de sel·leccionar la taula que conté les adreces i podré definir el format dedel bloc corresponent a l’adreça del destinatari
b) si he triat tipus correu electrònic, aleshores només he de dir-li la taula que conté les adreces
pas 4. Puc crear, opcionalment, un bloc de salutació.
pas 5. En aquest pas, puc previsualitzar  els documents combinats, o descartar-ne alguns.
pas 6. En entrar en aquest pas es generen els documents. Ara puc editar individualment cadascun d’ells.
pas 7. Finalment, en aquest punt puc desar el document de plantilla inicial, o bé  desar el document combinat (com un únic document, o com un document per cada combinació), o imprimir el combinat, o puc enviar cada document combinat per correu a la seva adreça d’enviament. Faré això últim

pas 8. A "paràmetres del correu electrònic" li dic el nom de columna que conté l’adreça de correu dels destinataris. Poso un títol i indico de quina forma vull enviar els correus combinats: com cos del missatge, o com adjunt al missatge. En cas d’enviat-lo com adjunt, puc afegir (fent click a propietats) un petit text de presentació.

Finalment, faig click a "Envia els documents" i vet aquí que si tot ha estat correctament configurat, els correus són enviats.

Com accedir a bases de dades SQLite des d’OpenOffice en Linux

Primer de tot, què és SQLite? Segons la Viquipèdia: SQLite és una base de dades relacional continguda en una llibreria escrita C. A diferència d’altres bases de dades relacionals, SQLite no és un sistema de gestió de base de dades que funcioni amb un paradigma client-servidor. SQLite no és un procés autònom, sinó que s’integra dins
d’altres programes.

Les bases de dades SQLite s’emmagatzemen en un fitxer que conté tant
la definició de l’estructura de les dades com les dades mateixes.

Aquesta sistema ens recorda a les bases de dades d’Access (els fitxers .mdb).

OpenOffice Base fa servir un sistema de bases de dades del mateix estil, però basat en la HyperSonic DB.

SQLite és una tria intressant perquè a Linux disposem d’entorns RAD de programació com Gambas2, o Lazarus (Free Pascal) que permeten accedir fàcilment a aquesta base de dades. A l’hora de distribuir les nostres aplicacions, és molt senzill empaquetar la base de dades juntament amb l’aplicatiu.

De versions de SQLite a Ubuntu 10 en podem trobar dues de principals: la
SQLite2 i la SQLite3. Per a la SQLite3, la més moderna, existeixen
aplicacions gràfiques com SQLiteman o l’SQLite Database Browser (tots dos disponibles al "Centre de programari Ubuntu") que
permeten dissenyar taules i fer consultes. Per a la SQLite2 no serveixen les aplicacions anteriors i cal fer servir el client de línia d’ordres per a les tasques de disseny i administració.

Per a l’SQLite2, si tenim instal·lat el Gambas2 podem fer servir l’eina gambas2-database-manager.gambas. 

Posats a triar entre SQLite3 i SQLite2 la versió més moderna és l’elecció obvia. Jo ho veig així. Tanmateix, en el cas de l’Ubuntu 10.04, per alguna raó que desconec, no s’ha incorporat el paquet php5-sqlite3 al "Centre de programari Ubuntu". Evidentment, és possible configurar el PHP per a accedir a BD del tipus sqlite3 però això implica alguna tasca addicional. Amb els paquets "out of the box" el que sí que funciona a la primera amb PHP és l’SQLite2.

Per la rao anterior potser hi haurà algun usuari d’Ubuntu 10.04 que preferirà muntar SQLite2 d’entrada en comptes de l’elecció més natural SQLite3.

OpenOffice Base a més de les pròpies bases de dades del tipus HyperSonic DB també permet accedir directament a altres tipus de bases de dades com MySQl, Oracle… i indirectament a totes aquelles per a les que es pugui trobar un driver JDBC, o drivers ODBC.

SQLite no és accessible directament sinó mitjançant un pas intermedi. En el meu cas, Ubuntu 10.04, és necessari configurar l’accés mitjançant ODBC.

Es tracta, doncs, d’instal·lar des del "Centre de programari de l’Ubuntu":

1. el paquet unixodbc-bin  (Unix ODBC)

2. el paquet libsqliteodbc (el driver Unix ODBC  per a SQLite)

Aleshores podrem utilitzar l’aplicació ODBCConfig per a configurar un DSN (DataSource Name, nomenclatura Microsoft!) al fitxer SQLite de base de dades que ens interessi.

Ara, des del nostre OpenOffice Base, ja podrem accedir a la base de dades SQLite sense més que fer "Nou" i accedir a una BD existent del tipus ODBC. Se’ns obrirà el ODBCConfig des del que podrem triar quin DSN volem fer servir.

I si accedim a una SQLite2, de pas, ara podrem fer servir l’OpenOffice Base com un excel·lent client gràfic per a crear taules, consultes i exportar-ne on importar-ne les dades.

Com fer un estalvi de pantalla del tipus pas de diapositives (i 2)

La primera part d’aquest post la podeu trobar en aquest enllaç. El que faré ara és afegir una mica de chillout com música de fons a l’estalvi de pantalla.

La música triada és troba, fins on he vist, sota l’empara d’una llicència Creative Commons: Es tracta de "Zpaces" del disc "Epic Zilence" del músic Zilent Zpott (enllaç de descàrrega aquí).

Bé, un cop tenim la música, el que cal fer és recuperar el codi slideshow.mxml i

1- afegirem el so. L’encastarem dins del swf. Immediatament després de import flash.media.*; posem

// embed del so
[Embed(source="assets/zilent_zpott-zpaces.mp3")]

2 – Aleshores, un cop es carregui l’aplicació, li direm que executi el so. Caldrà modificar el el mètode init(). Ens caldran algunes variables.

        // variables bindable
        [Bindable]
        var sndCls:Class;

        […]

        // variables
        var snd:Sound = new sndCls() as Sound;
        var sndChannel:SoundChannel;

        // variables que ja hi eren
        var timControl:Timer = new Timer(9000, 0);
        var iComptador:int = 0;

        […]

        function init(): void {
            // activa el so
            sndChannel=snd.play();
        

            timControl.addEventListener(TimerEvent.TIMER, Intermitent);

            timControl.start();

        }

Amb sndChannel=snd.play();  la cançó només sonarà un cop. Si volguèssim que sonés continuament podriem posar sndChannel=snd.play(0, int.MAX_VALUE); No hi ha una forma d’indicar-li nombre de repeticions "infinit", però el valor int.MAX_VALUE que correspon a 2.147.483.647 sembla suficient per a la majoria dels casos. El primer argument correspon a l’off-set d’execució,  és dir que 0 significa "executa des del principi".

I ja està. Aleshores caldrà compilar el slideshow.mxml i fer servir l’assistent de InstantStorm per generar l’estalvi de pantalla.