diff --git a/sat/memory/sqlite.py b/sat/memory/sqlite.py index 97ddf336..fb1620e1 100644 --- a/sat/memory/sqlite.py +++ b/sat/memory/sqlite.py @@ -1193,6 +1193,30 @@ class Updater(object): def update_v7(self): """Update database from v6 to v7 (history unique constraint change)""" log.info(u"Database update to v7, this may take a while") + + log.info(u"some cleaning first") + # we need to fix duplicate stanza_id, as it can result in conflicts with the new schema + # normally database should not contain any, but better safe than sorry. + rows = yield self.dbpool.runQuery( + u"SELECT stanza_id, COUNT(*) as c FROM history WHERE stanza_id is not NULL " + u"GROUP BY stanza_id HAVING c>1") + if rows: + count = sum([r[1] for r in rows]) - len(rows) + log.info(u"{count} duplicate stanzas found, cleaning".format(count=count)) + for stanza_id, count in rows: + log.info(u"cleaning duplicate stanza {stanza_id}".format(stanza_id=stanza_id)) + row_uids = yield self.dbpool.runQuery( + "SELECT uid FROM history WHERE stanza_id = ? LIMIT ?", + (stanza_id, count-1)) + uids = [r[0] for r in row_uids] + yield self.dbpool.runQuery( + "DELETE FROM history WHERE uid IN ({})".format(u",".join(u"?"*len(uids))), + uids) + + log.info(u'Deleting "info" messages (this can take a while, please be patient)') + yield self.dbpool.runQuery(u"DELETE FROM history where type='info'"); + log.info(u"Cleaning done") + # we have to rename table we will replace # tables referencing history need to be replaced to, else reference would # be to the old table (which will be dropped at the end). This buggy behaviour @@ -1202,25 +1226,6 @@ class Updater(object): yield self.dbpool.runQuery("ALTER TABLE subject RENAME TO subject_old") yield self.dbpool.runQuery("ALTER TABLE thread RENAME TO thread_old") - # we need to fix duplicate stanza_id, as it can result in conflicts with the new schema - # normally database should not contain any, but better safe than sorry. - rows = yield self.dbpool.runQuery( - u"SELECT stanza_id, COUNT(*) as c FROM history_old WHERE stanza_id is not NULL " - u"GROUP BY stanza_id HAVING c>1") - if rows: - count = sum([r[1] for r in rows]) - len(rows) - log.info(u"{count} duplicate stanzas found, cleaning".format(count=count)) - for stanza_id, count in rows: - log.info(u"cleaning duplicate stanza {stanza_id}".format(stanza_id=stanza_id)) - row_uids = yield self.dbpool.runQuery( - "SELECT uid FROM history_old WHERE stanza_id = ? LIMIT ?", - (stanza_id, count-1)) - uids = [r[0] for r in row_uids] - yield self.dbpool.runQuery( - "DELETE FROM history_old WHERE uid IN ({})".format(u",".join(u"?"*len(uids))), - uids) - log.info(u"Cleaning done") - # history query = (u"CREATE TABLE history (uid TEXT PRIMARY KEY, stanza_id TEXT, " u"update_uid TEXT, profile_id INTEGER, source TEXT, dest TEXT, " @@ -1249,8 +1254,7 @@ class Updater(object): u"history(uid) ON DELETE CASCADE)") yield self.dbpool.runQuery(query) - log.info(u"Now transfering old data to new tables, this can be really long " - u"depending on your history size, please be patient.") + log.info(u"Now transfering old data to new tables, please be patient.") log.info(u"\nTransfering table history") query = (u"INSERT INTO history (uid, stanza_id, update_uid, profile_id, source, " @@ -1275,10 +1279,12 @@ class Updater(object): u", history_uid, thread_id, parent_id FROM thread_old") yield self.dbpool.runQuery(query) - yield self.dbpool.runQuery("DROP TABLE history_old") - yield self.dbpool.runQuery("DROP TABLE message_old") - yield self.dbpool.runQuery("DROP TABLE subject_old") + # because of foreign keys, tables referencing history_old + # must be deleted first yield self.dbpool.runQuery("DROP TABLE thread_old") + yield self.dbpool.runQuery("DROP TABLE subject_old") + yield self.dbpool.runQuery("DROP TABLE message_old") + yield self.dbpool.runQuery("DROP TABLE history_old") log.info(u"Database update done :)") @defer.inlineCallbacks