diff --git a/CHANGELOG b/CHANGELOG index c92def288..cfcdad2b4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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) diff --git a/lib/sequel/plugins/tactical_eager_loading.rb b/lib/sequel/plugins/tactical_eager_loading.rb index 671438fca..181e3bda5 100644 --- a/lib/sequel/plugins/tactical_eager_loading.rb +++ b/lib/sequel/plugins/tactical_eager_loading.rb @@ -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 diff --git a/spec/extensions/tactical_eager_loading_spec.rb b/spec/extensions/tactical_eager_loading_spec.rb index 9da797ac2..c99f46f13 100644 --- a/spec/extensions/tactical_eager_loading_spec.rb +++ b/spec/extensions/tactical_eager_loading_spec.rb @@ -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