This Firebird adapter represents an original effort and differs significantly from the adapter submitted under ticket #1418, so I am posting it under a separate ticket.
This adapter is based on the FireRuby Ruby extension for connecting to a Firebird database, which (imho) provides several improvements over the older Interbase extension. FireRuby is published as a gem, provides a richer API, is actively supported and well documented.
Implementing the Firebird adapter required several small changes to ActiveRecord. All of these changes are fully backward compatible and have been tested against Firebird (of course) as well as SQLite, MySQL and PostgreSQL.
Summary of ActiveRecord changes:
- Modified validates_uniqueness_of method in validations.rb to address "= NULL" comparison issue (see #1391 for background). To generate the correct NULL comparison syntax, I call the existing attribute_condition method (in base.rb). I also refactored validates_uniqueness_of to eliminate some duplication and make it more readable.
- Modified several methods in base.rb and associations.rb to ensure that column names are properly quoted. This was a problem because "type" (the default inheritance column name) is a reserved word for Firebird. The problem is addressed by calling quote_column_name, which is implemented by each of the adapters.
- This fix caused some unit tests to fail in SQLite3. I was able to address the problem by changing the quote_column_name method in the sqlite adapter to use double-quotes instead of single-quotes.
- Several test fixtures and unit tests reference "type" in find conditions, so I had to ensure that "type" is quoted in tests as well. I added a QUOTED_TYPE constant to abstract_unit.rb, and replaced all explicit references to "type".
- Firebird uses sequence generators as opposed to AUTO INCREMENT or IDENTITY columns to handle auto-generated primary key values. The only reliable way to know what pk value was used in an insert it to pre-fetch it and explicitly include the column/value pair in the insert. This is concurrency-safe because sequence generators are not subject to transactional context (so they aren't rolled-back). To implement this, I modified Base#create (in base.rb) to pre-fetch the next pk value from the correct sequence if the adapter requires it.
If this patch is accepted, tickets #1391 and #1418 may be closed.