[Sqlalchemy-tickets] Issue #3963: aliased vs. non-aliased specificity in loader options on lazy loa
Brought to you by:
zzzeek
From: Michael B. <iss...@bi...> - 2017-04-10 18:14:32
|
New issue 3963: aliased vs. non-aliased specificity in loader options on lazy load https://bitbucket.org/zzzeek/sqlalchemy/issues/3963/aliased-vs-non-aliased-specificity-in Michael Bayer: all of these cases emit eager load for B.cs when they are specified as lazyload: ``` #!python from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class A(Base): __tablename__ = 'a' id = Column(Integer, primary_key=True) bs = relationship("B") class B(Base): __tablename__ = 'b' id = Column(Integer, primary_key=True) a_id = Column(ForeignKey('a.id')) cs = relationship("C") class C(Base): __tablename__ = 'c' id = Column(Integer, primary_key=True) b_id = Column(ForeignKey('b.id')) e = create_engine("sqlite://", echo=True) Base.metadata.create_all(e) s = Session(e) s.add(A(bs=[B(cs=[C()])])) s.add(A()) s.commit() s.close() aa = aliased(A) q = s.query(aa, A).filter(aa.id == 1).filter(A.id == 2).options(joinedload(A.bs).joinedload(B.cs)) for a, real_a in q: for b in a.bs: # was eager loaded, when should lazy load for c in b.cs: print c s.close() print "--------------------------------" aa = aliased(A) q = s.query(aa, A).filter(aa.id == 1).filter(A.id == 2).options(defaultload(A.bs).joinedload(B.cs)) for a, real_a in q: for b in a.bs: # was eager loaded, when should lazy load for c in b.cs: print c s.close() print "--------------------------------" aa = aliased(A) q = s.query(A, aa).filter(A.id == 1).filter(aa.id == 2).options(defaultload(aa.bs).joinedload(B.cs)) for a, real_a in q: for b in a.bs: # was eager loaded, when should lazy load for c in b.cs: print c ``` _chop_path is important here, this fixes: ``` #!diff diff --git a/lib/sqlalchemy/orm/strategy_options.py b/lib/sqlalchemy/orm/strategy_options.py index bae2b73..60ed2be 100644 --- a/lib/sqlalchemy/orm/strategy_options.py +++ b/lib/sqlalchemy/orm/strategy_options.py @@ -376,7 +376,8 @@ class _UnboundLoad(Load): _WILDCARD_TOKEN,) and c_token != p_prop.key: return None elif isinstance(c_token, PropComparator): - if c_token.property is not p_prop: + if c_token.property is not p_prop or \ + c_token._parententity is not p_mapper: return None else: i += 1 ``` |