Lazarus Databases

October 26, 2017 | Author: Alexandra Si Adrian Mesarosiu | Category: Database Transaction, Microsoft Sql Server, Databases, Sql, Library (Computing)
Share Embed Donate


Short Description

Database - Lazarus programming...

Description

Databases This page is an introduction to the topic 'Lazarus and databases'. The following table provides an overview of supported databases. Only the database components for which there are client libraries should be installed (if the database needs any client libaries), otherwise Lazarus could fail to start because of missing files. Then Lazarus must be reinstalled as uninstalling the component is not possible.   



 



Contents 1 Supported databases 2 The bindings to the database clients 3 Datasets o 3.1 Using datasets from code o 3.2 Using the visual (data-aware) controls o 3.3 Dataset State o 3.4 Dataset UpdateStatus o 3.5 Post and Cancel o 3.6 Inserting a new record o 3.7 How to quickly jump to 1 particular record in the table  3.7.1 After selecting all records of the table  3.7.2 Selecting only the desired record o 3.8 Filtering o 3.9 Locate/lookup o 3.10 Using TSQLQuery o 3.11 Exporting 4 Data Controls o 4.1 Datasource Control o 4.2 Single Field Controls o 4.3 DBGrid control o 4.4 Navigator Control 5 Running FPC database tests 6 Database packages contained in Lazarus o 6.1 sqldblaz.lpk o 6.2 dbflaz.lpk o 6.3 sqlitelaz.lpk o 6.4 sdflaz.lpk o 6.5 lazreport.lpk o 6.6 lazdbexport.lpk 7 External packages / libraries o 7.1 Zeos DataBase Objects o 7.2 Pascal Data Objects o 7.3 TPSQL o 7.4 FIBL o 7.5 IBX o 7.6 FBLib Firebird Library o 7.7 Unified Interbase o 7.8 TechInsite Object Persistence Framework (tiOPF) o 7.9 Advantage TDataSet Descendant o 7.10 ZMSQL, sql-enhanced in-memory database

Supported databases Database

Package name

Need client lib?

Need server?

Supported versions

Supported platforms

Advantage

TAdsDataSet

Yes

No

10.1 and greater

i386: Linux, Win32

DBase

DBFLaz

No

No

III+, IV, VII

All

In memory

memds

No

No

-

All

In memory

bufdataset

No

No

-

All

1 - 2.5

i386: Linux, Win32

Firebird

SQLdb

Yes

Depends

1

Pagina 1 din 69

Database

Package name

Need client lib?

Need server?

Supported versions

(Visual) FoxPro

DBFLaz

No

No

2.0, 2.5, 3.0 (not All completely)

Interbase

SQLdb

Yes

Yes

4-6

i386: Linux, Win32

SQLdb

Yes

Yes

6-

FPC 2.6.2+. Linux, OSX, Win32, probably *BSD, probably Solaris2

MySQL

SQLdb

Yes

Yes

3.0 - 5.5

i386: Linux, Win32

ODBC

SQLdb

Yes

Depends

3.x 3

i386: Linux, Win32

Oracle

SQLdb

Yes

Yes

-

-

Paradox

TParadoxDataSet No

No

up to Table Level All 7 (and up ??)

PostgreSQL

SQLdb

Yes

Yes

6.6 - 8

i386: Linux, Win32

Sybase Server (ASE)

Adaptive Enterprise SQLdb

Yes

Yes

Any

Linux, OSX, Win32, probably *BSD, probably Solaris2)

SQLite

SQLdb

Yes

No

sqlite3

All

SQLite

SQLite(3)Laz

Yes

No

sqlite2,sqlite3

All

Microsoft Server

SQL

Supported platforms

Text files sdf No No All Note (1): You can use an embedded version of Firebird on Windows and Linux (possibly on Mac OS X too), or you can connect to a Firebird server running on Windows/Unix/OSX/FreeBSD/other Firebird supported platforms Note (2): These connectors use the FreeTDS library as a driver. The FreeTDS documentation indicates it should build on at least these platforms. Windows versions for x86 and x64 can be downloaded from e.g. [1] and [2] Note (3): This version number refers to the ODBC standard, not to the version number of a driver or driver manager. There are ODBC 3.x drivers for most DBMSs.

The bindings to the database clients If you want to use one of the databases that need client libraries, those libraries have to be installed. Not only on the computer you're programming on, but also on the computers where the application must run. Note that some databases (in particular MySQL) only work if the bindings which are compiled in the application are from the same version as those of the installed libraries. You can find out how to install those libraries (.so files on *nix systems, and .dlls on windows) on the website of the database developers. The binding units can be found in the packages/base directory in the fpc-sources. They basically consist of the client API calls like mysql_connect_database, which are completely different for each database. It is possible to write database applications using these units, but it is usually far more work and bug-sensitive than using the DB-unit Lazarus components. Most of these bindings packages are hard-linked to the client libraries. This means that if the application is compiled with one of these units in it, the whole application can not be linked if the client libraries are not available on the workstation. This means that your program executable will not be generated if you do not have installed - for example - a MySQL client on your computer, and you are using the mysql4.pp unit in your program. If you succeed in compiling the program on a computer which has the MySQL client libraries installed, it still won't start on any other machine without the appropriate MySQL client libraries. In other words: for these databases, you need to install client libraries on your development machine, and you need to install these client libraries with your application. To avoid such problems some of the packages are also able to link dynamically to the libraries. Before any calls to those libraries can be made, the unit has to be 'initialized'. This initialization fails if the database client isn't installed on the computer. If the program is ready using the client library, the unit has to be 'released'.

Datasets Database use in Lazarus (or Free Pascal) is fundamentally based on the TDataset class. This represents a table or query to your application. However, like many other such fundamental classes, you don't use the TDataset class itself, you use a descendant of it. There are many of these. They provide access to different

Pagina 2 din 69

kinds of databases, such as local dbase or text files, or back-end databases such as PostgreSQL, Firebird, MySQL and so forth. Some dataset descendants link directly to database tables, while others use additional components or libraries to perform the link. Dataset descendants, being non-visual components are (usually) part of the Free Component Library (FCL) rather than the Lazarus Component Library (LCL). Datasets can be used both programmatically and with visual controls. A typical Lazarus database application will often use both methods. In either case, the first step is to create the TDataset descendant, initialise it to connect to the table or query you want, and open it. This can be done either in code at run time or by putting a component on your form and setting it's properties at design time. The details of this vary considerably with different TDataset descendants, so see the various guides under Databases for what has to be done for your database. When the dataset is opened, a set of field components are created, one for each field or column of the table or query you opened. Each field component is a descendant of TField, appropriate to the particular data type of the field, eg, TStringField.

Using datasets from code Programmatic access will be explained in more detail in Using Dataset and Field components, but as a very simple overview:  Use the TDataset descendant to open the table or query, filter the rows you want to see, and to move from row to row.  Use the TField descendants to:  Access general information about fields  Access the specific data values for the current row. (use the As... properties, such as AsString, AsInteger, etc.)  Access the fields of a TDataset descendant by using either:  The fields property, eg Fields[0] is the first field,  The FieldByName method, eg FieldByName('AGE') returns the field associated with the database field called 'AGE' See Database_field_type for a list of field types.

Using the visual (data-aware) controls To use databases in a simple, "RAD" style Lazarus application, you usually configure the dataset descendant at design time and the use the data-aware controls. To do this:  Add the dataset descendant for the database of your choice, together with any supporting components, to your form, and open it (Set the ' Active' property to true )  Add a TDataSource component (from the Data Access tab) to the form, and "link" it to the dataset (set the DataSet property)  Add data-aware controls from the Data Controls tab to the form, and link each one to the DataSource (not dataset) component  Most controls link to a single field, so you also need to set the Field for each tab. See #Data Controls below for more details on the controls

Dataset State Datasets can be in a number of states. While there are quite a few (look up TDataSetState in the source), the main ones to be aware of initally are State Function dsInactive The dataset is closed dsBrowse The user can browse through the dataset, looking at values dsEdit

The user can edit values on the current row.Values are not saved until a post is performed.

A new row has been added, and the user can set the values.The record is not saved until a post is performed The other states are fairly transitory, and are usually handled "automatically". They are used internally and in more complicated code. If your database only views data, and you open the dataset at design time, you can largely ignore the state, as it will mostly be dsBrowse. However, most applications will want to change the data at some stage. If you are using data-aware controls, they will handle a lot of this automatically. If you change the text in a TDBEdit control, for example, it will put the dataset into dsEdit state - unless you are already in dsEdit or dsInsert. If you "scroll" to a different record while the current state is dsEdit or dsInsert, that record will be "posted" and the dataset revert to dsBrowse. However, if you are accessing the dataset from code, you will often have to change the state in code as well. The TDBNavigator control (see below) allows the user to change the state explicitly. dsInsert

Dataset UpdateStatus Pagina 3 din 69

UpdateStatus determines the current state of the record buffer, if updates have not yet been applied to the database. Example how to detect if ApplyUpdates will Insert, Update or Delete data: procedure QueryAfterPost(DataSet: TDataSet); begin case DataSet.UpdateStatus of usUnmodified : ShowMessage('Unmodified'); usModified : ShowMessage('Modified'); usInserted : ShowMessage('Inserted'); usDeleted : ShowMessage('Deleted'); end; end; Value Explanation  usUnmodified: Record is unmodified  usModified: Record exists in the database but is locally modified  usInserted: Record does not yet exist in the database, but is locally inserted  usDeleted: Record exists in the database, but is locally deleted

Post and Cancel If you have edited or inserted a record, the new values are held in a buffer.  Calling the dataset cancel method removes the new record (insert) or reverts the values to their previous values (edit).  Calling the dataset post method saves the values (edit) or record (insert). In some dataset descendants, they will be written to the database immediately, while in others they will be stored in a list of updates until a further call is made to save all changes to the database. Finally, even when they are written to the database, you may still have to call a "commit" method to make the database write them permanently. All of this also varies considerably with the dataset descendant, so look up the details for the one you are using.

Inserting a new record To insert a new record into a TDataset descendent, one should use the method Insert. After that one can set the field values and then finally call Post to commit the new record, as the example below shows. The example also shows how to insert BLOB data from a file - you can also use LoadFromStream to load the data from a stream. MyDataset.Insert; MyDataset.Fields[0].AsInteger := 4; //an integer field MyDataset.Fields[1].AsString := 'First Name'; //a string field TBlobField(MyDataset.Fields[2]).LoadFromFile('SomeBlobfile.bin'); //blob field MyDataset.Post;

How to quickly jump to 1 particular record in the table After selecting all records of the table If you use SELECT * FROM to select all records of the table and then desires to quickly jump between them, you will have to build an index and search on it. It is more efficient to select only the record that you want.

Selecting only the desired record One fast solution to jump to a particular record is to select only it, for example doing: var MyDataset: TSQLQuery; begin //... MyDataset.FieldDefs.Add('SessionId', ftLargeint); MyDataset.FieldDefs.Add('GameEvent', ftLargeint); MyDataset.FieldDefs.Add('TableId', ftInteger); MyDataset.FieldDefs.Add('LoggedIn', ftBoolean); MyDataset.FieldDefs.Add('PlayerId', ftInteger); MyDataset.Active := False; { Non-parameterized format; may run into issues with text containing ' and dates SQLText := Format('select * from "GameSession" WHERE "SessionId"=%d', [ASessionId]); } // Solution: parameterized query:

Pagina 4 din 69

// Actually, if this is done in a loop, you only need to set the SQL.Text once, // and only change the parameter value MyDataset.SQL.Text := 'select * from "GameSession" WHERE "SessionID"=:SessionID'); MyDataSet.ParamByName('SessionID').AsLargeInt := ASessionID; try MyDataset.Active := True; except //... end; You can then read information using something like this: lPlayerId := MyDataset.Fields[4].AsInteger;

Filtering You can filter your dataset to restrict the records to a subset you want (e.g. all surnames starting with Smith).  Using .Filter:  TDbf, TBufDataset and descendants (including TSQLQuery) use the TDBF filtering parser; see Lazarus Tdbf Tutorial#Expressions for details on using this.  TMemDataset does not support .Filter  Using a callback/event procedure with OnFilter where you can program your own filter function

Locate/lookup Although more often used in non-SQL datasets (e.g. TParadoxDataSet, TDbf) you can jump between records using locate/lookup.

Using TSQLQuery For more information about TSQLQuery see Working With TSQLQuery

Exporting FPC/Lazarus contains functionality to let you export datasets to various formats; see e.g.  fpXMLXSDExport  fpdbfexport  the other components on the Data Export tab Of course, you could also do it manually e.g. FPSpreadsheet#Converting_a_database_to_a_spreadsheet for export to Excel format fpspreadsheet)

(see using

Data Controls To use any of these controls, add the control to a form and set at least the datasource property. Other key properties will be noted.

Datasource Control This control keeps track of which record the linked controls currently are on. The datasource contorl must be linked to a dataset (e.g. a TSQLQuery).

Single Field Controls These controls all attach to a single field. As well as datasource, set the field name. Controls include:  DBText control Displays a text field (readonly, no border)  DBEdit control Displays / edits a text field as an edit box  DBMemo control Displays / edits a text field in a multi-line edit box  DBImage control Displays a picture stored in a database as a BLOB. Note: by default, Lazarus stores a header with the image type before the image data in the database BLOB field. This is different from Delphi. However, you can make TDBImage Delphi compatible: see Lazarus For Delphi Users#TDBImage  DBListBox control and DBComboBox Control Allow the user to insert values into a database field from the list of values in the Items property of the controls  DBLookupListBox control and DBLookupComboBox control, see also dblookupcombobox Allow the user to insert values into a database field by displaying the contents of a lookup field in another table. Though these controls store their results in a single field, you need another field for the lookup values. Note: at lest for DBLookupComboBox, there is a bug with FPC 2.6.0 that requires the listfield to be present in the datasource as well, you can bypass it by declaring a calculated field with the same name as the listfield in the datasource's dataset that does nothing.  DBCheckBox control Displays / edits a boolean field by checking/clearing a check box  DBRadioGroup control Displays the items as in a normal radio group, reading/setting the field value from a matching values list

Pagina 5 din 69

 

DBCalendar control Displays / edits a date field using a calendar panel DBGroupBox control

DBGrid control This control can show a number of fields in a row/column layout - in fact by default it shows them all. However, you can put entries into the columns collection to restrict it to specific fields and to set the widths and titles of each column. Apart from the mentioned documentation, some more detail can be found here: Grids Reference Page#TCustomDBGrid

Navigator Control This control gives the user some direct control over the dataset. It allows the user to:  Move to the next or previous record, or to the start or end of the records  Add a new record (equivalent to a dataset.insert method call)  Put the dataset into edit mode  Delete a record  Post or Cancel current changes  Refresh the data (useful in multiuser database applications) Key Properties:  VisibleButtons: Lets you control what the user can do. For example, if deletes are not allowed, hide the delete button. If you have a DBGrid attached to the same dataset, you may decide you do not need the next and prior buttons.  Width: If you do not show all buttons, you may want to set the width to (height*number_of_visible_buttons)

Running FPC database tests Free Pascal database components include a fpcunit-based test framework, dbtestframework, that can be used to verify functionality. See the directory source\packages\fcl-db\tests\ in your FPC source tree. Included is a test framework that can be run on various database components, as well as some other tests (e.g. test of database export). To run the test framework on a certain database: 1. Save source\packages\fcl-db\tests\database.ini.txt as source\packages\fcl-db\tests\database.ini 2. Modify source\packages\fcl-db\tests\database.ini to choose which database type you will use. Example for Interbase/Firebird: [Database] type=interbase 3. In the same file, customize settings for your database. E.g. if you chose interbase before: [interbase] connector=sql connectorparams=interbase ; Database name/path (note: database needs to exist already) ; You can use aliases (see aliases.conf in your Firebird documentation) name=testdb user=sysdba password=masterkey ; your hostname may very well differ: ; Leave blank if you want to use an embedded Firebird database hostname=192.168.0.42 4. Compile and run source\packages\fcl-db\tests\dbtestframework.pas (You can also use Lazarus to compile and run the GUI version, dbtestframework_gui) If you are using an embedded database on Windows (e.g. Firebird embedded or sqlite), copy the required DLL files to the directory first. The output will be in XML format (or displayed on your screen if you use dbtestframework_gui). Please see source\packages\fcl-db\tests\README.txt for more details.

Database packages contained in Lazarus sqldblaz.lpk

This package provides access to different databases. These include:  Interbase/Firebird  Microsoft SQL Server (except on Lazarus/FPC x64 for Windows)  MySQL

Pagina 6 din 69

Oracle (except on Lazarus/FPC x64 for Windows) PostgreSQL (except on Lazarus/FPC x64 for Windows) SQLite (with support for the Spatialite extension) Sybase ASE (Adaptive Server Enterprise - not to be confused with Sybase ASA) (except on Lazarus/FPC x64 for Windows)  any database that has an ODBC driver. The components (TSQLQuery, TSQLTransaction, TIBConnection, TODBCConnection, TOracleConnection, TMSSQLConnection, TMySQL40Connection, TMySQL41Connection, TMySQL50Connection, TPQConnection, TSybaseConnection) are on the 'SQLdb' tab in the component palette.  SQLdb Package    

dbflaz.lpk This package provides access to dBase and FoxPro databases. You can get more information in the Lazarus Tdbf Tutorial. The TDbf component is on the Data Access tab in the component palette.

sqlitelaz.lpk This package provides access to SQLite databases. You can get more information in the Lazarus Database Overview.

sdflaz.lpk The component TSdfDataSet can be found on the Data Access tab in the component palette.

lazreport.lpk The homepage of the report generator is http://lazreport.sourceforge.net/. More informationen (et al. an additional link) can be found here. LazReport depends on the Printer4Lazarus package. With revision 11950 LazReport was included in the Lazarus SVN repository.

lazdbexport.lpk See lazdbexport.

External packages / libraries Zeos DataBase Objects These components provide access to different databases. You can find more information here. This wiki also contains a Zeos tutorial.

Pascal Data Objects There is now an alternative. Support:  MySQL 4.1 and 5.0  sqlite-2 and sqlite-3  pgsql-8.1  interbase-5, interbase-6, firebird-1.0, firebird-1.5, firebird-1.5E, firebird-2.0, firebird-2.0E  mssql (Microsoft library) and sybase (FreeTDS library)  oracle like prepared statements, binding, and stored procedures are supported by database API called Pascal Data Objects, which is inspired by PHP Data Objects. All the code and documentation necessary to use this new API is available on Sourceforge: http://pdo.sourceforge.net

TPSQL These components provide access via TCP/IP to PostgreSQL databases. You can find more information on this page.

FIBL These components provide access is http://sourceforge.net/projects/fibl.

to

Interbase

and

Firebird

databases.

The

homepage

IBX IBX For Lazarus are components to access Firebird databases: see IBX

FBLib Firebird Library FBLib is an open Source Library No Data Aware for direct access to Firebird Relational Database from Borland Delphi/Kylix, Free Pascal and Lazarus. Current Features include:  Direct Access to Firebird 1.0.x, 1.5.x and 2.x Classic or SuperServer  Multiplatform [Win32,Gnu/Linux,FreeBSD)  Automatic select client library 'fbclient' or 'gds32'  Query with params  Support SQL Dialect 1/3

Pagina 7 din 69

 LGPL License agreement  Extract Metadata  Simple Script Parser  Only 100-150 KB added into final EXE  Support BLOB Fields  Export Data to HTML SQL Script  Service manager (backup,restore,gfix...)  Events Alerter You can download documentation on FBLib's website.

Unified Interbase UIB provides access to Interbase, Firebird and YAFFIL databases. The homepage is www.progdigy.com. A svn repository is available under https://uib.svn.sourceforge.net/svnroot/uib .

TechInsite Object Persistence Framework (tiOPF) More information about tiOPF can be found on this page.

Advantage TDataSet Descendant The Advantage TDataSet Descedant provides a means of connecting to (and opening tables with) the Advantage Database Server. Advantage is a flexible, administration-free embedded database that provides Client/Server as well as Peer-to-peer access to Clipper, FoxPro and Visual FoxPro 9 DBF file formats, as well as a proprietary file format that provides a migration path allowing the use of newer features. Key Features:  Royalty-free peer-to-peer database access with migration path to Client/Server  Multi-Platform (Clients supported on Windows and Linux, Server supported on Windows, Linux, and NetWare)  Supports Both navigational and relational SQL database access  Full-text search engine  Table, Index, Memo, and communication encryption  Compatible with native TDataset components  Online Backup  Server supports Replication For more information, see the Advantage Database Server website.

ZMSQL, sql-enhanced in-memory database For more information, see the ZMSQL wiki page ZMSQL is an open source, TBufDataset descendant SQL enhanced in-memory database for Free Pascal (FPC), operating with semicolon-separated values flat text tables. Completely written in Pascal, it has no dependencies on external libraries. It uses JanSQL engine for SQL implementation. It offers:  Loading from and saving to flat text tables  Use of SQL to query the data  Copy data and schema from other datasets  Option to predefine fielddefs or create it on-the fly  Master/detail filtering  Referential integrity  Parameterized queries The download contains the source code, some demo applications illustrating the features of the component as well as a readme.

Pagina 8 din 69

Lazarus Database Overview Contents     

1 Overview 2 Lazarus and Interbase / Firebird 3 Lazarus and MySQL 4 Lazarus and MSSQL/Sybase 5 Lazarus and ODBC 5.1 Microsoft Access 6 Lazarus and Oracle 7 Lazarus and PostgreSQL 8 Lazarus and SQLite 9 Lazarus and Firebird/Interbase 10 Lazarus and dBase 11 Lazarus and Paradox 12 TSdfDataset and TFixedDataset 13 Lazarus and Advantage Database Server

o        

Overview This article is an overview of which databases can work with Lazarus. Lazarus supports several databases out of the box (using e.g. the SQLDB framework), however the developer must install the required packages (client libraries) for each one. You can access the database through code or by dropping components on a form. The data-aware components represent fields and are connected by setting the DataSource property to point to a TDataSource. The Datasource represents a table and is connected to the database components (examples: TPSQLDatabase, TSQLiteDataSet) by setting the DataSet property. The data-aware components are located on the Data Controls tab. The Datasource and the database controls are located on the "Data Access" tab. See the tutorials for Lazarus/FPC built in database access, suitable for Firebird, MySQL, SQLite, PostgreSQL etc:  SQLdb Tutorial0  SQLdb Tutorial1  SQLdb Tutorial2  SQLdb Tutorial3  SQLdb Tutorial4

Lazarus and Interbase / Firebird  

Firebird is very well supported out of the box by FPC/Lazarus (using SQLDB); please see Firebird for details. Other Firebird libraries has a list of alternative access libraries (e.g. PDO, Zeos, FBlib)

Lazarus and MySQL  1. 2. 3. 4.

Please see mysql for details on various access methods, which include: Built-in SQLdb support PDO Zeos MySQL data access Lazarus components

Lazarus and MSSQL/Sybase You can connect to Microsoft SQL Server databases using 1. SQL Server data access Lazarus components.They are working on Windows and Mac OS X. Free to download. 2. The built-in SQLdb connectors TMSSQLConnection and TSybaseConnection (since Lazarus 1.0.8/FPC 2.6.2): see mssqlconn. 3. Zeos component TZConnection (latest CVS, see links to Zeos elsewhere on this page) 1. On Windows you can choose between native library ntwdblib.dll (protocol mssql) or FreeTDS libraries (protocol FreeTDS_MsSQL-nnnn) where nnnn is one of four variants depending on the server version. For Delphi (not Lazarus) there is also another Zeos

Pagina 9 din 69

protocol ado for MSSQL 2005 or later. Using protocols mssql or ado generates code not platform independient. 2. On Linux the only way is with FreeTDS protocols and libraries (you should use libsybdb.so). 4. ODBC (MSSQL and Sybase ASE) with SQLdb TODBCConnection (consider using TMSSQLConnection and TSybaseConnection instead) 1. See also [1] 2. On Windows it uses native ODBC Microsoft libraries (like sqlsrv32.dll for MSSQL 2000) 3. On Linux it uses unixODBC + FreeTDS (packages unixodbc or iodbc, and tdsodbc). Since 2012 there is also a Microsoft SQL Server ODBC Driver 1.0 for Linux which is a binary product (no open source) and provides native connectivity, but was released only for 64 bits and only for RedHat.

Lazarus and ODBC ODBC is a general database connection standard which is available on Linux, Windows and OSX. You will need an ODBC driver from your database vendor and set up an ODBC "data source" (also known as DSN). You can use the SQLDB components (TODBCConnection) to connect to an ODBC data soruce. See ODBCConn for more details and examples.

Microsoft Access You can use the ODBC driver on Windows as well as Linux to access Access databases; see MS Access

Lazarus and Oracle 

See Oracle. Access methods include: 1. Built-in SQLDB support 2. Zeos 3. Oracle data access Lazarus component

Lazarus and PostgreSQL  

PostgreSQL is very well supported out of the box by FPC/Lazarus Please see postgres for details on various access methods, which include: 1. Built-in SQLdb support. Use component TPQConnection from the SQLdb tab of the Component Palette 2. Zeos. Use component TZConnection with protocol 'postgresql' from palette Zeos Access 3. PostgreSQL data access Lazarus component

Lazarus and SQLite SQLite is an embedded database; the database code can be distributed as a library (.dll/.so/.dylib) with your application to make it self-contained (comparable to Firebird embedded). SQLite is quite popular due to its relative simplicity, speed, small size and cross-platform support. Please see the SQLite page for details on various access methods, which include: 1. Built-in SQLDb support. Use component TSQLite3Connection from palette SQLdb 2. Zeos 3. SQLitePass 4. TSQLite3Dataset 5. SQLite data access Lazarus components

Lazarus and Firebird/Interbase InterBase (and FireBird) Data Access Components (IBDAC) is a library of components that provides native connectivity to InterBase, Firebird and Yaffil from Lazarus (and Free Pascal) on Windows, Mac OS X, iOS, Android, Linux, and FreeBSD for both 32-bit and 64-bit platforms. IBDAC-based applications connect to the server directly using the InterBase client. IBDAC is designed to help programmers develop faster and cleaner InterBase database applications. IBDAC is a complete replacement for standard InterBase connectivity solutions. It presents an efficient alternative to InterBase Express Components, the Borland Database Engine (BDE), and the standard dbExpress driver for access to InterBase. Firebird data access components for Lazarus are free to download.

Lazarus and dBase FPC includes a simple database component that is derived from the Delphi TTable component called "TDbf" TDbf Website). It supports various DBase and Foxpro formats. TDbf does not accept SQL commands but you can use the dataset methods etc and you can also use regular databound controls such as the DBGrid.

Pagina 10 din 69

It doesn't require any sort of runtime database engine. However it's not the best option for large database applications. See the TDbf Tutorial page for the tutorial as well as documentation. You can use e.g. OpenOffice/LibreOffice Base to visually create/edit dbf files, or create DBFs in code using TDbf.

Lazarus and Paradox Paradox was the default format for database files in old versions of Delphi. The concept is similar to DBase files/DBFs, where the "database" is a folder, and each table is a file inside that folder. Also, each index is a file too. To access this files from Lazarus we have these options:  TParadox: Install package "lazparadox 0.0" included in the standard distribution. When you install this package, you will see a new component labeled "PDX" in the "Data Access" palette. This component is not standalone, it uses a "native" library, namely the pdxlib library which is available for Linux and Windows. For example, to install in Debian, you could get pxlib1 from package manager. In Windows you need the pxlib.dll file.  TPdx: Paradox DataSet for Lazarus and Delphi from this site. This component is standalone (pure object pascal), not requiring any external library, but it can only read (not write) Paradox files. The package to install is "paradoxlaz.lpk" and the component should appear in the "Data Access" palette with PDX label (but orange colour).  TParadoxDataSet: is a TDataSet that can only read Paradox Files up to Version 7. See this wiki page. The approach is similar to the TPdx component, the package to install is "lazparadox.lpk" and the component should also appear in the "Data Access" palette.

TSdfDataset and TFixedDataset TSdfDataSet and TFixedFormatDataSet are two simple TDataSet descandants which offer a very simple textual storage format. These datasets are very convenient for small databases, because they are fully implemented as an Object Pascal unit, and thus require no external libraries. Also, their textual format allows them to be easily viewed/edited with a text editor. See CSV for example code.

Lazarus and Advantage Database Server Overview This brief tutorial is intended to get you started using the Advantage TDataSet descendent to access tables hosted by the Advantage Database Server.

Installing the Advantage TDataSet Windows If installing the Advantage TDataSet on Windows, you will need to download and install the Advantage Delphi Components (version 10.1 or greater). The install media can be obtained from the Advantage web site here.

Linux If installing the Advantage TDataSet on Linux, you will need to complete a two-part installation. First, download and install the Advantage Client Engine for Linux (version 10.1). Second, download and extract the Linux TDataSet source tarball. Both downloads are available at the Advantage Developer Zone at http://devzone.advantagedatabase.com. (The Advantage Client Engine download is located in the "Product Download" section of the site, and the Linux TDataSet source is available in the Delphi Applications section of the CodeCentral page of the Advantage Developer Zone.)

Installing the Advantage Package Once the TDataSet Descendant is installed, you'll want to move on to installing the package into Lazarus. 1. From Lazarus, click on "Package", then "Open Package File (.lpk)..." and browse to the adsl.lpk file in the TDataSet installation directory (or in the directory you extracted the TDataSet source). 2. In the package window, click the "Compile" button. 3. Upon successful compilation, click the "Install" button, and select "Yes" to rebuild Lazarus. 4. The Lazarus IDE should successfully compile and re-start with the Advantage components installed.

A simple Advantage project Start a new project to start working with Advantage data. 1. Drop a TAdsConnection object from the Advantage tab of the palette onto your form. (The TAdsConnection object is the left-most object on the Advantage tab.)

Pagina 11 din 69

2. In the Object Inspector, click the drop-down for the AliasName property, and select "ADTDemoData".  Alternately, you can select the ConnectPath property and enter (or browse to) the path to the Help\ADS_Data directory beneath your TDataSet (or acesdk on Linux) install directory. 3. Expand the AdsServerTypes property, and change the "stADS_LOCAL" property to True.  If you have an Advantage Database server configured and running, you may set "stADS_REMOTE" to true instead. 4. Drop a TAdsTable object on the form. (The TAdsTable object is immediately to the right of the TAdsConnection object on the tab, and it looks like a red table.) 5. Set the AdsConnection Property for AdsTable1 to AdsConnection1 (the connection object you just dropped in step 1.) 6. Scroll down to the "TableName" property, and use the drop-down box to select the biolife.adt table. 7. Drop a TDataSource component on the form, and set its DataSet property to "AdsTable1". 8. Drop a TDBGrid component on the form, and set its "DataSource" property to "Datasource1". 9. At this point, you should be able to select the AdsTable1 object and set its "Active" property to "True". 10. Finally, run the project. (Note that you may need to save the project before running it.) Since the Advantage components descend from the TDataSet, you can use these components with any data-aware component that supports the TDataSet. This extremely simple example should demonstrate how simple it is to get started with Advantage.

Pagina 12 din 69

SqlDBHowto This text is setup as a 'how-to'. I want to answer a number of questions one by one, and explain how you can use the various classes. All those questions are put one after the other and form a sort of tutorial. I will try to word it in such a way that the text can be used for Lazarus as well as FreePascal. However, the examples are for FreePascal (i.e. they are console applications.)    

    

Contents 1 Where can I find official documentation? 2 How to connect to a database server? 3 How to execute direct queries/make a table? 4 How to read data from a table? o 4.1 Example: reading data from a table o 4.2 Why does TSQLQuery.RecordCount always return 10? o 4.3 Lazarus 5 How to change data in a table? 6 How does SqlDB send the changes to the database server? 7 How to execute a query using TSQLQuery? 8 How to use parameters in a query? o 8.1 Select query o 8.2 Example 9 Troubleshooting: TSQLConnection logging o 9.1 FPC (or: the manual way) o 9.2 Lazarus (or: the quick way)

Where can I find official documentation? Please see the official documentation at SQLDB documentation.

How to connect to a database server? SqlDB doesn't connect to a database server directly but uses a client that corresponds to the used database server. SqlDB sends the commands to the client library; the client library connects to the database and and transfers the commands. This means that a client library must be installed on the computer to make a connection to a database. Under Windows a client is usually a .dll, under Linux an .so and under OS/X a .dylib. When the client library is installed properly you can connect to a database server using a TSQLConnection component. Various TSQLConnection components are available for different database servers (see SQLdb_Package):  Firebird/Interbase: TIBConnection  MS SQL Server: TMSSQLConnection (available since FPC 2.6.1)  MySQL v4.0: TMySQL40Connection  MySQL v4.1: TMySQL41Connection  MySQL v5.0: TMySQL50Connection  MySQL v5.1: TMySQL51Connection (available since FPC version 2.5.1  MySQL v5.5: TMySQL55Connection (available since Lazarus 1.0.8/FPC version 2.6.2  MySQL v5.6: TMySQL56Connection (available in Lazarus 1.2.4/FPC version 2.6.4  ODBC: TODBCConnection (see ODBCConn#TODBCConnection)  Oracle: TOracleConnection (see Oracle)  PostgreSQL: TPQConnection (see postgresql#SQLDB)  Sqlite3: TSQLite3Connection (available since FPC version 2.2.2, see SQLite#Built-in_SQLDB)  Sybase ASE: TSybaseConnection (available since FPC 2.6.1, see Lazarus and MSSQL/Sybase) Note for MySQL - There are many differences between the client versions to the extent that the clients and connections cannot be interchanged. If a MySQL client library version 4.1 is installed, you have to use a TMySQL41Connection. This is not related to the MySQL server; using the MySQL 4.1 client library you can probably connect to a MySQL 5.0 server (see MySQL documentation regarding what combinations are supported). Although details differ for the various databases, in general you need to set four properties to connect to a database server:  the server name or IP address  the name of the database  the username  the password

Pagina 13 din 69

When these properties are set, you can create a connection with the 'open' method. If the connection fails, a EDatabaseError exception is thrown. Use the property 'connected' to test if a connection has been made with the database server. Use the 'close' method to end the connection with the server. Program ConnectDB; function CreateConnection: TIBConnection; begin result := TIBConnection.Create(nil); result.Hostname := 'localhost'; result.DatabaseName := '/opt/firebird/examples/employee.fdb'; result.UserName := 'sysdba'; result.Password := 'masterkey'; end; var AConnection : TIBConnection; begin AConnection := CreateConnection; AConnection.Open; if Aconnection.Connected then writeln('Successful connect!') else writeln('This is not possible, because if the connection failed, ' + 'an exception should be raised, so this code would not ' + 'be executed'); AConnection.Close; AConnection.Free; end. If an exception is thrown, read the error message carefully. It may be that the database server is not running, the user name or password are incorrect or the database name or IP address are typed incorrectly. If the error message states that the client library cannot be found, then check if the client is installed correctly. Often the error message states literally the name of the file looked for.

How to execute direct queries/make a table? SqlDB - the name says it all - only works with database server that make use of SQL. SQL stands for 'Structured Query Language' SQL is a language developed to allow working with relational databases. Virtually every database system has its own dialect, but a large number of SQL statements are the same for all database systems. In FPC, there is a difference between:  SQL statements that return information (a dataset). For this, you have to use the TSQLQuery component; see #How to read data from a table?.  statements that do not return information but do something else, e.g. update data. For this, you may also use the 'ExecuteDirect' method of a TSQLConnection. (You can also use this if you get a dataset back but are not interested in the results, e.g. in a selectable stored procedure). Most database system execute SQL statements within a transaction. If you want changes made within a transaction available in other transactions, or have those changes available even after closing the transaction(!), then you have to 'commit' the transaction. To support transactions Sqldb contains the TSQLTransaction component. A SQL statement that is executed by Sqldb must always be executed within a transaction, even if the database system does not support transactions. Also, there are database systems that do support transaction for which TSQLConnection does not (yet) support transaction. Even then, you must use the TSQLTransaction component. To use TSQLConnection.ExecuteDirect to execute a SQL statement you must specify which 'Transaction' must be used. In turn, to use TSQLTransaction you must specify which TSQLConnection component must be used. The following example creates a table 'TBLNAMES' with fields 'NAME' and 'ID' and inserts two records. The used SQL statements are not explained. For more information about the SQL statements, their use and syntax, please refer to the database system documentation. The procedure 'CreateConnection' is defined in the code example in #How to connect to a database server? above. program CreateTable; function CreateTransaction(pDB: TIBConnection): TSQLTransaction; begin result := TSQLTransaction.Create(pDB);

Pagina 14 din 69

result.Database := pDB; end; var AConnection : TSQLConnection; ATransaction : TSQLTransaction; begin AConnection := CreateConnection; ATransaction := CreateTransaction(AConnection); AConnection.Transaction := ATransaction; AConnection.Open; ATransaction.StartTransaction; AConnection.ExecuteDirect('create table TBLNAMES varchar(40));');

(ID

integer,

NAME

// Some database-server types need a commit before you can use a newly created table. (Firebird) // With .Commit you also close the transaction ATransaction.Commit; ATransaction.StartTransaction; AConnection.ExecuteDirect('insert (1,'Name1');'); AConnection.ExecuteDirect('insert (2,'Name2');'); ATransaction.Commit; AConnection.Close; AConnection.Free; ATransaction.Free; end.

into

TBLNAMES

(ID,NAME)

values

into

TBLNAMES

(ID,NAME)

values

How to read data from a table? Use the TSQLQuery component to read data from a table. A TSQLQuery component must be connected to a TSQLConnection component and a TSQLTransaction component to do its work. Setting the TSQLConnection and TSQLTransaction is discussed in #How to connect to a database server? and #How to execute direct queries/make a table?. When the TSQLConnection, TSQLTransaction and TSQLQuery are connected, then TSQLQuery needs to be further configured to work. TSQLQuery has a 'SQL' property containing a TStrings object. The 'SQL' property contains a SQL statement that must be executed. If all data from a table tablename must be read, then set the 'SQL' property to: 'SELECT * FROM tablename;' . Use 'open' to read the table from the server and put the data in the TSQLQuery dataset. The data can be accessed through TSQLQuery until the query is closed using 'close'. TSQLQuery is a subclass of TDataset. TDataset has a 'Fields' collection that contains all columns of the table. The TDataset also keeps track of the current record. Use 'First', 'Next', 'Prior' and 'Last' to change the current record. 'Bof' returns 'True' if the first record is reached, and 'Eof' returns 'True' if the last record is reached. To read the value of a field in the current record, first find the right 'TField' object and then use 'AsString', 'AsInteger', etc.

Example: reading data from a table Below is an example that displays all values of the table as it was made in #How to execute direct queries/make a table? above. Program ShowData; function CreateQuery(pConnection: TSQLTransaction): TSQLQuery; begin result := TSQLQuery.Create(nil); result.Database := pConnection; result.Transaction := pTransaction end;

TIBConnection;

Pagina 15 din 69

pTransaction:

var AConnection : TSQLConnection; ATransaction : TSQLTransaction; Query : TSQLQuery; begin AConnection := CreateConnection; ATransaction := CreateTransaction(AConnection); Query := CreateQuery(AConnection, ATransaction); Query.SQL.Text := 'select * from tblNames'; AConnection.Open; Query.Open; while not Query.Eof do begin Writeln('ID: ', Query.FieldByName('ID').AsInteger, 'Name: ' + Query.FieldByName('Name').AsString); Query.Next; end; Query.Close; AConnection.Close; Query.Free; ATransaction.Free; AConnection.Free; end. (The code above of course is not quite finished, it misses 'try...finally' blocks. However, the above code intends to show the database code and thus the finishing touches are left out.) Please note that 'TSQLTransaction.StartTransaction' is not used. This is not necessary. When TSQLQuery is opened, the SQL statement is executed and if no transaction is available then a transaction is automatically started. The programmer does not need to start the transaction explicitly. The same applies for the connection maintained by TSQLConnection. The connection is opened as needed, the line 'Aconnection.Open' is not really required. If a TSQLTransaction is destroyed, an automatic 'rollback' will be executed. Possible changes to data contained in the transaction will be lost.

Why does TSQLQuery.RecordCount always return 10? To count the records in a dataset, use '.RecordCount'. However, notice that '.RecordCount' shows the number of records that is already loaded from the server. For performance reasons, SqlDB does not read all records when opening TSQLQuery by default, only the first 10. Only when the eleventh record is accessed will the next set of 10 records be loaded, etc. Using '.Last', all records will be loaded. When you want to know the real number of records on the server you can first call '.Last' and then call '.RecordCount'. An alternative is available. The number of records returned by the server is set by the '.PacketRecords' property. The default value is 10; if you make it -1 then all records will be loaded at once. In current stable FPC, '.RecordCount' does not take filters into account, i.e. it shows the unfiltered total. If you need the exact number of records, it often is a better idea to directly query the number of records in a query using another SQL query, but you would have to do that in the same transaction, as other transactions may have changed the number of records in the meanwhile.

Lazarus Lazarus has various components to show data from a TDataset on a form. Instead of a While-loop and Writeln statements as used above, you can use the components to show the data in a table. Place the right TSQLConnection, TSQLTransaction and TSQLQuery components on a form, then connect them and set them properly. In addition you will need a TDatasource; set the 'TDatasource.Dataset' property to the TSQLQuery component you used. (Note do not set the 'TSQLQuery.Datasource' property to the TDatasource compnent you used. The 'TSQLQuery.Datasource' property is used only in master-detail tables - see MasterDetail) Subsequently you may put a TDBGrid onto the form and set the 'Datasource' property of the grid to the TDatasource component you added before. To see if it all works, set the 'Connected' property of the TSQLConnection to 'True' in the Lazarus IDE. The IDE will try to connect to the database server immediately. If this works you can set the 'TSQLQuery.Active' property to 'True'. If everything is right, you will see - within the IDE - all data from the table immediately on the screen.

How to change data in a table? To change the data in a record, the TDataset (from which TSQLQuery is derived) must be set to edit mode. To enter edit mode call the '.Edit', '.Insert' or '.Append' methods. Use the '.Edit' method to change the current record. Use '.Insert' to insert a new record before the current record. Use '.Append' to insert a new

Pagina 16 din 69

record at the end of the table. In edit mode you can change field values through the 'Fields' property. Use 'Post' to validate the new data, if the data is valid then the edit mode is left. If you move to another record for example by using '.Next' - and the dataset is in edit mode, then first '.Post' is called. Use '.Cancel' to discard all changes you made since the last '.Post' call and leave the edit mode. Query.Edit; Query.FieldByName('NAME').AsString := 'Edited name'; Query.Post; The above is not the complete story yet. TSQLQuery is derived from TBufDataset which makes use of buffered updates. Buffered update means that after you called 'Post' the changes in the dataset are visible immediately, but they are not sent to the database server. What does happen is that the changes are maintained in a change log. When the '.ApplyUpdates' method is called, then all changes in the change log are sent to the database. Only then will database server know of the changes. The changes are sent to the server within a transaction of TSQLTransaction. Make sure to properly set the transaction before 'ApplyUpdates'. After applying the updates, a commit must be executed to save the changes on the database server. The below is an example of changing the data in a table, sending the changes to the server and comitting the transaction. Program EditData; var AConnection : TSQLConnection; ATransaction : TSQLTransaction; Query : TSQLQuery; begin AConnection := CreateConnection; ATransaction := CreateTransaction(AConnection); AConnection.Transaction := ATransaction; Query := CreateQuery(AConnection, ATransaction); Query.SQL.Text := 'select * from tblNames'; Query.Open; Query.Edit; Query.FieldByName('NAME').AsString := 'Edited name'; Query.Post; Query.UpdateMode := upWhereAll; Query.ApplyUpdates; ATransaction.Commit; Query.Free; ATransaction.Free; AConnection.Free; end. For a discussion of 'UpdateMode' continue reading.

How does SqlDB send the changes to the database server? In the code example in #How to change data in a table?, you will find the line Query.UpdateMode := upWhereAll; without explanation of what it does. The best way to find out what that line does is to leave it out. If you leave out the statement and the followed this howto precisely, then you will receive the following error message:

No update query specified and failed inclusion in where statement found)

to

generate

one.

(No

fields

for

To understand what went wrong, you must understand how changes are sent to the database server. The only way to get data in a SQL server is by executing SQL queries. SQL has three types of queries for three different ways of manupulating a record. To create a new record, change or delete a record insert, update and delete statements are executed respectively. An update statement may be as follows: UPDATE TBLNAMES SET NAME='Edited name' WHERE ID=1; To send a change to the database server, Sqldb must assemble an update query. To assemble the query, three things are needed: The name of the table The table name is retrieved from parsing the select query, although this doesn't always work. UPDATE or INSERT clause These contain the fields that must be changed.

Pagina 17 din 69

WHERE clause This contains the fields that determine which records should be changed. Every field (each TField in Fields) has a ProviderFlags property. Only fields with pfInUpdate in ProviderFlags will be used in the update or insert cluase of a query. By default all fields have pfInUpdate set in their ProviderFlags property. Which fields are used in the WHERE clause depends on the UpdateMode property of the query and the ProviderFlags property of the fields. Fields with pfInkey in their ProviderFlags are always used in the WHERE clause. A field will have the pfInKey flag set automatically if the field is part of the primary key of the table and 'TSQLQuery.UsePrimaryKeyAsKey' returns 'True'. The default value for UpdateMode of the query is upWhereKeyOnly. In this update mode only fields with pfInkey in their ProviderFlags property are used in the WHERE clause. If none of the fields have their pfInKey flag set, then no fields are available for the WHERE clause and the error message from the beginning of this section will be returned. You can solve the issue by:  Adding a primary key to the table and set TSQLQuery.UsePrimaryKeyAsKey to 'True', or  Setting the pfInkey flag for one or more fields in code. The UpdateMode property knows two more possible values. 'upWhereAll' can be used to add all fields with the 'pfInWhere' flag set to the WHERE clause. By default all fields have this flag set. 'upWhereChanged' can be used to add only those fields that have the 'pfInWhere' flag set and that are changed in the current record.

How to execute a query using TSQLQuery? Next to statements that return a dataset (see #How to read data from a table?) SQL has statements that do not return data. For example INSERT, UPDATE and DELETE statements do not return data. These statements can be executed using TSQLConnection.ExecuteDirect, but TSQLQuery can also be used. If you do not expect return data use TSQLQuery.ExecSQL instead of TSQLQuery.Open. As mentioned earlier, use TSQLQuery.Open to open the dataset returned by the SQL statement. The following procedure creates a table and inserts two records using TSQLQuery. procedure CreateTable; var Query : TSQLQuery; begin Query := CreateQuery(AConnection, ATransaction); Query.SQL.Text := 'create table TBLNAMES varchar(40));'; Query.ExecSQL;

(ID

integer,

NAME

Query.SQL.Text (1,''Name1'');'; Query.ExecSQL;

:=

'insert

into

TBLNAMES

(ID,NAME)

values

Query.SQL.Text (2,''Name2'');'; Query.ExecSQL;

:=

'insert

into

TBLNAMES

(ID,NAME)

values

Query.Close; Query.Free; end;

How to use parameters in a query? In the code example of #How to execute a query using TSQLQuery? the same query is used twice, only the values to be inserted differ. A better way to do this is by using parameters in the query. The syntax of parameters in queries is different per database system, but the differences are handled by TSQLQuery. Replace the values in the query with a colon followed by the name of the parameter you want to use. For example: Query.SQL.Text := 'insert into TBLNAMES (ID,NAME) values (:ID,:NAME);'; This query will create two parameters: 'ID' and 'NAME'. To determine the parameters, the query is parsed at the moment the text of TSQLQuery.SQL is assigned or changed. All existing parameters will be removed and the new parameters will be added to the

Pagina 18 din 69

'TSQLQuery.Params' property. Assigning a value to a parameter is similar to assigning a value to a field in the dataset: Query.Params.ParamByName('Name').AsString := 'Name1'; You can't tell from the query what kind of data must be stored in the parameter. The data type of the parameter is determined at the moment a value is first assigned to the parameter. By assigning a value using '.AsString', the parameter is assigned the data type 'ftString'. You can determine the data type directly by setting the 'DataType' property. If an incorrect datatype is assigned to the parameter, then problems will occur during opening or executing the query. See Database field type for more information on data types.

Select query An example of a select query with parameters would be to change something like this: Query.SQL.Text := 'select ID,NAME from TBLNAMES where NAME = '''+Edit1.Text+''' ORDER BY NAME '; to something like this: Query.SQL.Text := 'select ID,NAME from TBLNAMES where NAME = :NAMEPARAM ORDER BY NAME '; Query.Params.ParamByName('NAMEPARAM').AsString := Edit1.Text;

Example The following example creates the same table as the previous example, but now parameters are used: procedure CreateTableUsingParameters; var Query : TSQLQuery; begin Query := CreateQuery(AConnection, ATransaction); Query.SQL.Text := 'create table TBLNAMES varchar(40));'; Query.ExecSQL;

(ID

integer,

NAME

Query.SQL.Text := 'insert into TBLNAMES (ID,NAME) values (:ID,:NAME);'; Query.Prepare; Query.Params.ParamByName('ID').AsInteger := 1; Query.Params.ParamByName('NAME').AsString := 'Name1'; Query.ExecSQL; Query.Params.ParamByName('ID').AsInteger := 2; Query.Params.ParamByName('NAME').AsString := 'Name2'; Query.ExecSQL; //Query.UnPrepare; // no need to call this; should be called by Query.Close Query.Close; Query.Free; end; Notice that this example requires more code than the example without the parameters. Then what is the use of using parameters? Speed is one of the reasons. The example with parameters is faster, because the database server parses the query only once (in the .Prepare statement or at first run). Another reason to use prepared statements is prevention of SQL-injection (see also Secure programming. Finally, in some cases it just simplifies coding.

Troubleshooting: TSQLConnection logging You can let a TSQLConnection log what it is doing. This can be handy to see what your Lazarus program sends to the database exactly, to debug the database components themselves and perhaps to optimize your queries. NB: if you use prepared statements/parametrized queries (see section above), the parameters are often sent in binary by the TSQLConnection descendent (e.g. TIBConnection), so you can't just copy/paste the logged SQL into a database query tool. Regardless, connection logging can give a lot of insight in what your program is doing.

Pagina 19 din 69

Alternatives are: 1. you can use the debugger to step through the database code if you have built FPC (and Lazarus) with debugging enabled. 2. if you use ODBC drivers (at least on Windows) you could enable tracelog output in the ODBC control panel. 3. many databases allow you to monitor all statements sent to it from a certain IP address/connection. If you use TSQLConnection logging, two things are required: 1. indicate which event types your TSQLConnection should log 2. point TSQLConnection at a function that receives the events and processes them (logs them to file, prints them to screen, etc.). That function must be of type TDBLogNotifyEvent (see sqldb.pp), so it needs this signature: TDBLogNotifyEvent = Procedure (Sender : TSQLConnection; EventType : TDBEventType; Const Msg : String) of object;

FPC (or: the manual way) A code snippet can illustrate this: uses ... TSQLConnection, //or a child object like TIBConnection, TMSSQLConnection ... var type TMyApplication = class(TCustomApplication); //this is our application that uses the connection ... private // This example stores the logged events in this stringlist: FConnectionLog: TStringList; ... protected // This procedure will receive the events that are logged by the connection: procedure GetLogEvent(Sender: TSQLConnection; EventType: TDBEventType; Const Msg : String); ... procedure TMyApplication.GetLogEvent(Sender: TSQLConnection; EventType: TDBEventType; const Msg: String); // The procedure is called by TSQLConnection and saves the received log messages // in the FConnectionLog stringlist var Source: string; begin // Nicely right aligned... case EventType of detCustom: Source:='Custom: '; detPrepare: Source:='Prepare: '; detExecute: Source:='Execute: '; detFetch: Source:='Fetch: '; detCommit: Source:='Commit: '; detRollBack: Source:='Rollback:'; else Source:='Unknown event. Please fix program code.'; end; FConnectionLog.Add(Source + ' ' + Msg); end; ... // We do need to tell our TSQLConnection what to log: FConnection.LogEvents:=LogAllEvents; //= [detCustom, detPrepare, detExecute, detFetch, detCommit, detRollBack] // ... and to which procedure the connection should send the events:

Pagina 20 din 69

FConnection.OnLog:[email protected]; ... // now we can use the connection and the FConnectionLog stringlist will fill with log messages. You can also use TSQLConnection's GlobalDBLogHook instead to log everything from multiple connections.

Lazarus (or: the quick way) Finally, the description above is the FPC way of doing things as indicated in the introduction; if using Lazarus, a quicker way is to assign an event handler to the TSQLConnection's OnLog event.

Pagina 21 din 69

Working With TSQLQuery        

 

Contents 1 General 2 Official documentation 3 Commonly used controls 4 Updating data 5 Cached Updates 6 Primary key fields 7 Controlling the update 8 Customizing the SQL in TSQLQuery o 8.1 TSQLQuery.SQL: Basic SQL Customization o 8.2 TSQLQuery.InsertSQL, TSQLQuery.UpdateSQL and TSQLQuery.DeleteSQL: Basic Use of Parameters o 8.3 Parameters in TSQLQuery.SQL  8.3.1 Select query example  8.3.2 Insert query example o 8.4 Query with Format function 9 Running your own SQL and getting metadata 10 Troubleshooting o 10.1 Logging o 10.2 Poor performance o 10.3 Error messages o 10.4 Out of memory errors o 10.5 Dataset is read-only

General TSQLQuery is an object that can embody a dataset coming from a database (RDBMS that uses SQL, such as Firebird, MS SQL Server, Oracle...). Using a SELECT SQL statement in the TSQLQuery's SQL property, you can determine what data is retrieved from the database into the dataset. When the dataset is changed by the program (or user), the changes can be submitted back to the database. A TSQLQuery can also be used to directly modify data: if you specify the desired INSERT, UPDATE, DELETE etc SQL statement in the SQL property and call the ExecSQL method of the TSQLQuery, the query object will send the SQL to the database without retrieving any results. Apart from its use in FPC, Lazarus also provides a component: TSQLQuery

Official documentation See TSQLQuery documentation A lot of context-sensitive documentation is now available in Lazarus. Unfortunately, TSQLQuery does not appear in the index of Lazarus 1.0 help. If you place your cursor on TSQLQuery methods and properties, try pressing F1 to see if that code is documented; e.g. this will work: var Q: TSQLQuery ... Q.Open; //0). Next, we retrieve the data from the first row of results. If we wanted to move to the next row, we'd use FQuery.Next, but that is not necessary here. We put the results in the stringgrid, giving the lowest salary in the list. A similar approach can be taken for the highest salary.

Adapting SQL for various databases As we noticed above, various databases support various versions of SQL (either in addition to or in contradiction to the official ISO SQL standards). Fortunately, you can customize your application based on which DB it ends up using, which will be demonstrated by getting the standard deviation of the employees' salaries - built into e.g. PostgreSQL SQL but not available by default in e.g. Firebird. In our LoadSalaryGrid procedure, we'll use the SQL for PostgreSQL and build a code solution for all other databases. First detect which database is loaded, below the other lines add: ... SalaryGrid.Cells[3,2]:=FQuery.Fields[2].AsString; FQuery.Close; // Always commit(retain) an opened transaction, even if only reading FTran.Commit; //end of existing code if FConn.ConnectorType = 'PostGreSQL' then begin // For PostgreSQL, use a native SQL solution: FQuery.SQL.Text:='select stddev_pop(salary) from employee '; FTran.StartTransaction; FQuery.Open; if not FQuery.EOF then SalaryGrid.Cells[3,3]:=FQuery.Fields[0].AsString; FQuery.Close; // Always commit(retain) an opened transaction, even if only reading FTran.Commit; end else begin // For other database, use the code approach: ....see below... end; Notice the use of ConnectorType; the string used must match exactly. We also properly check for empty results from the query (which might happen if the employee table is empty). ... now let's implement a code-based solution for other databases that do not support standard deviation: // For other databases, use the code approach: // 1. Get average of values FQuery.SQL.Text:='select avg(salary) from employee '; FQuery.Open; if FQuery.EOF then SalaryGrid.Cells[3,3]:='No data' else begin Average:=FQuery.Fields[0].AsFloat; FQuery.Close; // 2. For each value, calculate the square of (value-average), and add it up FQuery.SQL.Text:='select salary from employee where salary is not null '; FQuery.Open; while not FQuery.EOF do begin DifferencesSquared:=DifferencesSquared+Sqr(FQuery.Fields[0].AsFloatAverage);

Pagina 52 din 69

Count:=Count+1; FQuery.Next; end; // 3. Now calculate the average "squared difference" and take the square root if Count>0 then //avoid division by 0 SalaryGrid.Cells[3,3]:=FloatToStr(Sqrt(DifferencesSquared/Count)) else SalaryGrid.Cells[3,3]:='No data'; end; FQuery.Close; Note that we use FQuery.EOF to check for empty data (and avoid division by zero errors etc). The loop shows how to:  retrieve a database value into a variable  use FQuery.Next to move to the next record  properly check if the query dataset has hit the last record, then stop retrieving data. The resulting screen should show something like this - note the use of a decimal comma - while your computer may show a decimal point depending on your locale:

Revisiting our lowest/highest salary This section gives some more useful details on SQL but is not required to work through for the rest of the tutorial Now we know how to deal with detecting various database connections, we can adjust the SQL that gets the lowest and highest salary as well to make use of db specific functionality. An example: this would work for MS SQL Server by limiting the number of returned rows to just the first: SELECT top 1 e.first_name, e.last_name, e.salary FROM employee e ORDER BY e.salary ASC to get the lowest salary. This efficiently returns one record. Other databases use other syntax, such as the ISO ROWS 1. The diligent SQL student will soon learn not to miss out that important part and request entire large recordsets just for one required record! Let's briefly examine other ways to achieve the same thing, that are worth knowing. Another way to retrieve the record(s) with the minimum salary would be :

Pagina 53 din 69

SELECT e.first_name, e.last_name, e.salary FROM employee e WHERE e.salary=(SELECT MIN(salary) FROM employee) SQL students would greatly benefit from researching Common Table Expressions. A CTE allows a virtual temporary table to be used in a following expression, allowing you to clearly code some very complex queries that otherwise may not be possible. Knowing about CTEs will catapult you ahead of colleagues who have never heard of them! For example the above may be rewritten (example in Microsoft SQL Server syntax) as : WITH TheMinimum AS ( SELECT MIN(salary) AS MinimumPay FROM Employee ) SELECT e.first_name, e.last_name, e.salary FROM Employee e WHERE e.salary=(SELECT MinimumPay FROM TheMinimum) Several such temporary tables may be chained together, each using the results from the previous tables. You can treat these virtual tables as though they were real tables in the database, using JOINs to link recordsets together. And it can be very useful for quick tests using hardcoded data - this can be run without any database connection : WITH TestEmployee AS ( SELECT 'Fred' AS first_name, 'Bloggs' AS last_name, 10500 AS salary UNION SELECT 'Joe' AS first_name, 'Public' AS last_name, 10000 AS salary UNION SELECT 'Mike' AS first_name, 'Mouse' AS last_name, 11000 AS salary ), TheMinimum AS ( SELECT MIN(salary) AS MinimumPay FROM TestEmployee ) SELECT e.first_name, e.last_name, e.salary FROM TestEmployee e WHERE e.salary=(SELECT MinimumPay FROM TheMinimum) You can end up with quite long strings for the code of such SQL queries, but it is only one query and may be called from anywhere where you are limited to a simple single expression - it can be useful to answer complex queries without resorting to functions or stored procedures.

Getting data out of normal controls into the database Previously, we have seen:  how to let SQLDB update the database with data-bound controls (earlier tutorials)  how to get data out of the database using queries (the section above) You can also execute SQL to get arbitrary data back into the database via code. This allows you to use variables or controls that have no db aware equivalent such as sliders or custom controls to enter data into the database, at the expense of a bit more coding. As an example, we are going to allow the user to change the lowest and highest salary in the stringgrid. For ease of editing, set the grid's Options/goEditing to true; then assign the procedure below to the OnValidate event for the grid, which will be called every time a user has finished updating the grid.

Parameterized queries The following code also demonstrates how to use parameterized queries to avoid SQL injection, fiddling with quoting for string values, date formatting, etc. As you can see in the code, you can name your parameters whatever you wish and prefix them with : in the SQL. In code, you can set/get their values by .Params.ParamByName('').As''; the code demonstrates .AsFloat and .AsString. Parameterized queries are especially useful (and can be much faster) if you run the same query, only with different parameters, in a loop (think e.g. bulk loading of data). Continuing with our example: after having set up the query SQL and parameters, the transaction is started (and later on committed) as usual, then the query is run by calling ExecSQL (which does not return a result set; if the SQL statement were e.g. a SELECT or INSERT...RETURNING that does return data, you would use Open as in the examples above): procedure TForm1.SalaryGridValidateEntry(sender: TObject; aCol, aRow: Integer; const OldValue: string; var NewValue: String); begin // Only these cells have min and max salary: if (aCol=3) and ((aRow=1) or (aRow=2)) then begin

Pagina 54 din 69

// Allow updates to min and max salary if positive numerical data is entered if StrToFloatDef(NewValue,-1)>0 then begin // Storing the primary key in e.g. a hidden cell in the grid and using that in our // update query would be cleaner, but we can do it the hard way as well: FQuery.SQL.Text:='update employee set salary=:newsalary '+ ' where first_name=:firstname and last_name=:lastname and salary=:salary '; FQuery.Params.ParamByName('newsalary').AsFloat:=StrToFloatDef(NewValue,0) ; FQuery.Params.ParamByName('firstname').AsString:=SalaryGrid.Cells[1,aRow] ; FQuery.Params.ParamByName('lastname').AsString:=SalaryGrid.Cells[2,aRow]; FQuery.Params.ParamByName('salary').AsFloat:=StrToFloatDef(OldValue,0); FTran.StartTransaction; FQuery.ExecSQL; FTran.Commit; LoadSalaryGrid; //reload standard deviation end else begin // Notify user that his input was wrong... he'll be wondering otherwise: Showmessage('Invalid salary entered.'); NewValue:=OldValue; end; end else begin // Silently discard edits to any other cells NewValue:=OldValue; end; end; Note how we forgot to add a try..except block to this code to nicely catch database errors and display a sensible error message. If you are running the Firebird sample EMPLOYEE database for this tutorial, try to change the salary to a very low value (say 1) and see what happens. Finally, while this example showed an UPDATE SQL query, you could just as well run INSERT queries to insert new data programmatically. Also, you can use parameters in any kind of SQL query (SELECT, UPDATE, etc) as long as you use them for fields, not for table/view/procedure names.

Summary This tutorial explained:  how to code for multiple database types  how to use a login form to decouple db access configuration from your program  how to retrieve and update data programmatically

Code Since November 2012, the code can be found in $(lazarusdir)examples/database/sqldbtutorial3 If you have an older version (e.g. Lazarus 1.0.2), you can also download the code via the Lazarus SVN website

Pagina 55 din 69

SQLdb Tutorial4     

Contents 1 Introduction 2 Why use datamodules? 3 Getting started 4 Everyone has their own way 5 More uses of data modules o 5.1 Additional components o 5.2 Debugging

Introduction This tutorial is an attempt to demonstrate the use of Lazarus Data Modules to isolate the data access components of a project from the program logic associated with the access. Such isolation makes program maintenance and debugging easier. The tutorial was developed using Windows 7 and SQLite3 as the database, with Lazarus 1.0.8 with FPC 2.6.2; however it should work with earlier versions. Similarly, other DBMS and Operating Systems should require minimal change, if any.

Why use datamodules? Simple - after following the Lazarus Tutorials:  SQLdb Tutorial0  SQLdb Tutorial1  SQLdb Tutorial2  SQLdb Tutorial3 developing a 'real' application becomes harder. 'Form1' grows to an exponential size handling the different Events and Database Queries. Isolating each table access into a single datamodule makes debugging and maintenance so much easier. An application may have any number of datamodules - a small application with just one or 2 tables can probably suffice with just one Datamodule - a larger application could probably benefit from having a data module for each table or view. The sample shown here uses just 2 tables with simple queries, but it can be expanded to include more options with each table.

Getting started In the Lazarus IDE, create a new Application and then click File --> New --> Data Module

You will be presented with a window as if you selected 'New Form': The difference is this window/form will only accept non-visual components. In fact, look at your Component Palette: it has been greatly reduced to only allow selection of ONLY non-visual components.

Pagina 56 din 69

Everyone has their own way Your use of data modules will vary to suit your own needs. but as an example, I have at least 2 data modules: Unit: DataModule1 On this module I 'drop' a T*Connection and a TSQLTransaction. DataModule1 is used as the connection for all queries. I then create a DataModuleN for each table or view. Each DataModuleN will need to have the DataModule1 unit (unit2 in this example) added to the USES clause to connect to the database. From here everything is the same as stated in SQLdb Tutorial1. The

components are connected in the same way and access is identical.

More uses of data modules Additional components In this example, DataModule1 had nothing more than a Connection and Transaction, but in a 'real' application, this container would typically also hold global non-visual components to be used by the application. For example, Load and Save INI settings, TOpenDialog, TSaveDialog, etc. The concept here is to isolate data access from the business logic of an application. A change in data source for any application is never a minimal task, but having the datasources isolated will make the change much easier.

Debugging Debugging a program is also a difficult task. By separating data access and business logic, the code to be viewed is halved. Data access and business logic can be tested separately to at least halve the problem. The importance of the DataModule will become even more obvious when developing other applications using the same database and tables. The data module can of course be reused in the new application.

Pagina 57 din 69

postgres    



Contents 1 Overview 2 Direct access to PostgreSQL 3 Zeos 4 SQLDB o 4.1 Example o 4.2 Event monitoring o 4.3 Installation and errors  4.3.1 Windows 64 bit driver  4.3.2 Error: "Can not load PostgreSQL client library "libpq.dll""  4.3.3 Problems clearing parameters 5 PostgreSQL package: the low level units o 5.1 Requirements o 5.2 Installation

Overview You can use Free Pascal/Lazarus to access a PostgreSQL database server. If you are looking for information on the postgres package in FPC, please see postgres#PostgreSQL_package:_the_low_level_units below. Advantages of PostgreSQL:  It is very widely used and available  Very stable and has a complete feature set  Liberal license (no costs) in comparison with MySQL Disadvantage of PostgreSQL:  Some hosters may not offer PostgreSQL)  No embedded version Win64: please see warning here on not using certain FPC/Lazarus Win64 versions.

Direct access to PostgreSQL You can connect Lazarus with PostgreSQL by using PostgreSQL Data Access Components (PgDAC). It is a library of components that provides native connectivity to PostgreSQL from Lazarus (and Free Pascal) on Windows, Mac OS X, iOS, Android, Linux, and FreeBSD for both 32-bit and 64-bit platforms. PgDAC is designed to help programmers develop really lightweight, faster and cleaner PostgreSQL database applications without deploying any additional libraries. You can download this Lazarus component for free.

Zeos Zeos supports PostgreSQL; please see ZeosDBO

SQLDB FPC/Lazarus supports PostgreSQL out of the box with a PostgreSQL connection component/class. If you are using FPC only or want to manually add PostgreSQL support, add pqconnection to your usesclause. Otherwise, Lazarus provides a component:

Note: The libpq C client contains some memory leaks (at least up till version 9.3 of Postgres) when a library is repeatedly loaded/unloaded. SQLDB loads the library when the first connection is made, and unloads it when the last connection closes. This means that whenever the last connection is closed, a small memory leak is created. To prevent this from happening (and speed up the application), you can load the library once at the start of the process with the InitialisePostgres3 call. The charset property is used for client encoding. The TPQConnection component does not directly support a Port property, but one can pass the port into the component via the Params parameter: PQConnection.Params.Add('port=' + VariableContainingPort); Other PostgreSQL specific connection parameters can be specified using the Params property: PQConnection.Params.Add('application_name=''yourappname''')

Example See SQLdb_Tutorial1 for a tutorial on creating a GUI database-enabled program that is written for PostgreSQL/SQLDB, as well as SQLite/SQLDB, Firebird/SQLDB, basically any RDBMS SQLDB supports).

Pagina 58 din 69

Event monitoring If you have FPC2.6.2+ and a recent version of Lazarus, you can use the TPQTEventMonitor component to monitor events coming from PostgreSQL. It is a thin wrapper around FPC PQEventMonitor; please see the FPC pqeventstest.pp example programs for details.

Installation and errors As with all sqldb units, you need to add your driver libraries (all required PostgreSQL .dll/.manifest files)  to a directory in the (library search) path (e.g. c:\windows\system32 for Windows)  or (Windows) to the program output directory (e.g. lib/something/ in your project directory, and the project directory

Windows 64 bit driver If you are developing 64 bit applications, you must use a 64 bit DLL. Note: FPC 2.6.0 (therefore Lazarus 1.0.4 or lower) does not yet support PostgreSQL on Windows 64 bit (unless you patch and recompile it).

A Windows 64 driver is fairly hard to find but can be downloaded here: [1]. The driver library can be installed in c:\windows\system32; 32 bit driver libraries can be installed in the confusingly named c:\windows\syswow64

Error: "Can not load PostgreSQL client library "libpq.dll"" The program cannot find your PostgreSQL driver files. See above on instructions where to install the libraries. A good example that demonstrates how to include drive DLL files when connecting Lazarus with PostgreSQL under Windows is easyDB. On Linux/Unix/OSX: make sure the PostgreSQL libraries are in your library search path, e.g.:  On Linux add the path to the libpq.so file to the libraries section in your /etc/fpc.cfg file. For example : -Fl/usr/local/pgsql/lib  It may be necessary to create a symbolic link from a specific library version to a general library name: ln -s /usr/lib/pqsql.so.5 /usr/lib/pqsql.so . Alternatively, install the postgresql client -dev package using your distribution's package manager

Problems clearing parameters Note: Verify this: is .paramtype really necessary?

At least in FPC
View more...

Comments

Copyright ©2017 KUPDF Inc.
SUPPORT KUPDF