server/repository.py
changeset 7894 ad0eeb0f7a8d
parent 7845 2172978be237
parent 7887 42a0b7398d31
child 7907 08320697ca1a
--- a/server/repository.py	Thu Sep 29 14:07:37 2011 +0200
+++ b/server/repository.py	Thu Sep 29 14:47:04 2011 +0200
@@ -1106,22 +1106,32 @@
         hook.CleanupNewEidsCacheOp.get_instance(session).add_data(entity.eid)
         self.system_source.add_info(session, entity, source, extid, complete)
 
-    def delete_info(self, session, entity, sourceuri, extid, scleanup=None):
+    def delete_info(self, session, entity, sourceuri, scleanup=None):
         """called by external source when some entity known by the system source
         has been deleted in the external source
         """
         # mark eid as being deleted in session info and setup cache update
         # operation
         hook.CleanupDeletedEidsCacheOp.get_instance(session).add_data(entity.eid)
-        self._delete_info(session, entity, sourceuri, extid, scleanup)
+        self._delete_info(session, entity, sourceuri, scleanup)
 
-    def _delete_info(self, session, entity, sourceuri, extid, scleanup=None):
+    def _delete_info(self, session, entity, sourceuri, scleanup=None):
         """delete system information on deletion of an entity:
+
         * delete all remaining relations from/to this entity
+
         * call delete info on the system source which will transfer record from
           the entities table to the deleted_entities table
+
+        When scleanup is specified, it's expected to be the source's eid, in
+        which case we'll specify the target's relation source so that this
+        source is ignored. E.g. we want to delete relations stored locally, as
+        the deletion information comes from the external source, it's its
+        responsability to have cleaned-up its own relations.
         """
         pendingrtypes = session.transaction_data.get('pendingrtypes', ())
+        if scleanup is not None:
+            source = self.sources_by_eid[scleanup]
         # delete remaining relations: if user can delete the entity, he can
         # delete all its relations without security checking
         with security_enabled(session, read=False, write=False):
@@ -1137,6 +1147,13 @@
                 else:
                     rql = 'DELETE Y %s X WHERE X eid %%(x)s' % rtype
                 if scleanup is not None:
+                    # if the relation can't be crossed, nothing to cleanup (we
+                    # would get a BadRQLQuery from the multi-sources planner).
+                    # This may still leave some junk if the mapping has changed
+                    # at some point, but one can still run db-check to catch
+                    # those
+                    if not source in self.can_cross_relation(rtype):
+                        continue
                     # source cleaning: only delete relations stored locally
                     # (here, scleanup
                     rql += ', NOT (Y cw_source S, S eid %(seid)s)'
@@ -1144,6 +1161,8 @@
                     session.execute(rql, {'x': eid, 'seid': scleanup},
                                     build_descr=False)
                 except Exception:
+                    if self.config.mode == 'test':
+                        raise
                     self.exception('error while cascading delete for entity %s '
                                    'from %s. RQL: %s', entity, sourceuri, rql)
         self.system_source.delete_info_multi(session, [entity], sourceuri)
@@ -1153,6 +1172,8 @@
         the same etype and belinging to the same source.
         """
         pendingrtypes = session.transaction_data.get('pendingrtypes', ())
+        if scleanup is not None:
+            source = self.sources_by_eid[scleanup]
         # delete remaining relations: if user can delete the entity, he can
         # delete all its relations without security checking
         with security_enabled(session, read=False, write=False):
@@ -1169,11 +1190,20 @@
                 else:
                     rql = 'DELETE Y %s X WHERE X eid IN (%s)' % (rtype, in_eids)
                 if scleanup is not None:
+                    # if the relation can't be crossed, nothing to cleanup (we
+                    # would get a BadRQLQuery from the multi-sources planner).
+                    # This may still leave some junk if the mapping has changed
+                    # at some point, but one can still run db-check to catch
+                    # those
+                    if not source in self.can_cross_relation(rtype):
+                        continue
                     # source cleaning: only delete relations stored locally
                     rql += ', NOT (Y cw_source S, S eid %(seid)s)'
                 try:
                     session.execute(rql, {'seid': scleanup}, build_descr=False)
                 except Exception:
+                    if self.config.mode == 'test':
+                        raise
                     self.exception('error while cascading delete for entity %s '
                                    'from %s. RQL: %s', entities, sourceuri, rql)
         self.system_source.delete_info_multi(session, entities, sourceuri)