annotate sat/memory/sqlite.py @ 2716:06160b529da6

core (memory/sqlite): changed history constraint /!\ Database schema change /!\ History was using a unique constraint on `profile_id, timestamp, source, dest, source_res, dest_res`, which can cause trouble because several messages send quickly by the same person can have a common timestamp (specially with delayed messages where precision is second), resulting in message loss. The new constraint use `profile_id, stanza_id, source, dest` where `stanza_id` is XEP-0359 stanza_id, so it's unique by definition, and no message should be lost anymore. Because sqlite doesn't support altering table with a constraint change, we have to create new tables and copy old data to new one, which can be pretty long. Sqlite update mechanism with "specifics" has been fixed when several updates are applied (e.g. moving from v5 to v7) and a specific is in the workflow.
author Goffi <goffi@goffi.org>
date Sun, 09 Dec 2018 14:07:26 +0100
parents b35c84ea73cf
children 453a12ff6f51
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1934
2daf7b4c6756 use of /usr/bin/env instead of /usr/bin/python in shebang
Goffi <goffi@goffi.org>
parents: 1766
diff changeset
1 #!/usr/bin/env python2
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
2 # -*- coding: utf-8 -*-
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
3
609
84a6e83157c2 fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents: 593
diff changeset
4 # SAT: a jabber client
2483
0046283a285d dates update
Goffi <goffi@goffi.org>
parents: 2414
diff changeset
5 # Copyright (C) 2009-2018 Jérôme Poisson (goffi@goffi.org)
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
6
609
84a6e83157c2 fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents: 593
diff changeset
7 # This program is free software: you can redistribute it and/or modify
84a6e83157c2 fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents: 593
diff changeset
8 # it under the terms of the GNU Affero General Public License as published by
84a6e83157c2 fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents: 593
diff changeset
9 # the Free Software Foundation, either version 3 of the License, or
84a6e83157c2 fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents: 593
diff changeset
10 # (at your option) any later version.
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
11
609
84a6e83157c2 fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents: 593
diff changeset
12 # This program is distributed in the hope that it will be useful,
84a6e83157c2 fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents: 593
diff changeset
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
84a6e83157c2 fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents: 593
diff changeset
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
84a6e83157c2 fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents: 593
diff changeset
15 # GNU Affero General Public License for more details.
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
16
609
84a6e83157c2 fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents: 593
diff changeset
17 # You should have received a copy of the GNU Affero General Public License
84a6e83157c2 fixed licences in docstrings (they are now in comments)
Goffi <goffi@goffi.org>
parents: 593
diff changeset
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
19
771
bfabeedbf32e core: i18n refactoring:
Goffi <goffi@goffi.org>
parents: 681
diff changeset
20 from sat.core.i18n import _
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
21 from sat.core.constants import Const as C
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
22 from sat.core import exceptions
993
301b342c697a core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents: 936
diff changeset
23 from sat.core.log import getLogger
301b342c697a core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents: 936
diff changeset
24 log = getLogger(__name__)
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
25 from sat.memory.crypto import BlockCipher, PasswordHasher
1045
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
26 from sat.tools.config import fixConfigOption
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
27 from twisted.enterprise import adbapi
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
28 from twisted.internet import defer
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
29 from twisted.words.protocols.jabber import jid
1961
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
30 from twisted.python import failure
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
31 from collections import OrderedDict
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
32 import re
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
33 import os.path
432
31e8c48b5f5d core: - memory refactoring (moved memory.py and sqlite.py from tools to memory)
Goffi <goffi@goffi.org>
parents: 425
diff changeset
34 import cPickle as pickle
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
35 import hashlib
1961
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
36 import sqlite3
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
37 import json
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
38
2716
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
39 CURRENT_DB_VERSION = 7
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
40
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
41 # XXX: DATABASE schemas are used in the following way:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
42 # - 'current' key is for the actual database schema, for a new base
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
43 # - x(int) is for update needed between x-1 and x. All number are needed between y and z to do an update
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
44 # e.g.: if CURRENT_DB_VERSION is 6, 'current' is the actuel DB, and to update from version 3, numbers 4, 5 and 6 are needed
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
45 # a 'current' data dict can contains the keys:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
46 # - 'CREATE': it contains an Ordered dict with table to create as keys, and a len 2 tuple as value, where value[0] are the columns definitions and value[1] are the table constraints
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
47 # - 'INSERT': it contains an Ordered dict with table where values have to be inserted, and many tuples containing values to insert in the order of the rows (#TODO: manage named columns)
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
48 # an update data dict (the ones with a number) can contains the keys 'create', 'delete', 'cols create', 'cols delete', 'cols modify', 'insert' or 'specific'. See Updater.generateUpdateData for more infos. This method can be used to autogenerate update_data, to ease the work of the developers.
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
49 # TODO: indexes need to be improved
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
50
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
51 DATABASE_SCHEMAS = {
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
52 "current": {'CREATE': OrderedDict((
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
53 ('profiles', (("id INTEGER PRIMARY KEY ASC", "name TEXT"),
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
54 ("UNIQUE (name)",))),
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
55 ('components', (("profile_id INTEGER PRIMARY KEY", "entry_point TEXT NOT NULL"),
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
56 ("FOREIGN KEY(profile_id) REFERENCES profiles(id) ON DELETE CASCADE",))),
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
57 ('message_types', (("type TEXT PRIMARY KEY",),
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
58 ())),
2699
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
59 ('history', (("uid TEXT PRIMARY KEY", "stanza_id TEXT", "update_uid TEXT", "profile_id INTEGER", "source TEXT", "dest TEXT", "source_res TEXT", "dest_res TEXT",
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
60 "timestamp DATETIME NOT NULL", "received_timestamp DATETIME", # XXX: timestamp is the time when the message was emitted. If received time stamp is not NULL, the message was delayed and timestamp is the declared value (and received_timestamp the time of reception)
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
61 "type TEXT", "extra BLOB"),
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
62 ("FOREIGN KEY(profile_id) REFERENCES profiles(id) ON DELETE CASCADE", "FOREIGN KEY(type) REFERENCES message_types(type)",
2716
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
63 "UNIQUE (profile_id, stanza_id, source, dest)" # avoid storing 2 times the same message
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
64 ))),
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
65 ('message', (("id INTEGER PRIMARY KEY ASC", "history_uid INTEGER", "message TEXT", "language TEXT"),
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
66 ("FOREIGN KEY(history_uid) REFERENCES history(uid) ON DELETE CASCADE",))),
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
67 ('subject', (("id INTEGER PRIMARY KEY ASC", "history_uid INTEGER", "subject TEXT", "language TEXT"),
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
68 ("FOREIGN KEY(history_uid) REFERENCES history(uid) ON DELETE CASCADE",))),
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
69 ('thread', (("id INTEGER PRIMARY KEY ASC", "history_uid INTEGER", "thread_id TEXT", "parent_id TEXT"),("FOREIGN KEY(history_uid) REFERENCES history(uid) ON DELETE CASCADE",))),
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
70 ('param_gen', (("category TEXT", "name TEXT", "value TEXT"),
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
71 ("PRIMARY KEY (category,name)",))),
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
72 ('param_ind', (("category TEXT", "name TEXT", "profile_id INTEGER", "value TEXT"),
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
73 ("PRIMARY KEY (category,name,profile_id)", "FOREIGN KEY(profile_id) REFERENCES profiles(id) ON DELETE CASCADE"))),
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
74 ('private_gen', (("namespace TEXT", "key TEXT", "value TEXT"),
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
75 ("PRIMARY KEY (namespace, key)",))),
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
76 ('private_ind', (("namespace TEXT", "key TEXT", "profile_id INTEGER", "value TEXT"),
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
77 ("PRIMARY KEY (namespace, key, profile_id)", "FOREIGN KEY(profile_id) REFERENCES profiles(id) ON DELETE CASCADE"))),
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
78 ('private_gen_bin', (("namespace TEXT", "key TEXT", "value BLOB"),
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
79 ("PRIMARY KEY (namespace, key)",))),
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
80 ('private_ind_bin', (("namespace TEXT", "key TEXT", "profile_id INTEGER", "value BLOB"),
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
81 ("PRIMARY KEY (namespace, key, profile_id)", "FOREIGN KEY(profile_id) REFERENCES profiles(id) ON DELETE CASCADE"))),
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
82 ('files', (("id TEXT NOT NULL", "version TEXT NOT NULL", "parent TEXT NOT NULL",
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
83 "type TEXT CHECK(type in ('{file}', '{directory}')) NOT NULL DEFAULT '{file}'".format(
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
84 file=C.FILE_TYPE_FILE, directory=C.FILE_TYPE_DIRECTORY),
2507
4c45df43ea44 core (memory/sqlite): renamed column for files from hash to file_hash:
Goffi <goffi@goffi.org>
parents: 2500
diff changeset
85 "file_hash TEXT", "hash_algo TEXT", "name TEXT NOT NULL", "size INTEGER",
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
86 "namespace TEXT", "mime_type TEXT",
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
87 "created DATETIME NOT NULL", "modified DATETIME",
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
88 "owner TEXT", "access TEXT", "extra TEXT", "profile_id INTEGER"),
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
89 ("PRIMARY KEY (id, version)", "FOREIGN KEY(profile_id) REFERENCES profiles(id) ON DELETE CASCADE"))),
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
90 )),
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
91 'INSERT': OrderedDict((
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
92 ('message_types', (("'chat'",),
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
93 ("'error'",),
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
94 ("'groupchat'",),
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
95 ("'headline'",),
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
96 ("'normal'",),
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
97 ("'info'",) # info is not standard, but used to keep track of info like join/leave in a MUC
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
98 )),
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
99 )),
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
100 },
2716
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
101 7: {'specific': 'update_v7'
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
102 },
2699
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
103 6: {'cols create': {'history': ('stanza_id TEXT',)},
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
104 },
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
105 5: {'create': {'files': (("id TEXT NOT NULL", "version TEXT NOT NULL", "parent TEXT NOT NULL",
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
106 "type TEXT CHECK(type in ('{file}', '{directory}')) NOT NULL DEFAULT '{file}'".format(
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
107 file=C.FILE_TYPE_FILE, directory=C.FILE_TYPE_DIRECTORY),
2507
4c45df43ea44 core (memory/sqlite): renamed column for files from hash to file_hash:
Goffi <goffi@goffi.org>
parents: 2500
diff changeset
108 "file_hash TEXT", "hash_algo TEXT", "name TEXT NOT NULL", "size INTEGER",
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
109 "namespace TEXT", "mime_type TEXT",
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
110 "created DATETIME NOT NULL", "modified DATETIME",
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
111 "owner TEXT", "access TEXT", "extra TEXT", "profile_id INTEGER"),
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
112 ("PRIMARY KEY (id, version)", "FOREIGN KEY(profile_id) REFERENCES profiles(id) ON DELETE CASCADE"))},
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
113 },
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
114 4: {'create': {'components': (('profile_id INTEGER PRIMARY KEY', 'entry_point TEXT NOT NULL'), ('FOREIGN KEY(profile_id) REFERENCES profiles(id) ON DELETE CASCADE',))}
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
115 },
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
116 3: {'specific': 'update_v3'
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
117 },
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
118 2: {'specific': 'update2raw_v2'
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
119 },
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
120 1: {'cols create': {'history': ('extra BLOB',)},
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
121 },
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
122 }
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
123
2699
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
124 NOT_IN_EXTRA = ('stanza_id', 'received_timestamp', 'update_uid') # keys which are in message data extra but not stored in sqlite's extra field
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
125 # this is specific to this sqlite storage and for now only used for received_timestamp
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
126 # because this value is stored in a separate field
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
127
1961
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
128
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
129 class ConnectionPool(adbapi.ConnectionPool):
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
130 # Workaround to avoid IntegrityError causing (i)pdb to be launched in debug mode
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
131 def _runQuery(self, trans, *args, **kw):
2357
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
132 retry = kw.pop('query_retry', 6)
1961
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
133 try:
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
134 trans.execute(*args, **kw)
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
135 except sqlite3.IntegrityError as e:
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
136 raise failure.Failure(e)
2357
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
137 except Exception as e:
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
138 # FIXME: in case of error, we retry a couple of times
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
139 # this is a workaround, we need to move to better
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
140 # Sqlite integration, probably with high level library
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
141 retry -= 1
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
142 if retry == 0:
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
143 log.error(_(u'too many db tries, we abandon! Error message: {msg}').format(
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
144 msg = e))
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
145 raise e
2358
71b10dd7a13a core (memory/sqlite): typo
Goffi <goffi@goffi.org>
parents: 2357
diff changeset
146 log.warning(_(u'exception while running query, retrying ({try_}): {msg}').format(
2357
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
147 try_ = 6 - retry,
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
148 msg = e))
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
149 kw['query_retry'] = retry
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
150 return self._runQuery(trans, *args, **kw)
1961
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
151 return trans.fetchall()
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
152
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
153
588
beaf6bec2fcd Remove every old-style class.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 587
diff changeset
154 class SqliteStorage(object):
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
155 """This class manage storage with Sqlite database"""
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
156
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
157 def __init__(self, db_filename, sat_version):
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
158 """Connect to the given database
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
159
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
160 @param db_filename: full path to the Sqlite database
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
161 """
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
162 self.initialized = defer.Deferred() # triggered when memory is fully initialised and ready
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
163 self.profiles = {} # we keep cache for the profiles (key: profile name, value: profile id)
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
164
993
301b342c697a core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents: 936
diff changeset
165 log.info(_("Connecting database"))
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
166 new_base = not os.path.exists(db_filename) # do we have to create the database ?
936
6404df5305e3 memory: be sure that local_dir exists before creating a new database
souliane <souliane@mailoo.org>
parents: 934
diff changeset
167 if new_base: # the dir may not exist if it's not the XDG recommended one
6404df5305e3 memory: be sure that local_dir exists before creating a new database
souliane <souliane@mailoo.org>
parents: 934
diff changeset
168 dir_ = os.path.dirname(db_filename)
6404df5305e3 memory: be sure that local_dir exists before creating a new database
souliane <souliane@mailoo.org>
parents: 934
diff changeset
169 if not os.path.exists(dir_):
6404df5305e3 memory: be sure that local_dir exists before creating a new database
souliane <souliane@mailoo.org>
parents: 934
diff changeset
170 os.makedirs(dir_, 0700)
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
171
2357
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
172 def foreignKeysOn(sqlite):
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
173 sqlite.execute('PRAGMA foreign_keys = ON')
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
174
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
175 self.dbpool = ConnectionPool("sqlite3", db_filename, cp_openfun=foreignKeysOn, check_same_thread=False, timeout=15)
624
70988f08d0ad core: fixed bad database creation on first run in sqlite storage
Goffi <goffi@goffi.org>
parents: 609
diff changeset
176
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
177 def getNewBaseSql():
993
301b342c697a core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents: 936
diff changeset
178 log.info(_("The database is new, creating the tables"))
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
179 database_creation = ["PRAGMA user_version=%d" % CURRENT_DB_VERSION]
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
180 database_creation.extend(Updater.createData2Raw(DATABASE_SCHEMAS['current']['CREATE']))
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
181 database_creation.extend(Updater.insertData2Raw(DATABASE_SCHEMAS['current']['INSERT']))
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
182 return database_creation
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
183
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
184 def getUpdateSql():
2716
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
185 updater = Updater(self, sat_version)
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
186 return updater.checkUpdates()
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
187
2357
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
188 # init_defer is the initialisation deferred, initialisation is ok when all its callbacks have been done
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
189
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
190 init_defer = defer.succeed(None)
fa43e285df1d core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents: 2209
diff changeset
191
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
192 init_defer.addCallback(lambda ignore: getNewBaseSql() if new_base else getUpdateSql())
2716
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
193 init_defer.addCallback(self.commitStatements)
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
194
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
195 def fillProfileCache(ignore):
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
196 d = self.dbpool.runQuery("SELECT profile_id, entry_point FROM components").addCallback(self._cacheComponentsAndProfiles)
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
197 d.chainDeferred(self.initialized)
587
952322b1d490 Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 572
diff changeset
198
624
70988f08d0ad core: fixed bad database creation on first run in sqlite storage
Goffi <goffi@goffi.org>
parents: 609
diff changeset
199 init_defer.addCallback(fillProfileCache)
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
200
2716
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
201 def commitStatements(self, statements):
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
202
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
203 if statements is None:
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
204 return defer.succeed(None)
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
205 log.debug(u"\n===== COMMITTING STATEMENTS =====\n%s\n============\n\n" % '\n'.join(statements))
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
206 d = self.dbpool.runInteraction(self._updateDb, tuple(statements))
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
207 return d
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
208
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
209 def _updateDb(self, interaction, statements):
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
210 for statement in statements:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
211 interaction.execute(statement)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
212
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
213 ## Profiles
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
214
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
215 def _cacheComponentsAndProfiles(self, components_result):
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
216 """Get components results and send requests profiles
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
217
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
218 they will be both put in cache in _profilesCache
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
219 """
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
220 return self.dbpool.runQuery("SELECT name,id FROM profiles").addCallback(
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
221 self._cacheComponentsAndProfiles2, components_result)
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
222
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
223 def _cacheComponentsAndProfiles2(self, profiles_result, components):
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
224 """Fill the profiles cache
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
225
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
226 @param profiles_result: result of the sql profiles query
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
227 """
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
228 self.components = dict(components)
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
229 for profile in profiles_result:
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
230 name, id_ = profile
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
231 self.profiles[name] = id_
587
952322b1d490 Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 572
diff changeset
232
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
233 def getProfilesList(self):
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
234 """"Return list of all registered profiles"""
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
235 return self.profiles.keys()
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
236
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
237 def hasProfile(self, profile_name):
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
238 """return True if profile_name exists
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
239
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
240 @param profile_name: name of the profile to check
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
241 """
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
242 return profile_name in self.profiles
587
952322b1d490 Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 572
diff changeset
243
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
244 def profileIsComponent(self, profile_name):
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
245 try:
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
246 return self.profiles[profile_name] in self.components
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
247 except KeyError:
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
248 raise exceptions.NotFound(u"the requested profile doesn't exists")
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
249
2144
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
250 def getEntryPoint(self, profile_name):
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
251 try:
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
252 return self.components[self.profiles[profile_name]]
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
253 except KeyError:
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
254 raise exceptions.NotFound(u"the requested profile doesn't exists or is not a component")
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
255
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
256 def createProfile(self, name, component=None):
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
257 """Create a new profile
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
258
2144
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
259 @param name(unicode): name of the profile
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
260 @param component(None, unicode): if not None, must point to a component entry point
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
261 @return: deferred triggered once profile is actually created
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
262 """
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
263
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
264 def getProfileId(ignore):
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
265 return self.dbpool.runQuery("SELECT (id) FROM profiles WHERE name = ?", (name, ))
587
952322b1d490 Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 572
diff changeset
266
2144
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
267 def setComponent(profile_id):
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
268 id_ = profile_id[0][0]
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
269 d_comp = self.dbpool.runQuery("INSERT INTO components(profile_id, entry_point) VALUES (?, ?)", (id_, component))
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
270 d_comp.addCallback(lambda dummy: profile_id)
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
271 return d_comp
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
272
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
273 def profile_created(profile_id):
2144
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
274 id_= profile_id[0][0]
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
275 self.profiles[name] = id_ # we synchronise the cache
587
952322b1d490 Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 572
diff changeset
276
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
277 d = self.dbpool.runQuery("INSERT INTO profiles(name) VALUES (?)", (name, ))
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
278 d.addCallback(getProfileId)
2144
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
279 if component is not None:
1d3f73e065e1 core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents: 2143
diff changeset
280 d.addCallback(setComponent)
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
281 d.addCallback(profile_created)
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
282 return d
587
952322b1d490 Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 572
diff changeset
283
420
acd908528ef7 core: profile creation/deletion through database
Goffi <goffi@goffi.org>
parents: 416
diff changeset
284 def deleteProfile(self, name):
acd908528ef7 core: profile creation/deletion through database
Goffi <goffi@goffi.org>
parents: 416
diff changeset
285 """Delete profile
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
286
420
acd908528ef7 core: profile creation/deletion through database
Goffi <goffi@goffi.org>
parents: 416
diff changeset
287 @param name: name of the profile
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
288 @return: deferred triggered once profile is actually deleted
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
289 """
1961
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
290 def deletionError(failure_):
1409
3265a2639182 massive (preventive) addition of 'u' (unicode) before the strings passed to logging functions
souliane <souliane@mailoo.org>
parents: 1396
diff changeset
291 log.error(_(u"Can't delete profile [%s]") % name)
1961
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
292 return failure_
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
293
934
34dd9287dfe5 plugin account: bug fix profile deletion from the database + unsubscribe the contacts
souliane <souliane@mailoo.org>
parents: 853
diff changeset
294 def delete(txn):
1705
3765e10ec52f core (sqlite storage): do explicit delete to profile linked tables for deleteProfile
Goffi <goffi@goffi.org>
parents: 1455
diff changeset
295 profile_id = self.profiles.pop(name)
934
34dd9287dfe5 plugin account: bug fix profile deletion from the database + unsubscribe the contacts
souliane <souliane@mailoo.org>
parents: 853
diff changeset
296 txn.execute("DELETE FROM profiles WHERE name = ?", (name,))
1705
3765e10ec52f core (sqlite storage): do explicit delete to profile linked tables for deleteProfile
Goffi <goffi@goffi.org>
parents: 1455
diff changeset
297 # FIXME: the following queries should be done by the ON DELETE CASCADE
3765e10ec52f core (sqlite storage): do explicit delete to profile linked tables for deleteProfile
Goffi <goffi@goffi.org>
parents: 1455
diff changeset
298 # but it seems they are not, so we explicitly do them by security
3765e10ec52f core (sqlite storage): do explicit delete to profile linked tables for deleteProfile
Goffi <goffi@goffi.org>
parents: 1455
diff changeset
299 # this need more investigation
3765e10ec52f core (sqlite storage): do explicit delete to profile linked tables for deleteProfile
Goffi <goffi@goffi.org>
parents: 1455
diff changeset
300 txn.execute("DELETE FROM history WHERE profile_id = ?", (profile_id,))
3765e10ec52f core (sqlite storage): do explicit delete to profile linked tables for deleteProfile
Goffi <goffi@goffi.org>
parents: 1455
diff changeset
301 txn.execute("DELETE FROM param_ind WHERE profile_id = ?", (profile_id,))
3765e10ec52f core (sqlite storage): do explicit delete to profile linked tables for deleteProfile
Goffi <goffi@goffi.org>
parents: 1455
diff changeset
302 txn.execute("DELETE FROM private_ind WHERE profile_id = ?", (profile_id,))
3765e10ec52f core (sqlite storage): do explicit delete to profile linked tables for deleteProfile
Goffi <goffi@goffi.org>
parents: 1455
diff changeset
303 txn.execute("DELETE FROM private_ind_bin WHERE profile_id = ?", (profile_id,))
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
304 txn.execute("DELETE FROM components WHERE profile_id = ?", (profile_id,))
934
34dd9287dfe5 plugin account: bug fix profile deletion from the database + unsubscribe the contacts
souliane <souliane@mailoo.org>
parents: 853
diff changeset
305 return None
34dd9287dfe5 plugin account: bug fix profile deletion from the database + unsubscribe the contacts
souliane <souliane@mailoo.org>
parents: 853
diff changeset
306
34dd9287dfe5 plugin account: bug fix profile deletion from the database + unsubscribe the contacts
souliane <souliane@mailoo.org>
parents: 853
diff changeset
307 d = self.dbpool.runInteraction(delete)
993
301b342c697a core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents: 936
diff changeset
308 d.addCallback(lambda ignore: log.info(_("Profile [%s] deleted") % name))
593
70bae685d05c core: added forgotten errback in sqlite's deleteProfile
Goffi <goffi@goffi.org>
parents: 592
diff changeset
309 d.addErrback(deletionError)
420
acd908528ef7 core: profile creation/deletion through database
Goffi <goffi@goffi.org>
parents: 416
diff changeset
310 return d
acd908528ef7 core: profile creation/deletion through database
Goffi <goffi@goffi.org>
parents: 416
diff changeset
311
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
312 ## Params
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
313 def loadGenParams(self, params_gen):
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
314 """Load general parameters
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
315
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
316 @param params_gen: dictionary to fill
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
317 @return: deferred
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
318 """
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
319
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
320 def fillParams(result):
413
dd4caab17008 core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents: 412
diff changeset
321 for param in result:
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
322 category, name, value = param
413
dd4caab17008 core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents: 412
diff changeset
323 params_gen[(category, name)] = value
1409
3265a2639182 massive (preventive) addition of 'u' (unicode) before the strings passed to logging functions
souliane <souliane@mailoo.org>
parents: 1396
diff changeset
324 log.debug(_(u"loading general parameters from database"))
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
325 return self.dbpool.runQuery("SELECT category,name,value FROM param_gen").addCallback(fillParams)
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
326
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
327 def loadIndParams(self, params_ind, profile):
432
31e8c48b5f5d core: - memory refactoring (moved memory.py and sqlite.py from tools to memory)
Goffi <goffi@goffi.org>
parents: 425
diff changeset
328 """Load individual parameters
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
329
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
330 @param params_ind: dictionary to fill
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
331 @param profile: a profile which *must* exist
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
332 @return: deferred
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
333 """
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
334
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
335 def fillParams(result):
413
dd4caab17008 core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents: 412
diff changeset
336 for param in result:
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
337 category, name, value = param
423
6c20c76abdcc backend: - bridge async D-Bus method now automatically manage callback and errback, we just have to return a deferred
Goffi <goffi@goffi.org>
parents: 420
diff changeset
338 params_ind[(category, name)] = value
1409
3265a2639182 massive (preventive) addition of 'u' (unicode) before the strings passed to logging functions
souliane <souliane@mailoo.org>
parents: 1396
diff changeset
339 log.debug(_(u"loading individual parameters from database"))
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
340 d = self.dbpool.runQuery("SELECT category,name,value FROM param_ind WHERE profile_id=?", (self.profiles[profile], ))
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
341 d.addCallback(fillParams)
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
342 return d
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
343
413
dd4caab17008 core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents: 412
diff changeset
344 def getIndParam(self, category, name, profile):
dd4caab17008 core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents: 412
diff changeset
345 """Ask database for the value of one specific individual parameter
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
346
413
dd4caab17008 core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents: 412
diff changeset
347 @param category: category of the parameter
dd4caab17008 core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents: 412
diff changeset
348 @param name: name of the parameter
dd4caab17008 core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents: 412
diff changeset
349 @param profile: %(doc_profile)s
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
350 @return: deferred
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
351 """
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
352 d = self.dbpool.runQuery("SELECT value FROM param_ind WHERE category=? AND name=? AND profile_id=?", (category, name, self.profiles[profile]))
413
dd4caab17008 core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents: 412
diff changeset
353 d.addCallback(self.__getFirstResult)
dd4caab17008 core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents: 412
diff changeset
354 return d
dd4caab17008 core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents: 412
diff changeset
355
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
356 def setGenParam(self, category, name, value):
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
357 """Save the general parameters in database
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
358
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
359 @param category: category of the parameter
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
360 @param name: name of the parameter
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
361 @param value: value to set
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
362 @return: deferred"""
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
363 d = self.dbpool.runQuery("REPLACE INTO param_gen(category,name,value) VALUES (?,?,?)", (category, name, value))
1409
3265a2639182 massive (preventive) addition of 'u' (unicode) before the strings passed to logging functions
souliane <souliane@mailoo.org>
parents: 1396
diff changeset
364 d.addErrback(lambda ignore: log.error(_(u"Can't set general parameter (%(category)s/%(name)s) in database" % {"category": category, "name": name})))
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
365 return d
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
366
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
367 def setIndParam(self, category, name, value, profile):
432
31e8c48b5f5d core: - memory refactoring (moved memory.py and sqlite.py from tools to memory)
Goffi <goffi@goffi.org>
parents: 425
diff changeset
368 """Save the individual parameters in database
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
369
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
370 @param category: category of the parameter
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
371 @param name: name of the parameter
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
372 @param value: value to set
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
373 @param profile: a profile which *must* exist
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
374 @return: deferred
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
375 """
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
376 d = self.dbpool.runQuery("REPLACE INTO param_ind(category,name,profile_id,value) VALUES (?,?,?,?)", (category, name, self.profiles[profile], value))
1409
3265a2639182 massive (preventive) addition of 'u' (unicode) before the strings passed to logging functions
souliane <souliane@mailoo.org>
parents: 1396
diff changeset
377 d.addErrback(lambda ignore: log.error(_(u"Can't set individual parameter (%(category)s/%(name)s) for [%(profile)s] in database" % {"category": category, "name": name, "profile": profile})))
412
62b17854254e database integration: first draft
Goffi <goffi@goffi.org>
parents:
diff changeset
378 return d
413
dd4caab17008 core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents: 412
diff changeset
379
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
380 ## History
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
381
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
382 def _addToHistoryCb(self, dummy, data):
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
383 # Message metadata were successfuly added to history
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
384 # now we can add message and subject
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
385 uid = data['uid']
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
386 for key in ('message', 'subject'):
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
387 for lang, value in data[key].iteritems():
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
388 d = self.dbpool.runQuery("INSERT INTO {key}(history_uid, {key}, language) VALUES (?,?,?)".format(key=key),
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
389 (uid, value, lang or None))
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
390 d.addErrback(lambda dummy: log.error(_(u"Can't save following {key} in history (uid: {uid}, lang:{lang}): {value}".format(
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
391 key=key, uid=uid, lang=lang, value=value))))
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
392 try:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
393 thread = data['extra']['thread']
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
394 except KeyError:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
395 pass
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
396 else:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
397 thread_parent = data['extra'].get('thread_parent')
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
398 d = self.dbpool.runQuery("INSERT INTO thread(history_uid, thread_id, parent_id) VALUES (?,?,?)",
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
399 (uid, thread, thread_parent))
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
400 d.addErrback(lambda dummy: log.error(_(u"Can't save following thread in history (uid: {uid}): thread:{thread}), parent:{parent}".format(
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
401 uid=uid, thread=thread, parent=thread_parent))))
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
402
1961
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
403 def _addToHistoryEb(self, failure_, data):
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
404 failure_.trap(sqlite3.IntegrityError)
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
405 sqlite_msg = failure_.value.args[0]
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
406 if "UNIQUE constraint failed" in sqlite_msg:
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
407 log.debug(u"message {} is already in history, not storing it again".format(data['uid']))
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
408 if 'received_timestamp' not in data:
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
409 log.warning(u"duplicate message is not delayed, this is maybe a bug: data={}".format(data))
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
410 # we cancel message to avoid sending duplicate message to frontends
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
411 raise failure.Failure(exceptions.CancelError("Cancelled duplicated message"))
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
412 else:
1961
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
413 log.error(u"Can't store message in history: {}".format(failure_))
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
414
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
415 def _logHistoryError(self, failure_, from_jid, to_jid, data):
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
416 if failure_.check(exceptions.CancelError):
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
417 # we propagate CancelError to avoid sending message to frontends
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
418 raise failure_
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
419 log.error(_(u"Can't save following message in history: from [{from_jid}] to [{to_jid}] (uid: {uid})"
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
420 .format(from_jid=from_jid.full(), to_jid=to_jid.full(), uid=data['uid'])))
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
421
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
422 def addToHistory(self, data, profile):
425
e4e9187e3b5b backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents: 423
diff changeset
423 """Store a new message in history
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
424
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
425 @param data(dict): message data as build by SatMessageProtocol.onMessage
425
e4e9187e3b5b backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents: 423
diff changeset
426 """
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
427 extra = pickle.dumps({k: v for k, v in data['extra'].iteritems() if k not in NOT_IN_EXTRA}, 0)
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
428 from_jid = data['from']
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
429 to_jid = data['to']
2699
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
430 d = self.dbpool.runQuery("INSERT INTO history(uid, stanza_id, update_uid, profile_id, source, dest, source_res, dest_res, timestamp, received_timestamp, type, extra) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)",
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
431 (data['uid'], data['extra'].get('stanza_id'), data['extra'].get('update_uid'), self.profiles[profile], data['from'].userhost(), to_jid.userhost(), from_jid.resource, to_jid.resource, data['timestamp'], data.get('received_timestamp'), data['type'], sqlite3.Binary(extra)))
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
432 d.addCallbacks(self._addToHistoryCb, self._addToHistoryEb, callbackArgs=[data], errbackArgs=[data])
1961
c73e08094a95 memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents: 1955
diff changeset
433 d.addErrback(self._logHistoryError, from_jid, to_jid, data)
425
e4e9187e3b5b backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents: 423
diff changeset
434 return d
e4e9187e3b5b backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents: 423
diff changeset
435
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
436 def sqliteHistoryToList(self, query_result):
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
437 """Get SQL query result and return a list of message data dicts"""
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
438 result = []
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
439 current = {'uid': None}
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
440 for row in reversed(query_result):
2699
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
441 uid, stanza_id, update_uid, source, dest, source_res, dest_res, timestamp, received_timestamp,\
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
442 type_, extra, message, message_lang, subject, subject_lang, thread, thread_parent = row
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
443 if uid != current['uid']:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
444 # new message
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
445 try:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
446 extra = pickle.loads(str(extra or ""))
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
447 except EOFError:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
448 extra = {}
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
449 current = {
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
450 'from': "%s/%s" % (source, source_res) if source_res else source,
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
451 'to': "%s/%s" % (dest, dest_res) if dest_res else dest,
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
452 'uid': uid,
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
453 'message': {},
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
454 'subject': {},
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
455 'type': type_,
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
456 'extra': extra,
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
457 'timestamp': timestamp,
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
458 }
2699
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
459 if stanza_id is not None:
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
460 current['extra']['stanza_id'] = stanza_id
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
461 if update_uid is not None:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
462 current['extra']['update_uid'] = update_uid
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
463 if received_timestamp is not None:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
464 current['extra']['received_timestamp'] = str(received_timestamp)
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
465 result.append(current)
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
466
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
467 if message is not None:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
468 current['message'][message_lang or ''] = message
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
469
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
470 if subject is not None:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
471 current['subject'][subject_lang or ''] = subject
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
472
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
473 if thread is not None:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
474 current_extra = current['extra']
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
475 current_extra['thread'] = thread
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
476 if thread_parent is not None:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
477 current_extra['thread_parent'] = thread_parent
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
478 else:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
479 if thread_parent is not None:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
480 log.error(u"Database inconsistency: thread parent without thread (uid: {uid}, thread_parent: {parent})"
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
481 .format(uid=uid, parent=thread_parent))
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
482
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
483 return result
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
484
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
485 def listDict2listTuple(self, messages_data):
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
486 """Return a list of tuple as used in bridge from a list of messages data"""
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
487 ret = []
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
488 for m in messages_data:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
489 ret.append((m['uid'], m['timestamp'], m['from'], m['to'], m['message'], m['subject'], m['type'], m['extra']))
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
490 return ret
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
491
2013
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
492 def historyGet(self, from_jid, to_jid, limit=None, between=True, filters=None, profile=None):
1222
e6e0ea4dc835 memory: add Parameter "Chat history limit"
souliane <souliane@mailoo.org>
parents: 1221
diff changeset
493 """Retrieve messages in history
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
494
1222
e6e0ea4dc835 memory: add Parameter "Chat history limit"
souliane <souliane@mailoo.org>
parents: 1221
diff changeset
495 @param from_jid (JID): source JID (full, or bare for catchall)
e6e0ea4dc835 memory: add Parameter "Chat history limit"
souliane <souliane@mailoo.org>
parents: 1221
diff changeset
496 @param to_jid (JID): dest JID (full, or bare for catchall)
e6e0ea4dc835 memory: add Parameter "Chat history limit"
souliane <souliane@mailoo.org>
parents: 1221
diff changeset
497 @param limit (int): maximum number of messages to get:
e6e0ea4dc835 memory: add Parameter "Chat history limit"
souliane <souliane@mailoo.org>
parents: 1221
diff changeset
498 - 0 for no message (returns the empty list)
e6e0ea4dc835 memory: add Parameter "Chat history limit"
souliane <souliane@mailoo.org>
parents: 1221
diff changeset
499 - None for unlimited
e6e0ea4dc835 memory: add Parameter "Chat history limit"
souliane <souliane@mailoo.org>
parents: 1221
diff changeset
500 @param between (bool): confound source and dest (ignore the direction)
2699
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
501 @param filters (dict[unicode, unicode]): pattern to filter the history results
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
502 @param profile (unicode): %(doc_profile)s
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
503 @return: list of tuple as in [messageNew]
425
e4e9187e3b5b backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents: 423
diff changeset
504 """
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
505 assert profile
2013
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
506 if filters is None:
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
507 filters = {}
1221
5e5661ab5c81 memory: getHistory with limit=0 now returns an empty list, use limit=None to return all messages
souliane <souliane@mailoo.org>
parents: 1099
diff changeset
508 if limit == 0:
5e5661ab5c81 memory: getHistory with limit=0 now returns an empty list, use limit=None to return all messages
souliane <souliane@mailoo.org>
parents: 1099
diff changeset
509 return defer.succeed([])
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
510
2699
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
511 query_parts = [u"SELECT uid, stanza_id, update_uid, source, dest, source_res, dest_res, timestamp, received_timestamp,\
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
512 type, extra, message, message.language, subject, subject.language, thread_id, thread.parent_id\
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
513 FROM history LEFT JOIN message ON history.uid = message.history_uid\
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
514 LEFT JOIN subject ON history.uid=subject.history_uid\
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
515 LEFT JOIN thread ON history.uid=thread.history_uid\
2699
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
516 WHERE profile_id=?"] # FIXME: not sure if it's the best request, messages and subjects can appear several times here
538
2c4016921403 core, frontends, bridgen plugins: fixed methods which were unproperly managing multi-profiles
Goffi <goffi@goffi.org>
parents: 512
diff changeset
517 values = [self.profiles[profile]]
425
e4e9187e3b5b backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents: 423
diff changeset
518
2699
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
519 def test_jid(type_, jid_):
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
520 values.append(jid_.userhost())
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
521 if jid_.resource:
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
522 values.append(jid_.resource)
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
523 return u'({type_}=? AND {type_}_res=?)'.format(type_=type_)
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
524 return u'{type_}=?'.format(type_=type_)
587
952322b1d490 Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 572
diff changeset
525
2699
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
526 if not from_jid and not to_jid:
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
527 # not jid specified, we want all one2one communications
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
528 pass
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
529 elif between:
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
530 if not from_jid or not to_jid:
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
531 # we only have one jid specified, we check all messages
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
532 # from or to this jid
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
533 jid_ = from_jid or to_jid
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
534 query_parts.append(u"AND ({source} OR {dest})".format(
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
535 source=test_jid(u'source', jid_),
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
536 dest=test_jid(u'dest' , jid_)))
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
537 else:
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
538 # we have 2 jids specified, we check all communications between
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
539 # those 2 jids
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
540 query_parts.append(
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
541 u"AND (({source_from} AND {dest_to}) "
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
542 u"OR ({source_to} AND {dest_from}))".format(
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
543 source_from=test_jid('source', from_jid),
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
544 dest_to=test_jid('dest', to_jid),
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
545 source_to=test_jid('source', to_jid),
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
546 dest_from=test_jid('dest', from_jid)))
425
e4e9187e3b5b backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents: 423
diff changeset
547 else:
2699
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
548 # we want one communication in specific direction (from somebody or
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
549 # to somebody).
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
550 q = []
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
551 if from_jid is not None:
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
552 q.append(test_jid('source', from_jid))
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
553 if to_jid is not None:
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
554 q.append(test_jid('dest', to_jid))
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
555 query_parts.append(u"AND " + u" AND ".join(q))
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
556
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
557 # set to True if "ORDER BY" is already added
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
558 order = False
448
17c7e48bf68f core: - history management improved
Goffi <goffi@goffi.org>
parents: 441
diff changeset
559
2013
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
560 if filters:
2715
b35c84ea73cf plugin XEP-0045: MAM implementation for MUC
Goffi <goffi@goffi.org>
parents: 2711
diff changeset
561 if u'body' in filters:
2013
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
562 # TODO: use REGEXP (function to be defined) instead of GLOB: https://www.sqlite.org/lang_expr.html
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
563 query_parts.append(u"AND message LIKE ?")
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
564 values.append(u"%{}%".format(filters['body']))
2715
b35c84ea73cf plugin XEP-0045: MAM implementation for MUC
Goffi <goffi@goffi.org>
parents: 2711
diff changeset
565 if u'search' in filters:
2013
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
566 query_parts.append(u"AND (message LIKE ? OR source_res LIKE ?)")
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
567 values.extend([u"%{}%".format(filters['search'])] * 2)
2715
b35c84ea73cf plugin XEP-0045: MAM implementation for MUC
Goffi <goffi@goffi.org>
parents: 2711
diff changeset
568 if u'types' in filters:
2013
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
569 types = filters['types'].split()
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
570 query_parts.append(u"AND type IN ({})".format(u','.join("?"*len(types))))
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
571 values.extend(types)
2715
b35c84ea73cf plugin XEP-0045: MAM implementation for MUC
Goffi <goffi@goffi.org>
parents: 2711
diff changeset
572 if u'not_types' in filters:
2013
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
573 types = filters['not_types'].split()
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
574 query_parts.append(u"AND type NOT IN ({})".format(u','.join("?"*len(types))))
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
575 values.extend(types)
2715
b35c84ea73cf plugin XEP-0045: MAM implementation for MUC
Goffi <goffi@goffi.org>
parents: 2711
diff changeset
576 if u'last_stanza_id' in filters:
2699
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
577 # this request get the last message with a "stanza_id" that we
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
578 # have in history. This is mainly used to retrieve messages sent
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
579 # while we were offline, using MAM (XEP-0313).
2715
b35c84ea73cf plugin XEP-0045: MAM implementation for MUC
Goffi <goffi@goffi.org>
parents: 2711
diff changeset
580 # It must be set after all other filters, because it contains an ORDER BY
2699
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
581 if (filters[u'last_stanza_id'] is not True
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
582 or limit != 1):
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
583 raise ValueError(u"Unexpected values for last_stanza_id filter")
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
584 query_parts.append(u"AND stanza_id IS NOT NULL ORDER BY history.rowid DESC")
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
585 order = True
2013
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
586
2715
b35c84ea73cf plugin XEP-0045: MAM implementation for MUC
Goffi <goffi@goffi.org>
parents: 2711
diff changeset
587
2699
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
588 if not order:
2716
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
589 # timestamp may be identical for 2 close message (specially when delay is used)
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
590 # that's why we order ties by rowid (which is in the same order as received_timestamp
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
591 # but has an index so is quick to order).
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
592
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
593 # We'll reverse the order in sqliteHistoryToList
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
594 query_parts.append(u"ORDER BY timestamp DESC, history.rowid DESC")
2699
310e41bd6666 core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents: 2562
diff changeset
595 # we use DESC here so LIMIT keep the last messages
1221
5e5661ab5c81 memory: getHistory with limit=0 now returns an empty list, use limit=None to return all messages
souliane <souliane@mailoo.org>
parents: 1099
diff changeset
596 if limit is not None:
2013
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
597 query_parts.append(u"LIMIT ?")
425
e4e9187e3b5b backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents: 423
diff changeset
598 values.append(limit)
587
952322b1d490 Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 572
diff changeset
599
2013
b536dd121da1 backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents: 1962
diff changeset
600 d = self.dbpool.runQuery(u" ".join(query_parts), values)
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
601 d.addCallback(self.sqliteHistoryToList)
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
602 d.addCallback(self.listDict2listTuple)
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
603 return d
425
e4e9187e3b5b backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents: 423
diff changeset
604
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
605 ## Private values
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
606
2182
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
607 def _privateDataEb(self, failure_, operation, namespace, key=None, profile=None):
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
608 """generic errback for data queries"""
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
609 log.error(_(u"Can't {operation} data in database for namespace {namespace}{and_key}{for_profile}: {msg}").format(
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
610 operation = operation,
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
611 namespace = namespace,
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
612 and_key = (u" and key " + key) if key is not None else u"",
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
613 for_profile = (u' [' + profile + u']') if profile is not None else u'',
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
614 msg = failure_))
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
615
2182
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
616 def _generateDataDict(self, query_result, binary):
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
617 if binary:
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
618 return {k: pickle.loads(str(v)) for k,v in query_result}
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
619 else:
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
620 return dict(query_result)
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
621
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
622 def _getPrivateTable(self, binary, profile):
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
623 """Get table to use for private values"""
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
624 table = [u'private']
425
e4e9187e3b5b backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents: 423
diff changeset
625
2182
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
626 if profile is None:
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
627 table.append(u'gen')
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
628 else:
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
629 table.append(u'ind')
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
630
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
631 if binary:
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
632 table.append(u'bin')
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
633
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
634 return u'_'.join(table)
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
635
2182
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
636 def getPrivates(self, namespace, keys=None, binary=False, profile=None):
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
637 """Get private value(s) from databases
592
e5a875a3311b Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents: 588
diff changeset
638
2182
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
639 @param namespace(unicode): namespace of the values
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
640 @param keys(iterable, None): keys of the values to get
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
641 None to get all keys/values
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
642 @param binary(bool): True to deserialise binary values
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
643 @param profile(unicode, None): profile to use for individual values
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
644 None to use general values
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
645 @return (dict[unicode, object]): gotten keys/values
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
646 """
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
647 log.debug(_(u"getting {type}{binary} private values from database for namespace {namespace}{keys}".format(
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
648 type = u"general" if profile is None else "individual",
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
649 binary = u" binary" if binary else u"",
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
650 namespace = namespace,
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
651 keys = u" with keys {}".format(u", ".join(keys)) if keys is not None else u"")))
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
652 table = self._getPrivateTable(binary, profile)
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
653 query_parts = [u"SELECT key,value FROM", table, "WHERE namespace=?"]
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
654 args = [namespace]
432
31e8c48b5f5d core: - memory refactoring (moved memory.py and sqlite.py from tools to memory)
Goffi <goffi@goffi.org>
parents: 425
diff changeset
655
2182
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
656 if keys is not None:
2209
ea41cf1e6d29 memory (persistent, sqlite): fixed getPrivates bug with keys arguments and its use in LazyPersistentBinaryDict
Goffi <goffi@goffi.org>
parents: 2182
diff changeset
657 placeholders = u','.join(len(keys) * u'?')
ea41cf1e6d29 memory (persistent, sqlite): fixed getPrivates bug with keys arguments and its use in LazyPersistentBinaryDict
Goffi <goffi@goffi.org>
parents: 2182
diff changeset
658 query_parts.append(u'AND key IN (' + placeholders + u')')
ea41cf1e6d29 memory (persistent, sqlite): fixed getPrivates bug with keys arguments and its use in LazyPersistentBinaryDict
Goffi <goffi@goffi.org>
parents: 2182
diff changeset
659 args.extend(keys)
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
660
2182
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
661 if profile is not None:
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
662 query_parts.append(u'AND profile_id=?')
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
663 args.append(self.profiles[profile])
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
664
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
665 d = self.dbpool.runQuery(u" ".join(query_parts), args)
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
666 d.addCallback(self._generateDataDict, binary)
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
667 d.addErrback(self._privateDataEb, u"get", namespace, profile=profile)
432
31e8c48b5f5d core: - memory refactoring (moved memory.py and sqlite.py from tools to memory)
Goffi <goffi@goffi.org>
parents: 425
diff changeset
668 return d
31e8c48b5f5d core: - memory refactoring (moved memory.py and sqlite.py from tools to memory)
Goffi <goffi@goffi.org>
parents: 425
diff changeset
669
2182
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
670 def setPrivateValue(self, namespace, key, value, binary=False, profile=None):
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
671 """Set a private value in database
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
672
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
673 @param namespace(unicode): namespace of the values
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
674 @param key(unicode): key of the value to set
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
675 @param value(object): value to set
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
676 @param binary(bool): True if it's a binary values
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
677 binary values need to be serialised, used for everything but strings
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
678 @param profile(unicode, None): profile to use for individual value
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
679 if None, it's a general value
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
680 """
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
681 table = self._getPrivateTable(binary, profile)
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
682 query_values_names = [u'namespace', u'key', u'value']
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
683 query_values = [namespace, key]
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
684
2182
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
685 if binary:
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
686 value = sqlite3.Binary(pickle.dumps(value, 0))
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
687
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
688 query_values.append(value)
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
689
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
690 if profile is not None:
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
691 query_values_names.append(u'profile_id')
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
692 query_values.append(self.profiles[profile])
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
693
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
694 query_parts = [u"REPLACE INTO", table, u'(', u','.join(query_values_names), u')',
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
695 u"VALUES (", u",".join(u'?'*len(query_values_names)), u')']
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
696
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
697 d = self.dbpool.runQuery(u" ".join(query_parts), query_values)
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
698 d.addErrback(self._privateDataEb, u"set", namespace, key, profile=profile)
432
31e8c48b5f5d core: - memory refactoring (moved memory.py and sqlite.py from tools to memory)
Goffi <goffi@goffi.org>
parents: 425
diff changeset
699 return d
31e8c48b5f5d core: - memory refactoring (moved memory.py and sqlite.py from tools to memory)
Goffi <goffi@goffi.org>
parents: 425
diff changeset
700
2182
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
701 def delPrivateValue(self, namespace, key, binary=False, profile=None):
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
702 """Delete private value from database
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
703
432
31e8c48b5f5d core: - memory refactoring (moved memory.py and sqlite.py from tools to memory)
Goffi <goffi@goffi.org>
parents: 425
diff changeset
704 @param category: category of the privateeter
31e8c48b5f5d core: - memory refactoring (moved memory.py and sqlite.py from tools to memory)
Goffi <goffi@goffi.org>
parents: 425
diff changeset
705 @param key: key of the private value
2182
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
706 @param binary(bool): True if it's a binary values
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
707 @param profile(unicode, None): profile to use for individual value
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
708 if None, it's a general value
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
709 """
2182
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
710 table = self._getPrivateTable(binary, profile)
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
711 query_parts = [u"DELETE FROM", table, u"WHERE namespace=? AND key=?"]
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
712 args = [namespace, key]
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
713 if profile is not None:
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
714 query_parts.append(u"AND profile_id=?")
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
715 args.append(self.profiles[profile])
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
716 d = self.dbpool.runQuery(u" ".join(query_parts), args)
087eec4c6c07 memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents: 2144
diff changeset
717 d.addErrback(self._privateDataEb, u"delete", namespace, key, profile=profile)
432
31e8c48b5f5d core: - memory refactoring (moved memory.py and sqlite.py from tools to memory)
Goffi <goffi@goffi.org>
parents: 425
diff changeset
718 return d
31e8c48b5f5d core: - memory refactoring (moved memory.py and sqlite.py from tools to memory)
Goffi <goffi@goffi.org>
parents: 425
diff changeset
719
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
720 ## Files
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
721
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
722 @defer.inlineCallbacks
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
723 def getFiles(self, client, file_id=None, version=u'', parent=None, type_=None,
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
724 file_hash=None, hash_algo=None, name=None, namespace=None, mime_type=None,
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
725 owner=None, access=None, projection=None, unique=False):
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
726 """retrieve files with with given filters
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
727
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
728 @param file_id(unicode, None): id of the file
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
729 None to ignore
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
730 @param version(unicode, None): version of the file
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
731 None to ignore
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
732 empty string to look for current version
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
733 @param parent(unicode, None): id of the directory containing the files
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
734 None to ignore
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
735 empty string to look for root files/directories
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
736 @param projection(list[unicode], None): name of columns to retrieve
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
737 None to retrieve all
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
738 @param unique(bool): if True will remove duplicates
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
739 other params are the same as for [setFile]
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
740 @return (list[dict]): files corresponding to filters
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
741 """
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
742 query_parts = ["SELECT"]
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
743 if unique:
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
744 query_parts.append('DISTINCT')
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
745 if projection is None:
2507
4c45df43ea44 core (memory/sqlite): renamed column for files from hash to file_hash:
Goffi <goffi@goffi.org>
parents: 2500
diff changeset
746 projection = ['id', 'version', 'parent', 'type', 'file_hash', 'hash_algo', 'name',
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
747 'size', 'namespace', 'mime_type', 'created', 'modified', 'owner',
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
748 'access', 'extra']
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
749 query_parts.append(','.join(projection))
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
750 query_parts.append("FROM files WHERE")
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
751 filters = ['profile_id=?']
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
752 args = [self.profiles[client.profile]]
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
753
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
754 if file_id is not None:
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
755 filters.append(u'id=?')
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
756 args.append(file_id)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
757 if version is not None:
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
758 filters.append(u'version=?')
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
759 args.append(version)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
760 if parent is not None:
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
761 filters.append(u'parent=?')
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
762 args.append(parent)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
763 if type_ is not None:
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
764 filters.append(u'type=?')
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
765 args.append(type_)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
766 if file_hash is not None:
2507
4c45df43ea44 core (memory/sqlite): renamed column for files from hash to file_hash:
Goffi <goffi@goffi.org>
parents: 2500
diff changeset
767 filters.append(u'file_hash=?')
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
768 args.append(file_hash)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
769 if hash_algo is not None:
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
770 filters.append(u'hash_algo=?')
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
771 args.append(hash_algo)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
772 if name is not None:
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
773 filters.append(u'name=?')
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
774 args.append(name)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
775 if namespace is not None:
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
776 filters.append(u'namespace=?')
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
777 args.append(namespace)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
778 if mime_type is not None:
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
779 filters.append(u'mime_type=?')
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
780 args.append(mime_type)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
781 if owner is not None:
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
782 filters.append(u'owner=?')
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
783 args.append(owner.full())
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
784 if access is not None:
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
785 raise NotImplementedError('Access check is not implemented yet')
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
786 # a JSON comparison is needed here
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
787
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
788 filters = u' AND '.join(filters)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
789 query_parts.append(filters)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
790 query = u' '.join(query_parts)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
791
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
792 result = yield self.dbpool.runQuery(query, args)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
793 files_data = [dict(zip(projection, row)) for row in result]
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
794 to_parse = {'access', 'extra'}.intersection(projection)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
795 to_filter = {'owner'}.intersection(projection)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
796 if to_parse or to_filter:
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
797 for file_data in files_data:
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
798 for key in to_parse:
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
799 value = file_data[key]
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
800 file_data[key] = {} if value is None else json.loads(value)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
801 owner = file_data.get('owner')
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
802 if owner is not None:
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
803 file_data['owner'] = jid.JID(owner)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
804 defer.returnValue(files_data)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
805
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
806 def setFile(self, client, name, file_id, version=u'', parent=None, type_=C.FILE_TYPE_FILE,
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
807 file_hash=None, hash_algo=None, size=None, namespace=None, mime_type=None,
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
808 created=None, modified=None, owner=None, access=None, extra=None):
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
809 """set a file metadata
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
810
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
811 @param client(SatXMPPClient): client owning the file
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
812 @param name(unicode): name of the file (must not contain "/")
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
813 @param file_id(unicode): unique id of the file
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
814 @param version(unicode): version of this file
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
815 @param parent(unicode): id of the directory containing this file
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
816 None if it is a root file/directory
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
817 @param type_(unicode): one of:
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
818 - file
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
819 - directory
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
820 @param file_hash(unicode): unique hash of the payload
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
821 @param hash_algo(unicode): algorithm used for hashing the file (usually sha-256)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
822 @param size(int): size in bytes
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
823 @param namespace(unicode, None): identifier (human readable is better) to group files
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
824 for instance, namespace could be used to group files in a specific photo album
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
825 @param mime_type(unicode): MIME type of the file, or None if not known/guessed
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
826 @param created(int): UNIX time of creation
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
827 @param modified(int,None): UNIX time of last modification, or None to use created date
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
828 @param owner(jid.JID, None): jid of the owner of the file (mainly useful for component)
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
829 @param access(dict, None): serialisable dictionary with access rules. See [memory.memory] for details
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
830 @param extra(dict, None): serialisable dictionary of any extra data
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
831 will be encoded to json in database
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
832 """
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
833 if extra is not None:
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
834 assert isinstance(extra, dict)
2507
4c45df43ea44 core (memory/sqlite): renamed column for files from hash to file_hash:
Goffi <goffi@goffi.org>
parents: 2500
diff changeset
835 query = ('INSERT INTO files(id, version, parent, type, file_hash, hash_algo, name, size, namespace, '
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
836 'mime_type, created, modified, owner, access, extra, profile_id) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)')
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
837 d = self.dbpool.runQuery(query, (file_id, version.strip(), parent, type_,
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
838 file_hash, hash_algo,
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
839 name, size, namespace,
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
840 mime_type, created, modified,
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
841 owner.full() if owner is not None else None,
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
842 json.dumps(access) if access else None,
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
843 json.dumps(extra) if extra else None,
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
844 self.profiles[client.profile]))
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
845 d.addErrback(lambda failure: log.error(_(u"Can't save file metadata for [{profile}]: {reason}".format(profile=client.profile, reason=failure))))
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
846 return d
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
847
2526
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
848 def _fileUpdate(self, cursor, file_id, column, update_cb):
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
849 query = 'SELECT {column} FROM files where id=?'.format(column=column)
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
850 for i in xrange(5):
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
851 cursor.execute(query, [file_id])
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
852 try:
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
853 older_value_raw = cursor.fetchone()[0]
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
854 except TypeError:
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
855 raise exceptions.NotFound
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
856 value = json.loads(older_value_raw)
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
857 update_cb(value)
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
858 value_raw = json.dumps(value)
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
859 update_query = 'UPDATE files SET {column}=? WHERE id=? AND {column}=?'.format(column=column)
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
860 update_args = (value_raw, file_id, older_value_raw)
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
861 try:
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
862 cursor.execute(update_query, update_args)
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
863 except sqlite3.Error:
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
864 pass
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
865 else:
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
866 if cursor.rowcount == 1:
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
867 break;
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
868 log.warning(_(u"table not updated, probably due to race condition, trying again ({tries})").format(tries=i+1))
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
869 else:
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
870 log.error(_(u"Can't update file table"))
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
871
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
872 def fileUpdate(self, file_id, column, update_cb):
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
873 """update a column value using a method to avoid race conditions
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
874
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
875 the older value will be retrieved from database, then update_cb will be applied
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
876 to update it, and file will be updated checking that older value has not been changed meanwhile
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
877 by an other user. If it has changed, it tries again a couple of times before failing
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
878 @param column(str): column name (only "access" or "extra" are allowed)
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
879 @param update_cb(callable): method to update the value of the colum
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
880 the method will take older value as argument, and must update it in place
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
881 update_cb must not care about serialization,
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
882 it get the deserialized data (i.e. a Python object) directly
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
883 Note that the callable must be thread-safe
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
884 @raise exceptions.NotFound: there is not file with this id
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
885 """
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
886 if column not in ('access', 'extra'):
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
887 raise exceptions.InternalError('bad column name')
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
888 return self.dbpool.runInteraction(self._fileUpdate, file_id, column, update_cb)
35d591086974 core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents: 2507
diff changeset
889
413
dd4caab17008 core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents: 412
diff changeset
890 ##Helper methods##
dd4caab17008 core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents: 412
diff changeset
891
dd4caab17008 core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents: 412
diff changeset
892 def __getFirstResult(self, result):
dd4caab17008 core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents: 412
diff changeset
893 """Return the first result of a database query
dd4caab17008 core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents: 412
diff changeset
894 Useful when we are looking for one specific value"""
416
32dc8b18c2ae core: param loading/purging on profile connection/disconnection
Goffi <goffi@goffi.org>
parents: 413
diff changeset
895 return None if not result else result[0][0]
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
896
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
897
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
898 class Updater(object):
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
899 stmnt_regex = re.compile(r"[\w/' ]+(?:\(.*?\))?[^,]*")
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
900 clean_regex = re.compile(r"^ +|(?<= ) +|(?<=,) +| +$")
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
901 CREATE_SQL = "CREATE TABLE %s (%s)"
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
902 INSERT_SQL = "INSERT INTO %s VALUES (%s)"
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
903 DROP_SQL = "DROP TABLE %s"
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
904 ALTER_SQL = "ALTER TABLE %s ADD COLUMN %s"
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
905 RENAME_TABLE_SQL = "ALTER TABLE %s RENAME TO %s"
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
906
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
907 CONSTRAINTS = ('PRIMARY', 'UNIQUE', 'CHECK', 'FOREIGN')
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
908 TMP_TABLE = "tmp_sat_update"
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
909
2716
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
910 def __init__(self, sqlite_storage, sat_version):
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
911 self._sat_version = sat_version
2716
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
912 self.sqlite_storage = sqlite_storage
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
913
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
914 @property
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
915 def dbpool(self):
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
916 return self.sqlite_storage.dbpool
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
917
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
918 def getLocalVersion(self):
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
919 """ Get local database version
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
920
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
921 @return: version (int)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
922 """
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
923 return self.dbpool.runQuery("PRAGMA user_version").addCallback(lambda ret: int(ret[0][0]))
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
924
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
925 def _setLocalVersion(self, version):
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
926 """ Set local database version
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
927
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
928 @param version: version (int)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
929 @return: deferred
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
930 """
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
931 return self.dbpool.runOperation("PRAGMA user_version=%d" % version)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
932
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
933 def getLocalSchema(self):
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
934 """ return raw local schema
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
935
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
936 @return: list of strings with CREATE sql statements for local database
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
937 """
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
938 d = self.dbpool.runQuery("select sql from sqlite_master where type = 'table'")
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
939 d.addCallback(lambda result: [row[0] for row in result])
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
940 return d
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
941
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
942 @defer.inlineCallbacks
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
943 def checkUpdates(self):
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
944 """ Check if a database schema/content update is needed, according to DATABASE_SCHEMAS
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
945
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
946 @return: deferred which fire a list of SQL update statements, or None if no update is needed
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
947 """
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
948 local_version = yield self.getLocalVersion()
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
949 raw_local_sch = yield self.getLocalSchema()
2500
898b6e1fdc7a memory (sqlite): files handling:
Goffi <goffi@goffi.org>
parents: 2483
diff changeset
950
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
951 local_sch = self.rawStatements2data(raw_local_sch)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
952 current_sch = DATABASE_SCHEMAS['current']['CREATE']
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
953 local_hash = self.statementHash(local_sch)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
954 current_hash = self.statementHash(current_sch)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
955
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
956 # Force the update if the schemas are unchanged but a specific update is needed
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
957 force_update = local_hash == current_hash and local_version < CURRENT_DB_VERSION \
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
958 and 'specific' in DATABASE_SCHEMAS[CURRENT_DB_VERSION]
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
959
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
960 if local_hash == current_hash and not force_update:
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
961 if local_version != CURRENT_DB_VERSION:
993
301b342c697a core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents: 936
diff changeset
962 log.warning(_("Your local schema is up-to-date, but database versions mismatch, fixing it..."))
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
963 yield self._setLocalVersion(CURRENT_DB_VERSION)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
964 else:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
965 # an update is needed
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
966
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
967 if local_version == CURRENT_DB_VERSION:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
968 # Database mismatch and we have the latest version
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
969 if self._sat_version.endswith('D'):
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
970 # we are in a development version
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
971 update_data = self.generateUpdateData(local_sch, current_sch, False)
993
301b342c697a core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents: 936
diff changeset
972 log.warning(_("There is a schema mismatch, but as we are on a dev version, database will be updated"))
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
973 update_raw = yield self.update2raw(update_data, True)
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
974 defer.returnValue(update_raw)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
975 else:
993
301b342c697a core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents: 936
diff changeset
976 log.error(_(u"schema version is up-to-date, but local schema differ from expected current schema"))
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
977 update_data = self.generateUpdateData(local_sch, current_sch, True)
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
978 update_raw = yield self.update2raw(update_data)
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
979 log.warning(_(u"Here are the commands that should fix the situation, use at your own risk (do a backup before modifying database), you can go to SàT's MUC room at sat@chat.jabberfr.org for help\n### SQL###\n%s\n### END SQL ###\n") % u'\n'.join("%s;" % statement for statement in update_raw))
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
980 raise exceptions.DatabaseError("Database mismatch")
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
981 else:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
982 # Database is not up-to-date, we'll do the update
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
983 if force_update:
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
984 log.info(_("Database content needs a specific processing, local database will be updated"))
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
985 else:
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
986 log.info(_("Database schema has changed, local database will be updated"))
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
987 update_raw = []
1019
6a16ec17a458 better PEP-8 compliance
souliane <souliane@mailoo.org>
parents: 993
diff changeset
988 for version in xrange(local_version + 1, CURRENT_DB_VERSION + 1):
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
989 try:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
990 update_data = DATABASE_SCHEMAS[version]
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
991 except KeyError:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
992 raise exceptions.InternalError("Missing update definition (version %d)" % version)
2716
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
993 if "specific" in update_data:
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
994 # if we have a specific, we must commit current statements
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
995 # because a specific may modify database itself, and the database
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
996 # must be in the expected state of the previous version.
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
997 yield self.sqlite_storage.commitStatements(update_raw)
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
998 del update_raw[:]
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
999 update_raw_step = yield self.update2raw(update_data)
2716
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1000 if update_raw_step is not None:
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1001 # can be None with specifics
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1002 update_raw.extend(update_raw_step)
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1003 update_raw.append("PRAGMA user_version=%d" % CURRENT_DB_VERSION)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1004 defer.returnValue(update_raw)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1005
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1006 @staticmethod
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1007 def createData2Raw(data):
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1008 """ Generate SQL statements from statements data
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
1009
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1010 @param data: dictionary with table as key, and statements data in tuples as value
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1011 @return: list of strings with raw statements
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1012 """
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1013 ret = []
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1014 for table in data:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1015 defs, constraints = data[table]
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1016 assert isinstance(defs, tuple)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1017 assert isinstance(constraints, tuple)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1018 ret.append(Updater.CREATE_SQL % (table, ', '.join(defs + constraints)))
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1019 return ret
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1020
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1021 @staticmethod
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1022 def insertData2Raw(data):
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1023 """ Generate SQL statements from statements data
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
1024
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1025 @param data: dictionary with table as key, and statements data in tuples as value
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1026 @return: list of strings with raw statements
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1027 """
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1028 ret = []
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1029 for table in data:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1030 values_tuple = data[table]
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1031 assert isinstance(values_tuple, tuple)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1032 for values in values_tuple:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1033 assert isinstance(values, tuple)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1034 ret.append(Updater.INSERT_SQL % (table, ', '.join(values)))
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1035 return ret
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1036
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1037 def statementHash(self, data):
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1038 """ Generate hash of template data
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
1039
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1040 useful to compare schemas
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1041 @param data: dictionary of "CREATE" statement, with tables names as key,
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1042 and tuples of (col_defs, constraints) as values
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1043 @return: hash as string
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1044 """
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1045 hash_ = hashlib.sha1()
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1046 tables = data.keys()
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1047 tables.sort()
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1048
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1049 def stmnts2str(stmts):
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1050 return ','.join([self.clean_regex.sub('',stmt) for stmt in sorted(stmts)])
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1051
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1052 for table in tables:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1053 col_defs, col_constr = data[table]
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1054 hash_.update("%s:%s:%s" % (table, stmnts2str(col_defs), stmnts2str(col_constr)))
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1055 return hash_.digest()
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1056
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1057 def rawStatements2data(self, raw_statements):
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1058 """ separate "CREATE" statements into dictionary/tuples data
2143
c3cac21157d4 memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents: 2013
diff changeset
1059
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1060 @param raw_statements: list of CREATE statements as strings
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1061 @return: dictionary with table names as key, and a (col_defs, constraints) tuple
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1062 """
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1063 schema_dict = {}
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1064 for create_statement in raw_statements:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1065 if not create_statement.startswith("CREATE TABLE "):
993
301b342c697a core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents: 936
diff changeset
1066 log.warning("Unexpected statement, ignoring it")
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1067 continue
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1068 _create_statement = create_statement[13:]
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1069 table, raw_col_stats = _create_statement.split(' ',1)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1070 if raw_col_stats[0] != '(' or raw_col_stats[-1] != ')':
993
301b342c697a core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents: 936
diff changeset
1071 log.warning("Unexpected statement structure, ignoring it")
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1072 continue
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1073 col_stats = [stmt.strip() for stmt in self.stmnt_regex.findall(raw_col_stats[1:-1])]
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1074 col_defs = []
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1075 constraints = []
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1076 for col_stat in col_stats:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1077 name = col_stat.split(' ',1)[0]
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1078 if name in self.CONSTRAINTS:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1079 constraints.append(col_stat)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1080 else:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1081 col_defs.append(col_stat)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1082 schema_dict[table] = (tuple(col_defs), tuple(constraints))
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1083 return schema_dict
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1084
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1085 def generateUpdateData(self, old_data, new_data, modify=False):
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1086 """ Generate data for automatic update between two schema data
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1087
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1088 @param old_data: data of the former schema (which must be updated)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1089 @param new_data: data of the current schema
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1090 @param modify: if True, always use "cols modify" table, else try to ALTER tables
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1091 @return: update data, a dictionary with:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1092 - 'create': dictionary of tables to create
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1093 - 'delete': tuple of tables to delete
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1094 - 'cols create': dictionary of columns to create (table as key, tuple of columns to create as value)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1095 - 'cols delete': dictionary of columns to delete (table as key, tuple of columns to delete as value)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1096 - 'cols modify': dictionary of columns to modify (table as key, tuple of old columns to transfert as value). With this table, a new table will be created, and content from the old table will be transfered to it, only cols specified in the tuple will be transfered.
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1097 """
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1098
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1099 create_tables_data = {}
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1100 create_cols_data = {}
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1101 modify_cols_data = {}
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1102 delete_cols_data = {}
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1103 old_tables = set(old_data.keys())
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1104 new_tables = set(new_data.keys())
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1105
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1106 def getChanges(set_olds, set_news):
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1107 to_create = set_news.difference(set_olds)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1108 to_delete = set_olds.difference(set_news)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1109 to_check = set_news.intersection(set_olds)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1110 return tuple(to_create), tuple(to_delete), tuple(to_check)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1111
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1112 tables_to_create, tables_to_delete, tables_to_check = getChanges(old_tables, new_tables)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1113
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1114 for table in tables_to_create:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1115 create_tables_data[table] = new_data[table]
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1116
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1117 for table in tables_to_check:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1118 old_col_defs, old_constraints = old_data[table]
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1119 new_col_defs, new_constraints = new_data[table]
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1120 for obj in old_col_defs, old_constraints, new_col_defs, new_constraints:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1121 if not isinstance(obj, tuple):
993
301b342c697a core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents: 936
diff changeset
1122 raise exceptions.InternalError("Columns definitions must be tuples")
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1123 defs_create, defs_delete, ignore = getChanges(set(old_col_defs), set(new_col_defs))
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1124 constraints_create, constraints_delete, ignore = getChanges(set(old_constraints), set(new_constraints))
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1125 created_col_names = set([name.split(' ',1)[0] for name in defs_create])
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1126 deleted_col_names = set([name.split(' ',1)[0] for name in defs_delete])
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1127 if (created_col_names.intersection(deleted_col_names or constraints_create or constraints_delete) or
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1128 (modify and (defs_create or constraints_create or defs_delete or constraints_delete))):
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1129 # we have modified columns, we need to transfer table
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1130 # we determinate which columns are in both schema so we can transfer them
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1131 old_names = set([name.split(' ',1)[0] for name in old_col_defs])
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1132 new_names = set([name.split(' ',1)[0] for name in new_col_defs])
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1133 modify_cols_data[table] = tuple(old_names.intersection(new_names));
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1134 else:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1135 if defs_create:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1136 create_cols_data[table] = (defs_create)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1137 if defs_delete or constraints_delete:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1138 delete_cols_data[table] = (defs_delete)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1139
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1140 return {'create': create_tables_data,
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1141 'delete': tables_to_delete,
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1142 'cols create': create_cols_data,
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1143 'cols delete': delete_cols_data,
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1144 'cols modify': modify_cols_data
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1145 }
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1146
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1147 @defer.inlineCallbacks
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1148 def update2raw(self, update, dev_version=False):
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1149 """ Transform update data to raw SQLite statements
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1150
1455
4fb3280c4568 tmp (wokkel.rsm): use of super instead of direct call in PubSubRequest
Goffi <goffi@goffi.org>
parents: 1409
diff changeset
1151 @param update: update data as returned by generateUpdateData
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1152 @param dev_version: if True, update will be done in dev mode: no deletion will be done, instead a message will be shown. This prevent accidental lost of data while working on the code/database.
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1153 @return: list of string with SQL statements needed to update the base
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1154 """
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1155 ret = self.createData2Raw(update.get('create', {}))
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1156 drop = []
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1157 for table in update.get('delete', tuple()):
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1158 drop.append(self.DROP_SQL % table)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1159 if dev_version:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1160 if drop:
993
301b342c697a core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents: 936
diff changeset
1161 log.info("Dev version, SQL NOT EXECUTED:\n--\n%s\n--\n" % "\n".join(drop))
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1162 else:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1163 ret.extend(drop)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1164
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1165 cols_create = update.get('cols create', {})
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1166 for table in cols_create:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1167 for col_def in cols_create[table]:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1168 ret.append(self.ALTER_SQL % (table, col_def))
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1169
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1170 cols_delete = update.get('cols delete', {})
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1171 for table in cols_delete:
993
301b342c697a core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents: 936
diff changeset
1172 log.info("Following columns in table [%s] are not needed anymore, but are kept for dev version: %s" % (table, ", ".join(cols_delete[table])))
853
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1173
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1174 cols_modify = update.get('cols modify', {})
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1175 for table in cols_modify:
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1176 ret.append(self.RENAME_TABLE_SQL % (table, self.TMP_TABLE))
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1177 main, extra = DATABASE_SCHEMAS['current']['CREATE'][table]
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1178 ret.append(self.CREATE_SQL % (table, ', '.join(main + extra)))
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1179 common_cols = ', '.join(cols_modify[table])
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1180 ret.append("INSERT INTO %s (%s) SELECT %s FROM %s" % (table, common_cols, common_cols, self.TMP_TABLE))
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1181 ret.append(self.DROP_SQL % self.TMP_TABLE)
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1182
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1183 insert = update.get('insert', {})
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1184 ret.extend(self.insertData2Raw(insert))
c2f6ada7858f core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents: 839
diff changeset
1185
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1186 specific = update.get('specific', None)
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1187 if specific:
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1188 cmds = yield getattr(self, specific)()
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1189 ret.extend(cmds or [])
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1190 defer.returnValue(ret)
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1191
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1192 @defer.inlineCallbacks
2716
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1193 def update_v7(self):
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1194 """Update database from v6 to v7 (history unique constraint change)"""
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1195 log.info(u"Database update to v7, this may take a while")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1196 # we have to rename table we will replace
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1197 # tables referencing history need to be replaced to, else reference would
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1198 # be to the old table (which will be dropped at the end). This buggy behaviour
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1199 # seems to be fixed in new version of Sqlite
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1200 yield self.dbpool.runQuery("ALTER TABLE history RENAME TO history_old")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1201 yield self.dbpool.runQuery("ALTER TABLE message RENAME TO message_old")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1202 yield self.dbpool.runQuery("ALTER TABLE subject RENAME TO subject_old")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1203 yield self.dbpool.runQuery("ALTER TABLE thread RENAME TO thread_old")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1204
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1205 # we need to fix duplicate stanza_id, as it can result in conflicts with the new schema
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1206 # normally database should not contain any, but better safe than sorry.
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1207 rows = yield self.dbpool.runQuery(
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1208 u"SELECT stanza_id, COUNT(*) as c FROM history_old WHERE stanza_id is not NULL "
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1209 u"GROUP BY stanza_id HAVING c>1")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1210 if rows:
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1211 count = sum([r[1] for r in rows]) - len(rows)
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1212 log.info(u"{count} duplicate stanzas found, cleaning".format(count=count))
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1213 for stanza_id, count in rows:
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1214 log.info(u"cleaning duplicate stanza {stanza_id}".format(stanza_id=stanza_id))
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1215 row_uids = yield self.dbpool.runQuery(
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1216 "SELECT uid FROM history_old WHERE stanza_id = ? LIMIT ?",
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1217 (stanza_id, count-1))
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1218 uids = [r[0] for r in row_uids]
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1219 yield self.dbpool.runQuery(
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1220 "DELETE FROM history_old WHERE uid IN ({})".format(u",".join(u"?"*len(uids))),
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1221 uids)
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1222 log.info(u"Cleaning done")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1223
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1224 # history
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1225 query = (u"CREATE TABLE history (uid TEXT PRIMARY KEY, stanza_id TEXT, "
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1226 u"update_uid TEXT, profile_id INTEGER, source TEXT, dest TEXT, "
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1227 u"source_res TEXT, dest_res TEXT, timestamp DATETIME NOT NULL, "
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1228 u"received_timestamp DATETIME, type TEXT, extra BLOB, "
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1229 u"FOREIGN KEY(profile_id) REFERENCES profiles(id) ON DELETE CASCADE, "
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1230 u"FOREIGN KEY(type) REFERENCES message_types(type), "
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1231 u"UNIQUE (profile_id, stanza_id, source, dest))")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1232 yield self.dbpool.runQuery(query)
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1233
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1234 # message
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1235 query = (u"CREATE TABLE message (id INTEGER PRIMARY KEY ASC, history_uid INTEGER"
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1236 u", message TEXT, language TEXT, FOREIGN KEY(history_uid) REFERENCES "
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1237 u"history(uid) ON DELETE CASCADE)")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1238 yield self.dbpool.runQuery(query)
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1239
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1240 # subject
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1241 query = (u"CREATE TABLE subject (id INTEGER PRIMARY KEY ASC, history_uid INTEGER"
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1242 u", subject TEXT, language TEXT, FOREIGN KEY(history_uid) REFERENCES "
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1243 u"history(uid) ON DELETE CASCADE)")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1244 yield self.dbpool.runQuery(query)
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1245
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1246 # thread
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1247 query = (u"CREATE TABLE thread (id INTEGER PRIMARY KEY ASC, history_uid INTEGER"
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1248 u", thread_id TEXT, parent_id TEXT, FOREIGN KEY(history_uid) REFERENCES "
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1249 u"history(uid) ON DELETE CASCADE)")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1250 yield self.dbpool.runQuery(query)
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1251
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1252 log.info(u"Now transfering old data to new tables, this can be really long "
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1253 u"depending on your history size, please be patient.")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1254
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1255 log.info(u"\nTransfering table history")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1256 query = (u"INSERT INTO history (uid, stanza_id, update_uid, profile_id, source, "
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1257 u"dest, source_res, dest_res, timestamp, received_timestamp, type, extra"
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1258 u") SELECT uid, stanza_id, update_uid, profile_id, source, dest, "
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1259 u"source_res, dest_res, timestamp, received_timestamp, type, extra "
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1260 u"FROM history_old")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1261 yield self.dbpool.runQuery(query)
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1262
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1263 log.info(u"\nTransfering table message")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1264 query = (u"INSERT INTO message (id, history_uid, message, language) SELECT id, "
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1265 u"history_uid, message, language FROM message_old")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1266 yield self.dbpool.runQuery(query)
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1267
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1268 log.info(u"\nTransfering table subject")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1269 query = (u"INSERT INTO subject (id, history_uid, subject, language) SELECT id, "
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1270 u"history_uid, subject, language FROM subject_old")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1271 yield self.dbpool.runQuery(query)
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1272
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1273 log.info(u"\nTransfering table thread")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1274 query = (u"INSERT INTO thread (id, history_uid, thread_id, parent_id) SELECT id"
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1275 u", history_uid, thread_id, parent_id FROM thread_old")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1276 yield self.dbpool.runQuery(query)
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1277
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1278 yield self.dbpool.runQuery("DROP TABLE history_old")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1279 yield self.dbpool.runQuery("DROP TABLE message_old")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1280 yield self.dbpool.runQuery("DROP TABLE subject_old")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1281 yield self.dbpool.runQuery("DROP TABLE thread_old")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1282 log.info(u"Database update done :)")
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1283
06160b529da6 core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents: 2715
diff changeset
1284 @defer.inlineCallbacks
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1285 def update_v3(self):
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1286 """Update database from v2 to v3 (message refactoring)"""
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1287 # XXX: this update do all the messages in one huge transaction
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1288 # this is really memory consuming, but was OK on a reasonably
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1289 # big database for tests. If issues are happening, we can cut it
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1290 # in smaller transactions using LIMIT and by deleting already updated
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1291 # messages
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1292 log.info(u"Database update to v3, this may take a while")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1293
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1294 # we need to fix duplicate timestamp, as it can result in conflicts with the new schema
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1295 rows = yield self.dbpool.runQuery("SELECT timestamp, COUNT(*) as c FROM history GROUP BY timestamp HAVING c>1")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1296 if rows:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1297 log.info("fixing duplicate timestamp")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1298 fixed = []
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1299 for timestamp, dummy in rows:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1300 ids_rows = yield self.dbpool.runQuery("SELECT id from history where timestamp=?", (timestamp,))
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1301 for idx, (id_,) in enumerate(ids_rows):
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1302 fixed.append(id_)
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1303 yield self.dbpool.runQuery("UPDATE history SET timestamp=? WHERE id=?", (float(timestamp) + idx * 0.001, id_))
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1304 log.info(u"fixed messages with ids {}".format(u', '.join([unicode(id_) for id_ in fixed])))
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1305
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1306 def historySchema(txn):
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1307 log.info(u"History schema update")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1308 txn.execute("ALTER TABLE history RENAME TO tmp_sat_update")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1309 txn.execute("CREATE TABLE history (uid TEXT PRIMARY KEY, update_uid TEXT, profile_id INTEGER, source TEXT, dest TEXT, source_res TEXT, dest_res TEXT, timestamp DATETIME NOT NULL, received_timestamp DATETIME, type TEXT, extra BLOB, FOREIGN KEY(profile_id) REFERENCES profiles(id) ON DELETE CASCADE, FOREIGN KEY(type) REFERENCES message_types(type), UNIQUE (profile_id, timestamp, source, dest, source_res, dest_res))")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1310 txn.execute("INSERT INTO history (uid, profile_id, source, dest, source_res, dest_res, timestamp, type, extra) SELECT id, profile_id, source, dest, source_res, dest_res, timestamp, type, extra FROM tmp_sat_update")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1311
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1312 yield self.dbpool.runInteraction(historySchema)
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1313
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1314 def newTables(txn):
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1315 log.info(u"Creating new tables")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1316 txn.execute("CREATE TABLE message (id INTEGER PRIMARY KEY ASC, history_uid INTEGER, message TEXT, language TEXT, FOREIGN KEY(history_uid) REFERENCES history(uid) ON DELETE CASCADE)")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1317 txn.execute("CREATE TABLE thread (id INTEGER PRIMARY KEY ASC, history_uid INTEGER, thread_id TEXT, parent_id TEXT, FOREIGN KEY(history_uid) REFERENCES history(uid) ON DELETE CASCADE)")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1318 txn.execute("CREATE TABLE subject (id INTEGER PRIMARY KEY ASC, history_uid INTEGER, subject TEXT, language TEXT, FOREIGN KEY(history_uid) REFERENCES history(uid) ON DELETE CASCADE)")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1319
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1320 yield self.dbpool.runInteraction(newTables)
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1321
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1322 log.info(u"inserting new message type")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1323 yield self.dbpool.runQuery("INSERT INTO message_types VALUES (?)", ('info',))
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1324
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1325 log.info(u"messages update")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1326 rows = yield self.dbpool.runQuery("SELECT id, timestamp, message, extra FROM tmp_sat_update")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1327 total = len(rows)
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1328
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1329 def updateHistory(txn, queries):
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1330 for query, args in iter(queries):
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1331 txn.execute(query, args)
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1332
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1333 queries = []
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1334 for idx, row in enumerate(rows, 1):
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1335 if idx % 1000 == 0 or total - idx == 0:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1336 log.info("preparing message {}/{}".format(idx, total))
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1337 id_, timestamp, message, extra = row
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1338 try:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1339 extra = pickle.loads(str(extra or ""))
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1340 except EOFError:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1341 extra = {}
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1342 except Exception:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1343 log.warning(u"Can't handle extra data for message id {}, ignoring it".format(id_))
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1344 extra = {}
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1345
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1346 queries.append(("INSERT INTO message(history_uid, message) VALUES (?,?)", (id_, message)))
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1347
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1348 try:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1349 subject = extra.pop('subject')
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1350 except KeyError:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1351 pass
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1352 else:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1353 try:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1354 subject = subject.decode('utf-8')
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1355 except UnicodeEncodeError:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1356 log.warning(u"Error while decoding subject, ignoring it")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1357 del extra['subject']
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1358 else:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1359 queries.append(("INSERT INTO subject(history_uid, subject) VALUES (?,?)", (id_, subject)))
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1360
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1361 received_timestamp = extra.pop('timestamp', None)
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1362 try:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1363 del extra['archive']
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1364 except KeyError:
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1365 # archive was not used
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1366 pass
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1367
1962
a45235d8dc93 memory (sqlite): fixed handling of extra (pickled data) by using sqlite3.Binary
Goffi <goffi@goffi.org>
parents: 1961
diff changeset
1368 queries.append(("UPDATE history SET received_timestamp=?,extra=? WHERE uid=?",(id_, received_timestamp, sqlite3.Binary(pickle.dumps(extra, 0)))))
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1369
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1370 yield self.dbpool.runInteraction(updateHistory, queries)
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1371
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1372 log.info("Dropping temporary table")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1373 yield self.dbpool.runQuery("DROP TABLE tmp_sat_update")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1374 log.info("Database update finished :)")
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1375
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1376 def update2raw_v2(self):
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1377 """Update the database from v1 to v2 (add passwords encryptions):
1955
633b5c21aefd backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents: 1934
diff changeset
1378
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1379 - the XMPP password value is re-used for the profile password (new parameter)
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1380 - the profile password is stored hashed
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1381 - the XMPP password is stored encrypted, with the profile password as key
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1382 - as there are no other stored passwords yet, it is enough, otherwise we
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1383 would need to encrypt the other passwords as it's done for XMPP password
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1384 """
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1385 xmpp_pass_path = ('Connection', 'Password')
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1386
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1387 def encrypt_values(values):
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1388 ret = []
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1389 list_ = []
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1390
1065
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1391 def prepare_queries(result, xmpp_password):
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1392 try:
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1393 id_ = result[0][0]
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1394 except IndexError:
1409
3265a2639182 massive (preventive) addition of 'u' (unicode) before the strings passed to logging functions
souliane <souliane@mailoo.org>
parents: 1396
diff changeset
1395 log.error(u"Profile of id %d is referenced in 'param_ind' but it doesn't exist!" % profile_id)
1099
1baa116501fa memory (sqlite): fixes upgrade Deferred issue
souliane <souliane@mailoo.org>
parents: 1065
diff changeset
1396 return defer.succeed(None)
1065
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1397
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1398 sat_password = xmpp_password
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1399 d1 = PasswordHasher.hash(sat_password)
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1400 personal_key = BlockCipher.getRandomKey(base64=True)
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1401 d2 = BlockCipher.encrypt(sat_password, personal_key)
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1402 d3 = BlockCipher.encrypt(personal_key, xmpp_password)
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1403
1065
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1404 def gotValues(res):
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1405 sat_cipher, personal_cipher, xmpp_cipher = res[0][1], res[1][1], res[2][1]
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1406 ret.append("INSERT INTO param_ind(category,name,profile_id,value) VALUES ('%s','%s',%s,'%s')" %
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1407 (C.PROFILE_PASS_PATH[0], C.PROFILE_PASS_PATH[1], id_, sat_cipher))
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1408
1065
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1409 ret.append("INSERT INTO private_ind(namespace,key,profile_id,value) VALUES ('%s','%s',%s,'%s')" %
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1410 (C.MEMORY_CRYPTO_NAMESPACE, C.MEMORY_CRYPTO_KEY, id_, personal_cipher))
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1411
1065
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1412 ret.append("REPLACE INTO param_ind(category,name,profile_id,value) VALUES ('%s','%s',%s,'%s')" %
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1413 (xmpp_pass_path[0], xmpp_pass_path[1], id_, xmpp_cipher))
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1414
1065
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1415 return defer.DeferredList([d1, d2, d3]).addCallback(gotValues)
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1416
1065
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1417 for profile_id, xmpp_password in values:
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1418 d = self.dbpool.runQuery("SELECT id FROM profiles WHERE id=?", (profile_id,))
1065
9378c80e3408 memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents: 1047
diff changeset
1419 d.addCallback(prepare_queries, xmpp_password)
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1420 list_.append(d)
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1421
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1422 d_list = defer.DeferredList(list_)
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1423 d_list.addCallback(lambda dummy: ret)
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1424 return d_list
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1425
1045
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
1426 def updateLiberviaConf(values):
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
1427 try:
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
1428 profile_id = values[0][0]
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
1429 except IndexError:
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
1430 return # no profile called "libervia"
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
1431
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
1432 def cb(selected):
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
1433 try:
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
1434 password = selected[0][0]
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
1435 except IndexError:
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
1436 log.error("Libervia profile exists but no password is set! Update Libervia configuration will be skipped.")
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
1437 return
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
1438 fixConfigOption('libervia', 'passphrase', password, False)
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
1439 d = self.dbpool.runQuery("SELECT value FROM param_ind WHERE category=? AND name=? AND profile_id=?", xmpp_pass_path + (profile_id,))
1047
5f7f913c05ac memory: synchronize the upgrade to database v2 to be sure libervia's profile password is read to be written in the config file before its encryption
souliane <souliane@mailoo.org>
parents: 1045
diff changeset
1440 return d.addCallback(cb)
1045
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
1441
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
1442 d = self.dbpool.runQuery("SELECT id FROM profiles WHERE name='libervia'")
65fffdcb97f1 memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents: 1030
diff changeset
1443 d.addCallback(updateLiberviaConf)
1047
5f7f913c05ac memory: synchronize the upgrade to database v2 to be sure libervia's profile password is read to be written in the config file before its encryption
souliane <souliane@mailoo.org>
parents: 1045
diff changeset
1444 d.addCallback(lambda dummy: self.dbpool.runQuery("SELECT profile_id,value FROM param_ind WHERE category=? AND name=?", xmpp_pass_path))
1030
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1445 d.addCallback(encrypt_values)
15f43b54d697 core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents: 1019
diff changeset
1446 return d