aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/lib/active_record/connection_adapters/column.rb16
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/column.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid.rb51
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb23
-rw-r--r--activerecord/lib/active_record/connection_adapters/type.rb1
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/binary.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/decimal.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/float.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/hash_lookup_type_map.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/integer.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/numeric.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/string.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/value.rb12
-rw-r--r--activerecord/test/cases/adapters/postgresql/composite_test.rb2
14 files changed, 75 insertions, 69 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb
index 420bb0f2e4..9557f41950 100644
--- a/activerecord/lib/active_record/connection_adapters/column.rb
+++ b/activerecord/lib/active_record/connection_adapters/column.rb
@@ -18,7 +18,7 @@ module ActiveRecord
alias :encoded? :coder
- delegate :type, to: :cast_type
+ delegate :type, :text?, :number?, :binary?, to: :cast_type
# Instantiates a new column in the table.
#
@@ -43,16 +43,6 @@ module ActiveRecord
@coder = nil
end
- # Returns +true+ if the column is either of type string or text.
- def text?
- type == :string || type == :text
- end
-
- # Returns +true+ if the column is either of type integer, float or decimal.
- def number?
- type == :integer || type == :float || type == :decimal
- end
-
def has_default?
!default.nil?
end
@@ -70,10 +60,6 @@ module ActiveRecord
end
end
- def binary?
- type == :binary
- end
-
# Casts a Ruby value to something appropriate for writing to the database.
# Numeric columns will typecast boolean and string to appropriate numeric
# values.
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
index e5118b5427..aba721eece 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
@@ -21,14 +21,6 @@ module ActiveRecord
@default_function = default if has_default_function?(default_value, default)
end
- def number?
- !array && super
- end
-
- def text?
- !array && super
- end
-
# :stopdoc:
class << self
include PostgreSQL::Cast
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
index 94afc3aec5..a951fa1522 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
@@ -14,6 +14,10 @@ module ActiveRecord
def initialize(type)
@type = type
end
+
+ def text?
+ false
+ end
end
class Bit < Type::String
@@ -276,43 +280,6 @@ This is not reliable and will be removed in the future.
end
end
- class TypeMap
- def initialize
- @mapping = {}
- end
-
- def []=(oid, type)
- @mapping[oid] = type
- end
-
- def [](oid)
- @mapping[oid]
- end
-
- def clear
- @mapping.clear
- end
-
- def key?(oid)
- @mapping.key? oid
- end
-
- def fetch(ftype, fmod)
- # The type for the numeric depends on the width of the field,
- # so we'll do something special here.
- #
- # When dealing with decimal columns:
- #
- # places after decimal = fmod - 4 & 0xffff
- # places before decimal = (fmod - 4) >> 16 & 0xffff
- if ftype == 1700 && (fmod - 4 & 0xffff).zero?
- ftype = 23
- end
-
- @mapping.fetch(ftype) { |oid| yield oid, fmod }
- end
- end
-
# This class uses the data from PostgreSQL pg_type table to build
# the OID -> Type mapping.
# - OID is and integer representing the type.
@@ -349,19 +316,19 @@ This is not reliable and will be removed in the future.
end
def register_array_type(row)
- if subtype = @store[row['typelem'].to_i]
+ if subtype = @store.lookup(row['typelem'].to_i)
register row['oid'], OID::Array.new(subtype)
end
end
def register_range_type(row)
- if subtype = @store[row['rngsubtype'].to_i]
+ if subtype = @store.lookup(row['rngsubtype'].to_i)
register row['oid'], OID::Range.new(subtype, row['typname'].to_sym)
end
end
def register_domain_type(row)
- if base_type = @store[row["typbasetype"].to_i]
+ if base_type = @store.lookup(row["typbasetype"].to_i)
register row['oid'], base_type
else
warn "unknown base type (OID: #{row["typbasetype"]}) for domain #{row["typname"]}."
@@ -369,7 +336,7 @@ This is not reliable and will be removed in the future.
end
def register_composite_type(row)
- if subtype = @store[row['typelem'].to_i]
+ if subtype = @store.lookup(row['typelem'].to_i)
register row['oid'], OID::Vector.new(row['typdelim'], subtype)
end
end
@@ -380,7 +347,7 @@ This is not reliable and will be removed in the future.
raise ArgumentError, "can't register nil type for OID #{oid}" if oid_type.nil?
return if @store.key?(oid)
- @store[oid] = oid_type
+ @store.register_type(oid, oid_type)
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index f46af35f55..ed3e884455 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -369,7 +369,7 @@ module ActiveRecord
raise "Your version of PostgreSQL (#{postgresql_version}) is too old, please upgrade!"
end
- @type_map = OID::TypeMap.new
+ @type_map = Type::HashLookupTypeMap.new
initialize_type_map(type_map)
@local_tz = execute('SHOW TIME ZONE', 'SCHEMA').first["TimeZone"]
@use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
@@ -543,12 +543,29 @@ module ActiveRecord
initialize_type_map(type_map, [oid])
end
- type_map.fetch(oid, fmod) {
+ type_map.fetch(normalize_oid_type(oid, fmod)) {
warn "unknown OID #{oid}: failed to recognize type of '#{column_name}'. It will be treated as String."
- type_map[oid] = Type::Value.new
+ Type::Value.new.tap do |cast_type|
+ type_map.register_type(oid, cast_type)
+ end
}
end
+ def normalize_oid_type(ftype, fmod)
+ # The type for the numeric depends on the width of the field,
+ # so we'll do something special here.
+ #
+ # When dealing with decimal columns:
+ #
+ # places after decimal = fmod - 4 & 0xffff
+ # places before decimal = (fmod - 4) >> 16 & 0xffff
+ if ftype == 1700 && (fmod - 4 & 0xffff).zero?
+ 23
+ else
+ ftype
+ end
+ end
+
def initialize_type_map(type_map, oids = nil)
if supports_ranges?
query = <<-SQL
diff --git a/activerecord/lib/active_record/connection_adapters/type.rb b/activerecord/lib/active_record/connection_adapters/type.rb
index f215266560..763176cb2b 100644
--- a/activerecord/lib/active_record/connection_adapters/type.rb
+++ b/activerecord/lib/active_record/connection_adapters/type.rb
@@ -1,3 +1,4 @@
+require 'active_record/connection_adapters/type/numeric'
require 'active_record/connection_adapters/type/time_value'
require 'active_record/connection_adapters/type/value'
diff --git a/activerecord/lib/active_record/connection_adapters/type/binary.rb b/activerecord/lib/active_record/connection_adapters/type/binary.rb
index 168d824d3d..e0ea226216 100644
--- a/activerecord/lib/active_record/connection_adapters/type/binary.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/binary.rb
@@ -5,6 +5,10 @@ module ActiveRecord
def type
:binary
end
+
+ def binary?
+ true
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/type/decimal.rb b/activerecord/lib/active_record/connection_adapters/type/decimal.rb
index 3a9c470dba..6fb1a6c3b0 100644
--- a/activerecord/lib/active_record/connection_adapters/type/decimal.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/decimal.rb
@@ -2,6 +2,8 @@ module ActiveRecord
module ConnectionAdapters
module Type
class Decimal < Value # :nodoc:
+ include Numeric
+
def type
:decimal
end
diff --git a/activerecord/lib/active_record/connection_adapters/type/float.rb b/activerecord/lib/active_record/connection_adapters/type/float.rb
index 2d436d4aa3..31d8e7d1d3 100644
--- a/activerecord/lib/active_record/connection_adapters/type/float.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/float.rb
@@ -2,6 +2,8 @@ module ActiveRecord
module ConnectionAdapters
module Type
class Float < Value # :nodoc:
+ include Numeric
+
def type
:float
end
diff --git a/activerecord/lib/active_record/connection_adapters/type/hash_lookup_type_map.rb b/activerecord/lib/active_record/connection_adapters/type/hash_lookup_type_map.rb
index 828ada00a7..8503d3ea1b 100644
--- a/activerecord/lib/active_record/connection_adapters/type/hash_lookup_type_map.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/hash_lookup_type_map.rb
@@ -2,10 +2,16 @@ module ActiveRecord
module ConnectionAdapters
module Type
class HashLookupTypeMap < TypeMap # :nodoc:
+ delegate :key?, to: :@mapping
+
def lookup(type)
@mapping.fetch(type, proc { default_value }).call(type)
end
+ def fetch(type, &block)
+ @mapping.fetch(type, block).call(type)
+ end
+
def alias_type(type, alias_type)
register_type(type) { lookup(alias_type) }
end
diff --git a/activerecord/lib/active_record/connection_adapters/type/integer.rb b/activerecord/lib/active_record/connection_adapters/type/integer.rb
index 3a216c6dd6..b41a726ef4 100644
--- a/activerecord/lib/active_record/connection_adapters/type/integer.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/integer.rb
@@ -2,6 +2,8 @@ module ActiveRecord
module ConnectionAdapters
module Type
class Integer < Value # :nodoc:
+ include Numeric
+
def type
:integer
end
diff --git a/activerecord/lib/active_record/connection_adapters/type/numeric.rb b/activerecord/lib/active_record/connection_adapters/type/numeric.rb
new file mode 100644
index 0000000000..a440de4d14
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/type/numeric.rb
@@ -0,0 +1,11 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module Type
+ module Numeric # :nodoc:
+ def number?
+ true
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/type/string.rb b/activerecord/lib/active_record/connection_adapters/type/string.rb
index d6c1c64834..24f9659c7b 100644
--- a/activerecord/lib/active_record/connection_adapters/type/string.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/string.rb
@@ -6,6 +6,10 @@ module ActiveRecord
:string
end
+ def text?
+ true
+ end
+
private
def cast_value(value)
diff --git a/activerecord/lib/active_record/connection_adapters/type/value.rb b/activerecord/lib/active_record/connection_adapters/type/value.rb
index a83f0e652d..506f402fef 100644
--- a/activerecord/lib/active_record/connection_adapters/type/value.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/value.rb
@@ -8,6 +8,18 @@ module ActiveRecord
cast_value(value) unless value.nil?
end
+ def text?
+ false
+ end
+
+ def number?
+ false
+ end
+
+ def binary?
+ false
+ end
+
private
def cast_value(value)
diff --git a/activerecord/test/cases/adapters/postgresql/composite_test.rb b/activerecord/test/cases/adapters/postgresql/composite_test.rb
index 1e7071c136..f01717d1a7 100644
--- a/activerecord/test/cases/adapters/postgresql/composite_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/composite_test.rb
@@ -83,7 +83,7 @@ end
class PostgresqlCompositeWithCustomOIDTest < ActiveRecord::TestCase
include PostgresqlCompositeBehavior
- class FullAddressType
+ class FullAddressType < ActiveRecord::ConnectionAdapters::Type::Value
def type; :full_address end
def type_cast(value)