Mike Bayer avatar Mike Bayer committed 7699a10

Fixed a regression from 0.7 caused by this ticket, which
made the check for recursion overflow in self-referential
eager joining too loose, missing a particular circumstance
where a subclass had lazy="joined" or "subquery" configured
and the load was a "with_polymorphic" against the base.
[ticket:2481]

Comments (0)

Files changed (3)

doc/build/changelog/changelog_08.rst

 
     .. change::
       :tags: bug, orm
+      :tickets: 2481
+
+      Fixed a regression from 0.7 caused by this ticket, which
+      made the check for recursion overflow in self-referential
+      eager joining too loose, missing a particular circumstance
+      where a subclass had lazy="joined" or "subquery" configured
+      and the load was a "with_polymorphic" against the base.
+
+    .. change::
+      :tags: bug, orm
       :tickets: 2718
 
       Fixed a regression from 0.7 where the contextmanager feature

lib/sqlalchemy/orm/util.py

             yield path[i], path[i + 1]
 
     def contains_mapper(self, mapper):
-        return mapper in self.path
+        for path_mapper in [
+            self.path[i] for i in range(0, len(self.path), 2)
+        ]:
+            if isinstance(path_mapper, mapperlib.Mapper) and \
+                path_mapper.isa(mapper):
+                return True
+        else:
+            return False
 
     def contains(self, reg, key):
         return (key, self.path) in reg._attributes

test/orm/test_eager_relations.py

         d = session.query(Director).options(joinedload('*')).first()
         assert len(list(session)) == 3
 
-
+class CyclicalInheritingEagerTestThree(fixtures.DeclarativeMappedTest,
+                        testing.AssertsCompiledSQL):
+    __dialect__ = 'default'
+
+    @classmethod
+    def setup_classes(cls):
+        Base = cls.DeclarativeBasic
+        class PersistentObject(Base):
+            __tablename__ = 'persistent'
+            id = Column(Integer, primary_key=True,
+                    test_needs_autoincrement=True)
+
+            __mapper_args__ = {'with_polymorphic': "*"}
+
+        class Director(PersistentObject):
+            __tablename__ = 'director'
+            id = Column(Integer, ForeignKey('persistent.id'), primary_key=True)
+            other_id = Column(Integer, ForeignKey('persistent.id'))
+            name = Column(String(50))
+            other = relationship(PersistentObject,
+                            primaryjoin=other_id==PersistentObject.id,
+                            lazy=False)
+            __mapper_args__ = {"inherit_condition": id==PersistentObject.id}
+
+    def test_gen_query_nodepth(self):
+        PersistentObject = self.classes.PersistentObject
+        sess = create_session()
+        self.assert_compile(
+            sess.query(PersistentObject),
+            "SELECT persistent.id AS persistent_id, director.id AS director_id,"
+            " director.other_id AS director_other_id, "
+            "director.name AS director_name FROM persistent "
+            "LEFT OUTER JOIN director ON director.id = persistent.id"
+        )
+
+    def test_gen_query_depth(self):
+        PersistentObject = self.classes.PersistentObject
+        Director = self.classes.Director
+        sess = create_session()
+        self.assert_compile(
+            sess.query(PersistentObject).options(joinedload(Director.other, join_depth=1)),
+            "SELECT persistent.id AS persistent_id, director.id AS director_id, "
+            "director.other_id AS director_other_id, "
+            "director.name AS director_name, anon_1.persistent_id AS "
+            "anon_1_persistent_id, anon_1.director_id AS anon_1_director_id, "
+            "anon_1.director_other_id AS anon_1_director_other_id, "
+            "anon_1.director_name AS anon_1_director_name "
+            "FROM persistent LEFT OUTER JOIN director ON director.id = persistent.id "
+            "LEFT OUTER JOIN (SELECT persistent.id AS persistent_id, "
+                "director.id AS director_id, director.other_id AS director_other_id, "
+                "director.name AS director_name "
+                "FROM persistent LEFT OUTER JOIN director ON "
+                "director.id = persistent.id) "
+            "AS anon_1 ON director.other_id = anon_1.persistent_id"
+        )
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.