1072 """ |
1072 """ |
1073 # begin by inserting eid/type/source/extid into the entities table |
1073 # begin by inserting eid/type/source/extid into the entities table |
1074 hook.CleanupNewEidsCacheOp.get_instance(session).add_data(entity.eid) |
1074 hook.CleanupNewEidsCacheOp.get_instance(session).add_data(entity.eid) |
1075 self.system_source.add_info(session, entity, source, extid) |
1075 self.system_source.add_info(session, entity, source, extid) |
1076 |
1076 |
1077 def delete_info(self, session, entity, sourceuri): |
1077 def _delete_cascade_multi(self, session, entities): |
1078 """called by external source when some entity known by the system source |
1078 """same as _delete_cascade but accepts a list of entities with |
1079 has been deleted in the external source |
1079 the same etype and belonging to the same source. |
1080 """ |
|
1081 # mark eid as being deleted in session info and setup cache update |
|
1082 # operation |
|
1083 hook.CleanupDeletedEidsCacheOp.get_instance(session).add_data(entity.eid) |
|
1084 self._delete_info(session, entity, sourceuri) |
|
1085 |
|
1086 def _delete_info(self, session, entity, sourceuri): |
|
1087 """delete system information on deletion of an entity: |
|
1088 |
|
1089 * delete all remaining relations from/to this entity |
|
1090 * call delete info on the system source |
|
1091 """ |
|
1092 pendingrtypes = session.transaction_data.get('pendingrtypes', ()) |
|
1093 # delete remaining relations: if user can delete the entity, he can |
|
1094 # delete all its relations without security checking |
|
1095 with session.security_enabled(read=False, write=False): |
|
1096 eid = entity.eid |
|
1097 for rschema, _, role in entity.e_schema.relation_definitions(): |
|
1098 rtype = rschema.type |
|
1099 if rtype in schema.VIRTUAL_RTYPES or rtype in pendingrtypes: |
|
1100 continue |
|
1101 if role == 'subject': |
|
1102 # don't skip inlined relation so they are regularly |
|
1103 # deleted and so hooks are correctly called |
|
1104 rql = 'DELETE X %s Y WHERE X eid %%(x)s' % rtype |
|
1105 else: |
|
1106 rql = 'DELETE Y %s X WHERE X eid %%(x)s' % rtype |
|
1107 try: |
|
1108 session.execute(rql, {'x': eid}, build_descr=False) |
|
1109 except Exception: |
|
1110 if self.config.mode == 'test': |
|
1111 raise |
|
1112 self.exception('error while cascading delete for entity %s ' |
|
1113 'from %s. RQL: %s', entity, sourceuri, rql) |
|
1114 self.system_source.delete_info_multi(session, [entity]) |
|
1115 |
|
1116 def _delete_info_multi(self, session, entities): |
|
1117 """same as _delete_info but accepts a list of entities with |
|
1118 the same etype and belinging to the same source. |
|
1119 """ |
1080 """ |
1120 pendingrtypes = session.transaction_data.get('pendingrtypes', ()) |
1081 pendingrtypes = session.transaction_data.get('pendingrtypes', ()) |
1121 # delete remaining relations: if user can delete the entity, he can |
1082 # delete remaining relations: if user can delete the entity, he can |
1122 # delete all its relations without security checking |
1083 # delete all its relations without security checking |
1123 with session.security_enabled(read=False, write=False): |
1084 with session.security_enabled(read=False, write=False): |
1144 except Exception: |
1105 except Exception: |
1145 if self.config.mode == 'test': |
1106 if self.config.mode == 'test': |
1146 raise |
1107 raise |
1147 self.exception('error while cascading delete for entity %s. RQL: %s', |
1108 self.exception('error while cascading delete for entity %s. RQL: %s', |
1148 entities, rql) |
1109 entities, rql) |
1149 self.system_source.delete_info_multi(session, entities) |
|
1150 |
1110 |
1151 def init_entity_caches(self, cnx, entity, source): |
1111 def init_entity_caches(self, cnx, entity, source): |
1152 """add entity to connection entities cache and repo's extid cache. |
1112 """add entity to connection entities cache and repo's extid cache. |
1153 Return entity's ext id if the source isn't the system source. |
1113 Return entity's ext id if the source isn't the system source. |
1154 """ |
1114 """ |
1182 self.hm.call_hooks('before_add_entity', cnx, entity=entity) |
1142 self.hm.call_hooks('before_add_entity', cnx, entity=entity) |
1183 relations = preprocess_inlined_relations(cnx, entity) |
1143 relations = preprocess_inlined_relations(cnx, entity) |
1184 edited.set_defaults() |
1144 edited.set_defaults() |
1185 if cnx.is_hook_category_activated('integrity'): |
1145 if cnx.is_hook_category_activated('integrity'): |
1186 edited.check(creation=True) |
1146 edited.check(creation=True) |
|
1147 self.add_info(cnx, entity, source, extid) |
1187 try: |
1148 try: |
1188 source.add_entity(cnx, entity) |
1149 source.add_entity(cnx, entity) |
1189 except UniqueTogetherError as exc: |
1150 except UniqueTogetherError as exc: |
1190 userhdlr = cnx.vreg['adapters'].select( |
1151 userhdlr = cnx.vreg['adapters'].select( |
1191 'IUserFriendlyError', cnx, entity=entity, exc=exc) |
1152 'IUserFriendlyError', cnx, entity=entity, exc=exc) |
1192 userhdlr.raise_user_exception() |
1153 userhdlr.raise_user_exception() |
1193 self.add_info(cnx, entity, source, extid) |
|
1194 edited.saved = entity._cw_is_saved = True |
1154 edited.saved = entity._cw_is_saved = True |
1195 # trigger after_add_entity after after_add_relation |
1155 # trigger after_add_entity after after_add_relation |
1196 self.hm.call_hooks('after_add_entity', cnx, entity=entity) |
1156 self.hm.call_hooks('after_add_entity', cnx, entity=entity) |
1197 # call hooks for inlined relations |
1157 # call hooks for inlined relations |
1198 for attr, value in relations: |
1158 for attr, value in relations: |
1303 source = self.system_source |
1263 source = self.system_source |
1304 for etype, entities in data_by_etype.iteritems(): |
1264 for etype, entities in data_by_etype.iteritems(): |
1305 if server.DEBUG & server.DBG_REPO: |
1265 if server.DEBUG & server.DBG_REPO: |
1306 print 'DELETE entities', etype, [entity.eid for entity in entities] |
1266 print 'DELETE entities', etype, [entity.eid for entity in entities] |
1307 self.hm.call_hooks('before_delete_entity', cnx, entities=entities) |
1267 self.hm.call_hooks('before_delete_entity', cnx, entities=entities) |
1308 self._delete_info_multi(cnx, entities) |
1268 self._delete_cascade_multi(cnx, entities) |
1309 source.delete_entities(cnx, entities) |
1269 source.delete_entities(cnx, entities) |
|
1270 source.delete_info_multi(cnx, entities) |
1310 self.hm.call_hooks('after_delete_entity', cnx, entities=entities) |
1271 self.hm.call_hooks('after_delete_entity', cnx, entities=entities) |
1311 # don't clear cache here, it is done in a hook on commit |
1272 # don't clear cache here, it is done in a hook on commit |
1312 |
1273 |
1313 def glob_add_relation(self, cnx, subject, rtype, object): |
1274 def glob_add_relation(self, cnx, subject, rtype, object): |
1314 """add a relation to the repository""" |
1275 """add a relation to the repository""" |