From: Mike Bayer Date: Mon, 13 May 2013 20:13:15 +0000 (-0400) Subject: Fixed a regression from 0.7 caused by this ticket, which X-Git-Tag: rel_0_8_2~74^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f574bcf98de0d30f0a28bf82aae84098157de0f4;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git 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] --- diff --git a/doc/build/changelog/changelog_08.rst b/doc/build/changelog/changelog_08.rst index aa8f0f8786..663d3a40b2 100644 --- a/doc/build/changelog/changelog_08.rst +++ b/doc/build/changelog/changelog_08.rst @@ -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 diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py index 35cb0bdf5d..390e83538d 100644 --- a/lib/sqlalchemy/orm/util.py +++ b/lib/sqlalchemy/orm/util.py @@ -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 diff --git a/test/orm/test_eager_relations.py b/test/orm/test_eager_relations.py index 2c59491b17..bd85e4ce83 100644 --- a/test/orm/test_eager_relations.py +++ b/test/orm/test_eager_relations.py @@ -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" + )