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.
This commit is contained in:
parent
31ffbf8d50
commit
c196ca72a0
@ -190,9 +190,7 @@ def find_target
|
|||||||
end
|
end
|
||||||
|
|
||||||
binds = AssociationScope.get_bind_values(owner, reflection.chain)
|
binds = AssociationScope.get_bind_values(owner, reflection.chain)
|
||||||
sc.execute(binds, conn) do |record|
|
sc.execute(binds, conn) { |record| set_inverse_instance(record) } || []
|
||||||
set_inverse_instance(record)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# The scope for this association.
|
# The scope for this association.
|
||||||
|
@ -37,8 +37,6 @@ def scope_for_create
|
|||||||
|
|
||||||
def find_target
|
def find_target
|
||||||
super.first
|
super.first
|
||||||
rescue ::RangeError
|
|
||||||
nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def replace(record)
|
def replace(record)
|
||||||
|
@ -169,15 +169,12 @@ def find(*ids) # :nodoc:
|
|||||||
where(key => params.bind).limit(1)
|
where(key => params.bind).limit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
record = statement.execute([id], connection).first
|
record = statement.execute([id], connection)&.first
|
||||||
unless record
|
unless record
|
||||||
raise RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}",
|
raise RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}",
|
||||||
name, primary_key, id)
|
name, primary_key, id)
|
||||||
end
|
end
|
||||||
record
|
record
|
||||||
rescue ::RangeError
|
|
||||||
raise RecordNotFound.new("Couldn't find #{name} with an out of range value for '#{primary_key}'",
|
|
||||||
name, primary_key)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def find_by(*args) # :nodoc:
|
def find_by(*args) # :nodoc:
|
||||||
@ -201,11 +198,9 @@ def find_by(*args) # :nodoc:
|
|||||||
where(wheres).limit(1)
|
where(wheres).limit(1)
|
||||||
}
|
}
|
||||||
begin
|
begin
|
||||||
statement.execute(hash.values, connection).first
|
statement.execute(hash.values, connection)&.first
|
||||||
rescue TypeError
|
rescue TypeError
|
||||||
raise ActiveRecord::StatementInvalid
|
raise ActiveRecord::StatementInvalid
|
||||||
rescue ::RangeError
|
|
||||||
nil
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -132,6 +132,8 @@ def execute(params, connection, &block)
|
|||||||
sql = query_builder.sql_for bind_values, connection
|
sql = query_builder.sql_for bind_values, connection
|
||||||
|
|
||||||
klass.find_by_sql(sql, bind_values, preparable: true, &block)
|
klass.find_by_sql(sql, bind_values, preparable: true, &block)
|
||||||
|
rescue ::RangeError
|
||||||
|
nil
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.unsupported_value?(value)
|
def self.unsupported_value?(value)
|
||||||
|
@ -1293,17 +1293,17 @@ def test_belongs_to_with_id_assigning
|
|||||||
end
|
end
|
||||||
|
|
||||||
def test_belongs_to_with_out_of_range_value_assigning
|
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
|
def self.name; "Temp"; end
|
||||||
validates :post, presence: true
|
validates :author_address, presence: true
|
||||||
end
|
end
|
||||||
|
|
||||||
comment = model.new
|
author = model.new
|
||||||
comment.post_id = 9223372036854775808 # out of range in the bigint
|
author.author_address_id = 9223372036854775808 # out of range in the bigint
|
||||||
|
|
||||||
assert_nil comment.post
|
assert_nil author.author_address
|
||||||
assert_not_predicate comment, :valid?
|
assert_not_predicate author, :valid?
|
||||||
assert_equal [{ error: :blank }], comment.errors.details[:post]
|
assert_equal [{ error: :blank }], author.errors.details[:author_address]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_polymorphic_with_custom_primary_key
|
def test_polymorphic_with_custom_primary_key
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
require "models/minivan"
|
require "models/minivan"
|
||||||
require "models/speedometer"
|
require "models/speedometer"
|
||||||
require "models/reference"
|
require "models/reference"
|
||||||
|
require "models/job"
|
||||||
require "models/college"
|
require "models/college"
|
||||||
require "models/student"
|
require "models/student"
|
||||||
require "models/pirate"
|
require "models/pirate"
|
||||||
@ -2926,6 +2927,11 @@ def test_create_children_could_be_rolled_back_by_after_save
|
|||||||
end
|
end
|
||||||
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
|
private
|
||||||
|
|
||||||
def force_signal37_to_load_all_clients_of_firm
|
def force_signal37_to_load_all_clients_of_firm
|
||||||
|
@ -4,6 +4,7 @@ class Reference < ActiveRecord::Base
|
|||||||
belongs_to :person
|
belongs_to :person
|
||||||
belongs_to :job
|
belongs_to :job
|
||||||
|
|
||||||
|
has_many :ideal_jobs, class_name: "Job", foreign_key: :ideal_reference_id
|
||||||
has_many :agents_posts_authors, through: :person
|
has_many :agents_posts_authors, through: :person
|
||||||
|
|
||||||
class << self; attr_accessor :make_comments; end
|
class << self; attr_accessor :make_comments; end
|
||||||
|
Loading…
Reference in New Issue
Block a user