Eager loading/preloading should be worked regardless of large number of records
Since 213796f
, bind params are used for IN clause if enabled prepared
statements.
Unfortunately, most adapter modules have a limitation for # of bind
params (mysql2 65535, pg 65535, sqlite3 250000). So if eager loading
large number of records at once, that query couldn't be sent to the
database.
Since eager loading/preloading queries are auto-generated by Active
Record itself, so it should be worked regardless of large number of
records like as before.
Fixes #33702.
This commit is contained in:
parent
82ac7555ab
commit
a50eacb03c
|
@ -57,10 +57,14 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def build_bind_attribute(column_name, value)
|
||||
attr = Relation::QueryAttribute.new(column_name.to_s, value, table.type(column_name))
|
||||
attr = build_query_attribute(column_name, value)
|
||||
Arel::Nodes::BindParam.new(attr)
|
||||
end
|
||||
|
||||
def build_query_attribute(column_name, value)
|
||||
Relation::QueryAttribute.new(column_name.to_s, value, table.type(column_name))
|
||||
end
|
||||
|
||||
protected
|
||||
def expand_from_hash(attributes)
|
||||
return ["1=0"] if attributes.empty?
|
||||
|
|
|
@ -21,10 +21,11 @@ module ActiveRecord
|
|||
when 0 then NullPredicate
|
||||
when 1 then predicate_builder.build(attribute, values.first)
|
||||
else
|
||||
bind_values = values.map do |v|
|
||||
predicate_builder.build_bind_attribute(attribute.name, v)
|
||||
end
|
||||
attribute.in(bind_values)
|
||||
values.map! do |v|
|
||||
attr = predicate_builder.build_query_attribute(attribute.name, v)
|
||||
attr.value_for_database if attr.boundable?
|
||||
end.compact!
|
||||
values.empty? ? NullPredicate : attribute.in(values)
|
||||
end
|
||||
|
||||
unless nils.empty?
|
||||
|
|
|
@ -18,6 +18,7 @@ require "models/job"
|
|||
require "models/subscriber"
|
||||
require "models/subscription"
|
||||
require "models/book"
|
||||
require "models/citation"
|
||||
require "models/developer"
|
||||
require "models/computer"
|
||||
require "models/project"
|
||||
|
@ -29,6 +30,18 @@ require "models/sponsor"
|
|||
require "models/mentor"
|
||||
require "models/contract"
|
||||
|
||||
class EagerLoadingTooManyIdsTest < ActiveRecord::TestCase
|
||||
fixtures :citations
|
||||
|
||||
def test_preloading_too_many_ids
|
||||
assert_equal Citation.count, Citation.preload(:citations).to_a.size
|
||||
end
|
||||
|
||||
def test_eager_loading_too_may_ids
|
||||
assert_equal Citation.count, Citation.eager_load(:citations).offset(0).size
|
||||
end
|
||||
end
|
||||
|
||||
class EagerAssociationTest < ActiveRecord::TestCase
|
||||
fixtures :posts, :comments, :authors, :essays, :author_addresses, :categories, :categories_posts,
|
||||
:companies, :accounts, :tags, :taggings, :people, :readers, :categorizations,
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
<% 65536.times do |i| %>
|
||||
fixture_no_<%= i %>:
|
||||
id: <%= i %>
|
||||
<% end %>
|
|
@ -2,4 +2,5 @@
|
|||
|
||||
class Citation < ActiveRecord::Base
|
||||
belongs_to :reference_of, class_name: "Book", foreign_key: :book2_id
|
||||
has_many :citations
|
||||
end
|
||||
|
|
|
@ -160,6 +160,7 @@ ActiveRecord::Schema.define do
|
|||
create_table :citations, force: true do |t|
|
||||
t.column :book1_id, :integer
|
||||
t.column :book2_id, :integer
|
||||
t.references :citation
|
||||
end
|
||||
|
||||
create_table :clubs, force: true do |t|
|
||||
|
|
Loading…
Reference in New Issue