Lazarus Database Tutorial/nl

From Lazarus wiki
Jump to navigationJump to search

Overzicht

Deze uitleg laat zien hoe je Lazarus kunt gebruiken met verschillende databases. Zoals je ziet zijn nog niet alle databases gedekt, dus ... help mee om dit deel uit te breiden.

Lazarus en MySQL

MySQL werkend krijgen onder Linux of Windows

Volg de instructies van het MySQL User Manual. Zorg er voor dat de mysqld service draait en dat alle mogelijke gebruikers (waaronder root, mysql, jijzelf en eventueel andere gebruikers) net zoveel rechten hebben als nodig is, vanaf net zoveel computers (hosts) als nodig is (waaronder 'localhost', de naam van de computer waarop MySQL draait en eventueel andere computers in je netwerk.) Het mag duidelijk zijn dat het het beste is als alle gebruikers gebruik maken van een paswoord. Controleer de werking van de database server op basis van de voorbeelden die in de handleiding worden gegeven. Controleer ook of alle gebruikers de door hen benodigde toegang hebben.

MySQL werkend krijgen met FPC in een terminal

In de directory $(FreePascal_directory)/packages/base/mysql/ staat een voorbeeld programma. Deze directiry bevat ook de units mysql.pp, mysql_com.pp and mysql_version.pp. Voordat je het test script uitvoert, moet je een database genaamd "testdb" aanmaken. Dit kun je doen door in te loggen met behulp van de mysql monitor (als root met alle rechten) en het volgende SQL statement uit te voeren.

CREATE DATABASE testdb;

zorg er dan voor dat alle gebruikers voldoende rechten hebben door

GRANT ALL ON testdb TO johnny-user IDENTIFIED BY 'johnnyspassword'; 

uit te voeren. Er is script genaamd mkdb, dat je nu moet uitvoeren:

sh ./mkdb

Waarschijnlijk mislukt dit omdat het systeem niet toestaat dat een anonieme gebruiker de database benaderd. Wijzig het script nu zo dat de regel die mysql start er zo uit ziet:

mysql -u root -p  ${1-testdb} << EOF >/dev/null

en probeer het script nogmaals uit te voeren, waarbij het het root paswoord invult op de prompt. Met een beetje geluk heb je nu de test database gemaakt. Controleer dit door het volgende mysql statement uit te voeren, vanuit je mysql monitor:

select * from FPdev;

Als het goed is zie je nu een tabel met de ID, username en email adressen van een paar van FPC ontwikkelaars.

Probeer nu het testprogramma testdb.pp uit te voeren. (Waarschijnlijk moet dit eerst nog gecompileerd worden en zal het de eerste keer niet lukken om het succesvol uit te voeren!!)

Er kunnen een aantal redenen zijn waarom het programma geen verbinding kan maken met de mysql server:

  • Het systeem (SuSE Linux v9.0) installeert mysql v4.0.15 en niet de versie 3 waarvoor het package is ontworpen.
  • Het programma heeft een gebruikersnaam en paswoord nodig om de database te benaderen.
  • De compiler moet weten waar het de mysql libraries kan vinden. (ALS JE DE MYSQL ONTWIKKEL LIBRARIES NOG NIET HEBT GEÏNSTALLEERD, DOE DAT DAN NU!)

Als je een copy maakt van testdb.pp, bijvoorbeeld trydb.pp, in plaats van het origineel aan te passen, zullen de bestanden bij volgende CVS updates ook gewijzigd worden. Ook kun je de bestanden van de mysql/ver40/ subdirectory kopieren naar de mysql/ directory. Hernoem ze dan naar mysql_v4.pp, mysql_com_v4.pp and mysql_version_v4.pp, en zorg ervoor dat je de gebruikte units in iedere file ook aanpast. Dus: wijzig het uses statement in trydb.pp in

uses mysql_v4

en het statement in mysql_v4.pp in

uses mysql_com_v4

Waarschijnlijk moet er aan /etc/fpc.cfg een regel toegevoegd worden die wijst naar de libraries:

-Fl/lib;/usr/lib

en moet in de /usr/lib directory een link naar de mysqlclient library gemaakt worden. Dit kan bijvoorbeeld met het volgende shell commando:

ln -s libmysqlclient.so.12.0.0 lmysqlclient

Controleer wel even de naam van jouw libraries. Voor de goede orde kun je ook de volgende link aanmaken

ln -s libmysqlclient.so.12.0.0 mysqlclient

Sommige moeten misschien de volgende link opnemen:

ln -s libmysqlclient.so.12.0.0 libmysqlclient.so

Wijzig dan trydb.pp zodanig dat het de gebruiker details kent, door de host, user en paswoord als constanten op te nemen:

const
  host : Pchar= 'localhost';
  user : Pchar= 'myusername';
  passwd: Pchar = 'mypassword';

Het kan ook zijn dat je geen verbinding kunt maken met behulp de mysql_connect() call, en je de mysql_real_connect() call moet gebruiken die meer parameters heeft. Om de zaak nog wat gecompliceerder te maken is het aantal parameters gewijzigd van versie 3 (daar waren het er 7) naar versie 4 (waar het er 8 zijn). Voordat je mysql_real_connect kunt aanroepen moet je waarschijnlijk mysql_init() aanroepen, die niet is opgenomen in de originele mysql.pp maar wel in mysql_v4.pp.

Dus de code om verbinding te maken met de database is:

{ a few extra variables}
var
  alloc : PMYSQL;
 
{main program fragment}
 
begin
 if paramcount=1 then
   begin
   Dummy:=Paramstr(1)+#0;
   DataBase:=@Dummy[1];
   end;
 
Writeln ('Allocating Space...');
 alloc := mysql_init(PMYSQL(@qmysql));
 Write ('Connecting to MySQL...');
 sock :=  mysql_real_connect(alloc, host, user, passwd, database, 0, nil, 0);
 if sock=Nil then
   begin
   Writeln (stderr,'Couldnt connect to MySQL.');
   Writeln (stderr, 'Error was: ', mysql_error(@qmysql));
   halt(1);
   end;
 Writeln ('Done.');
 Writeln ('Connection data:');
{$ifdef Unix}
 writeln ('Mysql_port      : ',mysql_port);
 writeln ('Mysql_unix_port : ',mysql_unix_port);
{$endif}
 writeln ('Host info       : ',mysql_get_host_info(sock));
 writeln ('Server info     : ',mysql_stat(sock));
 writeln ('Client info     : ',mysql_get_client_info);
 
 Writeln ('Selecting Database ',DataBase,'...');
 if mysql_select_db(sock,DataBase) < 0 then
   begin
   Writeln (stderr,'Couldnt select database ',Database);
   Writeln (stderr,mysql_error(sock));
   halt (1);
   end;
{... as original contents of testdb.pp}


OK, klaar om trydb.pp te compileren?

 fpc trydb

success! En voer het uit:

 ./trydb

YES! Je hebt een lijst van FPC ontwikkelaars!

Een paar mogelijke verbeteringen: Je kunt de invoer van de gebuiker gegevens en the SQL commando's interactief maken. Hiervoor worden variabelen gebruikt in plaats van constanten. Er kunnen SQL commando's ingevoerd worden totdat het commando 'quit' wordt ingevoerd. Zie de volledige listing. In deze versie worden de gerbuikers gegevens in the console ingevoerd, waarna het programma in een loop komt waarbij SQL commando's kunnen worden ingevoerd en de resultaten worden getoond. Het programma eindigt als 'quit' wordt ingevoerd.

Zie ook Sample Console Listing.

Verbinding met MySQL vanuit een Lazarus Programma

Deze les toont hoe je Lazarus kunt verbinden met een MySQL database, en hoe je eenvoudige queries kunt laten uitvoeren met gebruik van de basic Lazarus componenten. Er worden geen data-aware componenten gebruikt, maar het laat de principes zien van het verbinden met de database.

Maak een nieuw project in Lazarus:

Project -> New Project -> Application

Kies voor Application en klik op Create. Er zal een nieuw automatisch gegenereerd Form worden getoond.

Vergroot het form zodat het ongeveer 600 bij 800 is. Geef het form een nieuwe naam en wijzig de caption in 'TryMySQL'.

Van de Standard Componenten tab plaats je drie Editboxes in de linker bovenhoek van het Form, en plaats direct boven elke editbox labels. Wijzig de en captions en namen in 'Host' (en HostLLabel,HostEdit), 'UserName' (en UserLabel, UserEdit) en 'Password' (with PasswdLabel and PasswdEdit). Je kunt natuurlijk ook gebruik maken van de LabelledEdit componenten van de Additional tab.

Selecteer de Passwd Editbox en zoek het PasswordChar property: wijzig dit in * , zodat wanneer je hier een paswoord intypt de letters niet getoond worden maar een serie van *-en. Zorg er voor dat de Text properties van alle editbox-en leeg zijn.

Plaats nu nog een Editbox en label aan de rechter bovenkant van je form. Wijzig het label in 'Enter SQL Command' en noem de Editbox CommandEdit.

Plaats drie Buttons op het form: twee aan de linker kant onder de Editbox-en en een aan de rechterkant onder de "command" editbox.

Geef de buttons aan de linkerkant 'Connect to Database' (ConnectButton) en 'Exit' (ExitButton) en de button aan de rechterkant 'Send Query' (QueryButton).

Plaats een grote Memo op het form genaamd 'Results' (ResultMemo) op de rechter onderkant, zodanig dat het het grootste deel van het form vult. Zet het ScrollBars property op ssAutoBoth zodat de scroll bars automatisch veschijnen als het memo wordt gevuld. Zet het WordWrap property op True.

Plaats een Status Bar (van de Common Controls tab) aan de onderkant van het Form, en zet het SimpleText property op 'TryMySQL'.

Een screenshot van het form kun je hier zien: Mysql Example Screenshot

Nu moeten we een aantal event handlers schrijven.

De drie Editbox-en aan de linkerkant worden gebruikt om de hostnaam, gebruikersnaam en het paswoord in te voeren. Wanneer deze zijn ingevuld kan er op de "Connect" button geklikt worden. De OnClick-event van deze button is gebaseerd op een deel van het FPC programma hierboven.

Omdat we nu de antwoorden van de database server niet met Write of WriteLn kunnen tonen, zullen we deze in het Memo laten zien. Hiervoor is het wel noodzakelijk dat we deze resultaten omzetten naar strings. We maken hiervoor een methode van ons form die de strings in het memo plaatst.

procedure TtrymysqlForm1.ShowString (S : string);
(* display a string in a Memo box *)
begin
       ResultsMemo.Lines.Add (S)
end;

Het OnClick-event van de ConnectButton wordt dan:

procedure TtrymysqlForm1.ConnectButtonClick(Sender: TObject);
(* Connect to MySQL using user data from Text entry boxes on Main Form *)
var 
  strg: string;
 
begin
  dummy1 := HostEdit.text+#0;
  host := @dummy1[1];
  dummy2 := UserEdit.text+#0;
  user := @dummy2[1] ;
  dummy3 := PasswdEdit.text+#0;
  passwd := @dummy3[1] ;
  alloc := mysql_init(PMYSQL(@qmysql));
  sock :=  mysql_real_connect(alloc, host, user, passwd, database, 0, nil, 0);
  if sock=Nil then begin
    strg :='Couldnt connect to MySQL.'; showstring (strg);
    Strg :='Error was: '+ StrPas(mysql_error(@qmysql)); showstring (strg);
  end else begin
    trymysqlForm1.statusBar1.simpletext := 'Connected to MySQL';
    strg := 'Now choosing database : ' + database; showstring (strg);
{$ifdef Unix}
    strg :='Mysql_port      : '+ IntToStr(mysql_port); showstring (strg);
    strg :='Mysql_unix_port : ' + StrPas(mysql_unix_port); showstring (strg);
{$endif}
    Strg :='Host info       : ' + StrPas(mysql_get_host_info(sock));
    showstring (strg);
    Strg :='Server info     : ' + StrPas(mysql_stat(sock)); showstring (strg);
    Strg :='Client info     : ' + Strpas(mysql_get_client_info);  showstring (strg);
    trymysqlForm1.statusbar1.simpletext := 'Selecting Database ' + DataBase +'...';
    if mysql_select_db(sock,DataBase) < 0 then begin
      strg :='Couldnt select database '+ Database; ShowString (strg);
      Strg := mysql_error(sock); ShowString (strg);
    end;
  end;
end;

In de EditBox rechts bovenin het form kan een SQL commando worden ingevoerd (zonder afsluitende punt-komma). Als er op de SendQuery button geklikt wordt, wordt het commando naar de server gestuurd en het resultaat wordt in het memo getoond.

Ook het OnClick-event van de SendQuery-button is gebaseerd op de code van de FPC versie hierboven.

In afwijking van het FPC programma, wordt het Lazarus programma niet afgebroken als er een fout optreedt. In plaats daarvan komt de controle weer terug bij het hoofd form (main form) en wordt de gelegenheid gegeven om het commando te verbeteren voordat het opnieuw wordt verstuurd naar de server. Het programma wordt afgelsoten als op de Exit button wordt geklikt, hierbij wordt ook de verbinding met de MySQL server gesloten.

Het OnCLick-event voor de SendQuery-button is als volgt:

procedure TtrymysqlForm1.QueryButtonClick(Sender: TObject);
var
  dumquery, strg: string;
begin
  dumquery := CommandEdit.text;
  dumquery := dumquery+#0;
  query := @dumquery[1];
  statusbar1.simpletext := 'Executing query : '+ dumQuery +'...';
  strg := 'Executing query : ' + dumQuery; showstring (strg);
  if (mysql_query(sock,Query) < 0) then begin
    Strg :='Query failed '+ StrPas(mysql_error(sock)); showstring (strg);
  end else begin
    recbuf := mysql_store_result(sock);
    if RecBuf=Nil then begin
      Strg :='Query returned nil result.'; showstring (strg);
    end else begin
      strg :='Number of records returned  : ' + IntToStr(mysql_num_rows (recbuf));
      Showstring (strg);
      Strg :='Number of fields per record : ' + IntToStr(mysql_num_fields(recbuf));
      showstring (strg);
      rowbuf := mysql_fetch_row(recbuf);
      while (rowbuf <>nil) do begin
        Strg :='(Id: '+ rowbuf[0]+', Name: ' + rowbuf[1]+ ', Email : ' + rowbuf[2] +')';
        showstring (strg);
        rowbuf := mysql_fetch_row(recbuf);
      end;
    end;
  end;
end;

OK! Sla je project op en klik op Run -> Run

Download MYSQL Source Code

Een volledige listing van het programma is hier te downloaden Sample Source Code

Een uitgebreidere versie

Op basis van bovenstaand programma heb ik een nieuwe versie geschreven. Deze laat iets meer zien van de mogelijkheden van MySQL en Lazarus. Zo kun je in deze demo zien hoe je de databases die op server beschikbaar zijn kunt opvragen, welke tabellen in die database staan en uit welke velden de tabellen zijn opgebouwd. Daarnaast laat deze versie zien hoe je de data in een ListView kunt tonen.

Scherm afdruk

Lazarus en Postgresql

Wie schrijft mij?

Lazarus en SQLite

door Luiz Américo

Introductie

Er zijn twee TDatasets afstammelingen die het mogelijk maken om SQLite2.x databases te benaderen. De eerste, de TSqlite class, is gedefinieerd in de SQLiteDataset unit. De tweede is gedefinieerd in de SQLiteds unit en is nieuwer en wordt bij de nieuwere fpc versie geïnstalleerd. De laatste heeft nog een paar voordelen boven de eerste versie, hij is sneller, maakt toevoegen, wijzigen en verwijderen mogelijk en kan deze updates automatisch door de database laten verwerken. De aanwijzigingen die hier gegeven worden gaan uit van de TSqliteDataset uit de unit sqliteds.pas. Het is zelfs zo dat de "oude" sqlitedataset.pas file onder de nieuwere versie van fpc (1.9.8) niet meer gecompileerd kan worden.

Benodigdheden

  • fpc 1.9.8
  • sqliteds.pas (Haal deze eventueel van fpc/fcl/db/sqlite op de CVS-server)
  • sqlite runtime library 2.8.15 of hoger (Haal deze van www.sqlite.org)

Voordat je een Lazarus project begint, controleer dan dat:

  • de sqlite library te vinden is in het system PATH
  • onder linux moet cmem als de eerste unit in de uses clause van het Main form vermeld worden

De grondbeginselen

De sqlite package die bij de standaard lazarus installatie zie is gebaseerd op de oude sqlitedataset unit. Je kunt een package die gebruik maakt van de nieuwe unit hierdownloaden.

Tijdens het ontwerp moet je de volgende properties zetten:

  • FileName: pad naar de sqlite file [verplicht]
  • TableName: de naam van de tabel die gebruikt wordt in het sql statement [verplicht]
  • Sql: een SQL select statement [optioneel]

Een Table (Dataset) maken

Op dit moment is het niet mogelijk een tabel gedurende het programma ontwerp te maken dus is het noodzakelijk de tabel tijdens de uitvoering van het programma te maken als deze tenminste nog niet bestaat. Het beste moment hiervoor is in het OnCreate event van het "main" form.

Het voorbeeld hieronder laat zien hoe je dit kunt doen. (dsTest is een instantie van TSqliteDataSet):

 // Maake een tabel met alle door de TSqliteDataset ondersteunde veld typen
 with dsTest do
 begin
   if not TableExists then begin
     with FieldDefs do begin
       Clear;
       Add('Integer',ftInteger);
       Add('AutoInc',ftAutoInc);
       Add('String',ftString);
       Add('Memo',ftMemo);
       Add('Bool',ftBoolean); 
       Add('Float',ftFloat);
       Add('Word',ftWord);
       Add('DateTime',ftDateTime);
       Add('Date',ftDate);
       Add('Time',ftTime);
     end;
     CreateTable; 
   end;
 end;

Gegevens opvragen

Nadat de tabel is gemaakt, kun je deze benaderen met de Open method. Als het SQL property geen waarde heeft worden alle velden van alle records uit de tabel opgehaald, dus alsof

 SQL:='Select * from TABLENAME'; 

Maar het is natuurlijk ook mogelijk om een combinatie van velden op te vragen door het SQL property te zetten zoals:

 SQL:='Select Float from TABLENAME';
 SQL:='Select String,Date,Word from TABLENAME';

Onthoud dat de beschikbare velden en de volgorde van deze velden na het openen van de dataset bepaald worden door het opgegeven select statement. In boven genoemde voorbeelden zijn er dus respectievelijk 10, 1 en 3 velden beschikbaar.

Wijzigingen doorvoeren op de onderliggende database

Voor het opslaan van de wijzigingen in de onderliggende database is het noodzakelijk dat de tabel een Primary key heeft. Bijvoorbeeld een AutoInc veld.

Als bijvoorbeeld het veld 'Integer' waarden bevat die altijd aanwezig en uniek zijn, dan kunnen na

 FieldIndexName:='Integer';

gegevens in de database file worden opgeslagen.

Hiervoor kun je de ApplyUpdates method gebruiken.

Opmerkingen

  • Hoewel dit tijdens een test met 10000 records goed werkte, moet je er wel rekening mee houden dat de TSqliteDataset alle gegevens in het geheugen houdt. Dus haal alleen de noodzakelijke gegevens op.
  • Een database file kan meerdere tabellen bevatten.
  • Het is mogelijke meerdere datasets (met verschillende velden) te maken die dezelfde database tabel benaderen.
  • Het is mogelijk om de data te filteren met behulp van een WHERE statement. Het sluiten en het weer openen vban een dataset (of het aanroepen van de RefetchData method) is ook mogelijk.
  • Je kunt ook complexe SQL statements gebruiken waarin aliases en joins worden gebruikt. Het is in dit geval echter niet mogelijk om gegevens te wijzigen, ApplyUpdates werkt dus niet. Als je echter toch complexe queries wilt gebruiken en gegevens wilt kunnen wijzigen, dan mag je mij een mailtje sturen en ik zal je een paar hints geven over hoe je dat kunt doen.
  • Als je gebruik maakt van een bestand die niet is aangemaakt met behulp van een TSqliteDataset zijn er een paar beperkingen. Niet alle velden worden dan juist gedetecteerd. De niet herkende veldtype worden als een string behandeld.

Een algemeen voorbeeld kan gevonden worden in de fpc/fcl/sqlite CVS directory.

Luiz Américo pascalive(at)bol(dot)com(dot)br

Lazarus en MSSQL

Wie schrijft mij?

Lazarus en dBase

Tony Maro

Kijk ook eens naar de aanzet voor een TDbf Tutorial page

FPC bevat een simpel database component die qua functionaliteit is te vergelijken met het TTable component van Delphi. Dit component ("TDbf", (TDbf Website)) ondersteund een aantal basis handelingen met dBase files. Omdat het niet standaard wordt geïnstallleerd, zul je dit component dus zelf moeten doen. Je kunt het package vinden in de "lazarus/components/tdbf" directory. Na installatie van het package en een "rebuild" van je Lazarus IDE, vind je het component naast het TDatasource component in je componenten palette.

Het voordeel van het TDbf component is dat er geen extra libraries nodig zijn, maar het is niet de beste keuze voor een grote database applicatie.

Het gebruik van een TDbf component is erg eenvoudig. Plaats eenTDbf component op je form, vul het FilePathFull property met het pad naar de directory waar de bestanden staan, vul het TableName property met de naam van de tabel en verbind het met een TDatasource.

Voor het echte werk zul je echter nog wel iets meer moeten doen. Als een tabel nog niet bestaat, zul je hem met behulp van je programma moeten aanmaken. Of er moet een compatibele tabellen maker zijn die ik niet ken.

Als je een niet bestaande tabel probeert te openen zal er een error gegenereert worden. Je kunt tijdens runtime een tabel aanmaken als het pad (FilePathFull) en de naam (TableName) een waarde hebben.

De volgende code maakt een tabel genaamd "dvds" om he dvd verzameling in te registreren. Dus plaats een TDbf component op je form in in het OnCreate event van je form plaats je de volgende code:

   Dbf1.FilePathFull = '/pad/naar/mijn/database';
   Dbf1.TableName = 'dvds';
   With Dbf1.FieldDefs do begin
       Add('Name', ftString, 80, True);
       Add('Description', ftMemo, 0, False);
       Add('Rating', ftString, 5, False);
   end;
   Dbf1.CreateTable;

Nadat deze code is uitgevoerd is er een bestand "dvds.dbf" aangemaakt. Hierna kun je met behulp van alle data aware componenten, die via een DataSource aan het TDbf component zijn verbonden, de gegevens in de tabel eenvoudig benaderen en wijzigen.

Het maken van een index

Het toevoegen van een index wijkt een beetje of van de typische TTable. Het moet namelijk gedaan worden, nadat de tabel is geopend. Op deze wijze moeten ook de index opnieuw opgebouwd worden. Bijvoorbeeld:

   Dbf1.Exclusive := True;
   Dbf1.Open;
   Dbf1.AddIndex('dvdsname','Name',[ixPrimary, ixUnique, ixCaseInsensitive]);
   Dbf1.AddIndex('rating.ndx', 'Rating', [ixCaseInsensitive]);
   Dbf1.Close;

De eerste (primaire) index wordt opgeslagen in een bestand "dvdsname.mdx" en de tweede index wordt opgeslagen in een bestand genaamd "rating.ndx". Omdat index opgeslagen worden in aparte bestanden moet je er dus voor zorgen dat je niet twee maal dezelfde naam gebruikt.

Ik zal proberen om op een later moment een meer gedetaileerd voorbeeld toe te voegen, maar ik hoop dat dit de delphi programmeurs snel op weg helpt bij het gebruik van databases in Lazarus!

Vertalingen van deze pagina

Lazarus Database Tutorial Het origineel door Chris Kirkpatrick.
Spaans door Eduardo Lopez (thanks! :)

Gerelateerde Links

Creating Databases Applications with Lazarus using the DB-unit