Module: ArJdbc::Firebird

Defined in:
lib/arjdbc/firebird/adapter.rb

Defined Under Namespace

Modules: Column

Constant Summary collapse

ADAPTER_NAME =
'Firebird'.freeze
NATIVE_DATABASE_TYPES =
{
  :primary_key => "integer not null primary key",
  :string => { :name => "varchar", :limit => 255 },
  :text => { :name => "blob sub_type text" },
  :integer => { :name => "integer" },
  :float => { :name => "float" },
  :datetime => { :name => "timestamp" },
  :timestamp => { :name => "timestamp" },
  :time => { :name => "time" },
  :date => { :name => "date" },
  :binary => { :name => "blob" },
  :boolean => { :name => 'char', :limit => 1 },
  :numeric => { :name => "numeric" },
  :decimal => { :name => "decimal" },
  :char => { :name => "char" },
}
IDENTIFIER_LENGTH =

usual DB meta-identifier: 31 chars maximum

31
@@update_lob_values =
true

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.arel2_visitors(config = nil) ⇒ Object

Deprecated.

no longer used



61
62
63
# File 'lib/arjdbc/firebird/adapter.rb', line 61

def self.arel2_visitors(config = nil)
  { 'firebird' => arel_visitor_type, 'firebirdsql' => arel_visitor_type }
end

.arel_visitor_type(config = nil) ⇒ Object

See Also:

  • ArelHelper::ClassMethods#arel_visitor_type


56
57
58
# File 'lib/arjdbc/firebird/adapter.rb', line 56

def self.arel_visitor_type(config = nil)
  require 'arel/visitors/firebird'; ::Arel::Visitors::Firebird
end

.column_selectorObject

See Also:

  • ActiveRecord::ConnectionAdapters::JdbcColumn#column_types


19
20
21
# File 'lib/arjdbc/firebird/adapter.rb', line 19

def self.column_selector
  [ /firebird/i, lambda { |cfg, column| column.extend(Column) } ]
end

.emulate_booleansObject

Deprecated.

Use #emulate_booleans? instead.



74
# File 'lib/arjdbc/firebird/adapter.rb', line 74

def self.emulate_booleans; @@emulate_booleans; end

.emulate_booleans=(emulate) ⇒ Object

See Also:

  • #emulate_booleans?


76
# File 'lib/arjdbc/firebird/adapter.rb', line 76

def self.emulate_booleans=(emulate); @@emulate_booleans = emulate; end

.emulate_booleans?Boolean

Boolean emulation can be disabled using :

ArJdbc::Firebird.emulate_booleans = false

Returns:

  • (Boolean)


72
# File 'lib/arjdbc/firebird/adapter.rb', line 72

def self.emulate_booleans?; @@emulate_booleans; end

.update_lob_values=(update) ⇒ Object



87
# File 'lib/arjdbc/firebird/adapter.rb', line 87

def self.update_lob_values=(update); @@update_lob_values = update; end

.update_lob_values?Boolean

Updating records with LOB values (binary/text columns) in a separate statement can be disabled using :

ArJdbc::Firebird.update_lob_values = false

Returns:

  • (Boolean)


85
# File 'lib/arjdbc/firebird/adapter.rb', line 85

def self.update_lob_values?; @@update_lob_values; end

Instance Method Details

#adapter_nameObject



98
99
100
# File 'lib/arjdbc/firebird/adapter.rb', line 98

def adapter_name
  ADAPTER_NAME
end

#add_limit_offset!(sql, options) ⇒ Object



178
179
180
181
182
183
184
# File 'lib/arjdbc/firebird/adapter.rb', line 178

def add_limit_offset!(sql, options)
  if options[:limit]
    limit_string = "FIRST #{options[:limit]}"
    limit_string << " SKIP #{options[:offset]}" if options[:offset]
    sql.sub!(/\A(\s*SELECT\s)/i, '\&' + limit_string + ' ')
  end
end

#change_column(table_name, column_name, type, options = {}) ⇒ Object



233
234
235
# File 'lib/arjdbc/firebird/adapter.rb', line 233

def change_column(table_name, column_name, type, options = {})
  execute "ALTER TABLE #{table_name} ALTER  #{column_name} TYPE #{type_to_sql(type, options[:limit])}"
end

#column_name_lengthObject



201
# File 'lib/arjdbc/firebird/adapter.rb', line 201

def column_name_length; IDENTIFIER_LENGTH; end

#create_table(name, options = {}) ⇒ Object



218
219
220
221
# File 'lib/arjdbc/firebird/adapter.rb', line 218

def create_table(name, options = {})
  super(name, options)
  execute "CREATE GENERATOR #{name}_seq"
end

#default_sequence_name(table_name, column = nil) ⇒ Object



203
204
205
206
# File 'lib/arjdbc/firebird/adapter.rb', line 203

def default_sequence_name(table_name, column = nil)
  # TODO: remove schema prefix if present (before truncating)
  "#{table_name.to_s[0, IDENTIFIER_LENGTH - 4]}_seq"
end

#drop_table(name, options = {}) ⇒ Object



228
229
230
231
# File 'lib/arjdbc/firebird/adapter.rb', line 228

def drop_table(name, options = {})
  super(name)
  execute "DROP GENERATOR #{name}_seq" rescue nil
end

#ids_in_list_limitObject

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



169
170
171
# File 'lib/arjdbc/firebird/adapter.rb', line 169

def ids_in_list_limit
  1499
end

#index_name_lengthObject



200
# File 'lib/arjdbc/firebird/adapter.rb', line 200

def index_name_length;  IDENTIFIER_LENGTH; end

#insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) ⇒ Object



173
174
175
176
# File 'lib/arjdbc/firebird/adapter.rb', line 173

def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
  execute(sql, name, binds)
  id_value
end

#native_database_typesObject



119
120
121
# File 'lib/arjdbc/firebird/adapter.rb', line 119

def native_database_types
  NATIVE_DATABASE_TYPES
end

#next_sequence_value(sequence_name) ⇒ Object



214
215
216
# File 'lib/arjdbc/firebird/adapter.rb', line 214

def next_sequence_value(sequence_name)
  select_one("SELECT GEN_ID(#{sequence_name}, 1 ) FROM RDB$DATABASE;")["gen_id"]
end

#prefetch_primary_key?(table_name = nil) ⇒ Boolean

Should primary key values be selected from their corresponding sequence before the insert statement?

Returns:

  • (Boolean)

See Also:



190
191
192
193
194
# File 'lib/arjdbc/firebird/adapter.rb', line 190

def prefetch_primary_key?(table_name = nil)
  return true if table_name.nil?
  table_name = table_name.to_s
  columns(table_name).count { |column| column.primary } == 1
end

#quote(value, column = nil) ⇒ Object



246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/arjdbc/firebird/adapter.rb', line 246

def quote(value, column = nil)
  return value.quoted_id if value.respond_to?(:quoted_id)
  return value if sql_literal?(value)

  type = column && column.type

  # BLOBs are updated separately by an after_save trigger.
  if type == :binary || type == :text
    if update_lob_values?
      return value.nil? ? "NULL" : BLOB_VALUE_MARKER
    else
      return "'#{quote_string(value)}'"
    end
  end

  case value
  when String, ActiveSupport::Multibyte::Chars
    value = value.to_s
    if type == :integer
      value.to_i.to_s
    elsif type == :float
      value.to_f.to_s
    else
      "'#{quote_string(value)}'"
    end
  when NilClass then 'NULL'
  when TrueClass then (type == :integer ? '1' : quoted_true)
  when FalseClass then (type == :integer ? '0' : quoted_false)
  when Float, Fixnum, Bignum then value.to_s
  # BigDecimals need to be output in a non-normalized form and quoted.
  when BigDecimal then value.to_s('F')
  when Symbol then "'#{quote_string(value.to_s)}'"
  else
    if type == :time && value.acts_like?(:time)
      return "'#{get_time(value).strftime("%H:%M:%S")}'"
    end
    if type == :date && value.acts_like?(:date)
      return "'#{value.strftime("%Y-%m-%d")}'"
    end
    super
  end
end

#quote_column_name(column_name) ⇒ Object



321
322
323
324
# File 'lib/arjdbc/firebird/adapter.rb', line 321

def quote_column_name(column_name)
  column_name = column_name.to_s
  %Q("#{column_name =~ /[[:upper:]]/ ? column_name : column_name.upcase}")
end

#quote_string(string) ⇒ Object



301
302
303
# File 'lib/arjdbc/firebird/adapter.rb', line 301

def quote_string(string)
  string.gsub(/'/, "''")
end

#quote_table_name_for_assignment(table, attr) ⇒ Object



316
317
318
# File 'lib/arjdbc/firebird/adapter.rb', line 316

def quote_table_name_for_assignment(table, attr)
  quote_column_name(attr)
end

#quoted_date(value) ⇒ Object



290
291
292
293
294
295
296
297
298
# File 'lib/arjdbc/firebird/adapter.rb', line 290

def quoted_date(value)
  if value.acts_like?(:time) && value.respond_to?(:usec)
    usec = sprintf "%04d", (value.usec / 100.0).round
    value = ::ActiveRecord::Base.default_timezone == :utc ? value.getutc : value.getlocal
    "#{value.strftime("%Y-%m-%d %H:%M:%S")}.#{usec}"
  else
    super
  end
end

#quoted_falseObject



311
312
313
# File 'lib/arjdbc/firebird/adapter.rb', line 311

def quoted_false
  quote(0)
end

#quoted_trueObject



306
307
308
# File 'lib/arjdbc/firebird/adapter.rb', line 306

def quoted_true
  quote(1)
end

#remove_index(table_name, options) ⇒ Object



241
242
243
# File 'lib/arjdbc/firebird/adapter.rb', line 241

def remove_index(table_name, options)
  execute "DROP INDEX #{index_name(table_name, options)}"
end

#rename_column(table_name, column_name, new_column_name) ⇒ Object



237
238
239
# File 'lib/arjdbc/firebird/adapter.rb', line 237

def rename_column(table_name, column_name, new_column_name)
  execute "ALTER TABLE #{table_name} ALTER  #{column_name} TO #{new_column_name}"
end

#rename_table(name, new_name) ⇒ Object



223
224
225
226
# File 'lib/arjdbc/firebird/adapter.rb', line 223

def rename_table(name, new_name)
  execute "RENAME #{name} TO #{new_name}"
  execute "UPDATE RDB$GENERATORS SET RDB$GENERATOR_NAME='#{new_name}_seq' WHERE RDB$GENERATOR_NAME='#{name}_seq'" rescue nil
end

#reset_sequence!(table, column, sequence = nil) ⇒ Object

Set the sequence to the max value of the table's column.



209
210
211
212
# File 'lib/arjdbc/firebird/adapter.rb', line 209

def reset_sequence!(table, column, sequence = nil)
  max_id = select_value("SELECT max(#{column}) FROM #{table}")
  execute("ALTER SEQUENCE #{default_sequence_name(table, column)} RESTART WITH #{max_id}")
end

#supports_count_distinct?Boolean

Does this adapter support using DISTINCT within COUNT?

Returns:

  • (Boolean)


156
157
158
# File 'lib/arjdbc/firebird/adapter.rb', line 156

def supports_count_distinct?
  true
end

#supports_ddl_transactions?Boolean

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.

Returns:

  • (Boolean)


163
164
165
# File 'lib/arjdbc/firebird/adapter.rb', line 163

def supports_ddl_transactions?
  false
end

#supports_migrations?Boolean

Does this adapter support migrations?

Returns:

  • (Boolean)


145
146
147
# File 'lib/arjdbc/firebird/adapter.rb', line 145

def supports_migrations?
  true
end

#supports_primary_key?Boolean

Can this adapter determine the primary key for tables not attached to an Active Record class, such as join tables?

Returns:

  • (Boolean)


151
152
153
# File 'lib/arjdbc/firebird/adapter.rb', line 151

def supports_primary_key?
  true
end

#table_alias_lengthObject



198
# File 'lib/arjdbc/firebird/adapter.rb', line 198

def table_alias_length; IDENTIFIER_LENGTH; end

#table_name_lengthObject



199
# File 'lib/arjdbc/firebird/adapter.rb', line 199

def table_name_length;  IDENTIFIER_LENGTH; end

#type_to_sql(type, limit = nil, precision = nil, scale = nil) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/arjdbc/firebird/adapter.rb', line 123

def type_to_sql(type, limit = nil, precision = nil, scale = nil)
  case type
  when :integer
    case limit
      when nil  then 'integer'
      when 1..2 then 'smallint'
      when 3..4 then 'integer'
      when 5..8 then 'bigint'
      else raise(ActiveRecordError, "No integer type has byte size #{limit}. "<<
                                    "Use a NUMERIC with PRECISION 0 instead.")
    end
  when :float
    if limit.nil? || limit <= 4
      'float'
    else
      'double precision'
    end
  else super
  end
end

#update_lob_values?Boolean

Returns:

  • (Boolean)

See Also:



90
# File 'lib/arjdbc/firebird/adapter.rb', line 90

def update_lob_values?; Firebird.update_lob_values?; end