Merge "Adapt from "localparent" in joinedloader"

This commit is contained in:
mike bayer
2017-01-09 17:42:03 -05:00
committed by Gerrit Code Review
3 changed files with 86 additions and 3 deletions
+13
View File
@@ -15,6 +15,19 @@
.. include:: changelog_07.rst
:start-line: 5
.. changelog::
:version: 1.0.17
.. change::
:tags: bug, orm
:tickets: 3884
:versions: 1.1.5
Fixed bug involving joined eager loading against multiple entities
when polymorphic inheritance is also in use which would throw
"'NoneType' object has no attribute 'isa'". The issue was introduced
by the fix for :ticket:`3611`.
.. changelog::
:version: 1.0.16
:released: November 15, 2016
+2 -2
View File
@@ -1368,8 +1368,8 @@ class JoinedLoader(AbstractRelationshipLoader):
# name on it.
efm = inspect(adapter.aliased_class).\
_entity_for_mapper(
parentmapper
if parentmapper.isa(self.parent) else self.parent)
localparent
if localparent.isa(self.parent) else self.parent)
# look for our attribute on the adapted entity, else fall back
# to our straight property
+71 -1
View File
@@ -1,6 +1,6 @@
from sqlalchemy.orm import create_session, relationship, mapper, \
contains_eager, joinedload, subqueryload, subqueryload_all,\
Session, aliased, with_polymorphic, joinedload_all
Session, aliased, with_polymorphic, joinedload_all, backref
from sqlalchemy import Integer, String, ForeignKey, select, func
from sqlalchemy.engine import default
@@ -1934,3 +1934,73 @@ class SameNameOnJoined(fixtures.MappedTest):
s.commit()
eq_(s.query(B).count(), 0)
class BetweenSubclassJoinWExtraJoinedLoad(
fixtures.DeclarativeMappedTest,
testing.AssertsCompiledSQL):
"""test for [ticket:3884]"""
run_define_tables = None
__dialect__ = 'default'
@classmethod
def setup_classes(cls):
Base = cls.DeclarativeBasic
class Person(Base):
__tablename__ = 'people'
id = Column(Integer, primary_key=True)
discriminator = Column('type', String(50))
__mapper_args__ = {'polymorphic_on': discriminator}
class Manager(Person):
__tablename__ = 'managers'
__mapper_args__ = {'polymorphic_identity': 'manager'}
id = Column(Integer, ForeignKey('people.id'), primary_key=True)
class Engineer(Person):
__tablename__ = 'engineers'
__mapper_args__ = {'polymorphic_identity': 'engineer'}
id = Column(Integer, ForeignKey('people.id'), primary_key=True)
primary_language = Column(String(50))
manager_id = Column(Integer, ForeignKey('managers.id'))
manager = relationship(
Manager, primaryjoin=(Manager.id == manager_id))
class LastSeen(Base):
__tablename__ = 'seen'
id = Column(Integer, ForeignKey('people.id'), primary_key=True)
timestamp = Column(Integer)
taggable = relationship(
Person, primaryjoin=(Person.id == id),
backref=backref("last_seen", lazy=False))
def test_query(self):
Engineer, Manager = self.classes("Engineer", "Manager")
sess = Session()
# eager join is both from Enginer->LastSeen as well as
# Manager->LastSeen. In the case of Manager->LastSeen,
# Manager is internally aliased, and comes to JoinedEagerLoader
# with no "parent" entity but an adapter.
q = sess.query(Engineer, Manager).join(Engineer.manager)
self.assert_compile(
q,
"SELECT people.type AS people_type, engineers.id AS engineers_id, "
"people.id AS people_id, "
"engineers.primary_language AS engineers_primary_language, "
"engineers.manager_id AS engineers_manager_id, "
"people_1.type AS people_1_type, managers_1.id AS managers_1_id, "
"people_1.id AS people_1_id, seen_1.id AS seen_1_id, "
"seen_1.timestamp AS seen_1_timestamp, seen_2.id AS seen_2_id, "
"seen_2.timestamp AS seen_2_timestamp "
"FROM people JOIN engineers ON people.id = engineers.id "
"JOIN (people AS people_1 JOIN managers AS managers_1 "
"ON people_1.id = managers_1.id) "
"ON managers_1.id = engineers.manager_id LEFT OUTER JOIN "
"seen AS seen_1 ON people.id = seen_1.id LEFT OUTER JOIN "
"seen AS seen_2 ON people_1.id = seen_2.id"
)