summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2015-12-15 14:00:50 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2015-12-15 14:00:50 -0500
commita8ec3491983ed5e68452514b4d52a4347377809f (patch)
tree7692578b83a8c6cade1306f389e3e206eef79319
parentc42725ed54a61d7e5a0931404ee83aa6b94d0aea (diff)
downloadsqlalchemy-a8ec3491983ed5e68452514b4d52a4347377809f.tar.gz
- Fixed regression caused in 1.0.10 by the fix for :ticket:`3593` where
the check added for a polymorphic joinedload from a poly_subclass->class->poly_baseclass connection would fail for the scenario of class->poly_subclass->class. fixes #3611
-rw-r--r--doc/build/changelog/changelog_10.rst10
-rw-r--r--lib/sqlalchemy/orm/strategies.py4
-rw-r--r--test/orm/inheritance/test_relationship.py117
3 files changed, 112 insertions, 19 deletions
diff --git a/doc/build/changelog/changelog_10.rst b/doc/build/changelog/changelog_10.rst
index 950e2a5d9..ab261c615 100644
--- a/doc/build/changelog/changelog_10.rst
+++ b/doc/build/changelog/changelog_10.rst
@@ -20,6 +20,16 @@
.. change::
:tags: bug, orm
+ :tickets: 3611
+ :versions: 1.1.0b1
+
+ Fixed regression caused in 1.0.10 by the fix for :ticket:`3593` where
+ the check added for a polymorphic joinedload from a
+ poly_subclass->class->poly_baseclass connection would fail for the
+ scenario of class->poly_subclass->class.
+
+ .. change::
+ :tags: bug, orm
:tickets: 3610
:versions: 1.1.0b1
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py
index 21152e304..b60e47bb3 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -1330,7 +1330,9 @@ class JoinedLoader(AbstractRelationshipLoader):
# specific mapper's entity before looking for our attribute
# name on it.
efm = inspect(adapter.aliased_class).\
- _entity_for_mapper(self.parent)
+ _entity_for_mapper(
+ parentmapper
+ if parentmapper.isa(self.parent) else self.parent)
# look for our attribute on the adapted entity, else fall back
# to our straight property
diff --git a/test/orm/inheritance/test_relationship.py b/test/orm/inheritance/test_relationship.py
index 5dae7c26f..e75d974d4 100644
--- a/test/orm/inheritance/test_relationship.py
+++ b/test/orm/inheritance/test_relationship.py
@@ -1364,7 +1364,7 @@ class SubClassToSubClassMultiTest(AssertsCompiledSQL, fixtures.MappedTest):
class JoinedloadOverWPolyAliased(
fixtures.DeclarativeMappedTest,
testing.AssertsCompiledSQL):
- """exercise issues in #3593"""
+ """exercise issues in #3593 and #3611"""
run_setup_mappers = 'each'
run_setup_classes = 'each'
@@ -1375,6 +1375,20 @@ class JoinedloadOverWPolyAliased(
def setup_classes(cls):
Base = cls.DeclarativeBasic
+ class Owner(Base):
+ __tablename__ = 'owner'
+
+ id = Column(Integer, primary_key=True)
+ type = Column(String(20))
+
+ __mapper_args__ = {
+ 'polymorphic_on': type,
+ 'with_polymorphic': ('*', None),
+ }
+
+ class SubOwner(Owner):
+ __mapper_args__ = {'polymorphic_identity': 'so'}
+
class Parent(Base):
__tablename__ = 'parent'
@@ -1397,14 +1411,11 @@ class JoinedloadOverWPolyAliased(
child_id = Column(
Integer, ForeignKey('parent.id'), primary_key=True)
- child = relationship(
- Parent,
- primaryjoin=child_id == Parent.id,
- )
-
def _fixture_from_base(self):
Parent = self.classes.Parent
Link = self.classes.Link
+ Link.child = relationship(
+ Parent, primaryjoin=Link.child_id == Parent.id)
Parent.links = relationship(
Link,
@@ -1415,6 +1426,9 @@ class JoinedloadOverWPolyAliased(
def _fixture_from_subclass(self):
Sub1 = self.classes.Sub1
Link = self.classes.Link
+ Parent = self.classes.Parent
+ Link.child = relationship(
+ Parent, primaryjoin=Link.child_id == Parent.id)
Sub1.links = relationship(
Link,
@@ -1422,13 +1436,50 @@ class JoinedloadOverWPolyAliased(
)
return Sub1
+ def _fixture_to_subclass_to_base(self):
+ Owner = self.classes.Owner
+ Parent = self.classes.Parent
+ Sub1 = self.classes.Sub1
+ Link = self.classes.Link
+
+ # Link -> Sub1 -> Owner
+
+ Link.child = relationship(
+ Sub1, primaryjoin=Link.child_id == Sub1.id)
+
+ Parent.owner_id = Column(ForeignKey('owner.id'))
+
+ Parent.owner = relationship(Owner)
+ return Parent
+
+ def _fixture_to_base_to_base(self):
+ Owner = self.classes.Owner
+ Parent = self.classes.Parent
+ Link = self.classes.Link
+
+ # Link -> Parent -> Owner
+
+ Link.child = relationship(
+ Parent, primaryjoin=Link.child_id == Parent.id)
+
+ Parent.owner_id = Column(ForeignKey('owner.id'))
+
+ Parent.owner = relationship(Owner)
+ return Parent
+
def test_from_base(self):
- self._test(self._fixture_from_base)
+ self._test_poly_single_poly(self._fixture_from_base)
def test_from_sub(self):
- self._test(self._fixture_from_subclass)
+ self._test_poly_single_poly(self._fixture_from_subclass)
- def _test(self, fn):
+ def test_to_sub_to_base(self):
+ self._test_single_poly_poly(self._fixture_to_subclass_to_base)
+
+ def test_to_base_to_base(self):
+ self._test_single_poly_poly(self._fixture_to_base_to_base)
+
+ def _test_poly_single_poly(self, fn):
cls = fn()
Link = self.classes.Link
@@ -1448,17 +1499,47 @@ class JoinedloadOverWPolyAliased(
self.assert_compile(
q,
"SELECT parent.id AS parent_id, parent.type AS parent_type, "
- "parent_1.id AS parent_1_id, parent_1.type AS parent_1_type, "
"link_1.parent_id AS link_1_parent_id, "
"link_1.child_id AS link_1_child_id, "
+ "parent_1.id AS parent_1_id, parent_1.type AS parent_1_type, "
"link_2.parent_id AS link_2_parent_id, "
"link_2.child_id AS link_2_child_id "
"FROM parent "
- "LEFT OUTER JOIN link AS link_2 ON parent.id = link_2.parent_id "
+ "LEFT OUTER JOIN link AS link_1 ON parent.id = link_1.parent_id "
"LEFT OUTER JOIN parent "
- "AS parent_1 ON link_2.child_id = parent_1.id "
- "LEFT OUTER JOIN link AS link_1 "
- "ON parent_1.id = link_1.parent_id" + extra
+ "AS parent_1 ON link_1.child_id = parent_1.id "
+ "LEFT OUTER JOIN link AS link_2 "
+ "ON parent_1.id = link_2.parent_id" + extra
+ )
+
+ def _test_single_poly_poly(self, fn):
+ parent_cls = fn()
+ Link = self.classes.Link
+
+ session = Session()
+ q = session.query(Link).options(
+ joinedload_all(
+ Link.child,
+ parent_cls.owner
+ )
+ )
+
+ if Link.child.property.mapper.class_ is self.classes.Sub1:
+ extra = "AND parent_1.type IN (:type_1) "
+ else:
+ extra = ""
+
+ self.assert_compile(
+ q,
+ "SELECT link.parent_id AS link_parent_id, "
+ "link.child_id AS link_child_id, parent_1.id AS parent_1_id, "
+ "parent_1.type AS parent_1_type, "
+ "parent_1.owner_id AS parent_1_owner_id, "
+ "owner_1.id AS owner_1_id, owner_1.type AS owner_1_type "
+ "FROM link LEFT OUTER JOIN parent AS parent_1 "
+ "ON link.child_id = parent_1.id " + extra +
+ "LEFT OUTER JOIN owner AS owner_1 "
+ "ON owner_1.id = parent_1.owner_id"
)
def test_local_wpoly(self):
@@ -1477,15 +1558,15 @@ class JoinedloadOverWPolyAliased(
self.assert_compile(
q,
"SELECT parent.id AS parent_id, parent.type AS parent_type, "
- "parent_1.id AS parent_1_id, parent_1.type AS parent_1_type, "
"link_1.parent_id AS link_1_parent_id, "
"link_1.child_id AS link_1_child_id, "
+ "parent_1.id AS parent_1_id, parent_1.type AS parent_1_type, "
"link_2.parent_id AS link_2_parent_id, "
"link_2.child_id AS link_2_child_id FROM parent "
- "LEFT OUTER JOIN link AS link_2 ON parent.id = link_2.parent_id "
+ "LEFT OUTER JOIN link AS link_1 ON parent.id = link_1.parent_id "
"LEFT OUTER JOIN parent AS parent_1 "
- "ON link_2.child_id = parent_1.id "
- "LEFT OUTER JOIN link AS link_1 ON parent_1.id = link_1.parent_id"
+ "ON link_1.child_id = parent_1.id "
+ "LEFT OUTER JOIN link AS link_2 ON parent_1.id = link_2.parent_id"
)