diff options
Diffstat (limited to 'activerecord/lib/active_record/connection_adapters')
20 files changed, 235 insertions, 332 deletions
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 |