class ActiveRecord::ConnectionAdapters::FbAdapter

The Fb adapter relies on the Fb extension.

Usage Notes

Sequence (Generator) Names

The Fb adapter supports the same approach adopted for the Oracle adapter. See ActiveRecord::ModelSchema::ClassMethods#sequence_name= for more details.

Note that in general there is no need to create a BEFORE INSERT trigger corresponding to a Firebird sequence generator when using ActiveRecord. In other words, you don’t have to try to make Firebird simulate an AUTO_INCREMENT or IDENTITY column. When saving a new record, ActiveRecord pre-fetches the next sequence value for the table and explicitly includes it in the INSERT statement. (Pre-fetching the next primary key value is the only reliable method for the Fb adapter to report back the id after a successful insert.)

BOOLEAN Domain

Firebird 2.5 does not provide a native BOOLEAN type (Only in Firebird 3.x). But you can easily define a BOOLEAN domain for this purpose, e.g.:

CREATE DOMAIN D_BOOLEAN AS SMALLINT CHECK (VALUE IN (0, 1));

When the Fb adapter encounters a column that is based on a domain that includes “BOOLEAN” in the domain name, it will attempt to treat the column as a BOOLEAN.

By default, the Fb adapter will assume that the BOOLEAN domain is defined as above. This can be modified if needed. For example, if you have a legacy schema with the following BOOLEAN domain defined:

CREATE DOMAIN BOOLEAN AS CHAR(1) CHECK (VALUE IN ('T', 'F'));

…you can add the following line to your environment.rb file:

ActiveRecord::ConnectionAdapters::FbAdapter.boolean_domain = { :true => 'T', :false => 'F', :name => 'BOOLEAN', :type => 'char' }

Column Name Case Semantics

Firebird and ActiveRecord have somewhat conflicting case semantics for column names.

Firebird

The standard practice is to use unquoted column names, which can be thought of as case-insensitive. (In fact, Firebird converts them to uppercase.) Quoted column names (not typically used) are case-sensitive.

ActiveRecord

Attribute accessors corresponding to column names are case-sensitive. The defaults for primary key and inheritance columns are lowercase, and in general, people use lowercase attribute names.

In order to map between the differing semantics in a way that conforms to common usage for both Firebird and ActiveRecord, uppercase column names in Firebird are converted to lowercase attribute names in ActiveRecord, and vice-versa. Mixed-case column names retain their case in both directions. Lowercase (quoted) Firebird column names are not supported. This is similar to the solutions adopted by other adapters.

In general, the best approach is to use unquoted (case-insensitive) column names in your Firebird DDL (or if you must quote, use uppercase column names). These will correspond to lowercase attributes in ActiveRecord.

For example, a Firebird table based on the following DDL:

CREATE TABLE products (
  id BIGINT NOT NULL PRIMARY KEY,
  "TYPE" VARCHAR(50),
  name VARCHAR(255) );

…will correspond to an ActiveRecord model class called Product with the following attributes: id, type, name.

Quoting "TYPE" and other Firebird reserved words:

In ActiveRecord, the default inheritance column name is type. The word type is a Firebird reserved word, so it must be quoted in any Firebird SQL statements. Because of the case mapping described above, you should always reference this column using quoted-uppercase syntax ("TYPE") within Firebird DDL or other SQL statements (as in the example above). This holds true for any other Firebird reserved words used as column names as well.

Migrations

The Fb adapter currently support Migrations.

Connection Options

The following options are supported by the Fb adapter.

:database

Required option. Specifies one of: (i) a Firebird database alias; (ii) the full path of a database file; or (iii) a full Firebird connection string. Do not specify :host, :service or :port as separate options when using a full connection string.

:username

Specifies the database user. Defaults to ‘sysdba’.

:password

Specifies the database password. Defaults to ‘masterkey’.

:charset

Specifies the character set to be used by the connection. Refer to the Firebird documentation for valid options.

Public Class Methods

boolean_domain=(domain) click to toggle source
# File lib/active_record/connection_adapters/fb_adapter.rb, line 138
def self.boolean_domain=(domain)
  FbColumn::TRUE_VALUES << domain[:true]
  @@boolean_domain = domain
end
new(connection, logger, config=nil) click to toggle source
Calls superclass method
# File lib/active_record/connection_adapters/fb_adapter.rb, line 150
def initialize(connection, logger, config=nil)
  super(connection, logger)
  @config = config
  @visitor = Arel::Visitors::Fb.new(self)
end

Public Instance Methods

active?() click to toggle source

Checks whether the connection to the database is still active. This includes checking whether the database is actually capable of responding, i.e. whether the connection isn’t stale.

# File lib/active_record/connection_adapters/fb_adapter.rb, line 215
def active?
  return false unless @connection.open?
  # return true if @connection.transaction_started
  @connection.query("SELECT 1 FROM RDB$DATABASE")
  true
rescue
  false
end
adapter_name() click to toggle source

Returns the human-readable name of the adapter. Use mixed case - one can always use downcase if needed.

# File lib/active_record/connection_adapters/fb_adapter.rb, line 158
def adapter_name
  'Fb'
end
create_savepoint(name = current_savepoint_name) click to toggle source
# File lib/active_record/connection_adapters/fb_adapter.rb, line 254
def create_savepoint(name = current_savepoint_name)
  execute("SAVEPOINT #{name}")
end
disconnect!() click to toggle source

Disconnects from the database if already connected. Otherwise, this method does nothing.

Calls superclass method
# File lib/active_record/connection_adapters/fb_adapter.rb, line 233
def disconnect!
  super
  @connection.close rescue nil
end
ids_in_list_limit() click to toggle source

Does this adapter restrict the number of ids you can use in a list. Oracle has a limit of 1000.

# File lib/active_record/connection_adapters/fb_adapter.rb, line 206
def ids_in_list_limit
  1499
end
prefetch_primary_key?(table_name = nil) click to toggle source

Should primary key values be selected from their corresponding sequence before the insert statement? If true, next_sequence_value is called before each insert to set the record’s primary key. This is false for all adapters but Firebird.

# File lib/active_record/connection_adapters/fb_adapter.rb, line 201
def prefetch_primary_key?(table_name = nil)
  true
end
reconnect!() click to toggle source

Disconnects from the database if already connected, and establishes a new connection with the database.

# File lib/active_record/connection_adapters/fb_adapter.rb, line 226
def reconnect!
  disconnect!
  @connection = ::Fb::Database.connect(@config)
end
release_savepoint(name = current_savepoint_name) click to toggle source
# File lib/active_record/connection_adapters/fb_adapter.rb, line 262
def release_savepoint(name = current_savepoint_name)
  execute("RELEASE SAVEPOINT #{name}")
end
requires_reloading?() click to toggle source

Returns true if its required to reload the connection between requests for development mode. This is not the case for FirebirdSQL and it’s not necessary for any adapters except SQLite.

# File lib/active_record/connection_adapters/fb_adapter.rb, line 250
def requires_reloading?
  false
end
reset!() click to toggle source

Reset the state of this connection, directing the DBMS to clear transactions and other connection-related server-side state. Usually a database-dependent operation.

The default implementation does nothing; the implementation should be overridden by concrete adapters.

# File lib/active_record/connection_adapters/fb_adapter.rb, line 244
def reset!
  reconnect!
end
rollback_to_savepoint(name = current_savepoint_name) click to toggle source
# File lib/active_record/connection_adapters/fb_adapter.rb, line 258
def rollback_to_savepoint(name = current_savepoint_name)
  execute("ROLLBACK TO SAVEPOINT #{name}")
end
supports_count_distinct?() click to toggle source

Does this adapter support using DISTINCT within COUNT? This is true for all adapters except sqlite.

# File lib/active_record/connection_adapters/fb_adapter.rb, line 177
def supports_count_distinct?
  true
end
supports_ddl_transactions?() click to toggle source

Does this adapter support DDL rollbacks in transactions? That is, would CREATE TABLE or ALTER TABLE get rolled back by a transaction? PostgreSQL, SQL Server, and others support this. MySQL and others do not.

# File lib/active_record/connection_adapters/fb_adapter.rb, line 184
def supports_ddl_transactions?
  true
end
supports_migrations?() click to toggle source

Does this adapter support migrations? Backend specific, as the abstract adapter always returns false.

# File lib/active_record/connection_adapters/fb_adapter.rb, line 164
def supports_migrations?
  true
end
supports_primary_key?() click to toggle source

Can this adapter determine the primary key for tables not attached to an Active Record class, such as join tables? Backend specific, as the abstract adapter always returns false.

# File lib/active_record/connection_adapters/fb_adapter.rb, line 171
def supports_primary_key?
  true
end
supports_savepoints?() click to toggle source

Does this adapter support savepoints? FirebirdSQL does

# File lib/active_record/connection_adapters/fb_adapter.rb, line 193
def supports_savepoints?
  true
end
supports_transaction_isolation?() click to toggle source
# File lib/active_record/connection_adapters/fb_adapter.rb, line 188
def supports_transaction_isolation?
  true
end

Protected Instance Methods

initialize_type_map(m) click to toggle source

Maps SQL types to ActiveRecord 4.2+ type objects

Calls superclass method
# File lib/active_record/connection_adapters/fb_adapter.rb, line 269
def initialize_type_map(m)
  super
  m.register_type %r(timestamp)i, Type::DateTime.new
  m.alias_type    %r(blob sub_type text)i, 'text'
end
translate_exception(e, message) click to toggle source
Calls superclass method
# File lib/active_record/connection_adapters/fb_adapter.rb, line 275
def translate_exception(e, message)
  case e.message
  when /violation of FOREIGN KEY constraint/
    InvalidForeignKey.new(message, e)
  when /violation of PRIMARY or UNIQUE KEY constraint/, /attempt to store duplicate value/
    RecordNotUnique.new(message, e)
  when /This operation is not defined for system tables/
    ActiveRecordError.new(message)
  else
    super
  end
end