]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- A column can be added to a joined-table declarative
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 15 Oct 2009 20:52:06 +0000 (20:52 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 15 Oct 2009 20:52:06 +0000 (20:52 +0000)
superclass after the class has been constructed
(i.e. via class-level attribute assignment), and
the column will be propagated down to
subclasses. [ticket:1570]  This is the reverse
situation as that of [ticket:1523], fixed in 0.5.6.

CHANGES
lib/sqlalchemy/orm/mapper.py
test/ext/test_declarative.py

diff --git a/CHANGES b/CHANGES
index 9fa1632a23d528bfd907bad03ffeae0babbd088a..f2549eca29ff94995317bc57e9d155d1f99e80bc 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -482,6 +482,13 @@ CHANGES
       Trusted_Connection when constructing pyodbc connect
       arguments [ticket:1561]
 
+- ext 
+    - A column can be added to a joined-table declarative 
+      superclass after the class has been constructed 
+      (i.e. via class-level attribute assignment), and
+      the column will be propagated down to 
+      subclasses. [ticket:1570]  This is the reverse
+      situation as that of [ticket:1523], fixed in 0.5.6.
       
 0.5.6
 =====
index a9dad91766df480c7b371135d278a5a4081bf51d..b15abc114f6a99a312078d2b3eb3373a24fd8c9c 100644 (file)
@@ -559,6 +559,7 @@ class Mapper(object):
                         if mc is not None:
                             # if the column is in the local table but not the mapped table,
                             # this corresponds to adding a column after the fact to the local table.
+                            # [ticket:1523]
                             self.mapped_table._reset_exported()
                         mc = self.mapped_table.corresponding_column(c)
                         if mc is None:
@@ -577,7 +578,24 @@ class Mapper(object):
 
         if isinstance(prop, ColumnProperty):
             col = self.mapped_table.corresponding_column(prop.columns[0])
-            # col might not be present! the selectable given to the mapper need not include "deferred"
+            
+            # if the column is not present in the mapped table, 
+            # test if a column has been added after the fact to the parent table
+            # (or their parent, etc.)
+            # [ticket:1570]
+            if col is None and self.inherits:
+                path = [self]
+                for m in self.inherits.iterate_to_root():
+                    col = m.local_table.corresponding_column(prop.columns[0])
+                    if col is not None:
+                        for m2 in path:
+                            m2.mapped_table._reset_exported()
+                        col = self.mapped_table.corresponding_column(prop.columns[0])
+                        break
+                    path.append(m)
+                
+            # otherwise, col might not be present! the selectable given 
+            # to the mapper need not include "deferred"
             # columns (included in zblog tests)
             if col is None:
                 col = prop.columns[0]
index 6bd45833c7181f0905030a4045e3ff62fe2c9192..c54e34e67a2fddc3a20e42190a61005e0bb1cbc6 100644 (file)
@@ -1007,6 +1007,66 @@ class DeclarativeInheritanceTest(DeclarativeTestBase):
         eq_(sess.query(Person).first(),
             Engineer(primary_language='java', name='dilbert')
         )
+    
+    def test_add_parentcol_after_the_fact(self):
+        class Person(Base, ComparableEntity):
+            __tablename__ = 'people'
+            id = Column('id', Integer, primary_key=True, test_needs_autoincrement=True)
+            discriminator = Column('type', String(50))
+            __mapper_args__ = {'polymorphic_on':discriminator}
+
+        class Engineer(Person):
+            __tablename__ = 'engineers'
+            __mapper_args__ = {'polymorphic_identity':'engineer'}
+            primary_language = Column(String(50))
+            id = Column('id', Integer, ForeignKey('people.id'), primary_key=True)
+        
+        Person.name = Column('name', String(50))
+        
+        Base.metadata.create_all()
+
+        sess = create_session()
+        e1 = Engineer(primary_language='java', name='dilbert')
+        sess.add(e1)
+        sess.flush()
+        sess.expunge_all()
+
+        eq_(sess.query(Person).first(),
+            Engineer(primary_language='java', name='dilbert')
+        )
+
+    def test_add_sub_parentcol_after_the_fact(self):
+        class Person(Base, ComparableEntity):
+            __tablename__ = 'people'
+            id = Column('id', Integer, primary_key=True, test_needs_autoincrement=True)
+            discriminator = Column('type', String(50))
+            __mapper_args__ = {'polymorphic_on':discriminator}
+
+        class Engineer(Person):
+            __tablename__ = 'engineers'
+            __mapper_args__ = {'polymorphic_identity':'engineer'}
+            primary_language = Column(String(50))
+            id = Column('id', Integer, ForeignKey('people.id'), primary_key=True)
+        
+        class Admin(Engineer):
+            __tablename__ = 'admins'
+            __mapper_args__ = {'polymorphic_identity':'admin'}
+            workstation = Column(String(50))
+            id = Column('id', Integer, ForeignKey('engineers.id'), primary_key=True)
+            
+        Person.name = Column('name', String(50))
+
+        Base.metadata.create_all()
+
+        sess = create_session()
+        e1 = Admin(primary_language='java', name='dilbert', workstation='foo')
+        sess.add(e1)
+        sess.flush()
+        sess.expunge_all()
+
+        eq_(sess.query(Person).first(),
+            Admin(primary_language='java', name='dilbert', workstation='foo')
+        )
         
     def test_subclass_mixin(self):
         class Person(Base, ComparableEntity):