Migrating from InterBase 6.01 to Firebird 1.5 and 2.0
1 Introduction
We recently converted our InterBase 6.01 application to Firebird 2.0 Beta and kept a record of differences and their effect on our conversion process. Before we started this, we searched for any conversion guidance document on the web and did not find any one summarizing document, so we decided to keep a record and make it available to others who might want to tread the same path.
Our application (http://www.topicscape.com) in its personal edition, used InterBase to store user data. We selected the database engine before Firebird was well established. Being a personal edition, our product was not designed for network or multi-user access, but InterBase, in its open source version, does not provide for direct connection, only access through the network drivers. Now we have converted to a direct connection using Firebird.
Our application is mainly written in Java, and being a 3D application, uses OpenGL through the GL4Java binding. The Windows version (the first deployed) makes some native calls through JNI.
2 Errors here?
If you have a more intimate knowledge of the inner workings of Firebird and InterBase than us, and find any errors below, we would be happy to make corrections or additions.
We have already had valuable contributions from the leader of the Jaybird sub-project, Roman Rokytskyy. As a result, we have been able to remove some items, provide solutions to some and add appropriate commentary to others. Information below from Roman is introduced as [RR]:" ".
3 Differences that affected us
3.1 Embedded server
InterBase is said to allow a local connection using LIBS, but after a search, we concluded that this is not available for the open source version of InterBase – 6.01.
The embedded Firebird database server allows a direct connection between server and application. This is useful for single-user, single-PC applications as it bypasses network drivers, with a consequent gain in application performance.
Locations of versions that we used:
Live Firebird 1.5 http://prdownloads.sourceforge.net/firebird/Firebird-1.5.2.4731_embed_win32.zip
or
Beta 1 Firebird 2 http://www.firebirdsql.org/download/prerelease/win32/Firebird-2.0.0.11675-0_embed_win32.zip
We believe that later version have been released and should certainly be used in preference to the above, as they had issues that we worked around.
The application with embedded server required three files (around 2MB in total): fbembed.dll; jaybird.dll; and firebirdsql-full.jar.
Using the Firebird embedded server also overcomes problems caused by three personal-security software products that block InterBase when the user is running client and server on one computer. This can happen when all necessary permissions are given, or even if the security software is just installed, not running (see http://groups.yahoo.com/group/firebird-support/message/61830).
3.2 Firebird 2 embedded server and Jaybird 2.0 required libraries:
The main dll files required are: fbembed.dll, jaybird2.dll, and jaybird-full -2.0.0.jar, icudt30.dll, icuin30.dll, icuuc30.dll Libraries required if you perform GFIX and GBAK are: fbclient.dll, gds32.dll, And if you use user-defined functions: ib_udf.dll
3.3 SQL differences
3.3.1 Syntax:
If you are using SQL Dialect 1 syntax and double-quotes (") for literals instead of single-quote ('), you will need either a) to convert any queries using " to ' or b) include a statement to switch Firebird to Dialect 1 (see below). InterBase accepts both dialects; Firebird, in its default Dialect 3, accepts only single quote (standard SQL).
A suitable statement might be something like:
Connection conn = DriverManager.getConnection("jdbc:firebirdsql:embedded:" + fileName + "?isc_dpb_sql_dialect=1", "SYSDBA", "masterkey");
The TO_DATE function should be replaced by CAST(‘09-30-2005 00:00.00’, TIMESTAMP) to support casting a string to a date format attribute in a database.
Firebird 2.0: We believe that the following SQL is valid (it was extracted from Firebird documentation Firebird-2.0.0.11675-0_win32docambiguity.txt), but it will return an error message:
UPDATE TableA SET FieldA = ( SELECT SUM(A.FieldB) FROM TableA A WHERE A.FieldID = TableA.FieldID )
Cannot use “IN” keyword within nested query (permitted in InterBase); use “EXISTS” to replace any such uses of the “IN” keyword.
[RR]: "There are some differences in the "NOW" function behavior".
3.3.2 With Java:
- Our testing in Java seemed to indicate CallableStatement can accept only one argument in Firebird / Jaybird 1.5. [RR]: "Firebird 1.5 with Jaybird 2.0.2 should also be OK (Jaybird 2.0.2 is due to be released in 2nd half December 2005).Jaybird 1.5.x has bug in parsing the SQL statement in a form EXECUTE PROCEDURE <name> (….) (note the space after the name and before the opening “(“). There is no limit on the number of parameters in either Firebird, or in Jaybird. Jaybird 2.0 can be safely used with Firebird 1.5.x."
After creating a VIEW in Java, you should perform COMMIT before performing a query on the VIEW. [RR]: "This is normal behavior in Firebird but is an anomoly. This works in InterBase. Before the Firebird issue is resolved, it is highly recommended not to mix DDL and DML statements in one transaction"
In Java, a SQL string cannot contain " or ', so you can only specify the quote using a single quote. Use of r n, etc. still works, however.
In Java using Firebird you cannot perform a COMMIT after a SELECT statement. This happens to work with Java in InterBase. [RR]: "The JDBC specification defines such a result set as closed and Jaybird handles it correctly according to the specification. Jaybird 2.0 supports holdable result sets (according to the JDBC specification they "survive" commit), but the drawback is that the complete result set is cached in memory."
3.3.3 Restrictions on using Jaybird: Some useful references
updatable result set: http://jaybirdwiki.firebirdsql.org/jaybird/doku.php?id=tip:result_sets#scrollable_result_sets
limit of connections:
“As a practical guideline, work on a base maximum of about 150 concurrent Superserver clients for a normal interactive application on a server of low-to-medium specification, with low-to-moderate contention, before performance might make you consider upgrading (and this is without taking the needs of the JVM into account). For Classic, the numbers may be lower because each client consumes more resources.”
http://jaybirdwiki.firebirdsql.org/jaybird/doku.php?id=tip:other#limit_of_connections
Jaybird does not provide own row set implementation. http://jaybirdwiki.firebirdsql.org/jaybird/doku.php?id=tip:result_sets#rowset_support
3.3.4 other SQL differences:
- Connection parameter “charSet” with a value of “UTF8” in InterBase, will have to be changed to “UTF-8” in Firebird.
- when Firebird cannot handle an exception, it will usually throw a Dynamic SQL Error.
3.4 Existing databases of InterBase origin
InterBase databases should be backed up and restored with Firebird GBAK before accessing them with Firebird.
InterBase has a lower version ODS than Firebird, so Firebird can read InterBase files but not vice versa.
3.5 GBAK and GFIX
GBAK performs backup and restore of a database file, which is used for database recovery.
GFIX performs validation of a database file, which is used to validate if a database is corrupt.
Firebird’s GBAK and GFIX utilities appear to do the same as those of InterBase.
3.6 Using Firebird with Excelsior JET
We compile the Windows version of our application with Jet. While still using Firebird 1.5, Jaybird 1.5 and Jet v.3.6, we found that we could not retrieve data if a database table contained NULL values. See next section under Firebird /Jaybird 1.5 vs. Firebird 2.0. A SELECT query cannot be performed using Connection.createStatement() if we put a transaction commit before iterating through the result set.
4 Firebird /Jaybird 1.5 vs. Firebird 2.0
We had to switch to Firebird 2.0 Beta and Jaybird 2.0 because:
- Firebird 1.5 with Jaybird 1.5 does not fully support Callable Statements, and we required these to execute stored procedures. [RR]: "In fact, you do not need CallableStatement if you use EXECUTE PROCEDURE syntax. The main goal of CallableStatement is to support vendor-neutral escape JDBC syntax . For stored procedures that is {call <name> [<arg1>,….]} or {? = call <name> [<arg1>,…]} which should hide from the application developer specifics of the procedure call. Jaybird converts such syntax into EXECUTE PROCEDURE <name> …. call (that is why we needed a parser, otherwise we would rely on Firebird). Note, that in order to use selectable procedures (SELECT * FROM <name>[?, …] call) you have to use FirebirdCallableStatement.setSelectable(boolean) method."
- We experienced some problems with question marks inside a string. Jaybird 1.5 interprets any question marks in Callable Statements as an argument. [RR]: "This is a Jaybird bug."
- JET 3.6 cannot retrieve data with Firebird 1.5 / Jaybird 1.5 if a NULL value is found within a database table. We moved on to Jet 4.0 and the problem disappeared, so there is no evidence that this is a Firebird/Jaybird problem.
4.1 Differences between Firebird 1.5 and Firebird 2.0:
(The following comparison is based on Firebird 1.5 and Firebird 2.0 alpha 3)
Firebird 2.0 changes the ODS (on-disk structure) to version 11. Therefore, after a backup and restore (GBAK) using Firebird 2, the data file can no longer be opened by either InterBase version or Firebird 1.5.
Firebird 2.0 supports Callable Statements with multiple arguments.
Firebird 2.0 required some more external libraries: icudt30.dll, icuin30.dll, icuuc30.dll
Useful new SQL keywords are introduced.
Several bugs in Firebird 1.5 are fixed in Firebird 2.0 (since Firebird 2.0 Alpha 3):
When an alias is present it must be used or no alias at all must be used in Firebird 2.0. This query was allowed in FB1.5 and earlier versions:
SELECT RDB$RELATIONS.RDB$RELATION_NAME FROM RDB$RELATIONS R
but will now correctly report an error that the field "RDB$RELATIONS.RDB$RELATION_NAME" couldn't be found.
Solution:
SELECT R.RDB$RELATION_NAME FROM RDB$RELATIONS R
or:
SELECT RDB$RELATION_NAME FROM RDB$RELATIONS R
This example didn't run correctly in FB1.5 and earlier:
SELECT RDB$RELATIONS.RDB$RELATION_NAME, R2.RDB$RELATION_NAME FROM RDB$RELATIONS JOIN RDB$RELATIONS R2 ON ( R2.RDB$RELATION_NAME = RDB$RELATIONS.RDB$RELATION_NAME )
If RDB$RELATIONS contains 90 records, it would return 90 * 90 = 8100 records, but in FB2.0 it will correctly return 90 records.
5 From the Firebird_v1.5.ReleaseNotes.pdf
Obviously the release notes need to be studied in full, but we found it handy to have this extract to hand.
5.1 New Reserved Words
The following new Firebird keywords should be added to the list of reserved words published for InterBase 6.0.1.:
BIGINT (1.5) CASE (1.5) CURRENT_CONNECTION (1.5) CURRENT_ROLE CURRENT_TRANSACTION (1.5) CURRENT_USER RECREATE ROW_COUNT (1.5) RELEASE SAVEPOINT
The following keywords are reserved for future planned use:
ABS BOOLEAN BOTH CHAR_LENGTH CHARACTER_LENGTH FALSE LEADING OCTET_LENGTH TRIM TRAILING TRUE UNKNOWN
The following non-reserved words are recognized in 1.5 as keywords when used in their respective structural contexts:
COALESCE DELETING INSERTING LAST LEAVE LOCK NULLIF NULLS STATEMENT UPDATING USING
There is other information about keywords in the release notes but they are not relevant to migration from InterBase 6.01 to FB 1.5
6 From the Firebird_v2.0.0.ReleaseNotes.pdf
Obviously the release notes need to be studied in full, but we found it handy to have this extract to hand.
6.1 New Reserved Words & Changes
The following keywords have been added, or have changed status, since Firebird 1.5. Those marked with an asterisk (*) are not present in the SQL standard.
6.2 Added as reserved words
BIT_LENGTH BOTH CHAR_LENGTH CHARACTER_LENGTH CLOSE CROSS FETCH LEADING LOWER OCTET_LENGTH OPEN ROWS TRAILING TRIM CLOSE OPEN
6.4 Added as non-reserved words
BACKUP * BLOCK * COLLATION COMMENT * DIFFERENCE * IIF * NEXT SCALAR_ARRAY * SEQUENCE RESTART RETURNING *
6.5 Changed from reserved words to non-reserved
Firebird v.200.30 Reserved Words, Third Alpha http://rusty/fb2/reserved_words.html (1 of 2) [7/07/2005 8:10:38 AM]
ACTION RESTRICT WEEKDAY * CASCADE ROLE YEARDAY * FREE_IT * TYPE
No longer reserved words:
BASENAME * GROUP_COMMIT_WAIT * NUM_LOG_BUFS * CACHE * LOGFILE * RAW_PARTITIONS * CHECK_POINT_LEN * LOG_BUF_SIZE *
7 Extract from forums
7.1 About ODS:
http://www.ibphoenix.com/main.nfs?a=ibphoenix&l=;KNOWLEDGEBASE;ID='20'
- Question:
- When connecting to InterBase V3.3 database from InterBase V4.0 on HP and getting error "Unsupported on-disk structure for file /path/v3.gdb: found 1, support 8".
- Answer:
The first release on HP 10.20 was InterBase 4.0. Therefore, there is no V3 kit that InterBase can build the bridge from.
Here are two workarounds for this problem: * GBAK the database with transportable option on V3.3 and restore it on V4.0 on HP10. * There is a bridge for the V4.0 InterBase kit on HP9.
Firebird/InterBase Version: 4.0 Operating System: HP-UX
7.2 Subject: Re: [IB-Conversions] transferring InterBase gdb to firebird
7.3 Update InterBase data file to Firebird:
8 Differences that we read about but that did not affect us
We did not confirm the stated “Limits of Firebird Database” but this reference may be useful: http://www.ibphoenix.com/main.nfs?a=ibphoenix&l=;FAQS;NAME='System+Limits'