]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Fixed bug in polymorphic inheritance where incorrect
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 27 Jan 2008 02:21:23 +0000 (02:21 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 27 Jan 2008 02:21:23 +0000 (02:21 +0000)
exception is raised when base polymorphic_on
column does not correspond to any columns within
the local selectable of an inheriting mapper more
than one level deep

CHANGES
lib/sqlalchemy/orm/mapper.py
test/orm/inheritance/polymorph2.py

diff --git a/CHANGES b/CHANGES
index e39f891a458a1b92944ad04b00145b2c85f03c94..069192a445d247b9bb9627890546873a85deec29 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -83,6 +83,12 @@ CHANGES
       need to be sent to query.get(), among other things.
       [ticket:933]
 
+    - Fixed bug in polymorphic inheritance where incorrect
+      exception is raised when base polymorphic_on
+      column does not correspond to any columns within 
+      the local selectable of an inheriting mapper more 
+      than one level deep
+      
     - Fixed bug in polymorphic inheritance which made it
       difficult to set a working "order_by" on a polymorphic
       mapper.
index d9dc70a5853d889b12d7f845ddc50fd31698c39d..959cf274c4553fe45b5a3fa364507b121eefcbe9 100644 (file)
@@ -352,9 +352,14 @@ class Mapper(object):
             if self.polymorphic_identity is not None:
                 self.inherits.polymorphic_map[self.polymorphic_identity] = self
                 if self.polymorphic_on is None:
-                    if self.inherits.polymorphic_on is not None:
-                        self.polymorphic_on = self.mapped_table.corresponding_column(self.inherits.polymorphic_on)
+                    for mapper in self.iterate_to_root():
+                        # try to set up polymorphic on using correesponding_column(); else leave
+                        # as None
+                        if mapper.polymorphic_on:
+                            self.polymorphic_on = self.mapped_table.corresponding_column(mapper.polymorphic_on)
+                            break
                     else:
+                        # TODO: this exception not covered
                         raise exceptions.ArgumentError("Mapper '%s' specifies a polymorphic_identity of '%s', but no mapper in it's hierarchy specifies the 'polymorphic_on' column argument" % (str(self), self.polymorphic_identity))
 
             if self.polymorphic_identity is not None and not self.concrete:
index 0f0fff6729a4dbc0c38a63be7f5ccf9dbe94d0ef..75ec0c2b5ae11e139f756d03c28501a118282b32 100644 (file)
@@ -1010,6 +1010,54 @@ class InheritingEagerTest(ORMTest):
         instance = session.query(Employee).filter_by(id=1).limit(1).first()
         assert len(instance.tags) == 2
 
-
+class MissingPolymorphicOnTest(ORMTest):
+    def define_tables(self, metadata):
+        global tablea, tableb, tablec, tabled
+        tablea = Table('tablea', metadata, 
+            Column('id', Integer, primary_key=True),
+            Column('adata', String(50)),
+            )
+        tableb = Table('tableb', metadata, 
+            Column('id', Integer, primary_key=True),
+            Column('aid', Integer, ForeignKey('tablea.id')),
+            Column('data', String(50)),
+            )
+        tablec = Table('tablec', metadata, 
+            Column('id', Integer, ForeignKey('tablea.id'), primary_key=True),
+            Column('cdata', String(50)),
+            )
+        tabled = Table('tabled', metadata, 
+            Column('id', Integer, ForeignKey('tablec.id'), primary_key=True),
+            Column('ddata', String(50)),
+            )
+            
+    def test_polyon_col_setsup(self):
+        class A(fixtures.Base):
+            pass
+        class B(fixtures.Base):
+            pass
+        class C(A):
+            pass
+        class D(C):
+            pass
+            
+        poly_select = select([tablea, tableb.c.data.label('discriminator')], from_obj=tablea.join(tableb)).alias('poly')
+        
+        mapper(B, tableb)
+        mapper(A, tablea, select_table=poly_select, polymorphic_on=poly_select.c.discriminator, properties={
+            'b':relation(B, uselist=False)
+        })
+        mapper(C, tablec, inherits=A,polymorphic_identity='c')
+        mapper(D, tabled, inherits=C, polymorphic_identity='d')
+        
+        c = C(cdata='c1', adata='a1', b=B(data='c'))
+        d = D(cdata='c2', adata='a2', ddata='d2', b=B(data='d'))
+        sess = create_session()
+        sess.save(c)
+        sess.save(d)
+        sess.flush()
+        sess.clear()
+        self.assertEquals(sess.query(A).all(), [C(cdata='c1', adata='a1'), D(cdata='c2', adata='a2', ddata='d2')])
+        
 if __name__ == "__main__":
     testenv.main()