[source] update system table and internal structures on source renaming. Closes #1896721 stable
authorSylvain Thénault <sylvain.thenault@logilab.fr>
Thu, 04 Aug 2011 12:50:49 +0200
branchstable
changeset 7735 71adfd6bab38
parent 7734 59fea81647e5
child 7736 8767d03dab17
[source] update system table and internal structures on source renaming. Closes #1896721
hooks/syncsources.py
server/test/unittest_datafeed.py
--- a/hooks/syncsources.py	Thu Aug 04 12:50:48 2011 +0200
+++ b/hooks/syncsources.py	Thu Aug 04 12:50:49 2011 +0200
@@ -19,6 +19,7 @@
 
 from socket import gethostname
 
+from logilab.common.decorators import clear_cache
 from yams.schema import role_name
 
 from cubicweb import ValidationError
@@ -66,7 +67,7 @@
         SourceRemovedOp(self._cw, uri=self.entity.name)
 
 
-class SourceUpdatedOp(hook.DataOperationMixIn, hook.Operation):
+class SourceConfigUpdatedOp(hook.DataOperationMixIn, hook.Operation):
 
     def precommit_event(self):
         self.__processed = []
@@ -79,13 +80,45 @@
         for source, conf in self.__processed:
             source.repo_source.update_config(source, conf)
 
+
+class SourceRenamedOp(hook.LateOperation):
+
+    def precommit_event(self):
+        source = self.session.repo.sources_by_uri[self.oldname]
+        if source.copy_based_source:
+            sql = 'UPDATE entities SET asource=%(newname)s WHERE asource=%(oldname)s'
+        else:
+            sql = 'UPDATE entities SET source=%(newname)s, asource=%(newname)s WHERE source=%(oldname)s'
+        self.session.system_sql(sql, {'oldname': self.oldname,
+                                      'newname': self.newname})
+
+    def postcommit_event(self):
+        repo = self.session.repo
+        # XXX race condition
+        source = repo.sources_by_uri.pop(self.oldname)
+        source.uri = self.newname
+        source.public_config['uri'] = self.newname
+        repo.sources_by_uri[self.newname] = source
+        repo._type_source_cache.clear()
+        clear_cache(repo, 'source_defs')
+        if not source.copy_based_source:
+            repo._extid_cache.clear()
+            repo._clear_planning_caches()
+            for cnxset in repo.cnxsets:
+                cnxset.source_cnxs[self.oldname] = cnxset.source_cnxs.pop(self.oldname)
+
+
 class SourceUpdatedHook(SourceHook):
     __regid__ = 'cw.sources.configupdate'
     __select__ = SourceHook.__select__ & is_instance('CWSource')
-    events = ('after_update_entity',)
+    events = ('before_update_entity',)
     def __call__(self):
         if 'config' in self.entity.cw_edited:
-            SourceUpdatedOp.get_instance(self._cw).add_data(self.entity)
+            SourceConfigUpdatedOp.get_instance(self._cw).add_data(self.entity)
+        if 'name' in self.entity.cw_edited:
+            oldname, newname = self.entity.cw_edited.oldnewvalue('name')
+            SourceRenamedOp(self._cw, oldname=oldname, newname=newname)
+
 
 class SourceHostConfigUpdatedHook(SourceHook):
     __regid__ = 'cw.sources.hostconfigupdate'
@@ -97,7 +130,7 @@
                    not 'config' in self.entity.cw_edited:
                 return
             try:
-                SourceUpdatedOp.get_instance(self._cw).add_data(self.entity.cwsource)
+                SourceConfigUpdatedOp.get_instance(self._cw).add_data(self.entity.cwsource)
             except IndexError:
                 # XXX no source linked to the host config yet
                 pass
--- a/server/test/unittest_datafeed.py	Thu Aug 04 12:50:48 2011 +0200
+++ b/server/test/unittest_datafeed.py	Thu Aug 04 12:50:49 2011 +0200
@@ -94,9 +94,26 @@
         self.assertTrue(dfsource.latest_retrieval)
         self.assertTrue(dfsource.fresh())
 
+        # test_rename_source
+        req = self.request()
+        req.execute('SET S name "myrenamedfeed" WHERE S is CWSource, S name "myfeed"')
+        self.commit()
+        entity = self.execute('Card X').get_entity(0, 0)
+        self.assertEqual(entity.cwuri, 'http://www.cubicweb.org/')
+        self.assertEqual(entity.cw_source[0].name, 'myrenamedfeed')
+        self.assertEqual(entity.cw_metainformation(),
+                         {'type': 'Card',
+                          'source': {'uri': 'myrenamedfeed', 'type': 'datafeed', 'use-cwuri-as-url': True},
+                          'extid': 'http://www.cubicweb.org/'}
+                         )
+        self.assertEqual(self.repo._type_source_cache[entity.eid],
+                         ('Card', 'system', 'http://www.cubicweb.org/', 'myrenamedfeed'))
+        self.assertEqual(self.repo._extid_cache[('http://www.cubicweb.org/', 'system')],
+                         entity.eid)
+
         # test_delete_source
         req = self.request()
-        req.execute('DELETE CWSource S WHERE S name "myfeed"')
+        req.execute('DELETE CWSource S WHERE S name "myrenamedfeed"')
         self.commit()
         self.failIf(self.execute('Card X WHERE X title "cubicweb.org"'))
         self.failIf(self.execute('Any X WHERE X has_text "cubicweb.org"'))