From: Mike Bayer Date: Thu, 13 Nov 2014 18:17:38 +0000 (-0500) Subject: - Fixed a leak which would occur in the unsupported and highly X-Git-Tag: rel_1_0_0~19^2~22 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=026449c15ff35a9b89c2ca591d3e3cc791857272;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - Fixed a leak which would occur in the unsupported and highly non-recommended use case of replacing a relationship on a fixed mapped class many times, referring to an arbitrarily growing number of target mappers. A warning is emitted when the old relationship is replaced, however if the mapping were already used for querying, the old relationship would still be referenced within some registries. fixes #3251 --- diff --git a/doc/build/changelog/changelog_09.rst b/doc/build/changelog/changelog_09.rst index 66a7da8dab..abf564875d 100644 --- a/doc/build/changelog/changelog_09.rst +++ b/doc/build/changelog/changelog_09.rst @@ -13,6 +13,18 @@ .. changelog:: :version: 0.9.9 + .. change:: + :tags: bug, orm + :versions: 1.0.0 + :tickets: 3251 + + Fixed a leak which would occur in the unsupported and highly + non-recommended use case of replacing a relationship on a fixed + mapped class many times, referring to an arbitrarily growing number of + target mappers. A warning is emitted when the old relationship is + replaced, however if the mapping were already used for querying, the + old relationship would still be referenced within some registries. + .. change:: :tags: bug, sql :versions: 1.0.0 diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 7e88ba161f..863dab5cbf 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -1581,6 +1581,8 @@ class Mapper(InspectionAttr): self, prop, )) + oldprop = self._props[key] + self._path_registry.pop(oldprop, None) self._props[key] = prop diff --git a/test/aaa_profiling/test_memusage.py b/test/aaa_profiling/test_memusage.py index f4bce6b01b..63883daac6 100644 --- a/test/aaa_profiling/test_memusage.py +++ b/test/aaa_profiling/test_memusage.py @@ -658,6 +658,32 @@ class MemUsageTest(EnsureZeroed): row[t.c.x] go() + def test_many_discarded_relationships(self): + """a use case that really isn't supported, nonetheless we can + guard against memleaks here so why not""" + + m1 = MetaData() + t1 = Table('t1', m1, Column('id', Integer, primary_key=True)) + t2 = Table( + 't2', m1, Column('id', Integer, primary_key=True), + Column('t1id', ForeignKey('t1.id'))) + + class T1(object): + pass + t1_mapper = mapper(T1, t1) + + @testing.emits_warning() + @profile_memory() + def go(): + class T2(object): + pass + t2_mapper = mapper(T2, t2) + t1_mapper.add_property("bar", relationship(t2_mapper)) + s1 = Session() + # this causes the path_registry to be invoked + s1.query(t1_mapper)._compile_context() + go() + # fails on newer versions of pysqlite due to unusual memory behvior # in pysqlite itself. background at: # http://thread.gmane.org/gmane.comp.python.db.pysqlite.user/2290