Module: ArJdbc::Firebird
- Included in:
- ActiveRecord::ConnectionAdapters::FirebirdAdapter
- 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
- .column_selector ⇒ Object
-
.emulate_booleans ⇒ Object
deprecated
Deprecated.
Use #emulate_booleans? instead.
- .emulate_booleans=(emulate) ⇒ Object
-
.emulate_booleans? ⇒ Boolean
Boolean emulation can be disabled using :.
- .jdbc_connection_class ⇒ Object
- .update_lob_values=(update) ⇒ Object
-
.update_lob_values? ⇒ Boolean
Updating records with LOB values (binary/text columns) in a separate statement can be disabled using :.
Instance Method Summary collapse
- #adapter_name ⇒ Object
- #add_limit_offset!(sql, options) ⇒ Object
- #change_column(table_name, column_name, type, options = {}) ⇒ Object
- #clear_cache! ⇒ Object
- #column_name_length ⇒ Object
- #create_table(name, options = {}) ⇒ Object
- #default_sequence_name(table_name, column = nil) ⇒ Object
- #drop_table(name, options = {}) ⇒ Object
-
#ids_in_list_limit ⇒ Object
Does this adapter restrict the number of IDs you can use in a list.
- #index_name_length ⇒ Object
- #initialize_type_map(m) ⇒ Object
- #insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) ⇒ Object
- #insert_limit_offset!(sql, limit, offset) ⇒ Object
- #jdbc_column_class ⇒ Object
- #native_database_types ⇒ Object
- #next_sequence_value(sequence_name) ⇒ Object
-
#prefetch_primary_key?(table_name = nil) ⇒ Boolean
Should primary key values be selected from their corresponding sequence before the insert statement?.
- #quote(value, column = nil) ⇒ Object
- #quote_column_name(column_name) ⇒ Object
- #quote_string(string) ⇒ Object
- #quote_table_name_for_assignment(table, attr) ⇒ Object
- #quoted_date(value) ⇒ Object
- #quoted_false ⇒ Object
- #quoted_true ⇒ Object
- #remove_index(table_name, options) ⇒ Object
- #rename_column(table_name, column_name, new_column_name) ⇒ Object
- #rename_table(name, new_name) ⇒ Object
-
#reset_sequence!(table, column, sequence = nil) ⇒ Object
Set the sequence to the max value of the table's column.
-
#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.
-
#supports_migrations? ⇒ Boolean
Does this adapter support migrations?.
-
#supports_primary_key? ⇒ Boolean
Can this adapter determine the primary key for tables not attached to an Active Record class, such as join tables?.
- #table_alias_length ⇒ Object
- #table_name_length ⇒ Object
- #type_to_sql(type, limit = nil, precision = nil, scale = nil) ⇒ Object
- #update_lob_values? ⇒ Boolean
Class Method Details
.column_selector ⇒ Object
28 29 30 |
# File 'lib/arjdbc/firebird/adapter.rb', line 28 def self.column_selector [ /firebird/i, lambda { |cfg, column| column.extend(Column) } ] end |
.emulate_booleans ⇒ Object
Use #emulate_booleans? instead.
55 |
# File 'lib/arjdbc/firebird/adapter.rb', line 55 def self.emulate_booleans; @@emulate_booleans; end |
.emulate_booleans=(emulate) ⇒ Object
57 |
# File 'lib/arjdbc/firebird/adapter.rb', line 57 def self.emulate_booleans=(emulate); @@emulate_booleans = emulate; end |
.emulate_booleans? ⇒ Boolean
Boolean emulation can be disabled using :
ArJdbc::Firebird.emulate_booleans = false
53 |
# File 'lib/arjdbc/firebird/adapter.rb', line 53 def self.emulate_booleans?; @@emulate_booleans; end |
.jdbc_connection_class ⇒ Object
23 24 25 |
# File 'lib/arjdbc/firebird/adapter.rb', line 23 def self.jdbc_connection_class ::ActiveRecord::ConnectionAdapters::FirebirdJdbcConnection end |
.update_lob_values=(update) ⇒ Object
68 |
# File 'lib/arjdbc/firebird/adapter.rb', line 68 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
66 |
# File 'lib/arjdbc/firebird/adapter.rb', line 66 def self.update_lob_values?; @@update_lob_values; end |
Instance Method Details
#adapter_name ⇒ Object
79 80 81 |
# File 'lib/arjdbc/firebird/adapter.rb', line 79 def adapter_name ADAPTER_NAME end |
#add_limit_offset!(sql, options) ⇒ Object
216 217 218 219 220 |
# File 'lib/arjdbc/firebird/adapter.rb', line 216 def add_limit_offset!(sql, ) if limit = [:limit] insert_limit_offset!(sql, limit, [:offset]) end end |
#change_column(table_name, column_name, type, options = {}) ⇒ Object
282 283 284 |
# File 'lib/arjdbc/firebird/adapter.rb', line 282 def change_column(table_name, column_name, type, = {}) execute "ALTER TABLE #{table_name} ALTER #{column_name} TYPE #{type_to_sql(type, [:limit])}" end |
#clear_cache! ⇒ Object
144 145 146 147 |
# File 'lib/arjdbc/firebird/adapter.rb', line 144 def clear_cache! super reload_type_map end |
#column_name_length ⇒ Object
249 |
# File 'lib/arjdbc/firebird/adapter.rb', line 249 def column_name_length; IDENTIFIER_LENGTH; end |
#create_table(name, options = {}) ⇒ Object
266 267 268 269 |
# File 'lib/arjdbc/firebird/adapter.rb', line 266 def create_table(name, = {}) super(name, ) execute "CREATE GENERATOR #{default_sequence_name(name)}" end |
#default_sequence_name(table_name, column = nil) ⇒ Object
251 252 253 254 |
# File 'lib/arjdbc/firebird/adapter.rb', line 251 def default_sequence_name(table_name, column = nil) len = IDENTIFIER_LENGTH - 4 table_name.to_s.gsub (/(^|\.)([\w$-]{1,#{len}})([\w$-]*)$/), '\1\2_seq' end |
#drop_table(name, options = {}) ⇒ Object
277 278 279 280 |
# File 'lib/arjdbc/firebird/adapter.rb', line 277 def drop_table(name, = {}) super(name) execute_quietly "DROP GENERATOR #{default_sequence_name(name)}" end |
#ids_in_list_limit ⇒ Object
Does this adapter restrict the number of IDs you can use in a list. Oracle has a limit of 1000.
207 208 209 |
# File 'lib/arjdbc/firebird/adapter.rb', line 207 def ids_in_list_limit 1499 end |
#index_name_length ⇒ Object
248 |
# File 'lib/arjdbc/firebird/adapter.rb', line 248 def index_name_length; IDENTIFIER_LENGTH; end |
#initialize_type_map(m) ⇒ Object
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 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 104 def initialize_type_map(m) register_class_with_limit m, %r(binary)i, ActiveRecord::Type::Binary register_class_with_limit m, %r(text)i, ActiveRecord::Type::Text register_class_with_limit m, %r(date(?:\(.*?\))?$)i, DateType register_class_with_limit m, %r(time(?:\(.*?\))?$)i, ActiveRecord::Type::Time register_class_with_limit m, %r(float)i, ActiveRecord::Type::Float register_class_with_limit m, %r(int)i, ActiveRecord::Type::Integer m.alias_type %r(blob)i, 'binary' m.alias_type %r(clob)i, 'text' m.alias_type %r(double)i, 'float' m.register_type(%r(decimal)i) do |sql_type| scale = extract_scale(sql_type) precision = extract_precision(sql_type) if scale == 0 ActiveRecord::Type::Integer.new(precision: precision) else ActiveRecord::Type::Decimal.new(precision: precision, scale: scale) end end m.alias_type %r(numeric)i, 'decimal' register_class_with_limit m, %r(varchar)i, ActiveRecord::Type::String m.register_type(%r(^char)i) do |sql_type| precision = extract_precision(sql_type) if Firebird.emulate_booleans? && precision == 1 ActiveRecord::Type::Boolean.new else ActiveRecord::Type::String.new(:precision => precision) end end register_class_with_limit m, %r(datetime)i, ActiveRecord::Type::DateTime register_class_with_limit m, %r(timestamp)i, TimestampType end |
#insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) ⇒ Object
211 212 213 214 |
# File 'lib/arjdbc/firebird/adapter.rb', line 211 def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) execute(sql, name, binds) id_value end |
#insert_limit_offset!(sql, limit, offset) ⇒ Object
225 226 227 228 229 230 231 232 |
# File 'lib/arjdbc/firebird/adapter.rb', line 225 def insert_limit_offset!(sql, limit, offset) lim_off = '' lim_off << "FIRST #{limit}" if limit lim_off << " SKIP #{offset}" if offset lim_off.strip! sql.sub!(SELECT_RE, "\\&#{lim_off} ") unless lim_off.empty? end |
#jdbc_column_class ⇒ Object
44 |
# File 'lib/arjdbc/firebird/adapter.rb', line 44 def jdbc_column_class; ::ActiveRecord::ConnectionAdapters::FirebirdColumn end |
#native_database_types ⇒ Object
100 101 102 |
# File 'lib/arjdbc/firebird/adapter.rb', line 100 def native_database_types NATIVE_DATABASE_TYPES end |
#next_sequence_value(sequence_name) ⇒ Object
262 263 264 |
# File 'lib/arjdbc/firebird/adapter.rb', line 262 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?
238 239 240 241 242 |
# File 'lib/arjdbc/firebird/adapter.rb', line 238 def prefetch_primary_key?(table_name = nil) return true if table_name.nil? primary_keys(table_name.to_s).size == 1 # columns(table_name).count { |column| column.primary } == 1 end |
#quote(value, column = nil) ⇒ Object
295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 |
# File 'lib/arjdbc/firebird/adapter.rb', line 295 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
370 371 372 373 |
# File 'lib/arjdbc/firebird/adapter.rb', line 370 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
350 351 352 |
# File 'lib/arjdbc/firebird/adapter.rb', line 350 def quote_string(string) string.gsub(/'/, "''") end |
#quote_table_name_for_assignment(table, attr) ⇒ Object
365 366 367 |
# File 'lib/arjdbc/firebird/adapter.rb', line 365 def quote_table_name_for_assignment(table, attr) quote_column_name(attr) end |
#quoted_date(value) ⇒ Object
339 340 341 342 343 344 345 346 347 |
# File 'lib/arjdbc/firebird/adapter.rb', line 339 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_false ⇒ Object
360 361 362 |
# File 'lib/arjdbc/firebird/adapter.rb', line 360 def quoted_false quote(0) end |
#quoted_true ⇒ Object
355 356 357 |
# File 'lib/arjdbc/firebird/adapter.rb', line 355 def quoted_true quote(1) end |
#remove_index(table_name, options) ⇒ Object
290 291 292 |
# File 'lib/arjdbc/firebird/adapter.rb', line 290 def remove_index(table_name, ) execute "DROP INDEX #{index_name(table_name, )}" end |
#rename_column(table_name, column_name, new_column_name) ⇒ Object
286 287 288 |
# File 'lib/arjdbc/firebird/adapter.rb', line 286 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
271 272 273 274 275 |
# File 'lib/arjdbc/firebird/adapter.rb', line 271 def rename_table(name, new_name) execute "RENAME #{name} TO #{new_name}" name_seq, new_name_seq = default_sequence_name(name), default_sequence_name(new_name) execute_quietly "UPDATE RDB$GENERATORS SET RDB$GENERATOR_NAME='#{new_name_seq}' WHERE RDB$GENERATOR_NAME='#{name_seq}'" end |
#reset_sequence!(table, column, sequence = nil) ⇒ Object
Set the sequence to the max value of the table's column.
257 258 259 260 |
# File 'lib/arjdbc/firebird/adapter.rb', line 257 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_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.
201 202 203 |
# File 'lib/arjdbc/firebird/adapter.rb', line 201 def supports_ddl_transactions? false end |
#supports_migrations? ⇒ Boolean
Does this adapter support migrations?
188 189 190 |
# File 'lib/arjdbc/firebird/adapter.rb', line 188 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?
194 195 196 |
# File 'lib/arjdbc/firebird/adapter.rb', line 194 def supports_primary_key? true end |
#table_alias_length ⇒ Object
246 |
# File 'lib/arjdbc/firebird/adapter.rb', line 246 def table_alias_length; IDENTIFIER_LENGTH; end |
#table_name_length ⇒ Object
247 |
# File 'lib/arjdbc/firebird/adapter.rb', line 247 def table_name_length; IDENTIFIER_LENGTH; end |
#type_to_sql(type, limit = nil, precision = nil, scale = nil) ⇒ Object
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/arjdbc/firebird/adapter.rb', line 166 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
71 |
# File 'lib/arjdbc/firebird/adapter.rb', line 71 def update_lob_values?; Firebird.update_lob_values?; end |