Commits

Mike Bayer committed dcbeade

[ticket:728] foreign key checks for existing reflected FK and replaces itself

Comments (0)

Files changed (3)

   as it does in 0.3 since ~(x==y) compiles to "x != y", but still applies
   to operators like BETWEEN.
 
-- other tickets: [ticket:768]
+- other tickets: [ticket:768], [ticket:728]
 
 0.4.0beta5
 ----------

lib/sqlalchemy/schema.py

         if getattr(self, 'table', None) is not None:
             raise exceptions.ArgumentError("this Column already has a table!")
         if not self._is_oid:
+            self._pre_existing_column = table._columns.get(self.key)
             table._columns.add(self)
         if self.primary_key:
             table.primary_key.add(self)
 
     def _set_parent(self, column):
         self.parent = column
-
+        
+        if self.parent._pre_existing_column is not None:
+            # remove existing FK which matches us
+            for fk in self.parent._pre_existing_column.foreign_keys:
+                if fk._colspec == self._colspec:
+                    self.parent.table.foreign_keys.remove(fk)
+                    self.parent.table.constraints.remove(fk.constraint)
+            
         if self.constraint is None and isinstance(self.parent.table, Table):
             self.constraint = ForeignKeyConstraint([],[], use_alter=self.use_alter, name=self.name, onupdate=self.onupdate, ondelete=self.ondelete)
             self.parent.table.append_constraint(self.constraint)

test/engine/reflection.py

         finally:
             meta.drop_all()
             
-    def testoverridecolumns(self):
-        """test that you can override columns which contain foreign keys to other reflected tables"""
+    def test_override_create_fkcols(self):
+        """test that you can override columns and create new foreign keys to other reflected tables.
+        this is common with MySQL MyISAM tables."""
+        
         meta = MetaData(testbase.db)
         users = Table('users', meta, 
             Column('id', Integer, primary_key=True),
                 autoload=True)
             u2 = Table('users', meta2, autoload=True)
             
-            assert len(a2.c.user_id.foreign_keys)>0
+            assert len(a2.c.user_id.foreign_keys) == 1
+            assert len(a2.foreign_keys) == 1
+            assert [c.parent for c in a2.foreign_keys] == [a2.c.user_id]
+            assert [c.parent for c in a2.c.user_id.foreign_keys] == [a2.c.user_id]
             assert list(a2.c.user_id.foreign_keys)[0].parent is a2.c.user_id
             assert u2.join(a2).onclause == u2.c.id==a2.c.user_id
 
         finally:
             meta.drop_all()
 
-    def testoverridecolumns2(self):
+    def test_override_fkandpkcol(self):
         """test that you can override columns which contain foreign keys to other reflected tables,
         where the foreign key column is also a primary key column"""
         meta = MetaData(testbase.db)
         finally:
             meta.drop_all()
     
+    def test_override_existing_fkcols(self):
+        """test that you can override columns and specify new foreign keys to other reflected tables,
+        on columns which *do* already have that foreign key, and that the FK is not duped.
+        """
+        
+        meta = MetaData(testbase.db)
+        users = Table('users', meta, 
+            Column('id', Integer, primary_key=True),
+            Column('name', String(30)),
+            test_needs_fk=True)
+        addresses = Table('addresses', meta,
+            Column('id', Integer,primary_key=True),
+            Column('user_id', Integer, ForeignKey('users.id')),
+            test_needs_fk=True)
+            
+
+        meta.create_all()            
+        try:
+            meta2 = MetaData(testbase.db)
+            a2 = Table('addresses', meta2, 
+                Column('user_id',Integer, ForeignKey('users.id')),
+                autoload=True)
+            u2 = Table('users', meta2, autoload=True)
+            
+            assert len(a2.foreign_keys) == 1
+            assert len(a2.c.user_id.foreign_keys) == 1
+            assert len(a2.constraints) == 2
+            assert [c.parent for c in a2.foreign_keys] == [a2.c.user_id]
+            assert [c.parent for c in a2.c.user_id.foreign_keys] == [a2.c.user_id]
+            assert list(a2.c.user_id.foreign_keys)[0].parent is a2.c.user_id
+            assert u2.join(a2).onclause == u2.c.id==a2.c.user_id
+        finally:
+            meta.drop_all()
+        
     def test_pks_not_uniques(self):
         """test that primary key reflection not tripped up by unique indexes"""
         testbase.db.execute("""
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.