From b61a93b44e11046cc28605a8b4d2d17fe89927fd Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Thu, 27 Nov 2014 10:06:49 +0900 Subject: Fix undesirable RangeError by Type::Integer. Add Type::UnsignedInteger. --- .../connection_adapters/abstract_mysql_adapter.rb | 21 ++++++++++++++++----- activerecord/lib/active_record/type.rb | 1 + activerecord/lib/active_record/type/integer.rb | 6 +++++- .../lib/active_record/type/unsigned_integer.rb | 15 +++++++++++++++ 4 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 activerecord/lib/active_record/type/unsigned_integer.rb (limited to 'activerecord/lib') 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 a741314ac6..69582ebb6f 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -656,14 +656,15 @@ module ActiveRecord m.register_type %r(mediumblob)i, Type::Binary.new(limit: 2**24 - 1) m.register_type %r(longtext)i, Type::Text.new(limit: 2**32 - 1) m.register_type %r(longblob)i, Type::Binary.new(limit: 2**32 - 1) - 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) + register_integer_type m, %r(^bigint)i, limit: 8 + register_integer_type m, %r(^int)i, limit: 4 + register_integer_type m, %r(^mediumint)i, limit: 3 + register_integer_type m, %r(^smallint)i, limit: 2 + register_integer_type m, %r(^tinyint)i, limit: 1 + m.alias_type %r(tinyint\(1\))i, 'boolean' if emulate_booleans m.alias_type %r(set)i, 'varchar' m.alias_type %r(year)i, 'integer' @@ -676,6 +677,16 @@ module ActiveRecord end end + def register_integer_type(mapping, key, options) # :nodoc: + mapping.register_type(key) do |sql_type| + if /unsigned/i =~ sql_type + Type::UnsignedInteger.new(options) + else + Type::Integer.new(options) + end + end + end + # MySQL is too stupid to create a temporary table for use subquery, so we have # to give it some prompting in the form of a subsubquery. Ugh! def subquery_for(key, select) diff --git a/activerecord/lib/active_record/type.rb b/activerecord/lib/active_record/type.rb index e5acbbb6b3..250e8d5b23 100644 --- a/activerecord/lib/active_record/type.rb +++ b/activerecord/lib/active_record/type.rb @@ -17,6 +17,7 @@ require 'active_record/type/serialized' require 'active_record/type/string' require 'active_record/type/text' require 'active_record/type/time' +require 'active_record/type/unsigned_integer' require 'active_record/type/type_map' require 'active_record/type/hash_lookup_type_map' diff --git a/activerecord/lib/active_record/type/integer.rb b/activerecord/lib/active_record/type/integer.rb index 750f353472..fc260a081a 100644 --- a/activerecord/lib/active_record/type/integer.rb +++ b/activerecord/lib/active_record/type/integer.rb @@ -5,7 +5,7 @@ module ActiveRecord def initialize(*) super - @range = -max_value...max_value + @range = min_value...max_value end def type @@ -46,6 +46,10 @@ module ActiveRecord limit = self.limit || 4 1 << (limit * 8 - 1) # 8 bits per byte with one bit for sign end + + def min_value + -max_value + end end end end diff --git a/activerecord/lib/active_record/type/unsigned_integer.rb b/activerecord/lib/active_record/type/unsigned_integer.rb new file mode 100644 index 0000000000..ed3e527483 --- /dev/null +++ b/activerecord/lib/active_record/type/unsigned_integer.rb @@ -0,0 +1,15 @@ +module ActiveRecord + module Type + class UnsignedInteger < Integer # :nodoc: + private + + def max_value + super * 2 + end + + def min_value + 0 + end + end + end +end -- cgit v1.2.3