Skip to content

Commit

Permalink
Translate numeric value out of range to the specific exception
Browse files Browse the repository at this point in the history
Raise `ActiveRecord::RangeError` when values that executed are out of range.
  • Loading branch information
kamipo committed Dec 6, 2016
1 parent cf6c294 commit 49edce3
Show file tree
Hide file tree
Showing 7 changed files with 26 additions and 8 deletions.
Expand Up @@ -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
Expand All @@ -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
Expand Down
Expand Up @@ -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"
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions activerecord/lib/active_record/core.rb
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions activerecord/lib/active_record/errors.rb
Expand Up @@ -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.
Expand Down
8 changes: 4 additions & 4 deletions activerecord/lib/active_record/relation/finder_methods.rb
Expand Up @@ -76,15 +76,15 @@ 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

# Like #find_by, except that if no record is found, raises
# 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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
8 changes: 8 additions & 0 deletions activerecord/test/cases/adapter_test.rb
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb
Expand Up @@ -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
Expand Down

0 comments on commit 49edce3

Please sign in to comment.