aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r--activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb2
-rw-r--r--activerecord/lib/active_record/associations/preloader.rb13
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb3
-rw-r--r--activerecord/lib/active_record/connection_adapters/column.rb43
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb12
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql_adapter.rb162
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/cast.rb13
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/column.rb7
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid.rb213
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb20
-rw-r--r--activerecord/lib/active_record/connection_adapters/type.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/boolean.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/date.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/date_time.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/decimal.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/float.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/integer.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/string.rb10
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/time.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/time_value.rb24
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/value.rb10
22 files changed, 243 insertions, 339 deletions
diff --git a/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb b/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb
index 44486ad758..30b11c01eb 100644
--- a/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb
+++ b/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb
@@ -11,7 +11,7 @@ module ActiveRecord::Associations::Builder
end
def join_table
- @join_table ||= [@lhs_class.table_name, klass.table_name].sort.join("\0").gsub(/^(.*_)(.+)\0\1(.+)/, '\1\2_\3').gsub("\0", "_")
+ @join_table ||= [@lhs_class.table_name, klass.table_name].sort.join("\0").gsub(/^(.*[._])(.+)\0\1(.+)/, '\1\2_\3').gsub("\0", "_")
end
private
diff --git a/activerecord/lib/active_record/associations/preloader.rb b/activerecord/lib/active_record/associations/preloader.rb
index 20bd4947dc..42571d6af0 100644
--- a/activerecord/lib/active_record/associations/preloader.rb
+++ b/activerecord/lib/active_record/associations/preloader.rb
@@ -112,13 +112,14 @@ module ActiveRecord
end
def preloaders_for_hash(association, records, scope)
- parent, child = association.to_a.first # hash should only be of length 1
+ association.flat_map { |parent, child|
+ loaders = preloaders_for_one parent, records, scope
- loaders = preloaders_for_one parent, records, scope
-
- recs = loaders.flat_map(&:preloaded_records).uniq
- loaders.concat Array.wrap(child).flat_map { |assoc|
- preloaders_on assoc, recs, scope
+ recs = loaders.flat_map(&:preloaded_records).uniq
+ loaders.concat Array.wrap(child).flat_map { |assoc|
+ preloaders_on assoc, recs, scope
+ }
+ loaders
}
end
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 852b7105d3..86eb2a38d8 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -249,10 +249,9 @@ module ActiveRecord
raise NotImplementedError
end
- # Overridden by the adapters to instantiate their specific Column type.
def new_column(field, default, sql_type, null, collation, extra = "") # :nodoc:
cast_type = lookup_cast_type(sql_type)
- Column.new(field, default, cast_type, sql_type, null, collation, extra)
+ Column.new(field, default, cast_type, sql_type, null, collation, strict_mode?, extra)
end
# Must return the Mysql error number from the exception, if the exception has an
diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb
index 25a9cdafcf..f46f9af239 100644
--- a/activerecord/lib/active_record/connection_adapters/column.rb
+++ b/activerecord/lib/active_record/connection_adapters/column.rb
@@ -94,28 +94,10 @@ module ActiveRecord
# Casts value to an appropriate instance.
def type_cast(value)
- return nil if value.nil?
- return coder.load(value) if encoded?
-
- klass = self.class
-
- case type
- when :string, :text
- case value
- when TrueClass; "1"
- when FalseClass; "0"
- else
- value.to_s
- end
- when :integer then klass.value_to_integer(value)
- when :float then value.to_f
- when :decimal then klass.value_to_decimal(value)
- when :datetime then klass.string_to_time(value)
- when :time then klass.string_to_dummy_time(value)
- when :date then klass.value_to_date(value)
- when :binary then klass.binary_to_string(value)
- when :boolean then klass.value_to_boolean(value)
- else value
+ if encoded?
+ coder.load(value)
+ else
+ cast_type.type_cast(value)
end
end
@@ -132,6 +114,8 @@ module ActiveRecord
end
class << self
+ include Type::TimeValue
+
# Used to convert from BLOBs to Strings
def binary_to_string(value)
value
@@ -215,21 +199,6 @@ module ActiveRecord
end
end
- def new_time(year, mon, mday, hour, min, sec, microsec, offset = nil)
- # Treat 0000-00-00 00:00:00 as nil.
- return nil if year.nil? || (year == 0 && mon == 0 && mday == 0)
-
- if offset
- time = Time.utc(year, mon, mday, hour, min, sec, microsec) rescue nil
- return nil unless time
-
- time -= offset
- Base.default_timezone == :utc ? time : time.getlocal
- else
- Time.public_send(Base.default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil
- end
- end
-
def fast_string_to_date(string)
if string =~ Format::ISO_DATE
new_date $1.to_i, $2.to_i, $3.to_i
diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
index 2e39168374..0a14cdfe89 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
@@ -29,13 +29,6 @@ module ActiveRecord
module ConnectionAdapters
class Mysql2Adapter < AbstractMysqlAdapter
-
- class Column < AbstractMysqlAdapter::Column # :nodoc:
- def adapter
- Mysql2Adapter
- end
- end
-
ADAPTER_NAME = 'Mysql2'
def initialize(connection, logger, connection_options, config)
@@ -69,11 +62,6 @@ module ActiveRecord
end
end
- def new_column(field, default, sql_type, null, collation, extra = "") # :nodoc:
- cast_type = lookup_cast_type(sql_type)
- Column.new(field, default, cast_type, sql_type, null, collation, strict_mode?, extra)
- end
-
def error_number(exception)
exception.error_number if exception.respond_to?(:error_number)
end
diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
index bf09bfe217..acf4015672 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -66,35 +66,6 @@ module ActiveRecord
# * <tt>:sslcipher</tt> - Necessary to use MySQL with an SSL connection.
#
class MysqlAdapter < AbstractMysqlAdapter
-
- class Column < AbstractMysqlAdapter::Column #:nodoc:
- def self.string_to_time(value)
- return super unless Mysql::Time === value
- new_time(
- value.year,
- value.month,
- value.day,
- value.hour,
- value.minute,
- value.second,
- value.second_part)
- end
-
- def self.string_to_dummy_time(v)
- return super unless Mysql::Time === v
- new_time(2000, 01, 01, v.hour, v.minute, v.second, v.second_part)
- end
-
- def self.string_to_date(v)
- return super unless Mysql::Time === v
- new_date(v.year, v.month, v.day)
- end
-
- def adapter
- MysqlAdapter
- end
- end
-
ADAPTER_NAME = 'MySQL'
class StatementPool < ConnectionAdapters::StatementPool
@@ -156,11 +127,6 @@ module ActiveRecord
end
end
- def new_column(field, default, sql_type, null, collation, extra = "") # :nodoc:
- cast_type = lookup_cast_type(sql_type)
- Column.new(field, default, cast_type, sql_type, null, collation, strict_mode?, extra)
- end
-
def error_number(exception) # :nodoc:
exception.errno if exception.respond_to?(:errno)
end
@@ -297,85 +263,37 @@ module ActiveRecord
end
module Fields
- class Type
- def type; end
-
- def type_cast_for_write(value)
- value
- end
- end
-
- class Identity < Type
- def type_cast(value); value; end
- end
-
- class Integer < Type
- def type_cast(value)
- return if value.nil?
-
- value.to_i rescue value ? 1 : 0
+ class DateTime < Type::DateTime
+ def cast_value(value)
+ if Mysql::Time === value
+ new_time(
+ value.year,
+ value.month,
+ value.day,
+ value.hour,
+ value.minute,
+ value.second,
+ value.second_part)
+ else
+ super
+ end
end
end
- class Date < Type
- def type; :date; end
-
- def type_cast(value)
- return if value.nil?
-
- # FIXME: probably we can improve this since we know it is mysql
- # specific
- ConnectionAdapters::Column.value_to_date value
- end
- end
-
- class DateTime < Type
- def type; :datetime; end
-
- def type_cast(value)
- return if value.nil?
-
- # FIXME: probably we can improve this since we know it is mysql
- # specific
- ConnectionAdapters::Column.string_to_time value
- end
- end
-
- class Time < Type
- def type; :time; end
-
- def type_cast(value)
- return if value.nil?
-
- # FIXME: probably we can improve this since we know it is mysql
- # specific
- ConnectionAdapters::Column.string_to_dummy_time value
- end
- end
-
- class Float < Type
- def type; :float; end
-
- def type_cast(value)
- return if value.nil?
-
- value.to_f
- end
- end
-
- class Decimal < Type
- def type_cast(value)
- return if value.nil?
-
- ConnectionAdapters::Column.value_to_decimal value
- end
- end
-
- class Boolean < Type
- def type_cast(value)
- return if value.nil?
-
- ConnectionAdapters::Column.value_to_boolean value
+ class Time < Type::Time
+ def cast_value(value)
+ if Mysql::Time === value
+ new_time(
+ 2000,
+ 01,
+ 01,
+ value.hour,
+ value.minute,
+ value.second,
+ value.second_part)
+ else
+ super
+ end
end
end
@@ -395,29 +313,35 @@ module ActiveRecord
if field.type == Mysql::Field::TYPE_TINY && field.length > 1
TYPES[Mysql::Field::TYPE_LONG]
else
- TYPES.fetch(field.type) { Fields::Identity.new }
+ TYPES.fetch(field.type) { Type::Value.new }
end
end
- register_type Mysql::Field::TYPE_TINY, Fields::Boolean.new
- register_type Mysql::Field::TYPE_LONG, Fields::Integer.new
+ register_type Mysql::Field::TYPE_TINY, Type::Boolean.new
+ register_type Mysql::Field::TYPE_LONG, Type::Integer.new
alias_type Mysql::Field::TYPE_LONGLONG, Mysql::Field::TYPE_LONG
alias_type Mysql::Field::TYPE_NEWDECIMAL, Mysql::Field::TYPE_LONG
- register_type Mysql::Field::TYPE_VAR_STRING, Fields::Identity.new
- register_type Mysql::Field::TYPE_BLOB, Fields::Identity.new
- register_type Mysql::Field::TYPE_DATE, Fields::Date.new
+ register_type Mysql::Field::TYPE_VAR_STRING, Type::Value.new
+ register_type Mysql::Field::TYPE_BLOB, Type::Value.new
+ register_type Mysql::Field::TYPE_DATE, Type::Date.new
register_type Mysql::Field::TYPE_DATETIME, Fields::DateTime.new
register_type Mysql::Field::TYPE_TIME, Fields::Time.new
- register_type Mysql::Field::TYPE_FLOAT, Fields::Float.new
+ register_type Mysql::Field::TYPE_FLOAT, Type::Float.new
Mysql::Field.constants.grep(/TYPE/).map { |class_name|
Mysql::Field.const_get class_name
}.reject { |const| TYPES.key? const }.each do |const|
- register_type const, Fields::Identity.new
+ register_type const, Type::Value.new
end
end
+ def initialize_type_map(m) # :nodoc:
+ super
+ m.register_type %r(datetime)i, Fields::DateTime.new
+ m.register_type %r(time)i, Fields::Time.new
+ end
+
def exec_without_stmt(sql, name = 'SQL') # :nodoc:
# Some queries, like SHOW CREATE TABLE don't work through the prepared
# statement API. For those queries, we need to use this method. :'(
@@ -433,7 +357,7 @@ module ActiveRecord
fields << field_name
if field.decimals > 0
- types[field_name] = Fields::Decimal.new
+ types[field_name] = Type::Decimal.new
else
types[field_name] = Fields.find_type field
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb b/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb
index a14381acb6..0cbedb0987 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb
@@ -13,19 +13,6 @@ module ActiveRecord
string.split(',').map{ |v| Float(v) }
end
- def string_to_time(string) # :nodoc:
- return string unless String === string
-
- case string
- when 'infinity'; Float::INFINITY
- when '-infinity'; -Float::INFINITY
- when / BC$/
- super("-" + string.sub(/ BC$/, ""))
- else
- super
- end
- end
-
def string_to_bit(value) # :nodoc:
case value
when /^0x/i
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
index 1dd8acc257..e5118b5427 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
@@ -123,13 +123,6 @@ module ActiveRecord
end
end
- def type_cast(value)
- return if value.nil?
- return super if encoded?
-
- @oid_type.type_cast value
- end
-
def accessor
@oid_type.accessor
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
index 90bf6c6d1a..94afc3aec5 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
@@ -2,43 +2,21 @@ module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module OID # :nodoc:
- class Type < Type::Value
+ module Infinity
def infinity(options = {})
- ::Float::INFINITY * (options[:negative] ? -1 : 1)
+ options[:negative] ? -::Float::INFINITY : ::Float::INFINITY
end
end
- class Identity < Type
- def type_cast(value)
- value
- end
- end
-
- class String < Type
- def type; :string end
-
- def type_cast(value)
- return if value.nil?
-
- value.to_s
- end
- end
-
- class SpecializedString < OID::String
- def type; @type end
+ class SpecializedString < Type::String
+ attr_reader :type
def initialize(type)
@type = type
end
end
- class Text < OID::String
- def type; :text end
- end
-
- class Bit < Type
- def type; :string end
-
+ class Bit < Type::String
def type_cast(value)
if ::String === value
ConnectionAdapters::PostgreSQLColumn.string_to_bit value
@@ -48,20 +26,16 @@ module ActiveRecord
end
end
- class Bytea < Type
- def type; :binary end
-
- def type_cast(value)
- return if value.nil?
+ class Bytea < Type::Binary
+ def cast_value(value)
PGconn.unescape_bytea value
end
end
- class Money < Type
- def type; :decimal end
+ class Money < Type::Decimal
+ include Infinity
- def type_cast(value)
- return if value.nil?
+ def cast_value(value)
return value unless ::String === value
# Because money output is formatted according to the locale, there are two
@@ -80,11 +54,11 @@ module ActiveRecord
value.gsub!(/[^-\d,]/, '').sub!(/,/, '.')
end
- ConnectionAdapters::Column.value_to_decimal value
+ super(value)
end
end
- class Vector < Type
+ class Vector < Type::Value
attr_reader :delim, :subtype
# +delim+ corresponds to the `typdelim` column in the pg_types
@@ -103,9 +77,7 @@ module ActiveRecord
end
end
- class Point < Type
- def type; :string end
-
+ class Point < Type::String
def type_cast(value)
if ::String === value
ConnectionAdapters::PostgreSQLColumn.string_to_point value
@@ -115,10 +87,10 @@ module ActiveRecord
end
end
- class Array < Type
- def type; @subtype.type end
-
+ class Array < Type::Value
attr_reader :subtype
+ delegate :type, to: :subtype
+
def initialize(subtype)
@subtype = subtype
end
@@ -132,7 +104,7 @@ module ActiveRecord
end
end
- class Range < Type
+ class Range < Type::Value
attr_reader :subtype, :type
def initialize(subtype, type)
@@ -158,8 +130,8 @@ module ActiveRecord
infinity?(value) ? value : @subtype.type_cast(value)
end
- def type_cast(value)
- return if value.nil? || value == 'empty'
+ def cast_value(value)
+ return if value == 'empty'
return value if value.is_a?(::Range)
extracted = extract_bounds(value)
@@ -181,109 +153,77 @@ This is not reliable and will be removed in the future.
end
end
- class Integer < Type
- def type; :integer end
-
- def type_cast(value)
- return if value.nil?
-
- ConnectionAdapters::Column.value_to_integer value
- end
- end
-
- class Boolean < Type
- def type; :boolean end
-
- def type_cast(value)
- return if value.nil?
-
- ConnectionAdapters::Column.value_to_boolean value
- end
+ class Integer < Type::Integer
+ include Infinity
end
- class DateTime < Type
- def type; :datetime; end
-
- def type_cast(value)
- return if value.nil?
+ class DateTime < Type::DateTime
+ include Infinity
- # FIXME: probably we can improve this since we know it is PG
- # specific
- ConnectionAdapters::PostgreSQLColumn.string_to_time value
+ def cast_value(value)
+ if value.is_a?(::String)
+ case value
+ when 'infinity' then ::Float::INFINITY
+ when '-infinity' then -::Float::INFINITY
+ when / BC$/
+ super("-" + value.sub(/ BC$/, ""))
+ else
+ super
+ end
+ else
+ value
+ end
end
end
- class Date < Type
- def type; :date; end
-
- def type_cast(value)
- return if value.nil?
-
- # FIXME: probably we can improve this since we know it is PG
- # specific
- ConnectionAdapters::Column.value_to_date value
- end
+ class Date < Type::Date
+ include Infinity
end
- class Time < Type
- def type; :time end
-
- def type_cast(value)
- return if value.nil?
-
- # FIXME: probably we can improve this since we know it is PG
- # specific
- ConnectionAdapters::Column.string_to_dummy_time value
- end
+ class Time < Type::Time
+ include Infinity
end
- class Float < Type
- def type; :float end
+ class Float < Type::Float
+ include Infinity
def type_cast(value)
case value
- when nil; nil
- when 'Infinity'; ::Float::INFINITY
- when '-Infinity'; -::Float::INFINITY
- when 'NaN'; ::Float::NAN
- else
- value.to_f
+ when nil then nil
+ when 'Infinity' then ::Float::INFINITY
+ when '-Infinity' then -::Float::INFINITY
+ when 'NaN' then ::Float::NAN
+ else value.to_f
end
end
end
- class Decimal < Type
- def type; :decimal end
-
- def type_cast(value)
- return if value.nil?
-
- ConnectionAdapters::Column.value_to_decimal value
- end
-
+ class Decimal < Type::Decimal
def infinity(options = {})
BigDecimal.new("Infinity") * (options[:negative] ? -1 : 1)
end
end
- class Enum < Type
- def type; :enum end
+ class Enum < Type::Value
+ def type
+ :enum
+ end
def type_cast(value)
value.to_s
end
end
- class Hstore < Type
- def type; :hstore end
+ class Hstore < Type::Value
+ def type
+ :hstore
+ end
def type_cast_for_write(value)
ConnectionAdapters::PostgreSQLColumn.hstore_to_string value
end
- def type_cast(value)
- return if value.nil?
-
+ def cast_value(value)
ConnectionAdapters::PostgreSQLColumn.string_to_hstore value
end
@@ -292,28 +232,32 @@ This is not reliable and will be removed in the future.
end
end
- class Cidr < Type
- def type; :cidr end
- def type_cast(value)
- return if value.nil?
+ class Cidr < Type::Value
+ def type
+ :cidr
+ end
+ def cast_value(value)
ConnectionAdapters::PostgreSQLColumn.string_to_cidr value
end
end
+
class Inet < Cidr
- def type; :inet end
+ def type
+ :inet
+ end
end
- class Json < Type
- def type; :json end
+ class Json < Type::Value
+ def type
+ :json
+ end
def type_cast_for_write(value)
ConnectionAdapters::PostgreSQLColumn.json_to_string value
end
- def type_cast(value)
- return if value.nil?
-
+ def cast_value(value)
ConnectionAdapters::PostgreSQLColumn.string_to_json value
end
@@ -322,8 +266,11 @@ This is not reliable and will be removed in the future.
end
end
- class Uuid < Type
- def type; :uuid end
+ class Uuid < Type::Value
+ def type
+ :uuid
+ end
+
def type_cast(value)
value.presence
end
@@ -442,7 +389,7 @@ This is not reliable and will be removed in the future.
# type_map is then dynamically built with oids as the key and type
# objects as values.
NAMES = Hash.new { |h,k| # :nodoc:
- h[k] = OID::Identity.new
+ h[k] = Type::Value.new
}
# Register an OID type named +name+ with a typecasting object in
@@ -469,12 +416,12 @@ This is not reliable and will be removed in the future.
register_type 'numeric', OID::Decimal.new
register_type 'float4', OID::Float.new
alias_type 'float8', 'float4'
- register_type 'text', OID::Text.new
- register_type 'varchar', OID::String.new
+ register_type 'text', Type::Text.new
+ register_type 'varchar', Type::String.new
alias_type 'char', 'varchar'
alias_type 'name', 'varchar'
alias_type 'bpchar', 'varchar'
- register_type 'bool', OID::Boolean.new
+ register_type 'bool', Type::Boolean.new
register_type 'bit', OID::Bit.new
alias_type 'varbit', 'bit'
register_type 'timestamp', OID::DateTime.new
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 39fa75518b..f46af35f55 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -545,7 +545,7 @@ module ActiveRecord
type_map.fetch(oid, fmod) {
warn "unknown OID #{oid}: failed to recognize type of '#{column_name}'. It will be treated as String."
- type_map[oid] = OID::Identity.new
+ type_map[oid] = Type::Value.new
}
end
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index 03ff0d4ead..a5e2619cb8 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -41,14 +41,12 @@ module ActiveRecord
end
module ConnectionAdapters #:nodoc:
- class SQLite3Column < Column #:nodoc:
- class << self
- def binary_to_string(value)
- if value.encoding != Encoding::ASCII_8BIT
- value = value.force_encoding(Encoding::ASCII_8BIT)
- end
- value
+ class SQLite3Binary < Type::Binary # :nodoc:
+ def cast_value(value)
+ if value.encoding != Encoding::ASCII_8BIT
+ value = value.force_encoding(Encoding::ASCII_8BIT)
end
+ value
end
end
@@ -395,7 +393,7 @@ module ActiveRecord
sql_type = field['type']
cast_type = lookup_cast_type(sql_type)
- SQLite3Column.new(field['name'], field['dflt_value'], cast_type, sql_type, field['notnull'].to_i == 0)
+ Column.new(field['name'], field['dflt_value'], cast_type, sql_type, field['notnull'].to_i == 0)
end
end
@@ -502,6 +500,12 @@ module ActiveRecord
end
protected
+
+ def initialize_type_map(m)
+ super
+ m.register_type(/binary/i, SQLite3Binary.new)
+ end
+
def select(sql, name = nil, binds = []) #:nodoc:
exec_query(sql, name, binds)
end
diff --git a/activerecord/lib/active_record/connection_adapters/type.rb b/activerecord/lib/active_record/connection_adapters/type.rb
index 0268e0d569..fbc4cd7e32 100644
--- a/activerecord/lib/active_record/connection_adapters/type.rb
+++ b/activerecord/lib/active_record/connection_adapters/type.rb
@@ -1,4 +1,6 @@
+require 'active_record/connection_adapters/type/time_value'
require 'active_record/connection_adapters/type/value'
+
require 'active_record/connection_adapters/type/binary'
require 'active_record/connection_adapters/type/boolean'
require 'active_record/connection_adapters/type/date'
diff --git a/activerecord/lib/active_record/connection_adapters/type/boolean.rb b/activerecord/lib/active_record/connection_adapters/type/boolean.rb
index 938d227632..c60a980e80 100644
--- a/activerecord/lib/active_record/connection_adapters/type/boolean.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/boolean.rb
@@ -5,6 +5,12 @@ module ActiveRecord
def type
:boolean
end
+
+ private
+
+ def cast_value(value)
+ Column.value_to_boolean(value)
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/type/date.rb b/activerecord/lib/active_record/connection_adapters/type/date.rb
index 1632f3c8f4..9208da6efe 100644
--- a/activerecord/lib/active_record/connection_adapters/type/date.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/date.rb
@@ -5,6 +5,12 @@ module ActiveRecord
def type
:date
end
+
+ private
+
+ def cast_value(value)
+ Column.value_to_date(value)
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/type/date_time.rb b/activerecord/lib/active_record/connection_adapters/type/date_time.rb
index 1485fd3d80..757553cd68 100644
--- a/activerecord/lib/active_record/connection_adapters/type/date_time.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/date_time.rb
@@ -2,9 +2,17 @@ module ActiveRecord
module ConnectionAdapters
module Type
class DateTime < Value # :nodoc:
+ include TimeValue
+
def type
:datetime
end
+
+ private
+
+ def cast_value(string)
+ Column.string_to_time(string)
+ 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 5b39ea9e2f..9581cd5964 100644
--- a/activerecord/lib/active_record/connection_adapters/type/decimal.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/decimal.rb
@@ -5,6 +5,12 @@ module ActiveRecord
def type
:decimal
end
+
+ private
+
+ def cast_value(value)
+ Column.value_to_decimal(value)
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/type/float.rb b/activerecord/lib/active_record/connection_adapters/type/float.rb
index 089169e7c9..2d436d4aa3 100644
--- a/activerecord/lib/active_record/connection_adapters/type/float.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/float.rb
@@ -5,6 +5,12 @@ module ActiveRecord
def type
:float
end
+
+ private
+
+ def cast_value(value)
+ value.to_f
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/type/integer.rb b/activerecord/lib/active_record/connection_adapters/type/integer.rb
index 5510a11bd4..b839e043ad 100644
--- a/activerecord/lib/active_record/connection_adapters/type/integer.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/integer.rb
@@ -5,6 +5,12 @@ module ActiveRecord
def type
:integer
end
+
+ private
+
+ def cast_value(value)
+ Column.value_to_integer(value)
+ 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 0feb4299f5..d6c1c64834 100644
--- a/activerecord/lib/active_record/connection_adapters/type/string.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/string.rb
@@ -5,6 +5,16 @@ module ActiveRecord
def type
:string
end
+
+ private
+
+ def cast_value(value)
+ case value
+ when true then "1"
+ when false then "0"
+ else value.to_s
+ end
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/type/time.rb b/activerecord/lib/active_record/connection_adapters/type/time.rb
index a3a687a8ad..b621e8f39c 100644
--- a/activerecord/lib/active_record/connection_adapters/type/time.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/time.rb
@@ -2,9 +2,17 @@ module ActiveRecord
module ConnectionAdapters
module Type
class Time < Value # :nodoc:
+ include TimeValue
+
def type
:time
end
+
+ private
+
+ def cast_value(value)
+ Column.string_to_dummy_time(value)
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/type/time_value.rb b/activerecord/lib/active_record/connection_adapters/type/time_value.rb
new file mode 100644
index 0000000000..d9564d7f48
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/type/time_value.rb
@@ -0,0 +1,24 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module Type
+ module TimeValue # :nodoc:
+ private
+
+ def new_time(year, mon, mday, hour, min, sec, microsec, offset = nil)
+ # Treat 0000-00-00 00:00:00 as nil.
+ return if year.nil? || (year == 0 && mon == 0 && mday == 0)
+
+ if offset
+ time = ::Time.utc(year, mon, mday, hour, min, sec, microsec) rescue nil
+ return unless time
+
+ time -= offset
+ Base.default_timezone == :utc ? time : time.getlocal
+ else
+ ::Time.public_send(Base.default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/type/value.rb b/activerecord/lib/active_record/connection_adapters/type/value.rb
index f7d7b9351b..a83f0e652d 100644
--- a/activerecord/lib/active_record/connection_adapters/type/value.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/value.rb
@@ -3,6 +3,16 @@ module ActiveRecord
module Type
class Value # :nodoc:
def type; end
+
+ def type_cast(value)
+ cast_value(value) unless value.nil?
+ end
+
+ private
+
+ def cast_value(value)
+ value
+ end
end
end
end