Skip to content

Commit

Permalink
Limit tactically eager loading to objects that have the same associat…
Browse files Browse the repository at this point in the history
…ion reflection

In cases where inheritance is used, a subclass could define an
association with the same name differently than a parent class.
In this case, attempting to eager load may cause problems.
  • Loading branch information
jeremyevans committed Jun 21, 2024
1 parent a687bdd commit 68279d0
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 2 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
=== master

* Limit tactically eager loading to objects that have the same association reflection (jeremyevans) (#2181)

* Fix race condition in threaded/sharded_threaded connection pools that could cause stalls (jeremyevans)

* Emulate dropping a unique column or a column that is part of an index on SQLite 3.35.0+ (jeremyevans) (#2176)
Expand Down
8 changes: 6 additions & 2 deletions lib/sequel/plugins/tactical_eager_loading.rb
Original file line number Diff line number Diff line change
Expand Up @@ -158,15 +158,19 @@ def load_associated_objects(opts, dynamic_opts=OPTS, &block)
end

# Filter the objects used when tactical eager loading.
# By default, this removes frozen objects and objects that alreayd have the association loaded
# By default, this removes frozen objects and objects that alreayd have the association loaded,
# as well as objects where the reflection for the association is not the same as the receiver's
# reflection for the association.
def _filter_tactical_eager_load_objects(opts)
objects = defined?(super) ? super : retrieved_with.dup
name = opts[:name]
if opts[:eager_reload]
objects.reject!(&:frozen?)
else
name = opts[:name]
objects.reject!{|x| x.frozen? || x.associations.include?(name)}
end
reflection = self.class.association_reflection(name)
objects.select!{|x| x.class.association_reflection(name).equal?(reflection)}
objects
end
end
Expand Down
6 changes: 6 additions & 0 deletions spec/extensions/tactical_eager_loading_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@ class ::TacticalEagerLoadingModel < Sequel::Model(:t)
sql_match('SELECT * FROM t', 'SELECT * FROM t WHERE (t.id IN (101, 102))')
objs[0].associations.keys.must_equal [:parent]
objs[1].associations.keys.must_equal [:parent]

c.many_to_one :parent, :class=>@c, :key=>:parent_id
objs = @c.dataset.with_row_proc(proc{|r| (r[:parent_id] == 101 ? c : @c).call(r)}).all{|x| x.parent if x.is_a?(c)}
sql_match('SELECT * FROM t', 'SELECT * FROM t WHERE (t.id IN (101))')
objs[0].associations.keys.must_equal [:parent]
objs[1].associations.keys.must_equal []
end

it "association getter methods should not eagerly load the association if an instance is frozen" do
Expand Down

0 comments on commit 68279d0

Please sign in to comment.