F. Gabriel Gosselin avatar F. Gabriel Gosselin committed 712d1fc

Wipe out the constraint cache for the entire database (since MySQL updates the whole cache at once)
This ensures all foreign key constraints are up to date and a referred table rename.

Comments (0)

Files changed (2)

south/db/mysql.py

         return func(self, table_name, column_old, column_new, *args, **opts)
     return _column_cp
 
+def invalidate_table_constraints(func):
+    """
+    For MySQL we grab all table constraints simultaneously, so this is
+    effective.
+    It further solves the issues of invalidating referred table constraints.
+    """
+    def _cache_clear(self, table, *args, **opts):
+        db_name = self._get_setting('NAME')
+        if db_name in self._constraint_cache:
+            del self._constraint_cache[db_name]
+            del self._reverse_cache[db_name]
+            del self._constraint_references[db_name]
+        return func(self, table, *args, **opts)
+    return _cache_clear
 
 class DatabaseOperations(generic.DatabaseOperations):
     """
 
     @copy_column_constraints
     @delete_column_constraints
-    @generic.invalidate_table_constraints
+    @invalidate_table_constraints
     def rename_column(self, table_name, old, new):
         if old == new or self.dry_run:
             return []
     def delete_column(self, table_name, name):
         super(DatabaseOperations, self).delete_column(table_name, name)
 
+    @invalidate_table_constraints
+    def rename_table(self, old_table_name, table_name):
+        super(DatabaseOperations, self).rename_table(old_table_name,
+                table_name)
 
     def _lookup_constraint_references(self, table_name, cname):
         """

south/tests/db_mysql.py

         db.rename_table(main_table, renamed_table)
         db.execute_deferred_sql()  #Create constraints
         constraints = db._find_foreign_constraints(renamed_table, 'foreign_id')
-        print constraints
         self.assertEquals(len(constraints), 1)
         (rtable, rcolumn) = db._lookup_constraint_references(
                 renamed_table, constraints[0])
         db.delete_table(renamed_table)
         db.delete_table(ref_table)
 
+    def test_renamed_referenced_table(self):
+        """Rename a table referred to in a foreign key"""
+        main_table = 'test_rn_refd_table'
+        ref_table = 'test_rrt_ref'
+        renamed_table = 'test_renamed_ref'
+        self._create_foreign_tables(main_table, ref_table)
+        db.execute_deferred_sql()
+        constraints = db._lookup_reverse_constraint(ref_table)
+        self.assertEquals(len(constraints), 1)
+        db.rename_table(ref_table, renamed_table)
+        db.execute_deferred_sql()  #Create constraints
+        constraints = db._find_foreign_constraints(main_table, 'foreign_id')
+        self.assertEquals(len(constraints), 1)
+        (rtable, rcolumn) = db._lookup_constraint_references(
+                main_table, constraints[0])
+        self.assertEquals(renamed_table, rtable)
+        db.delete_table(main_table)
+        db.delete_table(renamed_table)
+
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.