]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- merged r6312 of trunk for [ticket:1523]
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 1 Sep 2009 22:27:28 +0000 (22:27 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 1 Sep 2009 22:27:28 +0000 (22:27 +0000)
CHANGES
lib/sqlalchemy/orm/mapper.py
test/ext/test_declarative.py
test/orm/test_mapper.py

diff --git a/CHANGES b/CHANGES
index 6f579532dfd9ed5d1c5594774116a2fae2dd2e9e..bfae7b8093edf099434c487c6e94bfd5cbff6253 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -114,6 +114,14 @@ CHANGES
      __table_args__ is passed as a tuple with no dict argument.
      Improved documentation.  [ticket:1468]
 
+   - A column can be added to a joined-table subclass after
+     the class has been constructed (i.e. via class-level
+     attribute assignment).  The column is added to the underlying
+     Table as always, but now the mapper will rebuild its
+     "join" to include the new column, instead of raising
+     an error about "no such column, use column_property()
+     instead".  [ticket:1523]
+     
 - test
    - Added examples into the test suite so they get exercised
      regularly and cleaned up a couple deprecation warnings.
index 078056a01c4272bdedac424871ce655ab163bad4..b8842a5f8652261ecbd4feff7880b75fd9fbe58e 100644 (file)
@@ -547,9 +547,16 @@ class Mapper(object):
                 for c in columns:
                     mc = self.mapped_table.corresponding_column(c)
                     if not mc:
-                        raise sa_exc.ArgumentError("Column '%s' is not represented in mapper's table.  "
-                            "Use the `column_property()` function to force this column "
-                            "to be mapped as a read-only attribute." % c)
+                        mc = self.local_table.corresponding_column(c)
+                        if mc:
+                            # 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.
+                            self.mapped_table._reset_exported()
+                        mc = self.mapped_table.corresponding_column(c)
+                        if not mc:
+                            raise sa_exc.ArgumentError("Column '%s' is not represented in mapper's table.  "
+                                "Use the `column_property()` function to force this column "
+                                "to be mapped as a read-only attribute." % c)
                     mapped_column.append(mc)
                 prop = ColumnProperty(*mapped_column)
             else:
index 224f41731a9d696ce22ce3b171735745e2fc8ba2..f48777886928165f0914ab5d4cb6028dd9db51c6 100644 (file)
@@ -862,7 +862,34 @@ class DeclarativeInheritanceTest(DeclarativeTestBase):
         def go():
             assert sess.query(Person).filter(Manager.name=='dogbert').one().id
         self.assert_sql_count(testing.db, go, 1)
+    
+    def test_add_subcol_after_the_fact(self):
+        class Person(Base, ComparableEntity):
+            __tablename__ = 'people'
+            id = Column('id', Integer, primary_key=True, test_needs_autoincrement=True)
+            name = Column('name', String(50))
+            discriminator = Column('type', String(50))
+            __mapper_args__ = {'polymorphic_on':discriminator}
+
+        class Engineer(Person):
+            __tablename__ = 'engineers'
+            __mapper_args__ = {'polymorphic_identity':'engineer'}
+            id = Column('id', Integer, ForeignKey('people.id'), primary_key=True)
+        
+        Engineer.primary_language = Column('primary_language', 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_subclass_mixin(self):
         class Person(Base, ComparableEntity):
             __tablename__ = 'people'
index af8ea2aa4d7fbbaa92c745fc953c9cd8eedace27..774ec47c0258b148d00beb5693a29b81e3c8d58a 100644 (file)
@@ -159,6 +159,12 @@ class MapperTest(_fixtures.FixtureTest):
         assert 'email_addres' not in a.__dict__
         eq_(a.email_address, 'jack@bean.com')
 
+    @testing.resolve_artifact_names
+    def test_column_not_present(self):
+        assert_raises_message(sa.exc.ArgumentError, "not represented in mapper's table", mapper, User, users, properties={
+            'foo':addresses.c.user_id
+        })
+        
     @testing.resolve_artifact_names
     def test_bad_constructor(self):
         """If the construction of a mapped class fails, the instance does not get placed in the session"""