]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Fixed a regression from 0.7 caused by this ticket, which
authorMike Bayer <mike_mp@zzzcomputing.com>
Mon, 13 May 2013 20:13:15 +0000 (16:13 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Mon, 13 May 2013 20:13:15 +0000 (16:13 -0400)
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]

doc/build/changelog/changelog_08.rst
lib/sqlalchemy/orm/util.py
test/orm/test_eager_relations.py

index aa8f0f8786b168b4b83e4f74ff2f8c9c73e27b65..663d3a40b2cba6d9edd758abce2350313afde472 100644 (file)
@@ -6,6 +6,16 @@
 .. changelog::
     :version: 0.8.2
 
+    .. 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
index 35cb0bdf5dd5198360386ed433db92fa953dcce4..390e83538d34c3b0fa6b780fbd18009f899d1591 100644 (file)
@@ -304,7 +304,14 @@ class PathRegistry(object):
             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
index 2c59491b1768f15ff1c8d5732a3fa99fb774fdc2..bd85e4ce830f01070dc11fa60db1c0292d7b7b6b 100644 (file)
@@ -2663,4 +2663,58 @@ class CyclicalInheritingEagerTestTwo(fixtures.DeclarativeMappedTest,
         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"
+        )