The Firebird Backend — Peculiarities¶
Firebird supports Firebird 4.0 and newer. It is built on
AbstractSql2008Backend, i.e. it pages with the
standard OFFSET ? ROWS FETCH FIRST ? ROWS ONLY. This document collects what deviates from the other backends and
what the model must take into account.
The backend is selected by the JDBC URL of the Jaybird driver,
jdbc:firebirdsql://host/databaseorjdbc:firebird://host/database(org.firebirdsql.jdbc.FBDriver, which the application has to provide).
Minimum version. Firebird.validateVersion() requires Firebird 4.0, the first version with identifiers of
up to 63 characters and decimals with a precision of up to 38 digits.
Type Mapping¶
SqlType |
Firebird type | Note |
|---|---|---|
VARCHAR(n) |
VARCHAR(n) |
n is capped at 8191: 32 765 bytes with up to 4 bytes per UTF-8 character |
VARCHAR |
VARCHAR(8191) |
an attribute without a size |
CLOB |
BLOB SUB_TYPE TEXT |
|
XML |
BLOB SUB_TYPE TEXT |
no native XML type; isSqlxmlSupported() is false |
JSON |
BLOB SUB_TYPE TEXT |
no native JSON type; isJsonSupported() is false |
BLOB |
BLOB SUB_TYPE BINARY |
|
BIT |
BOOLEAN |
defaults are written as TRUE/FALSE, not as strings |
TINYINT |
SMALLINT |
there is no TINYINT |
FLOAT / DOUBLE |
FLOAT / DOUBLE PRECISION |
|
DECIMAL |
DECIMAL(19) |
if the model gives no size — see below |
UUID |
— | isUUIDSupported() is false, so a UUID is stored as a string |
Firebird reads a bare DECIMAL as DECIMAL(9,0) and would silently round away every fraction digit, so an
attribute without an explicit size becomes DECIMAL(19,<scale>) (getDefaultSize) — the same remedy as on
MySQL.
Locking¶
Firebird's FOR UPDATE only declares an updatable cursor — it does not lock anything. A write-locking select
therefore ends with FOR UPDATE WITH LOCK, after the paging clauses:
WITH LOCK is only allowed for a select from a single table; the database rejects a write-locking select that
joins other tables.
Indexes¶
- The sort order belongs to the index, not to a column. An index whose columns are all descending is
generated as
CREATE DESCENDING INDEX foo_idx ON foo (a, b). An index mixing ascending and descending columns cannot be created at all:sqlCreateIndex()throws aBackendExceptionwhile the DDL is generated. - No filtered and no function-based indexes in the model's syntax (
isFilteredIndexSupported(),isFunctionBasedIndexSupported()). A model index using either is commented out if it is optional, and rejected otherwise. - Indexes cannot be renamed (
sqlRenameIndex()returnsnull), so the migration drops and re-creates them.
Migration¶
- Tables cannot be renamed.
sqlRenameTable()throws aBackendException, so a migration renaming a table fails when it is generated rather than when it is applied. Create the new table, copy the data and drop the old one by hand. - Columns change one property at a time:
ALTER TABLE foo ALTER COLUMN name TO labelrenames,ALTER COLUMN name TYPE VARCHAR(64)retypes, and the null constraint and the default change separately (SET/DROP NOT NULL,SET/DROP DEFAULT). Firebird rejects type changes that could lose data, such as shrinking a column. ADDandDROPtake noCOLUMNkeyword:ALTER TABLE foo ADD extra INTEGER,ALTER TABLE foo DROP extra.- Defaults are read back as source text. Depending on the driver version, the default of a column is reported
including the
DEFAULTkeyword.FirebirdColumnMetaDatastrips it, so the migration compares the value only.
Other Peculiarities¶
- No schemas.
isSchemaSupported()returnsfalse— schemas arrive with Firebird 6. A model using schemas must map them, see Table Names. - 63-character identifiers, starting with a letter. As on Oracle, the migrator's temporary names
start with
tmp_instead of an underscore, and names starting with an underscore are rejected at build time. - Reserved names. The system tables
RDB$...,MON$...andSEC$...are reserved table names. Firebird's reserved words beyond SQL:2003, such asINDEX,PLAN,OFFSET,ROW_COUNTandVARIABLE, are rejected at build time (RESERVED_WORDS_FIREBIRD). - The default comes before the null constraint in a column declaration:
DEFAULT 0 NOT NULL. - Sequences are created with
START WITHbeforeINCREMENT BYand read withSELECT NEXT VALUE FOR seq FROM RDB$DATABASE. The keep-alive select isSELECT 1 FROM RDB$DATABASE. - Comments on tables, columns, indexes and sequences via
COMMENT ON. - Vendor error codes. Besides SQLState
40001, the ISC error codes 335544336 (deadlock), 335544345 (lock conflict), 335544451 (update conflict) and 335544510 (lock timeout) are transient. - No deferrable constraints, no
IF EXISTSon generated drops, and every derived table gets an alias.
Related Documentation¶
- Tentackle SQL — the backend abstraction this backend implements.
- Table Names — schema mapping, required on Firebird because it has no schemas.
- Model Definition — where sizes, scales and indexes are declared.
- Tentackle SQL Maven Plugin — generates the DDL and the migration scripts discussed above.