server/repository.py
changeset 7894 ad0eeb0f7a8d
parent 7845 2172978be237
parent 7887 42a0b7398d31
child 7907 08320697ca1a
equal deleted inserted replaced
7889:6cebeb1f386a 7894:ad0eeb0f7a8d
  1104         """
  1104         """
  1105         # begin by inserting eid/type/source/extid into the entities table
  1105         # begin by inserting eid/type/source/extid into the entities table
  1106         hook.CleanupNewEidsCacheOp.get_instance(session).add_data(entity.eid)
  1106         hook.CleanupNewEidsCacheOp.get_instance(session).add_data(entity.eid)
  1107         self.system_source.add_info(session, entity, source, extid, complete)
  1107         self.system_source.add_info(session, entity, source, extid, complete)
  1108 
  1108 
  1109     def delete_info(self, session, entity, sourceuri, extid, scleanup=None):
  1109     def delete_info(self, session, entity, sourceuri, scleanup=None):
  1110         """called by external source when some entity known by the system source
  1110         """called by external source when some entity known by the system source
  1111         has been deleted in the external source
  1111         has been deleted in the external source
  1112         """
  1112         """
  1113         # mark eid as being deleted in session info and setup cache update
  1113         # mark eid as being deleted in session info and setup cache update
  1114         # operation
  1114         # operation
  1115         hook.CleanupDeletedEidsCacheOp.get_instance(session).add_data(entity.eid)
  1115         hook.CleanupDeletedEidsCacheOp.get_instance(session).add_data(entity.eid)
  1116         self._delete_info(session, entity, sourceuri, extid, scleanup)
  1116         self._delete_info(session, entity, sourceuri, scleanup)
  1117 
  1117 
  1118     def _delete_info(self, session, entity, sourceuri, extid, scleanup=None):
  1118     def _delete_info(self, session, entity, sourceuri, scleanup=None):
  1119         """delete system information on deletion of an entity:
  1119         """delete system information on deletion of an entity:
       
  1120 
  1120         * delete all remaining relations from/to this entity
  1121         * delete all remaining relations from/to this entity
       
  1122 
  1121         * call delete info on the system source which will transfer record from
  1123         * call delete info on the system source which will transfer record from
  1122           the entities table to the deleted_entities table
  1124           the entities table to the deleted_entities table
       
  1125 
       
  1126         When scleanup is specified, it's expected to be the source's eid, in
       
  1127         which case we'll specify the target's relation source so that this
       
  1128         source is ignored. E.g. we want to delete relations stored locally, as
       
  1129         the deletion information comes from the external source, it's its
       
  1130         responsability to have cleaned-up its own relations.
  1123         """
  1131         """
  1124         pendingrtypes = session.transaction_data.get('pendingrtypes', ())
  1132         pendingrtypes = session.transaction_data.get('pendingrtypes', ())
       
  1133         if scleanup is not None:
       
  1134             source = self.sources_by_eid[scleanup]
  1125         # delete remaining relations: if user can delete the entity, he can
  1135         # delete remaining relations: if user can delete the entity, he can
  1126         # delete all its relations without security checking
  1136         # delete all its relations without security checking
  1127         with security_enabled(session, read=False, write=False):
  1137         with security_enabled(session, read=False, write=False):
  1128             eid = entity.eid
  1138             eid = entity.eid
  1129             for rschema, _, role in entity.e_schema.relation_definitions():
  1139             for rschema, _, role in entity.e_schema.relation_definitions():
  1135                     # deleted and so hooks are correctly called
  1145                     # deleted and so hooks are correctly called
  1136                     rql = 'DELETE X %s Y WHERE X eid %%(x)s' % rtype
  1146                     rql = 'DELETE X %s Y WHERE X eid %%(x)s' % rtype
  1137                 else:
  1147                 else:
  1138                     rql = 'DELETE Y %s X WHERE X eid %%(x)s' % rtype
  1148                     rql = 'DELETE Y %s X WHERE X eid %%(x)s' % rtype
  1139                 if scleanup is not None:
  1149                 if scleanup is not None:
       
  1150                     # if the relation can't be crossed, nothing to cleanup (we
       
  1151                     # would get a BadRQLQuery from the multi-sources planner).
       
  1152                     # This may still leave some junk if the mapping has changed
       
  1153                     # at some point, but one can still run db-check to catch
       
  1154                     # those
       
  1155                     if not source in self.can_cross_relation(rtype):
       
  1156                         continue
  1140                     # source cleaning: only delete relations stored locally
  1157                     # source cleaning: only delete relations stored locally
  1141                     # (here, scleanup
  1158                     # (here, scleanup
  1142                     rql += ', NOT (Y cw_source S, S eid %(seid)s)'
  1159                     rql += ', NOT (Y cw_source S, S eid %(seid)s)'
  1143                 try:
  1160                 try:
  1144                     session.execute(rql, {'x': eid, 'seid': scleanup},
  1161                     session.execute(rql, {'x': eid, 'seid': scleanup},
  1145                                     build_descr=False)
  1162                                     build_descr=False)
  1146                 except Exception:
  1163                 except Exception:
       
  1164                     if self.config.mode == 'test':
       
  1165                         raise
  1147                     self.exception('error while cascading delete for entity %s '
  1166                     self.exception('error while cascading delete for entity %s '
  1148                                    'from %s. RQL: %s', entity, sourceuri, rql)
  1167                                    'from %s. RQL: %s', entity, sourceuri, rql)
  1149         self.system_source.delete_info_multi(session, [entity], sourceuri)
  1168         self.system_source.delete_info_multi(session, [entity], sourceuri)
  1150 
  1169 
  1151     def _delete_info_multi(self, session, entities, sourceuri, scleanup=None):
  1170     def _delete_info_multi(self, session, entities, sourceuri, scleanup=None):
  1152         """same as _delete_info but accepts a list of entities with
  1171         """same as _delete_info but accepts a list of entities with
  1153         the same etype and belinging to the same source.
  1172         the same etype and belinging to the same source.
  1154         """
  1173         """
  1155         pendingrtypes = session.transaction_data.get('pendingrtypes', ())
  1174         pendingrtypes = session.transaction_data.get('pendingrtypes', ())
       
  1175         if scleanup is not None:
       
  1176             source = self.sources_by_eid[scleanup]
  1156         # delete remaining relations: if user can delete the entity, he can
  1177         # delete remaining relations: if user can delete the entity, he can
  1157         # delete all its relations without security checking
  1178         # delete all its relations without security checking
  1158         with security_enabled(session, read=False, write=False):
  1179         with security_enabled(session, read=False, write=False):
  1159             eids = [_e.eid for _e in entities]
  1180             eids = [_e.eid for _e in entities]
  1160             in_eids = ','.join((str(eid) for eid in eids))
  1181             in_eids = ','.join((str(eid) for eid in eids))
  1167                     # deleted and so hooks are correctly called
  1188                     # deleted and so hooks are correctly called
  1168                     rql = 'DELETE X %s Y WHERE X eid IN (%s)' % (rtype, in_eids)
  1189                     rql = 'DELETE X %s Y WHERE X eid IN (%s)' % (rtype, in_eids)
  1169                 else:
  1190                 else:
  1170                     rql = 'DELETE Y %s X WHERE X eid IN (%s)' % (rtype, in_eids)
  1191                     rql = 'DELETE Y %s X WHERE X eid IN (%s)' % (rtype, in_eids)
  1171                 if scleanup is not None:
  1192                 if scleanup is not None:
       
  1193                     # if the relation can't be crossed, nothing to cleanup (we
       
  1194                     # would get a BadRQLQuery from the multi-sources planner).
       
  1195                     # This may still leave some junk if the mapping has changed
       
  1196                     # at some point, but one can still run db-check to catch
       
  1197                     # those
       
  1198                     if not source in self.can_cross_relation(rtype):
       
  1199                         continue
  1172                     # source cleaning: only delete relations stored locally
  1200                     # source cleaning: only delete relations stored locally
  1173                     rql += ', NOT (Y cw_source S, S eid %(seid)s)'
  1201                     rql += ', NOT (Y cw_source S, S eid %(seid)s)'
  1174                 try:
  1202                 try:
  1175                     session.execute(rql, {'seid': scleanup}, build_descr=False)
  1203                     session.execute(rql, {'seid': scleanup}, build_descr=False)
  1176                 except Exception:
  1204                 except Exception:
       
  1205                     if self.config.mode == 'test':
       
  1206                         raise
  1177                     self.exception('error while cascading delete for entity %s '
  1207                     self.exception('error while cascading delete for entity %s '
  1178                                    'from %s. RQL: %s', entities, sourceuri, rql)
  1208                                    'from %s. RQL: %s', entities, sourceuri, rql)
  1179         self.system_source.delete_info_multi(session, entities, sourceuri)
  1209         self.system_source.delete_info_multi(session, entities, sourceuri)
  1180 
  1210 
  1181     def locate_relation_source(self, session, subject, rtype, object):
  1211     def locate_relation_source(self, session, subject, rtype, object):