]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Fixed bug whereby ORM would run the wrong kind of
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 12 Apr 2013 00:04:57 +0000 (20:04 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 12 Apr 2013 00:04:57 +0000 (20:04 -0400)
query when refreshing an inheritance-mapped class
where the superclass was mapped to a non-Table
object, like a custom join() or a select(),
running a query that assumed a hierarchy that's
mapped to individual Table-per-class.
[ticket:2697]

doc/build/changelog/changelog_08.rst
lib/sqlalchemy/orm/mapper.py
test/orm/inheritance/test_basic.py

index 13c044351c8e7ef40a34feb7d30305e23512615a..60d61cb8dadc49f6dbd3e6f7c42330c15b971919 100644 (file)
@@ -6,6 +6,17 @@
 .. changelog::
     :version: 0.8.1
 
+    .. change::
+      :tags: bug, orm
+      :tickets: 2697
+
+      Fixed bug whereby ORM would run the wrong kind of
+      query when refreshing an inheritance-mapped class
+      where the superclass was mapped to a non-Table
+      object, like a custom join() or a select(),
+      running a query that assumed a hierarchy that's
+      mapped to individual Table-per-class.
+
     .. change::
       :tags: bug, orm
 
index d258a20b60cb223c6ece9bee5625d88e467d7f96..914c29b7fafa52122beb8faaf4a8fd801baf51c6 100644 (file)
@@ -1933,6 +1933,8 @@ class Mapper(_InspectionAttr):
             for mapper in reversed(list(self.iterate_to_root())):
                 if mapper.local_table in tables:
                     start = True
+                elif not isinstance(mapper.local_table, expression.TableClause):
+                    return None
                 if start and not mapper.single:
                     allconds.append(visitors.cloned_traverse(
                                                 mapper.inherit_condition,
index 3cd3db92806678954026294b9a3758ce13fe189e..f883a07a7ba8953cc89eb74f3021c72cda762ed1 100644 (file)
@@ -1637,6 +1637,53 @@ class OptimizedLoadTest(fixtures.MappedTest):
             Column('b', String(10))
         )
 
+    def test_no_optimize_on_map_to_join(self):
+        base, sub = self.tables.base, self.tables.sub
+
+        class Base(fixtures.ComparableEntity):
+            pass
+
+        class JoinBase(fixtures.ComparableEntity):
+            pass
+        class SubJoinBase(JoinBase):
+            pass
+
+        mapper(Base, base)
+        mapper(JoinBase, base.outerjoin(sub), properties={
+                'id': [base.c.id, sub.c.id],
+                'counter': [base.c.counter, sub.c.counter]
+            })
+        mapper(SubJoinBase, inherits=JoinBase)
+
+        sess = Session()
+        sess.add(Base(data='data'))
+        sess.commit()
+
+        sjb = sess.query(SubJoinBase).one()
+        sjb_id = sjb.id
+        sess.expire(sjb)
+
+        # this should not use the optimized load,
+        # which assumes discrete tables
+        def go():
+            eq_(sjb.data, 'data')
+
+        self.assert_sql_execution(
+            testing.db,
+            go,
+            CompiledSQL(
+                "SELECT base.counter AS base_counter, "
+                "sub.counter AS sub_counter, base.id AS base_id, "
+                "sub.id AS sub_id, base.data AS base_data, "
+                "base.type AS base_type, sub.sub AS sub_sub, "
+                "sub.counter2 AS sub_counter2 FROM base "
+                "LEFT OUTER JOIN sub ON base.id = sub.id "
+                "WHERE base.id = :param_1",
+                {'param_1': sjb_id}
+            ),
+        )
+
+
     def test_optimized_passes(self):
         """"test that the 'optimized load' routine doesn't crash when
         a column in the join condition is not available."""
@@ -1678,7 +1725,7 @@ class OptimizedLoadTest(fixtures.MappedTest):
             pass
         mapper(Base, base, polymorphic_on=base.c.type, polymorphic_identity='base')
         mapper(Sub, sub, inherits=Base, polymorphic_identity='sub', properties={
-            'concat':column_property(sub.c.sub + "|" + sub.c.sub)
+            'concat': column_property(sub.c.sub + "|" + sub.c.sub)
         })
         sess = sessionmaker()()
         s1 = Sub(data='s1data', sub='s1sub')
@@ -1697,7 +1744,7 @@ class OptimizedLoadTest(fixtures.MappedTest):
             pass
         mapper(Base, base, polymorphic_on=base.c.type, polymorphic_identity='base')
         mapper(Sub, sub, inherits=Base, polymorphic_identity='sub', properties={
-            'concat':column_property(base.c.data + "|" + sub.c.sub)
+            'concat': column_property(base.c.data + "|" + sub.c.sub)
         })
         sess = sessionmaker()()
         s1 = Sub(data='s1data', sub='s1sub')