提交 c196ca72 编写于 作者: R Ryuta Kamizono

Ensure `StatementCache#execute` never raises `RangeError`

Since 31ffbf8d, finder methods no longer raise `RangeError`. So
`StatementCache#execute` is the only place to raise the exception for
finder queries.

`StatementCache` is used for simple equality queries in the codebase.
This means that if `StatementCache#execute` raises `RangeError`, the
result could always be regarded as empty.
So `StatementCache#execute` just return nil in that range error case,
and treat that as empty in the caller side, then we can avoid catching
the exception in much places.
上级 31ffbf8d
......@@ -190,9 +190,7 @@ def find_target
end
binds = AssociationScope.get_bind_values(owner, reflection.chain)
sc.execute(binds, conn) do |record|
set_inverse_instance(record)
end
sc.execute(binds, conn) { |record| set_inverse_instance(record) } || []
end
# The scope for this association.
......
......@@ -37,8 +37,6 @@ def scope_for_create
def find_target
super.first
rescue ::RangeError
nil
end
def replace(record)
......
......@@ -169,15 +169,12 @@ def find(*ids) # :nodoc:
where(key => params.bind).limit(1)
}
record = statement.execute([id], connection).first
record = statement.execute([id], connection)&.first
unless record
raise RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}",
name, primary_key, id)
end
record
rescue ::RangeError
raise RecordNotFound.new("Couldn't find #{name} with an out of range value for '#{primary_key}'",
name, primary_key)
end
def find_by(*args) # :nodoc:
......@@ -201,11 +198,9 @@ def find_by(*args) # :nodoc:
where(wheres).limit(1)
}
begin
statement.execute(hash.values, connection).first
statement.execute(hash.values, connection)&.first
rescue TypeError
raise ActiveRecord::StatementInvalid
rescue ::RangeError
nil
end
end
......
......@@ -132,6 +132,8 @@ def execute(params, connection, &block)
sql = query_builder.sql_for bind_values, connection
klass.find_by_sql(sql, bind_values, preparable: true, &block)
rescue ::RangeError
nil
end
def self.unsupported_value?(value)
......
......@@ -1293,17 +1293,17 @@ def test_belongs_to_with_id_assigning
end
def test_belongs_to_with_out_of_range_value_assigning
model = Class.new(Comment) do
model = Class.new(Author) do
def self.name; "Temp"; end
validates :post, presence: true
validates :author_address, presence: true
end
comment = model.new
comment.post_id = 9223372036854775808 # out of range in the bigint
author = model.new
author.author_address_id = 9223372036854775808 # out of range in the bigint
assert_nil comment.post
assert_not_predicate comment, :valid?
assert_equal [{ error: :blank }], comment.errors.details[:post]
assert_nil author.author_address
assert_not_predicate author, :valid?
assert_equal [{ error: :blank }], author.errors.details[:author_address]
end
def test_polymorphic_with_custom_primary_key
......
......@@ -27,6 +27,7 @@
require "models/minivan"
require "models/speedometer"
require "models/reference"
require "models/job"
require "models/college"
require "models/student"
require "models/pirate"
......@@ -2926,6 +2927,11 @@ def test_create_children_could_be_rolled_back_by_after_save
end
end
def test_has_many_with_out_of_range_value
reference = Reference.create!(id: 2147483648) # out of range in the integer
assert_equal [], reference.ideal_jobs
end
private
def force_signal37_to_load_all_clients_of_firm
......
......@@ -4,6 +4,7 @@ class Reference < ActiveRecord::Base
belongs_to :person
belongs_to :job
has_many :ideal_jobs, class_name: "Job", foreign_key: :ideal_reference_id
has_many :agents_posts_authors, through: :person
class << self; attr_accessor :make_comments; end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册