Sign in Join
Wiki copytemporary

Firebird

English · Français · Русский · 日本語

This is a guide about using Firebird database in Lazarus/FPC, using Firebird with SQLDB (the FPC/Lazarus built-in database library). Other access methods are described in Other Firebird libraries.

Overview

Firebird is an open source, free database server that has been in use and developed for decades (it developed out of the Interbase 6 database that was open sourced by Borland). It includes rich support for SQL statements (e.g. INSERT...RETURNING), stored procedures, triggers, etc. You can write compiled UDFs (User-Defined Functions) libraries for the server in FreePascal if you want to extend the already extensive function list of Firebird.

The database requires very little manual DBA work once it is set up, making it ideal for small business use or embedded use. It can grow to terabyte scale given proper tuning, although PostgreSQL may be a better choice for such large environments.

Firebird offers both embedded (file-based) and client-server database - usable without having to change a single line of code in FPC/Lazarus. If used as an embedded database, it offers a richer SQL support than SQLite as well as seamless migration to a client-server database, although SQLite is a quite capable embedded database itself.

The latest stable version, Firebird 2.5, runs on Windows (32- and 64-bit), various Linux versions (32- and 64-bit), Solaris (Sparc and Intel), HP-UX (PA-Risc) and OSX.

It is being ported to Android at the moment; it is not available on Windows CE/Windows Mobile.

Support for Firebird in FPC's SQLDB is quite good, comparable to the level of PostgreSQL support.

Documentation

Official documentation is included in FPC 2.6.2+: SQLDB documentation for IBConnection

Client/server and embedded installation

Firebird can run in client/server and embedded mode.

Client/Server means that you have a physical Firebird server somewhere: either on your local machine or another machine reachable over your network. Connections to the server go through TCP/IP; when specifying the connection, the hostname contains a name or IP address. The Firebird DLL you need for this is fbclient.dll (along with its support files).

Embedded Firebird means that your application loads the Firebird DLLs to access a Firebird database on the local machine. When specifying the connection, the hostname is always empty. The Firebird DLL you need for this is fbembed.dll (along with its support files). See the wiki page on Firebird embedded for more details.

Note that fbembed.dll can be used both for client/server and embedded use, so installing only this dll may be a smart thing to do.

Windows

Win64: please see warning here on not using certain FPC/Lazarus Win64 versions.

On Windows: (this applies to all SQLDB database drivers) you must have fbclient.dll (or fbembed.dll) and its support dlls installed in:

As with all (database) DLLs, the bitness of the DLL must match your application: use a 32 bit library for a 32 bit compiled program and a 64 bit library for a 64 bit program.

Unix/Linux/macOS

On FreeBSD/Linux/macOS, the Firebird client library should be installed (e.g. by your package manager; install the regular package and the -dev package), or they should be placed in the library search path.

FPC searches for the most common library names (e.g. libfbclient.so.2.5, libgds.so, and libfbembed.so.2.5; please check ibase60.inc if your version is different). If you want to, you can explicitly specify the library name. There are 2 ways for this:

Connection examples

Example for client/server:

Hostname: 192.168.1.1
* The database is on the server with IP address 192.168.1.1. 
DatabaseName: /interdata/example.fdb  
* The name of the database file is "example.fdb" in the /interdata directory of the server (the machine with IP address 192.168.1.1).
Username: SYSDBA
Password: masterkey

Another example for client/server:

Hostname: dbhost
* The database is on the server with the host name dbhost
DatabaseName: F:\Program Files\firebird\examples\employee.fdb  
* The name of the database file is "employee.fdb" in the Program Files\firebird\examples directory on the F: drive of dbhost.
Username: SYSDBA
Password: masterkey

An embedded example:

Hostname: <empty string>
* Leaving the hostname empty selects embedded use.
DatabaseName: test.fdb
* The database file is "test.fdb" in the directory where the application runs (make sure fbembed.dll is in the application executable directory)
Username: SYSDBA
* On embedded, you do have to specify a username...
Password: <empty string>
* ... but it doesn't matter what password you give.

Troubleshooting client/server access issues

Make sure you started the Interbase/Firebird server on the server IP/hostname you specified. You can test connectivity by telnetting to the machine. Firebird usually listens on port 3050:

bash
telnet 192.168.1.1 3050

You should see something, maybe just a blank screen, but you can type something. This means you can send data to the Firebird database.

For further information, please see the Firebird documentation.

Monitoring Events

FPC/Lazarus comes with a component to monitor events coming from Firebird databases; see TFBEventMonitor.

Creating objects programmatically

While you can use tools such as Flamerobin to create tables etc, you can also create these programmatically/dynamically, which could be handy when you want your programs to update existing database schemas to a new schema.

You can use e.g. TSQLQuery.ExecSQL to perform this task:

pascal
Query.ExecSQL('CREATE TABLE TEST(ID INTEGER NOT NULL, TESTNAME VARCHAR(800))');
// You need to commit the transaction after DDL before any DML - SELECT, INSERT etc statements.
// Otherwise the SQL won't see the created objects

To do this, use the TSQLScript object - see TSQLScript.

Database Administration

FPC/Lazarus has a component for database adminstration; see TFBAdmin

Common problems and solutions

Sometimes using Firebird in Lazarus seems to be tricky. Please find solutions below.

Attempted update of read-only column / COMPUTED BY fields

If you have COMPUTED BY fields (server-side calculated fields) in your Firebird table, SQLDB will not pick up that these are read only fields (for performance reasons).

In this case, auto-generated INSERTSQL,UPDATESQL statements can lead to error messages like "attempted update of read-only column". The solution is to manually specify that the field in question may not be updated after setting the TSQLQuery's SQL property, something like:

pascal
// Disable updating this field or searching for changed values as user cannot change it
sqlquery1.fieldbyname('full_name').ProviderFlags:=[];

Bigint: lost precision

If you use the bigint datatype (64 bit signed integer) in Firebird, please use .AsLargeInt instead of .AsInteger for parameters:

pascal
// Assuming ID is bigint here
sqlquery1.sql.text := 'insert into ADDRESS (ID) values (:ID)';
// Use this:
sqlquery1.params.parambyname('ID').aslargeint := <some qword or 64 bit integer variable>;
// Do not use this:
//sqlquery1.params.parambyname('ID').asinteger := <some qword or 64 bit integer variable>;
...

... otherwise you might get errors like duplicate PK (primary key) - if using the bigint as a primary key.

Boolean data types

Firebird versions below 3.0 do not support boolean data types.

At least on FPC trunk (2.7.1) this datatype can be emulated:

Use a DOMAIN that uses a SMALLINT type (other integer types may work as well - please test and adjust text):

sql
CREATE DOMAIN "BOOLEAN"
 AS SMALLINT
 CHECK (VALUE IS NULL OR VALUE IN (-1,0,1))
 /* -1 used for compatibility with FPC SQLDB; 1 is used by many other data access layers */
;

Let your field/column use this domain type e.g.

sql
CREATE TABLE MYTABLE
(
...
  MYBOOLEANCOLUMN "BOOLEAN",
);

To do: verify this works with Lazarus grids etc as well.

INSERT INTO...RETURNING problems/Cursor is not open

= If you try to select SQL (e.g. Query.Open) with SQL like this:

sql
INSERT INTO PEOPLE (NICKNAME) VALUES ('Superman') RETURNING ID

and get something like this error:

dos
Database error:  : Fetch :
 -Dynamic SQL Error
 -SQL error code = -504
 -Invalid cursor reference
 -Cursor is not open(error code: 335544569)

while running FPC 2.6.0 (which is supplied with Lazarus 1.0) or lower, then you probably ran into an FPC SQLDB parser bug.

SQLDB thinks the statement you're running is a normal INSERT statement, which doesn't return data. Obviously, it should return data. Newer FPC code has fixes for this.

If you're using generators/sequences for your primary keys (like many do), a workaround is to first get the next sequence number:

sql
SELECT NEXT VALUE FOR GEN_PEOPLEID FROM RDB$DATABASE /* If your generator name is GEN_PEOPLEID */

then use that to do a regular INSERT. see FAQ entry

Locate does not seem to work

Source: Issue ##21988

When running locate on UTF8 (or presumably other multibyte character sets) CHAR fields, locate may not find your record.

The problem is related mostly to UTF8 charset used and how Firebird reports column length. In case of UTF8 Firebird reports the maximum column length (in bytes) as 4*"character length". So if you have a column defined as char(8), Firebird reports 4*8=32.

Values are right-padded to this length 32. When locating say '57200001' there is no match because the field actually stores '57200001 ........................' (with trailing spaces represented by dots here).

Workaround: rewrite your select query:

sql
SELECT substring(THEFIELD from 1 for 8) AS THEFIELD ...

or

sql
SELECT cast(THEFIELD as varchar(8)) as THEFIELD ...

or use VARCHAR fields.

Note: this problem may occur for other databases as well depending on their reporting of field length.

Advanced transactions

Sources for this information/further reading:

Transaction isolation levels

If you want to, you can change the transaction isolation levels by adding a line in the transaction's Parameters property:

Example:

pascal
SQLTransaction1.Params.text:='isc_tpb_read_committed';

You can also add additional parameters that have an effect on the transaction (taken from the ibconnection.pp source file and 1):

Access mode

This allow reads only or read/write

Lock resolution

Table reservation

Deals with locking entire tables.

Combinations:

can update the table. All transactions can read the table

read committed transactions can read the table

read the table

Record versions

This setting is apparently only relevant for isc_tpb_read_committed isolation mode for records being modified by other transactions:

Various options

For completeness, some more options appearing in the Firebird/Interbase FPC code. You will likely only ever use isc_tpb_no_auto_undo to speed up batch inserts/edits.

Firebird and ISO transactions

Firebird transaction do not map 1 to 1 to ISO/ANSI transaction levels. An approximation is:

Common combinations

Default is (probably, will have to check) read committed.

Batch/bulk insert

isc_tpb_read_committed and isc_tpb_no_rec_version could be a good combination: it allows other transactions to function while the batch is going on.

Read only transaction

If you want to only have read access to the database, you can do so by setting these transaction parameters:

This combination will not block garbage collection, which is a good thing. Source: 4

Note: the Firebird FAQ indicates you will need write access to the database file even if you only read from it, unless you set the database read-only flag (e.g. using gfix).

Links and more information

The list below shows links to more information on Firebird and related tools.

Lazarus Firebird samples

Tools

Firebird


From the Free Pascal wiki, page "Firebird", as it stood on 2020-02-16 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.

Revision 2, last changed by WikiArchive .

Talk about this page

Nobody has opened a bench for this page yet. Sign in to open one.