]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Added an informative error message when
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 21 Jul 2011 15:44:41 +0000 (11:44 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 21 Jul 2011 15:44:41 +0000 (11:44 -0400)
    ForeignKeyConstraint refers to a column name in
    the parent that is not found.
- add tests for [ticket:2226], as if we hit each @declared_attr
directly with obj.__get__(obj, name) instead of using
getattr(cls, name).  Basic inheritance mechanics are improperly
used in this case, so 2226 is invalid.

CHANGES
lib/sqlalchemy/schema.py
test/engine/test_metadata.py
test/ext/test_declarative.py

diff --git a/CHANGES b/CHANGES
index bfe5ceaafd26502b47e920b86bab11ad670ac211..7feaca8cc0c695e5c26548fa603cbc7ef75ca938 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -48,6 +48,11 @@ CHANGES
     when used with certain dialects.  This
     bug is not in 0.7.
 
+- schema
+  - Added an informative error message when 
+    ForeignKeyConstraint refers to a column name in 
+    the parent that is not found.
+
 - oracle
   - Added ORA-00028 to disconnect codes, use 
     cx_oracle _Error.code to get at the code,
index 6c73aabfa3ea76c7b7354ce467a17b437dd0033e..0ab90380d270e2da32f7ef0742cc618e434a737e 100644 (file)
@@ -1802,7 +1802,13 @@ class ForeignKeyConstraint(Constraint):
             # string-specified column names now get
             # resolved to Column objects
             if isinstance(col, basestring):
-                col = table.c[col]
+                try:
+                    col = table.c[col]
+                except KeyError:
+                    raise exc.ArgumentError(
+                                "Can't create ForeignKeyConstraint "
+                                "on table '%s': no column "
+                                "named '%s' is present." % (table.description, col))
             fk._set_parent(col)
 
         if self.use_alter:
index f4678cb185455f13e3be48a4ea9a208322e07bc8..2773e31dec5c044f5e079f8da13c5888994ec6a6 100644 (file)
@@ -146,6 +146,39 @@ class MetaDataTest(TestBase, ComparesTables):
         fk1 = ForeignKeyConstraint(('foo', ), ('bar', ), table=t1)
         assert fk1 in t1.constraints
 
+    def test_fk_no_such_parent_col_error(self):
+        meta = MetaData()
+        a = Table('a', meta, Column('a', Integer))
+        b = Table('b', meta, Column('b', Integer))
+
+        def go():
+            a.append_constraint(
+                ForeignKeyConstraint(['x'], ['b.b'])
+            )
+        assert_raises_message(
+            exc.ArgumentError,
+            "Can't create ForeignKeyConstraint on "
+            "table 'a': no column named 'x' is present.",
+            go
+        )
+
+    def test_fk_no_such_target_col_error(self):
+        meta = MetaData()
+        a = Table('a', meta, Column('a', Integer))
+        b = Table('b', meta, Column('b', Integer))
+        a.append_constraint(
+            ForeignKeyConstraint(['a'], ['b.x'])
+        )
+
+        def go():
+            list(a.c.a.foreign_keys)[0].column
+        assert_raises_message(
+            exc.NoReferencedColumnError,
+            "Could not create ForeignKey 'b.x' on "
+            "table 'a': table 'b' has no column named 'x'",
+            go
+        )
+
     @testing.exclude('mysql', '<', (4, 1, 1), 'early types are squirrely')
     def test_to_metadata(self):
         meta = MetaData()
index d47dda75f5131774266ffd4bbe67e842f8f020b3..a67e72c9cd57208bc49764deaef1d7df1516538d 100644 (file)
@@ -3023,6 +3023,40 @@ class DeclarativeMixinTest(DeclarativeTestBase):
         eq_(Model.__table__.c.keys(), ['col1', 'col3', 'col2', 'col4',
             'id'])
 
+    def test_honor_class_mro_one(self):
+        class HasXMixin(object):
+            @declared_attr
+            def x(self):
+                return Column(Integer)
+
+        class Parent(HasXMixin, Base):
+            __tablename__ = 'parent'
+            id = Column(Integer, primary_key=True)
+
+        class Child(Parent):
+            __tablename__ = 'child'
+            id = Column(Integer, ForeignKey('parent.id'), primary_key=True)
+
+        assert "x" not in Child.__table__.c
+
+    def test_honor_class_mro_two(self):
+        class HasXMixin(object):
+            @declared_attr
+            def x(self):
+                return Column(Integer)
+
+        class Parent(HasXMixin, Base):
+            __tablename__ = 'parent'
+            id = Column(Integer, primary_key=True)
+            def x(self):
+                return "hi"
+
+        class C(Parent):
+            __tablename__ = 'c'
+            id = Column(Integer, ForeignKey('parent.id'), primary_key=True)
+
+        assert C().x() == 'hi'
+
 class DeclarativeMixinPropertyTest(DeclarativeTestBase):
 
     def test_column_property(self):