From: Mike Bayer Date: Thu, 17 May 2012 18:20:26 +0000 (-0400) Subject: - [bug] Fixed bug whereby subqueryload() from X-Git-Tag: rel_0_7_8~27 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7bb964e9e57849de921821b58260b86389b4b939;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - [bug] Fixed bug whereby subqueryload() from a polymorphic mapping to a target would incur a new invocation of the query for each distinct class encountered in the polymorphic result. [ticket:2480] --- diff --git a/CHANGES b/CHANGES index d29e6287ab..f260aabe5d 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,15 @@ ======= CHANGES ======= +0.7.8 +===== +- orm + - [bug] Fixed bug whereby subqueryload() from + a polymorphic mapping to a target would incur + a new invocation of the query for each + distinct class encountered in the polymorphic + result. [ticket:2480] + 0.7.7 ===== - orm diff --git a/lib/sqlalchemy/__init__.py b/lib/sqlalchemy/__init__.py index 4e00437ea9..ab3a28db21 100644 --- a/lib/sqlalchemy/__init__.py +++ b/lib/sqlalchemy/__init__.py @@ -117,7 +117,7 @@ from sqlalchemy.engine import create_engine, engine_from_config __all__ = sorted(name for name, obj in locals().items() if not (name.startswith('_') or inspect.ismodule(obj))) -__version__ = '0.7.7' +__version__ = '0.7.8' del inspect, sys diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index 37980e1114..9f32cc6a66 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -934,7 +934,13 @@ class SubqueryLoader(AbstractRelationshipLoader): q = context.attributes[('subquery', reduced_path)] - collections = dict( + # cache the loaded collections in the context + # so that inheriting mappers don't re-load when they + # call upon create_row_processor again + if ('collections', reduced_path) in context.attributes: + collections = context.attributes[('collections', reduced_path)] + else: + collections = context.attributes[('collections', reduced_path)] = dict( (k, [v[0] for v in v]) for k, v in itertools.groupby( q, diff --git a/test/orm/test_subquery_relations.py b/test/orm/test_subquery_relations.py index d309a95124..70a015f29f 100644 --- a/test/orm/test_subquery_relations.py +++ b/test/orm/test_subquery_relations.py @@ -1184,4 +1184,84 @@ class SelfReferentialTest(fixtures.MappedTest): ], d) self.assert_sql_count(testing.db, go, 4) +class InheritanceToRelatedTest(fixtures.MappedTest): + @classmethod + def define_tables(cls, metadata): + Table('foo', metadata, + Column("id", Integer, primary_key=True), + Column("type", String(50)), + Column("related_id", Integer, ForeignKey("related.id")) + ) + Table("bar", metadata, + Column("id", Integer, ForeignKey('foo.id'), primary_key=True), + ) + Table("baz", metadata, + Column("id", Integer, ForeignKey('foo.id'), primary_key=True), + ) + Table("related", metadata, + Column("id", Integer, primary_key=True), + ) + + @classmethod + def setup_classes(cls): + class Foo(cls.Comparable): + pass + class Bar(Foo): + pass + class Baz(Foo): + pass + class Related(cls.Comparable): + pass + @classmethod + def fixtures(cls): + return dict( + foo = [ + ('id', 'type', 'related_id'), + (1, 'bar', 1), + (2, 'bar', 2), + (3, 'baz', 1), + (4, 'baz', 2), + ], + bar = [ + ('id', ), + (1,), + (2,) + ], + baz = [ + ('id', ), + (3,), + (4,) + ], + related = [ + ('id', ), + (1,), + (2,) + ] + ) + @classmethod + def setup_mappers(cls): + mapper(cls.classes.Foo, cls.tables.foo, properties={ + 'related':relationship(cls.classes.Related) + }, polymorphic_on=cls.tables.foo.c.type) + mapper(cls.classes.Bar, cls.tables.bar, polymorphic_identity='bar', + inherits=cls.classes.Foo) + mapper(cls.classes.Baz, cls.tables.baz, polymorphic_identity='baz', + inherits=cls.classes.Foo) + mapper(cls.classes.Related, cls.tables.related) + + def test_caches_query_per_base(self): + Foo, Bar, Baz, Related = self.classes.Foo, self.classes.Bar, \ + self.classes.Baz, self.classes.Related + s = Session(testing.db) + def go(): + eq_( + s.query(Foo).with_polymorphic([Bar, Baz]).order_by(Foo.id).options(subqueryload(Foo.related)).all(), + [ + Bar(id=1,related=Related(id=1)), + Bar(id=2,related=Related(id=2)), + Baz(id=3,related=Related(id=1)), + Baz(id=4,related=Related(id=2)) + ] + ) + self.assert_sql_count(testing.db, go, 2) \ No newline at end of file