class ActiveRecord::ConnectionAdapters::JdbcTypeConverter
I want to use JDBC's DatabaseMetaData#getTypeInfo to choose the best native types to use for ActiveRecord's Adapter#native_database_types in a database-independent way, but apparently a database driver can return multiple types for a given java.sql.Types constant. So this type converter uses some heuristics to try to pick the best (most common) type to use. It's not great, it would be better to just delegate to each database's existing AR adapter's native_database_types method, but I wanted to try to do this in a way that didn't pull in all the other adapters as dependencies. Improvements appreciated.
Constants
- AR_TO_JDBC_TYPES
The basic ActiveRecord types, mapped to an array of procs that are used to select the best type. The procs are used as selectors in order until there is only one type left. If all the selectors are applied and there is still more than one type, an exception will be raised.
- BINARY_TYPES
@private
- FLOAT_TYPES
@private
- TEXT_TYPES
@private
Public Class Methods
# File lib/arjdbc/jdbc/type_converter.rb, line 93 def initialize(types) @types = types @types.each {|t| t['type_name'] ||= t['local_type_name']} # Sybase driver seems to want 'local_type_name' end
Public Instance Methods
# File lib/arjdbc/jdbc/type_converter.rb, line 98 def choose_best_types type_map = {} @types.each do |row| name = row['type_name'].downcase k = name.to_sym type_map[k] = { :name => name } set_limit_to_nonzero_precision(type_map[k], row) end AR_TO_JDBC_TYPES.keys.each do |ar_type| typerow = choose_type(ar_type) type_map[ar_type] = { :name => typerow['type_name'].downcase } case ar_type when :integer, :string, :decimal set_limit_to_nonzero_precision(type_map[ar_type], typerow) when :boolean type_map[ar_type][:limit] = 1 end end type_map end
# File lib/arjdbc/jdbc/type_converter.rb, line 120 def choose_type(ar_type) types = @types AR_TO_JDBC_TYPES[ar_type].each do |proc| new_types = types.reject {|r| r["data_type"].to_i == Jdbc::Types::OTHER} new_types = new_types.select(&proc) new_types = new_types.inject([]) do |typs,t| typs << t unless typs.detect {|el| el['type_name'] == t['type_name']} typs end return new_types.first if new_types.length == 1 types = new_types if new_types.length > 0 end raise "unable to choose type for #{ar_type} from:\n#{types.collect{|t| t['type_name']}.inspect}" end
# File lib/arjdbc/jdbc/type_converter.rb, line 135 def set_limit_to_nonzero_precision(map, row) if row['precision'] && row['precision'].to_i > 0 map[:limit] = row['precision'].to_i end end