80 for rschema in entity.e_schema.object_relations(): |
80 for rschema in entity.e_schema.object_relations(): |
81 rtype = str(rschema) |
81 rtype = str(rschema) |
82 if rtype in schema.VIRTUAL_RTYPES or (rtype, 'object') in NO_CACHE_RELATIONS: |
82 if rtype in schema.VIRTUAL_RTYPES or (rtype, 'object') in NO_CACHE_RELATIONS: |
83 continue |
83 continue |
84 entity.cw_set_relation_cache(rtype, 'object', session.empty_rset()) |
84 entity.cw_set_relation_cache(rtype, 'object', session.empty_rset()) |
85 # set inlined relation cache before call to after_add_entity |
|
86 for attr, value in relations: |
|
87 session.update_rel_cache_add(entity.eid, attr, value) |
|
88 del_existing_rel_if_needed(session, entity.eid, attr, value) |
|
89 |
85 |
90 def del_existing_rel_if_needed(session, eidfrom, rtype, eidto): |
86 def del_existing_rel_if_needed(session, eidfrom, rtype, eidto): |
91 """delete existing relation when adding a new one if card is 1 or ? |
87 """delete existing relation when adding a new one if card is 1 or ? |
92 |
88 |
93 have to be done once the new relation has been inserted to avoid having |
89 have to be done once the new relation has been inserted to avoid having |
94 an entity without a relation for some time |
90 an entity without a relation for some time |
95 |
91 |
96 this kind of behaviour has to be done in the repository so we don't have |
92 this kind of behaviour has to be done in the repository so we don't have |
97 hooks order hazardness |
93 hooks order hazardness |
98 """ |
94 """ |
99 # skip that for internal session or if integrity explicitly disabled |
95 # skip that if integrity explicitly disabled |
100 # |
96 if not session.is_hook_category_activated('activeintegrity'): |
101 # XXX we should imo rely on the orm to first fetch existing entity if any |
|
102 # then delete it. |
|
103 if session.is_internal_session \ |
|
104 or not session.is_hook_category_activated('activeintegrity'): |
|
105 return |
97 return |
106 rdef = session.rtype_eids_rdef(rtype, eidfrom, eidto) |
98 rdef = session.rtype_eids_rdef(rtype, eidfrom, eidto) |
107 card = rdef.cardinality |
99 card = rdef.cardinality |
108 # one may be tented to check for neweids but this may cause more than one |
100 # one may be tented to check for neweids but this may cause more than one |
109 # relation even with '1?' cardinality if thoses relations are added in the |
101 # relation even with '1?' cardinality if thoses relations are added in the |
114 # |
106 # |
115 # notes: |
107 # notes: |
116 # * inlined relations will be implicitly deleted for the subject entity |
108 # * inlined relations will be implicitly deleted for the subject entity |
117 # * we don't want read permissions to be applied but we want delete |
109 # * we don't want read permissions to be applied but we want delete |
118 # permission to be checked |
110 # permission to be checked |
119 if card[0] in '1?' and not rdef.rtype.inlined: |
111 if card[0] in '1?': |
120 with security_enabled(session, read=False): |
112 with security_enabled(session, read=False): |
121 session.execute('DELETE X %s Y WHERE X eid %%(x)s, ' |
113 session.execute('DELETE X %s Y WHERE X eid %%(x)s, ' |
122 'NOT Y eid %%(y)s' % rtype, |
114 'NOT Y eid %%(y)s' % rtype, |
123 {'x': eidfrom, 'y': eidto}) |
115 {'x': eidfrom, 'y': eidto}) |
124 if card[1] in '1?': |
116 if card[1] in '1?': |
1221 # set caches asap |
1213 # set caches asap |
1222 extid = self.init_entity_caches(session, entity, source) |
1214 extid = self.init_entity_caches(session, entity, source) |
1223 if server.DEBUG & server.DBG_REPO: |
1215 if server.DEBUG & server.DBG_REPO: |
1224 print 'ADD entity', self, entity.__regid__, entity.eid, edited |
1216 print 'ADD entity', self, entity.__regid__, entity.eid, edited |
1225 relations = [] |
1217 relations = [] |
|
1218 prefill_entity_caches(entity, relations) |
1226 if source.should_call_hooks: |
1219 if source.should_call_hooks: |
1227 self.hm.call_hooks('before_add_entity', session, entity=entity) |
1220 self.hm.call_hooks('before_add_entity', session, entity=entity) |
|
1221 activintegrity = session.is_hook_category_activated('activeintegrity') |
1228 for attr in edited.iterkeys(): |
1222 for attr in edited.iterkeys(): |
1229 rschema = eschema.subjrels[attr] |
1223 rschema = eschema.subjrels[attr] |
1230 if not rschema.final: # inlined relation |
1224 if not rschema.final: # inlined relation |
1231 relations.append((attr, edited[attr])) |
1225 value = edited[attr] |
|
1226 relations.append((attr, value)) |
|
1227 session.update_rel_cache_add(entity.eid, attr, value) |
|
1228 rdef = session.rtype_eids_rdef(attr, entity.eid, value) |
|
1229 if rdef.cardinality[1] in '1?' and activintegrity: |
|
1230 with security_enabled(session, read=False): |
|
1231 session.execute('DELETE X %s Y WHERE Y eid %(y)s', |
|
1232 {'x': entity.eid, 'y': value}) |
1232 edited.set_defaults() |
1233 edited.set_defaults() |
1233 if session.is_hook_category_activated('integrity'): |
1234 if session.is_hook_category_activated('integrity'): |
1234 edited.check(creation=True) |
1235 edited.check(creation=True) |
1235 prefill_entity_caches(entity, relations) |
|
1236 try: |
1236 try: |
1237 source.add_entity(session, entity) |
1237 source.add_entity(session, entity) |
1238 except UniqueTogetherError, exc: |
1238 except UniqueTogetherError, exc: |
1239 userhdlr = session.vreg['adapters'].select( |
1239 userhdlr = session.vreg['adapters'].select( |
1240 'IUserFriendlyError', session, entity=entity, exc=exc) |
1240 'IUserFriendlyError', session, entity=entity, exc=exc) |