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 0e4bc1afcb5c4..84589bd5f26cd 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -738,6 +738,7 @@ def add_options_for_index_columns(quoted_columns, **options) ER_DO_NOT_HAVE_DEFAULT = 1364 ER_NO_REFERENCED_ROW_2 = 1452 ER_DATA_TOO_LONG = 1406 + ER_OUT_OF_RANGE = 1264 ER_LOCK_DEADLOCK = 1213 ER_CANNOT_ADD_FOREIGN = 1215 ER_CANNOT_CREATE_TABLE = 1005 @@ -758,6 +759,8 @@ def translate_exception(exception, message) end when ER_DATA_TOO_LONG ValueTooLong.new(message) + when ER_OUT_OF_RANGE + RangeError.new(message) when ER_NOT_NULL_VIOLATION, ER_DO_NOT_HAVE_DEFAULT NotNullViolation.new(message) when ER_LOCK_DEADLOCK diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 5262141995177..33cdcf9a76100 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -408,6 +408,7 @@ def postgresql_version # See http://www.postgresql.org/docs/current/static/errcodes-appendix.html VALUE_LIMIT_VIOLATION = "22001" + NUMERIC_VALUE_OUT_OF_RANGE = "22003" NOT_NULL_VIOLATION = "23502" FOREIGN_KEY_VIOLATION = "23503" UNIQUE_VIOLATION = "23505" @@ -424,6 +425,8 @@ def translate_exception(exception, message) InvalidForeignKey.new(message) when VALUE_LIMIT_VIOLATION ValueTooLong.new(message) + when NUMERIC_VALUE_OUT_OF_RANGE + RangeError.new(message) when NOT_NULL_VIOLATION NotNullViolation.new(message) when SERIALIZATION_FAILURE diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index 1fbe374adeef9..878d87638dab7 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -194,7 +194,7 @@ def find(*ids) # :nodoc: name, primary_key, id) end record - rescue RangeError + rescue ::RangeError raise RecordNotFound.new("Couldn't find #{name} with an out of range value for '#{primary_key}'", name, primary_key) end @@ -223,7 +223,7 @@ def find_by(*args) # :nodoc: statement.execute(hash.values, self, connection).first rescue TypeError raise ActiveRecord::StatementInvalid - rescue RangeError + rescue ::RangeError nil end end diff --git a/activerecord/lib/active_record/errors.rb b/activerecord/lib/active_record/errors.rb index 507615a222a0a..c812a0510177b 100644 --- a/activerecord/lib/active_record/errors.rb +++ b/activerecord/lib/active_record/errors.rb @@ -159,6 +159,10 @@ class NotNullViolation < StatementInvalid class ValueTooLong < StatementInvalid end + # Raised when values that executed are out of range. + class RangeError < StatementInvalid + end + # Raised when number of bind variables in statement given to +:condition+ key # (for example, when using {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] method) # does not match number of expected values supplied. diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 93c8722aa36e6..5e456452e97e0 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -76,7 +76,7 @@ def find(*args) # Post.find_by "published_at < ?", 2.weeks.ago def find_by(arg, *args) where(arg, *args).take - rescue RangeError + rescue ::RangeError nil end @@ -84,7 +84,7 @@ def find_by(arg, *args) # an ActiveRecord::RecordNotFound error. def find_by!(arg, *args) where(arg, *args).take! - rescue RangeError + rescue ::RangeError raise RecordNotFound.new("Couldn't find #{@klass.name} with an out of range value", @klass.name) end @@ -333,7 +333,7 @@ def exists?(conditions = :none) end connection.select_value(relation, "#{name} Exists", relation.bound_attributes) ? true : false - rescue RangeError + rescue ::RangeError false end @@ -458,7 +458,7 @@ def find_with_ids(*ids) else find_some(ids) end - rescue RangeError + rescue ::RangeError raise RecordNotFound, "Couldn't find #{@klass.name} with an out of range ID" end diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb index 2f0e8d866de48..8de69869a40c8 100644 --- a/activerecord/test/cases/adapter_test.rb +++ b/activerecord/test/cases/adapter_test.rb @@ -226,6 +226,14 @@ def test_value_limit_violations_are_translated_to_specific_exception assert_not_nil error.cause end + + def test_numeric_value_out_of_ranges_are_translated_to_specific_exception + error = assert_raises(ActiveRecord::RangeError) do + Book.connection.create("INSERT INTO books(author_id) VALUES (2147483648)") + end + + assert_not_nil error.cause + end end def test_disable_referential_integrity diff --git a/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb b/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb index 59475ad177427..268800d5384f5 100644 --- a/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb +++ b/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb @@ -34,10 +34,10 @@ class UnsignedType < ActiveRecord::Base assert_raise(ActiveModel::RangeError) do UnsignedType.create(unsigned_bigint: -10) end - assert_raise(ActiveRecord::StatementInvalid) do + assert_raise(ActiveRecord::RangeError) do UnsignedType.create(unsigned_float: -10.0) end - assert_raise(ActiveRecord::StatementInvalid) do + assert_raise(ActiveRecord::RangeError) do UnsignedType.create(unsigned_decimal: -10.0) end end