aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib')
-rw-r--r--activerecord/lib/active_record/attribute_methods.rb1
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_adapter.rb63
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb55
-rw-r--r--activerecord/lib/active_record/connection_adapters/column.rb18
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/column.rb22
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/money.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb36
-rw-r--r--activerecord/lib/active_record/connection_adapters/type.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/decimal.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/value.rb10
10 files changed, 111 insertions, 108 deletions
diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb
index 8bd51dc71f..6c2403d87e 100644
--- a/activerecord/lib/active_record/attribute_methods.rb
+++ b/activerecord/lib/active_record/attribute_methods.rb
@@ -200,6 +200,7 @@ module ActiveRecord
# this is probably horribly slow, but should only happen at most once for a given AR class
attribute_method.bind(self).call(*args, &block)
else
+ return super unless respond_to_missing?(method, true)
send(method, *args, &block)
end
else
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index 0c55dbb037..ea7703c82c 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -374,26 +374,31 @@ module ActiveRecord
end
def initialize_type_map(m) # :nodoc:
- m.register_type %r(boolean)i, Type::Boolean.new
- m.register_type %r(char)i, Type::String.new
- m.register_type %r(binary)i, Type::Binary.new
- m.alias_type %r(blob)i, 'binary'
- m.register_type %r(text)i, Type::Text.new
- m.alias_type %r(clob)i, 'text'
- m.register_type %r(date)i, Type::Date.new
- m.register_type %r(time)i, Type::Time.new
- m.alias_type %r(timestamp)i, 'datetime'
- m.register_type %r(datetime)i, Type::DateTime.new
- m.alias_type %r(numeric)i, 'decimal'
- m.alias_type %r(number)i, 'decimal'
- m.register_type %r(float)i, Type::Float.new
- m.alias_type %r(double)i, 'float'
- m.register_type %r(int)i, Type::Integer.new
+ register_class_with_limit m, %r(boolean)i, Type::Boolean
+ register_class_with_limit m, %r(char)i, Type::String
+ register_class_with_limit m, %r(binary)i, Type::Binary
+ register_class_with_limit m, %r(text)i, Type::Text
+ register_class_with_limit m, %r(date)i, Type::Date
+ register_class_with_limit m, %r(time)i, Type::Time
+ register_class_with_limit m, %r(datetime)i, Type::DateTime
+ register_class_with_limit m, %r(float)i, Type::Float
+ register_class_with_limit m, %r(int)i, Type::Integer
+
+ m.alias_type %r(blob)i, 'binary'
+ m.alias_type %r(clob)i, 'text'
+ m.alias_type %r(timestamp)i, 'datetime'
+ m.alias_type %r(numeric)i, 'decimal'
+ m.alias_type %r(number)i, 'decimal'
+ m.alias_type %r(double)i, 'float'
+
m.register_type(%r(decimal)i) do |sql_type|
- if Type.extract_scale(sql_type) == 0
- Type::Integer.new
+ scale = extract_scale(sql_type)
+ precision = extract_precision(sql_type)
+
+ if scale == 0
+ Type::Integer.new(precision: precision)
else
- Type::Decimal.new
+ Type::Decimal.new(precision: precision, scale: scale)
end
end
end
@@ -403,6 +408,28 @@ module ActiveRecord
initialize_type_map(type_map)
end
+ def register_class_with_limit(mapping, key, klass) # :nodoc:
+ mapping.register_type(key) do |*args|
+ limit = extract_limit(args.last)
+ klass.new(limit: limit)
+ end
+ end
+
+ def extract_scale(sql_type) # :nodoc:
+ case sql_type
+ when /\((\d+)\)/ then 0
+ when /\((\d+)(,(\d+))\)/ then $3.to_i
+ end
+ end
+
+ def extract_precision(sql_type) # :nodoc:
+ $1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
+ end
+
+ def extract_limit(sql_type) # :nodoc:
+ $1.to_i if sql_type =~ /\((.*)\)/
+ end
+
def translate_exception_class(e, sql)
message = "#{e.class.name}: #{e.message}: #{sql}"
@logger.error message if @logger
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
index 86eb2a38d8..d3f8470c30 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -86,44 +86,12 @@ module ActiveRecord
sql_type =~ /blob/i || type == :text
end
- # Must return the relevant concrete adapter
- def adapter
- raise NotImplementedError
- end
-
def case_sensitive?
collation && !collation.match(/_ci$/)
end
private
- def extract_limit(sql_type)
- case sql_type
- when /^enum\((.+)\)/i
- $1.split(',').map{|enum| enum.strip.length - 2}.max
- when /blob|text/i
- case sql_type
- when /tiny/i
- 255
- when /medium/i
- 16777215
- when /long/i
- 2147483647 # mysql only allows 2^31-1, not 2^32-1, somewhat inconsistently with the tiny/medium/normal cases
- else
- super # we could return 65535 here, but we leave it undecorated by default
- end
- when /^bigint/i; 8
- when /^int/i; 4
- when /^mediumint/i; 3
- when /^smallint/i; 2
- when /^tinyint/i; 1
- when /^float/i; 24
- when /^double/i; 53
- else
- super
- end
- end
-
# MySQL misreports NOT NULL column default when none is given.
# We can't detect this for columns which may have a legitimate ''
# default (string) but we can for others (integer, datetime, boolean,
@@ -636,10 +604,29 @@ module ActiveRecord
protected
- def initialize_type_map(m)
+ def initialize_type_map(m) # :nodoc:
super
+ m.register_type(%r(enum)i) do |sql_type|
+ limit = sql_type[/^enum\((.+)\)/i, 1]
+ .split(',').map{|enum| enum.strip.length - 2}.max
+ Type::String.new(limit: limit)
+ end
+
+ m.register_type %r(tinytext)i, Type::Text.new(limit: 255)
+ m.register_type %r(tinyblob)i, Type::Binary.new(limit: 255)
+ m.register_type %r(mediumtext)i, Type::Text.new(limit: 16777215)
+ m.register_type %r(mediumblob)i, Type::Binary.new(limit: 16777215)
+ m.register_type %r(longtext)i, Type::Text.new(limit: 2147483647)
+ m.register_type %r(longblob)i, Type::Binary.new(limit: 2147483647)
+ m.register_type %r(^bigint)i, Type::Integer.new(limit: 8)
+ m.register_type %r(^int)i, Type::Integer.new(limit: 4)
+ m.register_type %r(^mediumint)i, Type::Integer.new(limit: 3)
+ m.register_type %r(^smallint)i, Type::Integer.new(limit: 2)
+ m.register_type %r(^tinyint)i, Type::Integer.new(limit: 1)
+ m.register_type %r(^float)i, Type::Float.new(limit: 24)
+ m.register_type %r(^double)i, Type::Float.new(limit: 53)
+
m.alias_type %r(tinyint\(1\))i, 'boolean' if emulate_booleans
- m.alias_type %r(enum)i, 'varchar'
m.alias_type %r(set)i, 'varchar'
m.alias_type %r(year)i, 'integer'
m.alias_type %r(bit)i, 'binary'
diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb
index a718756b93..704868c058 100644
--- a/activerecord/lib/active_record/connection_adapters/column.rb
+++ b/activerecord/lib/active_record/connection_adapters/column.rb
@@ -13,12 +13,12 @@ module ActiveRecord
ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
end
- attr_reader :name, :default, :cast_type, :limit, :null, :sql_type, :precision, :scale, :default_function
+ attr_reader :name, :default, :cast_type, :null, :sql_type, :default_function
attr_accessor :primary, :coder
alias :encoded? :coder
- delegate :type, :klass, :text?, :number?, :binary?, :type_cast_for_write, to: :cast_type
+ delegate :type, :precision, :scale, :limit, :klass, :text?, :number?, :binary?, :type_cast_for_write, to: :cast_type
# Instantiates a new column in the table.
#
@@ -34,9 +34,6 @@ module ActiveRecord
@cast_type = cast_type
@sql_type = sql_type
@null = null
- @limit = extract_limit(sql_type)
- @precision = extract_precision(sql_type)
- @scale = extract_scale(sql_type)
@default = extract_default(default)
@default_function = nil
@primary = nil
@@ -67,17 +64,6 @@ module ActiveRecord
def extract_default(default)
type_cast(default)
end
-
- private
- delegate :extract_scale, to: :cast_type
-
- def extract_limit(sql_type)
- $1.to_i if sql_type =~ /\((.*)\)/
- end
-
- def extract_precision(sql_type)
- $2.to_i if sql_type =~ /^(numeric|decimal|number)\((\d+)(,\d+)?\)/i
- end
end
end
# :startdoc:
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
index 80c79642f3..b55766bde0 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
@@ -35,8 +35,6 @@ module ActiveRecord
require 'active_record/connection_adapters/postgresql/array_parser'
include PostgreSQL::ArrayParser
end
-
- attr_accessor :money_precision
end
# :startdoc:
@@ -112,26 +110,6 @@ module ActiveRecord
def has_default_function?(default_value, default)
!default_value && (%r{\w+\(.*\)} === default)
end
-
- def extract_limit(sql_type)
- case sql_type
- when /^bigint/i; 8
- when /^smallint/i; 2
- when /^timestamp/i; nil
- else super
- end
- end
-
- # Extracts the precision from PostgreSQL-specific data types.
- def extract_precision(sql_type)
- if sql_type == 'money'
- self.class.money_precision
- elsif sql_type =~ /timestamp/i
- $1.to_i if sql_type =~ /\((\d+)\)/
- else
- super
- end
- end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/money.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/money.rb
index 1e34c09c88..697dceb7c2 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/money.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/money.rb
@@ -5,7 +5,9 @@ module ActiveRecord
class Money < Type::Decimal
include Infinity
- def extract_scale(sql_type)
+ class_attribute :precision
+
+ def scale
2
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 7d1fa0dd08..e3a2422160 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -551,6 +551,8 @@ module ActiveRecord
}
end
+ OID_FOR_DECIMAL_TREATED_AS_INT = 23 # :nodoc:
+
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.
@@ -560,29 +562,27 @@ module ActiveRecord
# places after decimal = fmod - 4 & 0xffff
# places before decimal = (fmod - 4) >> 16 & 0xffff
if ftype == 1700 && (fmod - 4 & 0xffff).zero?
- 23
+ OID_FOR_DECIMAL_TREATED_AS_INT
else
ftype
end
end
def initialize_type_map(m)
- m.register_type 'int2', OID::Integer.new
+ register_class_with_limit m, 'int2', OID::Integer
m.alias_type 'int4', 'int2'
m.alias_type 'int8', 'int2'
m.alias_type 'oid', 'int2'
- m.register_type 'numeric', OID::Decimal.new
m.register_type 'float4', OID::Float.new
m.alias_type 'float8', 'float4'
m.register_type 'text', Type::Text.new
- m.register_type 'varchar', Type::String.new
+ register_class_with_limit m, 'varchar', Type::String
m.alias_type 'char', 'varchar'
m.alias_type 'name', 'varchar'
m.alias_type 'bpchar', 'varchar'
m.register_type 'bool', Type::Boolean.new
m.register_type 'bit', OID::Bit.new
m.alias_type 'varbit', 'bit'
- m.register_type 'timestamp', OID::DateTime.new
m.alias_type 'timestamptz', 'timestamp'
m.register_type 'date', OID::Date.new
m.register_type 'time', OID::Time.new
@@ -610,9 +610,33 @@ module ActiveRecord
m.alias_type 'lseg', 'varchar'
m.alias_type 'box', 'varchar'
+ m.register_type 'timestamp' do |_, sql_type|
+ precision = extract_precision(sql_type)
+ OID::DateTime.new(precision: precision)
+ end
+
+ m.register_type 'numeric' do |_, sql_type|
+ precision = extract_precision(sql_type)
+ scale = extract_scale(sql_type)
+ OID::Decimal.new(precision: precision, scale: scale)
+ end
+
+ m.register_type OID_FOR_DECIMAL_TREATED_AS_INT do |_, sql_type|
+ precision = extract_precision(sql_type)
+ OID::Integer.new(precision: precision)
+ end
+
load_additional_types(m)
end
+ def extract_limit(sql_type) # :nodoc:
+ case sql_type
+ when /^bigint/i; 8
+ when /^smallint/i; 2
+ else super
+ end
+ end
+
def load_additional_types(type_map, oids = nil)
if supports_ranges?
query = <<-SQL
@@ -713,7 +737,7 @@ module ActiveRecord
# Money type has a fixed precision of 10 in PostgreSQL 8.2 and below, and as of
# PostgreSQL 8.3 it has a fixed precision of 19. PostgreSQLColumn.extract_precision
# should know about this but can't detect it there, so deal with it here.
- PostgreSQLColumn.money_precision = (postgresql_version >= 80300) ? 19 : 10
+ OID::Money.precision = (postgresql_version >= 80300) ? 19 : 10
configure_connection
rescue ::PG::Error => error
diff --git a/activerecord/lib/active_record/connection_adapters/type.rb b/activerecord/lib/active_record/connection_adapters/type.rb
index 9103ae85c0..395a4160a8 100644
--- a/activerecord/lib/active_record/connection_adapters/type.rb
+++ b/activerecord/lib/active_record/connection_adapters/type.rb
@@ -19,14 +19,6 @@ require 'active_record/connection_adapters/type/hash_lookup_type_map'
module ActiveRecord
module ConnectionAdapters
module Type # :nodoc:
- class << self
- def extract_scale(sql_type)
- case sql_type
- when /\((\d+)\)/ then 0
- when /\((\d+)(,(\d+))\)/ then $3.to_i
- end
- end
- 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 a8cd1cf5b5..ac5af4b963 100644
--- a/activerecord/lib/active_record/connection_adapters/type/decimal.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/decimal.rb
@@ -4,8 +4,6 @@ module ActiveRecord
class Decimal < Value # :nodoc:
include Numeric
- delegate :extract_scale, to: Type
-
def type
:decimal
end
diff --git a/activerecord/lib/active_record/connection_adapters/type/value.rb b/activerecord/lib/active_record/connection_adapters/type/value.rb
index 52d9ed9bc0..54a3e9dd7a 100644
--- a/activerecord/lib/active_record/connection_adapters/type/value.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/value.rb
@@ -2,8 +2,16 @@ module ActiveRecord
module ConnectionAdapters
module Type
class Value # :nodoc:
+ attr_reader :precision, :scale, :limit
+
+ def initialize(options = {})
+ options.assert_valid_keys(:precision, :scale, :limit)
+ @precision = options[:precision]
+ @scale = options[:scale]
+ @limit = options[:limit]
+ end
+
def type; end
- def extract_scale(sql_type); end
def type_cast(value)
cast_value(value) unless value.nil?