140 session, session.entity_from_eid(self.eidfrom)) |
141 session, session.entity_from_eid(self.eidfrom)) |
141 elif ftcontainer == 'object': |
142 elif ftcontainer == 'object': |
142 session.repo.system_source.index_entity( |
143 session.repo.system_source.index_entity( |
143 session, session.entity_from_eid(self.eidto)) |
144 session, session.entity_from_eid(self.eidto)) |
144 |
145 |
|
146 |
|
147 |
|
148 # entity source handling ####################################################### |
|
149 |
|
150 class ChangeEntityUpdateCaches(hook.Operation): |
|
151 def postcommit_event(self): |
|
152 self.oldsource.reset_caches() |
|
153 repo = self.session.repo |
|
154 entity = self.entity |
|
155 extid = entity.cw_metainformation()['extid'] |
|
156 repo._type_source_cache[entity.eid] = ( |
|
157 entity.__regid__, self.newsource.uri, None) |
|
158 if self.oldsource.copy_based_source: |
|
159 uri = 'system' |
|
160 else: |
|
161 uri = self.oldsource.uri |
|
162 repo._extid_cache[(extid, uri)] = -entity.eid |
|
163 |
|
164 class ChangeEntitySourceDeleteHook(MetaDataHook): |
|
165 """support for moving an entity from an external source by watching 'Any |
|
166 cw_source CWSource' relation |
|
167 """ |
|
168 |
|
169 __regid__ = 'cw.metadata.source-change' |
|
170 __select__ = MetaDataHook.__select__ & hook.match_rtype('cw_source') |
|
171 events = ('before_delete_relation',) |
|
172 |
|
173 def __call__(self): |
|
174 if (self._cw.deleted_in_transaction(self.eidfrom) |
|
175 or self._cw.deleted_in_transaction(self.eidto)): |
|
176 return |
|
177 schange = self._cw.transaction_data.setdefault('cw_source_change', {}) |
|
178 schange[self.eidfrom] = self.eidto |
|
179 |
|
180 class ChangeEntitySourceAddHook(MetaDataHook): |
|
181 __regid__ = 'cw.metadata.source-change' |
|
182 __select__ = MetaDataHook.__select__ & hook.match_rtype('cw_source') |
|
183 events = ('before_add_relation',) |
|
184 |
|
185 def __call__(self): |
|
186 schange = self._cw.transaction_data.get('cw_source_change') |
|
187 if schange is not None and self.eidfrom in schange: |
|
188 newsource = self._cw.entity_from_eid(self.eidto) |
|
189 if newsource.name != 'system': |
|
190 raise Exception('changing source to something else than the ' |
|
191 'system source is unsupported') |
|
192 syssource = newsource.repo_source |
|
193 oldsource = self._cw.entity_from_eid(schange[self.eidfrom]) |
|
194 entity = self._cw.entity_from_eid(self.eidfrom) |
|
195 # copy entity if necessary |
|
196 if not oldsource.repo_source.copy_based_source: |
|
197 entity.complete(skip_bytes=False) |
|
198 entity.cw_edited = EditedEntity(entity, **entity.cw_attr_cache) |
|
199 syssource.add_entity(self._cw, entity) |
|
200 # we don't want the moved entity to be reimported later. To |
|
201 # distinguish this state, the trick is to change the associated |
|
202 # record in the 'entities' system table with eid=-eid while leaving |
|
203 # other fields unchanged, and to add a new record with eid=eid, |
|
204 # source='system'. External source will then have consider case |
|
205 # where `extid2eid` return a negative eid as 'this entity was known |
|
206 # but has been moved, ignore it'. |
|
207 self._cw.system_sql('UPDATE entities SET eid=-eid,source=%(source)s WHERE eid=%(eid)s', |
|
208 {'eid': self.eidfrom, 'source': newsource.name}) |
|
209 attrs = {'type': entity.__regid__, 'eid': entity.eid, 'extid': None, |
|
210 'source': 'system', 'mtime': datetime.now()} |
|
211 self._cw.system_sql(syssource.sqlgen.insert('entities', attrs), attrs) |
|
212 # register an operation to update repository/sources caches |
|
213 ChangeEntityUpdateCaches(self._cw, entity=entity, |
|
214 oldsource=oldsource.repo_source, |
|
215 newsource=syssource) |