Browse Source

Fix error when deleting project

When deleting a project, an error like:

  delete statement on table change_conflict expected to delete X rows

might occur.  This is because the self-referential many-to-many
relationship of change conflicts was trying to delete entries from
the secondary table twice.  Handle the case of deleting a project
better.

Change-Id: Ib919e36ede14a3a1054fcd6b95ea43ccae046d3e
James E. Blair 2 years ago
parent
commit
c20ec64ad8
2 changed files with 21 additions and 1 deletions
  1. 19
    0
      gertty/db.py
  2. 2
    1
      gertty/sync.py

+ 19
- 0
gertty/db.py View File

@@ -200,6 +200,25 @@ class Project(object):
200 200
         self.subscribed = subscribed
201 201
         self.description = description
202 202
 
203
+    def delete(self):
204
+        # This unusual delete method is to accomodate the
205
+        # self-referential many-to-many relationship from
206
+        # change_conflict.  With the default cascade configuration,
207
+        # the entry from the association table is deleted regardless
208
+        # of whether the change being deleted is change1 or change2.
209
+        # However, when both changes are deleted at once (only likely
210
+        # to happen when the entire project is deleted), SQLAlchemy
211
+        # cascades through both relationships and attempts to delete
212
+        # the entry twice.  Since we rarely delete projects, we add a
213
+        # special case here to delete a project's changes one at a
214
+        # time to avoid this situation.
215
+        session = Session.object_session(self)
216
+        for c in self.changes:
217
+            session.delete(c)
218
+            session.flush()
219
+            session.expire_all()
220
+        session.delete(self)
221
+
203 222
     def createChange(self, *args, **kw):
204 223
         session = Session.object_session(self)
205 224
         args = [self] + list(args)

+ 2
- 1
gertty/sync.py View File

@@ -236,7 +236,8 @@ class SyncProjectListTask(Task):
236 236
             local_keys = set(local.keys())
237 237
 
238 238
             for name in local_keys-remote_keys:
239
-                session.delete(local[name])
239
+                self.log.info("Deleted project %s", name)
240
+                local[name].delete()
240 241
 
241 242
             for name in remote_keys-local_keys:
242 243
                 p = remote[name]

Loading…
Cancel
Save