]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- [bug] Fixed bug whereby subqueryload() from
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 17 May 2012 18:20:26 +0000 (14:20 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 17 May 2012 18:20:26 +0000 (14:20 -0400)
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]

CHANGES
lib/sqlalchemy/__init__.py
lib/sqlalchemy/orm/strategies.py
test/orm/test_subquery_relations.py

diff --git a/CHANGES b/CHANGES
index d29e6287ab905d4a5a51fe5cfcc35db4ea2486fb..f260aabe5d8afcab9dbef54fea04a531e9fd62e9 100644 (file)
--- 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
index 4e00437ea9ee0c56be4581db4100ea5419bd938a..ab3a28db21c2a7a2e1c64f15da553b173e6ba5e2 100644 (file)
@@ -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
 
index 37980e11140e1f88de0c356ac63089085ae95ade..9f32cc6a6619e8c5630cfdf1b0662e999696f318 100644 (file)
@@ -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, 
index d309a951246d5387e13539173805ccda6c3c1d9f..70a015f29fb1240e58bdee655b5915ff584ffe92 100644 (file)
@@ -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