提交 aafee233 编写于 作者: S Sean Griffin

Remove most PG specific type subclasses

The latest version of the PG gem can actually convert the primitives for
us in C code, which gives a pretty substantial speed up. A few cases
were only there to add the `infinity` method, which I just put on the
range type (which is the only place it was used). Floats also needed to
parse `Infinity` and `NaN`, but it felt reasonable enough to put that on
the generic form.
上级 9a656a77
......@@ -85,7 +85,7 @@ platforms :ruby do
gem 'sqlite3', '~> 1.3.6'
group :db do
gem 'pg', '>= 0.15.0'
gem 'pg', '>= 0.18.0'
gem 'mysql', '>= 2.9.0'
gem 'mysql2', '>= 0.3.13'
end
......
require 'active_record/connection_adapters/postgresql/oid/infinity'
require 'active_record/connection_adapters/postgresql/oid/array'
require 'active_record/connection_adapters/postgresql/oid/bit'
require 'active_record/connection_adapters/postgresql/oid/bit_varying'
require 'active_record/connection_adapters/postgresql/oid/bytea'
require 'active_record/connection_adapters/postgresql/oid/cidr'
require 'active_record/connection_adapters/postgresql/oid/date'
require 'active_record/connection_adapters/postgresql/oid/date_time'
require 'active_record/connection_adapters/postgresql/oid/decimal'
require 'active_record/connection_adapters/postgresql/oid/enum'
require 'active_record/connection_adapters/postgresql/oid/float'
require 'active_record/connection_adapters/postgresql/oid/hstore'
require 'active_record/connection_adapters/postgresql/oid/inet'
require 'active_record/connection_adapters/postgresql/oid/integer'
require 'active_record/connection_adapters/postgresql/oid/json'
require 'active_record/connection_adapters/postgresql/oid/jsonb'
require 'active_record/connection_adapters/postgresql/oid/money'
require 'active_record/connection_adapters/postgresql/oid/point'
require 'active_record/connection_adapters/postgresql/oid/range'
require 'active_record/connection_adapters/postgresql/oid/specialized_string'
require 'active_record/connection_adapters/postgresql/oid/time'
require 'active_record/connection_adapters/postgresql/oid/uuid'
require 'active_record/connection_adapters/postgresql/oid/vector'
require 'active_record/connection_adapters/postgresql/oid/xml'
......
module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
class Date < Type::Date # :nodoc:
include Infinity
end
end
end
end
end
......@@ -3,8 +3,6 @@ module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
class DateTime < Type::DateTime # :nodoc:
include Infinity
def cast_value(value)
if value.is_a?(::String)
case value
......
module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
class Float < Type::Float # :nodoc:
include Infinity
def cast_value(value)
case value
when ::Float then value
when 'Infinity' then ::Float::INFINITY
when '-Infinity' then -::Float::INFINITY
when 'NaN' then ::Float::NAN
else value.to_f
end
end
end
end
end
end
end
module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
module Infinity # :nodoc:
def infinity(options = {})
options[:negative] ? -::Float::INFINITY : ::Float::INFINITY
end
end
end
end
end
end
module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
class Integer < Type::Integer # :nodoc:
include Infinity
end
end
end
end
end
......@@ -3,8 +3,6 @@ module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
class Money < Type::Decimal # :nodoc:
include Infinity
class_attribute :precision
def type
......
......@@ -59,13 +59,23 @@ def type_cast_single_for_database(value)
def extract_bounds(value)
from, to = value[1..-2].split(',')
{
from: (value[1] == ',' || from == '-infinity') ? @subtype.infinity(negative: true) : from,
to: (value[-2] == ',' || to == 'infinity') ? @subtype.infinity : to,
from: (value[1] == ',' || from == '-infinity') ? infinity(negative: true) : from,
to: (value[-2] == ',' || to == 'infinity') ? infinity : to,
exclude_start: (value[0] == '('),
exclude_end: (value[-1] == ')')
}
end
def infinity(negative: false)
if subtype.respond_to?(:infinity)
subtype.infinity(negative: negative)
elsif negative
-::Float::INFINITY
else
::Float::INFINITY
end
end
def infinity?(value)
value.respond_to?(:infinite?) && value.infinite?
end
......
module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
class Time < Type::Time # :nodoc:
include Infinity
end
end
end
end
end
......@@ -8,8 +8,9 @@ module OID # :nodoc:
# - Type is an OID::Type object.
# This class has side effects on the +store+ passed during initialization.
class TypeMapInitializer # :nodoc:
def initialize(store)
def initialize(store, run_complex_types = true)
@store = store
@run_complex_types = run_complex_types
end
def run(records)
......
......@@ -127,18 +127,15 @@ def type_classes_with_standard_constructor
bit_varying: OID::BitVarying,
binary: OID::Bytea,
cidr: OID::Cidr,
date: OID::Date,
date_time: OID::DateTime,
decimal: OID::Decimal,
enum: OID::Enum,
float: OID::Float,
hstore: OID::Hstore,
inet: OID::Inet,
json: OID::Json,
jsonb: OID::Jsonb,
money: OID::Money,
point: OID::Point,
time: OID::Time,
uuid: OID::Uuid,
vector: OID::Vector,
xml: OID::Xml,
......
......@@ -255,6 +255,8 @@ def initialize(connection, logger, connection_parameters, config)
@table_alias_length = nil
connect
add_pg_decoders
@statements = StatementPool.new @connection,
self.class.type_cast_config_to_integer(config.fetch(:statement_limit) { 1000 })
......@@ -459,11 +461,11 @@ def get_oid_type(oid, fmod, column_name, sql_type = '') # :nodoc:
end
def initialize_type_map(m) # :nodoc:
register_class_with_limit m, 'int2', OID::Integer
register_class_with_limit m, 'int4', OID::Integer
register_class_with_limit m, 'int8', OID::Integer
register_class_with_limit m, 'int2', Type::Integer
register_class_with_limit m, 'int4', Type::Integer
register_class_with_limit m, 'int8', Type::Integer
m.alias_type 'oid', 'int2'
m.register_type 'float4', OID::Float.new
m.register_type 'float4', Type::Float.new
m.alias_type 'float8', 'float4'
m.register_type 'text', Type::Text.new
register_class_with_limit m, 'varchar', Type::String
......@@ -474,8 +476,8 @@ def initialize_type_map(m) # :nodoc:
register_class_with_limit m, 'bit', OID::Bit
register_class_with_limit m, 'varbit', OID::BitVarying
m.alias_type 'timestamptz', 'timestamp'
m.register_type 'date', OID::Date.new
m.register_type 'time', OID::Time.new
m.register_type 'date', Type::Date.new
m.register_type 'time', Type::Time.new
m.register_type 'money', OID::Money.new
m.register_type 'bytea', OID::Bytea.new
......@@ -780,6 +782,36 @@ def can_perform_case_insensitive_comparison_for?(column)
end
end
end
def add_pg_decoders
coders_by_name = {
'int2' => PG::TextDecoder::Integer,
'int4' => PG::TextDecoder::Integer,
'int8' => PG::TextDecoder::Integer,
'oid' => PG::TextDecoder::Integer,
'float4' => PG::TextDecoder::Float,
'float8' => PG::TextDecoder::Float,
'bool' => PG::TextDecoder::Boolean,
}
query = <<-SQL
SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype
FROM pg_type as t
SQL
coders = execute_and_clear(query, "SCHEMA", []) do |result|
result
.map { |row| construct_coder(row, coders_by_name['typname']) }
.compact
end
map = PG::TypeMapByOid.new
coders.each { |coder| map.add_coder(coder) }
@connection.type_map_for_results = map
end
def construct_coder(row, coder_class)
return unless coder_class
coder_class.new(oid: row['oid'], name: row['typname'])
end
end
end
end
......@@ -12,7 +12,13 @@ def type
private
def cast_value(value)
value.to_f
case value
when ::Float then value
when "Infinity" then ::Float::INFINITY
when "-Infinity" then -::Float::INFINITY
when "NaN" then ::Float::NAN
else value.to_f
end
end
end
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册