# HG changeset patch # User Julien Cristau # Date 1421408146 -3600 # Node ID 4c64a41c0a1d04c14e59ef7878dedf9505fe1988 # Parent 249126034c0e5e3a4588f570277f4711d778717a Use a moved_entities table to record external entities moved to the system source Instead of using a negative eid in the entities table, move the record to a new table so we don't have an interval with a missing eid in entities. Related to #4846892 diff -r 249126034c0e -r 4c64a41c0a1d hooks/metadata.py --- a/hooks/metadata.py Fri Jan 16 12:43:32 2015 +0100 +++ b/hooks/metadata.py Fri Jan 16 12:35:46 2015 +0100 @@ -199,17 +199,15 @@ oldsource = self._cw.entity_from_eid(schange[self.eidfrom]) entity = self._cw.entity_from_eid(self.eidfrom) # we don't want the moved entity to be reimported later. To - # distinguish this state, the trick is to change the associated - # record in the 'entities' system table with eid=-eid while leaving - # other fields unchanged, and to add a new record with eid=eid, - # source='system'. External source will then have consider case - # where `extid2eid` return a negative eid as 'this entity was known - # but has been moved, ignore it'. - self._cw.system_sql('UPDATE entities SET eid=-eid WHERE eid=%(eid)s', - {'eid': self.eidfrom}) + # distinguish this state, move the record from the 'entities' table + # to 'moved_entities'. External source will then have consider + # case where `extid2eid` returns a negative eid as 'this entity was + # known but has been moved, ignore it'. + attrs = {'eid': entity.eid, 'extid': self._cw.entity_metas(entity.eid)['extid']} + self._cw.system_sql(syssource.sqlgen.insert('moved_entities', attrs), attrs) attrs = {'type': entity.cw_etype, 'eid': entity.eid, 'extid': None, 'asource': 'system'} - self._cw.system_sql(syssource.sqlgen.insert('entities', attrs), attrs) + self._cw.system_sql(syssource.sqlgen.update('entities', attrs, ['eid']), attrs) # register an operation to update repository/sources caches ChangeEntitySourceUpdateCaches(self._cw, entity=entity, oldsource=oldsource.repo_source, diff -r 249126034c0e -r 4c64a41c0a1d misc/migration/3.21.0_Any.py --- a/misc/migration/3.21.0_Any.py Fri Jan 16 12:43:32 2015 +0100 +++ b/misc/migration/3.21.0_Any.py Fri Jan 16 12:35:46 2015 +0100 @@ -2,4 +2,18 @@ helper = repo.system_source.dbhelper sql('DROP INDEX entities_extid_idx') sql(helper.sql_create_index('entities', 'extid', True)) + +sql(''' +CREATE TABLE moved_entities ( + eid INTEGER PRIMARY KEY NOT NULL, + extid VARCHAR(256) UNIQUE +) +''') + +moved_entities = sql('SELECT -eid, extid FROM entities WHERE eid < 0') +cu = session.cnxset.cu +cu.executemany('INSERT INTO moved_entities (eid, extid) VALUES (%s, %s)', + moved_entities) +sql('DELETE FROM entities WHERE eid < 0') + commit() diff -r 249126034c0e -r 4c64a41c0a1d server/sources/native.py --- a/server/sources/native.py Fri Jan 16 12:43:32 2015 +0100 +++ b/server/sources/native.py Fri Jan 16 12:35:46 2015 +0100 @@ -868,9 +868,10 @@ def extid2eid(self, cnx, extid): """get eid from an external id. Return None if no record found.""" assert isinstance(extid, str) + args = {'x': b64encode(extid)} cursor = self.doexec(cnx, 'SELECT eid FROM entities WHERE extid=%(x)s', - {'x': b64encode(extid)}) + args) # XXX testing rowcount cause strange bug with sqlite, results are there # but rowcount is 0 #if cursor.rowcount > 0: @@ -880,6 +881,17 @@ return result[0] except Exception: pass + cursor = self.doexec(cnx, + 'SELECT eid FROM moved_entities WHERE extid=%(x)s', + args) + try: + result = cursor.fetchone() + if result: + # entity was moved to the system source, return negative + # number to tell the external source to ignore it + return -result[0] + except Exception: + pass return None def _handle_is_relation_sql(self, cnx, sql, attrs): @@ -1390,6 +1402,10 @@ extid VARCHAR(256) UNIQUE );; CREATE INDEX entities_type_idx ON entities(type);; +CREATE TABLE moved_entities ( + eid INTEGER PRIMARY KEY NOT NULL, + extid VARCHAR(256) UNIQUE +);; CREATE TABLE transactions ( tx_uuid CHAR(32) PRIMARY KEY NOT NULL,