schema: reference package table by integer key
[~helmut/debian-dedup.git] / update_sharing.py
1 #!/usr/bin/python
2
3 import sqlite3
4
5 from dedup.utils import fetchiter
6
7 def add_values(cursor, insert_key, files, size):
8     cursor.execute("UPDATE sharing SET files = files + ?, size = size + ? WHERE pid1 = ? AND pid2 = ? AND func1 = ? AND func2 = ?;",
9                    (files, size) + insert_key)
10     if cursor.rowcount > 0:
11         return
12     cursor.execute("INSERT INTO sharing (pid1, pid2, func1, func2, files, size) VALUES (?, ?, ?, ?, ?, ?);",
13                    insert_key + (files, size))
14
15 def compute_pkgdict(rows):
16     pkgdict = dict()
17     for pid, _, filename, size, function in rows:
18         funcdict = pkgdict.setdefault(pid, {})
19         funcdict.setdefault(function, []).append((size, filename))
20     return pkgdict
21
22 def process_pkgdict(cursor, pkgdict):
23     for pid1, funcdict1 in pkgdict.items():
24         for function1, files in funcdict1.items():
25             numfiles = len(files)
26             size = sum(entry[0] for entry in files)
27             for pid2, funcdict2 in pkgdict.items():
28                 if pid1 == pid2:
29                     pkgnumfiles = numfiles - 1
30                     pkgsize = size - min(entry[0] for entry in files)
31                     if pkgnumfiles == 0:
32                         continue
33                 else:
34                     pkgnumfiles = numfiles
35                     pkgsize = size
36                 for function2 in funcdict2.keys():
37                     insert_key = (pid1, pid2, function1, function2)
38                     add_values(cursor, insert_key, pkgnumfiles, pkgsize)
39
40 def main():
41     db = sqlite3.connect("test.sqlite3")
42     cur = db.cursor()
43     cur.execute("PRAGMA foreign_keys = ON;")
44     cur.execute("DELETE FROM sharing;")
45     cur.execute("DELETE FROM duplicate;")
46     readcur = db.cursor()
47     readcur.execute("SELECT hash FROM hash GROUP BY hash HAVING count(*) > 1;")
48     for hashvalue, in fetchiter(readcur):
49         cur.execute("SELECT content.pid, content.id, content.filename, content.size, hash.function FROM hash JOIN content ON hash.cid = content.id WHERE hash = ?;",
50                     (hashvalue,))
51         rows = cur.fetchall()
52         print("processing hash %s with %d entries" % (hashvalue, len(rows)))
53         pkgdict = compute_pkgdict(rows)
54         cur.executemany("INSERT OR IGNORE INTO duplicate (cid) VALUES (?);",
55                         [(row[1],) for row in rows])
56         process_pkgdict(cur, pkgdict)
57     db.commit()
58
59 if __name__ == "__main__":
60     main()