]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- An exception is raised when a single-table subclass specifies
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 19 Mar 2010 17:23:06 +0000 (13:23 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 19 Mar 2010 17:23:06 +0000 (13:23 -0400)
a column that is already present on the base class.
[ticket:1732]

CHANGES
lib/sqlalchemy/ext/declarative.py
test/ext/test_declarative.py

diff --git a/CHANGES b/CHANGES
index 2e11bd38a1d156d02d2d863e220b7ca264793125..1e37432bdc42e3f3706d984ad7ea8d5edea9117a 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -331,7 +331,11 @@ CHANGES
     propagation from the parent.  mapper inheritance already
     propagates the things you want from the parent mapper.
     [ticket:1393]
-     
+
+  - An exception is raised when a single-table subclass specifies
+    a column that is already present on the base class.
+    [ticket:1732]
+    
 - mysql
   - Fixed reflection bug whereby when COLLATE was present, 
     nullable flag and server defaults would not be reflected.
index 0f55180451c49507297e65760fe132c2ac0fb899..775efbff1b434b3959cca5fb6e820d5e359575ad 100644 (file)
@@ -682,6 +682,11 @@ def _as_declarative(cls, classname, dict_):
                     raise exceptions.ArgumentError(
                         "Can't place primary key columns on an inherited class with no table."
                         )
+                if c.name in inherited_table.c:
+                    raise exceptions.ArgumentError(
+                                "Column '%s' on class %s conflicts with existing column '%s'" % 
+                                (c, cls, inherited_table.c[c.name])
+                            )
                 inherited_table.append_column(c)
     
         # single or joined inheritance
index 69b8848e979b7780e9ed4c6c1df701ded4389bcc..aa04cdf113b08aa8cfd82a5904abfff99c0d48b0 100644 (file)
@@ -1445,7 +1445,35 @@ class DeclarativeInheritanceTest(DeclarativeTestBase):
         assert not hasattr(Engineer, 'nerf_gun')
         assert not hasattr(Manager, 'nerf_gun')
         assert not hasattr(Manager, 'primary_language')
-            
+    
+    def test_single_detects_conflict(self):
+        class Person(Base):
+            __tablename__ = 'people'
+            id = Column(Integer, primary_key=True)
+            name = Column(String(50))
+            discriminator = Column('type', String(50))
+            __mapper_args__ = {'polymorphic_on':discriminator}
+
+        class Engineer(Person):
+            __mapper_args__ = {'polymorphic_identity':'engineer'}
+            primary_language = Column(String(50))
+        
+        # test sibling col conflict
+        def go():
+            class Manager(Person):
+                __mapper_args__ = {'polymorphic_identity':'manager'}
+                golf_swing = Column(String(50))
+                primary_language = Column(String(50))
+        assert_raises(sa.exc.ArgumentError, go)
+
+        # test parent col conflict
+        def go():
+            class Salesman(Person):
+                __mapper_args__ = {'polymorphic_identity':'manager'}
+                name = Column(String(50))
+        assert_raises(sa.exc.ArgumentError, go)
+
+        
     def test_single_no_special_cols(self):
         class Person(Base, ComparableEntity):
             __tablename__ = 'people'
@@ -1595,16 +1623,22 @@ def _produce_test(inline, stringbased):
                 user_id = Column(Integer, ForeignKey('users.id'))
                 if inline:
                     if stringbased:
-                        user = relationship("User", primaryjoin="User.id==Address.user_id", backref="addresses")
+                        user = relationship("User", 
+                                                    primaryjoin="User.id==Address.user_id",
+                                                    backref="addresses")
                     else:
                         user = relationship(User, primaryjoin=User.id==user_id, backref="addresses")
             
             if not inline:
                 compile_mappers()
                 if stringbased:
-                    Address.user = relationship("User", primaryjoin="User.id==Address.user_id", backref="addresses")
+                    Address.user = relationship("User", 
+                                            primaryjoin="User.id==Address.user_id",
+                                            backref="addresses")
                 else:
-                    Address.user = relationship(User, primaryjoin=User.id==Address.user_id, backref="addresses")
+                    Address.user = relationship(User, 
+                                            primaryjoin=User.id==Address.user_id,
+                                            backref="addresses")
 
         @classmethod
         def insert_data(cls):
@@ -1628,18 +1662,22 @@ def _produce_test(inline, stringbased):
     
         def test_aliased_join(self):
             # this query will screw up if the aliasing 
-            # enabled in query.join() gets applied to the right half of the join condition inside the any().
+            # enabled in query.join() gets applied to the right half of the 
+            # join condition inside the any().
             # the join condition inside of any() comes from the "primaryjoin" of the relationship,
             # and should not be annotated with _orm_adapt.  PropertyLoader.Comparator will annotate
             # the left side with _orm_adapt, though.
             sess = create_session()
             eq_(
                 sess.query(User).join(User.addresses, aliased=True).
-                    filter(Address.email=='ed@wood.com').filter(User.addresses.any(Address.email=='jack@bean.com')).all(),
+                    filter(Address.email=='ed@wood.com').
+                    filter(User.addresses.any(Address.email=='jack@bean.com')).all(),
                 []
             )
     
-    ExplicitJoinTest.__name__ = "ExplicitJoinTest%s%s" % (inline and 'Inline' or 'Separate', stringbased and 'String' or 'Literal')
+    ExplicitJoinTest.__name__ = "ExplicitJoinTest%s%s" % \
+                                    (inline and 'Inline' or 'Separate', 
+                                    stringbased and 'String' or 'Literal')
     return ExplicitJoinTest
 
 for inline in (True, False):