Mercurial > libervia-backend
annotate sat/memory/sqlite.py @ 3185:554b3b632378
memory (cache): purge + pathlib:
- cache is now purged on backend startup (every file which has passed EOL will be deleted)
- use of pathlib, getPath now returns a Path
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 26 Feb 2020 15:54:43 +0100 |
parents | 330a5f1d9eea |
children | 7255286a298a |
rev | line source |
---|---|
3028 | 1 #!/usr/bin/env python3 |
3137 | 2 |
412 | 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 |
3136 | 5 # Copyright (C) 2009-2020 Jérôme Poisson (goffi@goffi.org) |
412 | 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 | 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 | 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 | 19 |
771 | 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 |
1030
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
24 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
|
25 from sat.tools.config import fixConfigOption |
412 | 26 from twisted.enterprise import adbapi |
27 from twisted.internet import defer | |
2500 | 28 from twisted.words.protocols.jabber import jid |
1961
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
29 from twisted.python import failure |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
30 from collections import OrderedDict |
2964
17c61d09a85b
memory (sqlite): exit with an error if current db version is higher than version expected in current code
Goffi <goffi@goffi.org>
parents:
2928
diff
changeset
|
31 import sys |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
32 import re |
412 | 33 import os.path |
3028 | 34 import pickle 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 | 37 import json |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
38 |
2964
17c61d09a85b
memory (sqlite): exit with an error if current db version is higher than version expected in current code
Goffi <goffi@goffi.org>
parents:
2928
diff
changeset
|
39 log = getLogger(__name__) |
17c61d09a85b
memory (sqlite): exit with an error if current db version is higher than version expected in current code
Goffi <goffi@goffi.org>
parents:
2928
diff
changeset
|
40 |
2787 | 41 CURRENT_DB_VERSION = 8 |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
42 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
43 # XXX: DATABASE schemas are used in the following way: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
44 # - '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
|
45 # - 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
|
46 # 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
|
47 # a 'current' data dict can contains the keys: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
48 # - '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
|
49 # - '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) |
2787 | 50 # - 'INDEX': |
1030
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
51 # 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 | 52 # TODO: indexes need to be improved |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
53 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
54 DATABASE_SCHEMAS = { |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
55 "current": {'CREATE': OrderedDict(( |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
56 ('profiles', (("id INTEGER PRIMARY KEY ASC", "name TEXT"), |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
57 ("UNIQUE (name)",))), |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
58 ('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
|
59 ("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
|
60 ('message_types', (("type TEXT PRIMARY KEY",), |
2500 | 61 ())), |
2699
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
62 ('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
|
63 "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
|
64 "type TEXT", "extra BLOB"), |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
65 ("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
|
66 "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
|
67 ))), |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
68 ('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
|
69 ("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
|
70 ('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
|
71 ("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
|
72 ('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
|
73 ('param_gen', (("category TEXT", "name TEXT", "value TEXT"), |
2787 | 74 ("PRIMARY KEY (category, name)",))), |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
75 ('param_ind', (("category TEXT", "name TEXT", "profile_id INTEGER", "value TEXT"), |
2787 | 76 ("PRIMARY KEY (profile_id, category, name)", "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
|
77 ('private_gen', (("namespace TEXT", "key TEXT", "value TEXT"), |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
78 ("PRIMARY KEY (namespace, key)",))), |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
79 ('private_ind', (("namespace TEXT", "key TEXT", "profile_id INTEGER", "value TEXT"), |
2787 | 80 ("PRIMARY KEY (profile_id, namespace, key)", "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
|
81 ('private_gen_bin', (("namespace TEXT", "key TEXT", "value BLOB"), |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
82 ("PRIMARY KEY (namespace, key)",))), |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
83 ('private_ind_bin', (("namespace TEXT", "key TEXT", "profile_id INTEGER", "value BLOB"), |
2787 | 84 ("PRIMARY KEY (profile_id, namespace, key)", "FOREIGN KEY(profile_id) REFERENCES profiles(id) ON DELETE CASCADE"))), |
2500 | 85 ('files', (("id TEXT NOT NULL", "version TEXT NOT NULL", "parent TEXT NOT NULL", |
86 "type TEXT CHECK(type in ('{file}', '{directory}')) NOT NULL DEFAULT '{file}'".format( | |
87 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
|
88 "file_hash TEXT", "hash_algo TEXT", "name TEXT NOT NULL", "size INTEGER", |
2500 | 89 "namespace TEXT", "mime_type TEXT", |
90 "created DATETIME NOT NULL", "modified DATETIME", | |
91 "owner TEXT", "access TEXT", "extra TEXT", "profile_id INTEGER"), | |
92 ("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
|
93 )), |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
94 'INSERT': OrderedDict(( |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
95 ('message_types', (("'chat'",), |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
96 ("'error'",), |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
97 ("'groupchat'",), |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
98 ("'headline'",), |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
99 ("'normal'",), |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
100 ("'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
|
101 )), |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
102 )), |
2787 | 103 'INDEX': (('history', (('profile_id', 'timestamp'), |
104 ('profile_id', 'received_timestamp'))), | |
105 ('message', ('history_uid',)), | |
106 ('subject', ('history_uid',)), | |
107 ('thread', ('history_uid',)), | |
108 ('files', ('profile_id', 'mime_type', 'owner', 'parent'))), | |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
109 }, |
2787 | 110 8: {'specific': 'update_v8' |
111 }, | |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
112 7: {'specific': 'update_v7' |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
113 }, |
2699
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
114 6: {'cols create': {'history': ('stanza_id TEXT',)}, |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
115 }, |
2500 | 116 5: {'create': {'files': (("id TEXT NOT NULL", "version TEXT NOT NULL", "parent TEXT NOT NULL", |
117 "type TEXT CHECK(type in ('{file}', '{directory}')) NOT NULL DEFAULT '{file}'".format( | |
118 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
|
119 "file_hash TEXT", "hash_algo TEXT", "name TEXT NOT NULL", "size INTEGER", |
2500 | 120 "namespace TEXT", "mime_type TEXT", |
121 "created DATETIME NOT NULL", "modified DATETIME", | |
122 "owner TEXT", "access TEXT", "extra TEXT", "profile_id INTEGER"), | |
123 ("PRIMARY KEY (id, version)", "FOREIGN KEY(profile_id) REFERENCES profiles(id) ON DELETE CASCADE"))}, | |
124 }, | |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
125 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
|
126 }, |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
127 3: {'specific': 'update_v3' |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
128 }, |
1030
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
129 2: {'specific': 'update2raw_v2' |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
130 }, |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
131 1: {'cols create': {'history': ('extra BLOB',)}, |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
132 }, |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
133 } |
412 | 134 |
2699
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
135 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
|
136 # 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
|
137 # 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
|
138 |
1961
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
139 |
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
140 class ConnectionPool(adbapi.ConnectionPool): |
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
141 def _runQuery(self, trans, *args, **kw): |
2357
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
142 retry = kw.pop('query_retry', 6) |
1961
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
143 try: |
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
144 trans.execute(*args, **kw) |
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
145 except sqlite3.IntegrityError as e: |
2747
6487b8855c9a
memory (sqlite): minor comment move
Goffi <goffi@goffi.org>
parents:
2746
diff
changeset
|
146 # Workaround to avoid IntegrityError causing (i)pdb to be |
6487b8855c9a
memory (sqlite): minor comment move
Goffi <goffi@goffi.org>
parents:
2746
diff
changeset
|
147 # launched in debug mode |
1961
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
148 raise failure.Failure(e) |
2357
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
149 except Exception as e: |
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
150 # 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
|
151 # this is a workaround, we need to move to better |
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
152 # Sqlite integration, probably with high level library |
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
153 retry -= 1 |
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
154 if retry == 0: |
3028 | 155 log.error(_('too many db tries, we abandon! Error message: {msg}\n' |
156 'query was {query}' | |
157 .format(msg=e, query=' '.join([str(a) for a in args])))) | |
2357
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
158 raise e |
2746
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
159 log.warning( |
3028 | 160 _('exception while running query, retrying ({try_}): {msg}').format( |
2357
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
161 try_ = 6 - retry, |
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
162 msg = e)) |
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
163 kw['query_retry'] = retry |
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
164 return self._runQuery(trans, *args, **kw) |
1961
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
165 return trans.fetchall() |
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
166 |
2746
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
167 def _runInteraction(self, interaction, *args, **kw): |
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
168 # sometimes interaction may fail while committing in _runInteraction |
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
169 # and it may be due to a db lock. So we work around it in a similar way |
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
170 # as for _runQuery but with only 3 tries |
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
171 retry = kw.pop('interaction_retry', 4) |
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
172 try: |
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
173 return adbapi.ConnectionPool._runInteraction(self, interaction, *args, **kw) |
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
174 except Exception as e: |
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
175 retry -= 1 |
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
176 if retry == 0: |
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
177 log.error( |
3028 | 178 _('too many interaction tries, we abandon! Error message: {msg}\n' |
179 'interaction method was: {interaction}\n' | |
180 'interaction arguments were: {args}' | |
2919
e4715a609d75
memory (sqlite): minor log improvment
Goffi <goffi@goffi.org>
parents:
2918
diff
changeset
|
181 .format(msg=e, interaction=interaction, |
3028 | 182 args=', '.join([str(a) for a in args])))) |
2746
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
183 raise e |
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
184 log.warning( |
3028 | 185 _('exception while running interaction, retrying ({try_}): {msg}') |
2746
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
186 .format(try_ = 4 - retry, msg = e)) |
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
187 kw['interaction_retry'] = retry |
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
188 return self._runInteraction(interaction, *args, **kw) |
1e2f0856c845
memory (sqlite): retry _runInteraction in the same way as for _runQuery, this improve reliability
Goffi <goffi@goffi.org>
parents:
2735
diff
changeset
|
189 |
1961
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
190 |
588
beaf6bec2fcd
Remove every old-style class.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
587
diff
changeset
|
191 class SqliteStorage(object): |
412 | 192 """This class manage storage with Sqlite database""" |
193 | |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
194 def __init__(self, db_filename, sat_version): |
412 | 195 """Connect to the given database |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
196 |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
197 @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
|
198 """ |
3120 | 199 # triggered when memory is fully initialised and ready |
200 self.initialized = defer.Deferred() | |
201 # we keep cache for the profiles (key: profile name, value: profile id) | |
202 self.profiles = {} | |
412 | 203 |
993
301b342c697a
core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
204 log.info(_("Connecting database")) |
592
e5a875a3311b
Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
588
diff
changeset
|
205 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
|
206 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
|
207 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
|
208 if not os.path.exists(dir_): |
3028 | 209 os.makedirs(dir_, 0o700) |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
210 |
2357
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
211 def foreignKeysOn(sqlite): |
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
212 sqlite.execute('PRAGMA foreign_keys = ON') |
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
213 |
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
214 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
|
215 |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
216 def getNewBaseSql(): |
993
301b342c697a
core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
217 log.info(_("The database is new, creating the tables")) |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
218 database_creation = ["PRAGMA user_version=%d" % CURRENT_DB_VERSION] |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
219 database_creation.extend(Updater.createData2Raw(DATABASE_SCHEMAS['current']['CREATE'])) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
220 database_creation.extend(Updater.insertData2Raw(DATABASE_SCHEMAS['current']['INSERT'])) |
2787 | 221 database_creation.extend(Updater.indexData2Raw(DATABASE_SCHEMAS['current']['INDEX'])) |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
222 return database_creation |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
223 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
224 def getUpdateSql(): |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
225 updater = Updater(self, sat_version) |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
226 return updater.checkUpdates() |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
227 |
2357
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
228 # 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
|
229 |
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
230 init_defer = defer.succeed(None) |
fa43e285df1d
core (memory/sqlite): better stability:
Goffi <goffi@goffi.org>
parents:
2209
diff
changeset
|
231 |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
232 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
|
233 init_defer.addCallback(self.commitStatements) |
412 | 234 |
235 def fillProfileCache(ignore): | |
3120 | 236 return self.dbpool.runQuery("SELECT profile_id, entry_point FROM components").addCallback(self._cacheComponentsAndProfiles) |
587
952322b1d490
Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
572
diff
changeset
|
237 |
624
70988f08d0ad
core: fixed bad database creation on first run in sqlite storage
Goffi <goffi@goffi.org>
parents:
609
diff
changeset
|
238 init_defer.addCallback(fillProfileCache) |
3120 | 239 init_defer.chainDeferred(self.initialized) |
412 | 240 |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
241 def commitStatements(self, statements): |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
242 |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
243 if statements is None: |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
244 return defer.succeed(None) |
3028 | 245 log.debug("\n===== COMMITTING STATEMENTS =====\n%s\n============\n\n" % '\n'.join(statements)) |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
246 d = self.dbpool.runInteraction(self._updateDb, tuple(statements)) |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
247 return d |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
248 |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
249 def _updateDb(self, interaction, statements): |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
250 for statement in statements: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
251 interaction.execute(statement) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
252 |
2500 | 253 ## Profiles |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
254 |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
255 def _cacheComponentsAndProfiles(self, components_result): |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
256 """Get components results and send requests profiles |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
257 |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
258 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
|
259 """ |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
260 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
|
261 self._cacheComponentsAndProfiles2, components_result) |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
262 |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
263 def _cacheComponentsAndProfiles2(self, profiles_result, components): |
412 | 264 """Fill the profiles cache |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
265 |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
266 @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
|
267 """ |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
268 self.components = dict(components) |
412 | 269 for profile in profiles_result: |
592
e5a875a3311b
Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
588
diff
changeset
|
270 name, id_ = profile |
e5a875a3311b
Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
588
diff
changeset
|
271 self.profiles[name] = id_ |
587
952322b1d490
Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
572
diff
changeset
|
272 |
412 | 273 def getProfilesList(self): |
274 """"Return list of all registered profiles""" | |
3028 | 275 return list(self.profiles.keys()) |
412 | 276 |
277 def hasProfile(self, profile_name): | |
278 """return True if profile_name exists | |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
279 |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
280 @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
|
281 """ |
592
e5a875a3311b
Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
588
diff
changeset
|
282 return profile_name in self.profiles |
587
952322b1d490
Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
572
diff
changeset
|
283 |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
284 def profileIsComponent(self, profile_name): |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
285 try: |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
286 return self.profiles[profile_name] in self.components |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
287 except KeyError: |
3028 | 288 raise exceptions.NotFound("the requested profile doesn't exists") |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
289 |
2144
1d3f73e065e1
core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents:
2143
diff
changeset
|
290 def getEntryPoint(self, profile_name): |
1d3f73e065e1
core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents:
2143
diff
changeset
|
291 try: |
1d3f73e065e1
core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents:
2143
diff
changeset
|
292 return self.components[self.profiles[profile_name]] |
1d3f73e065e1
core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents:
2143
diff
changeset
|
293 except KeyError: |
3028 | 294 raise exceptions.NotFound("the requested profile doesn't exists or is not a component") |
2144
1d3f73e065e1
core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents:
2143
diff
changeset
|
295 |
1d3f73e065e1
core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents:
2143
diff
changeset
|
296 def createProfile(self, name, component=None): |
412 | 297 """Create a new profile |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
298 |
2144
1d3f73e065e1
core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents:
2143
diff
changeset
|
299 @param name(unicode): name of the profile |
1d3f73e065e1
core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents:
2143
diff
changeset
|
300 @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
|
301 @return: deferred triggered once profile is actually created |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
302 """ |
592
e5a875a3311b
Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
588
diff
changeset
|
303 |
412 | 304 def getProfileId(ignore): |
592
e5a875a3311b
Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
588
diff
changeset
|
305 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
|
306 |
2144
1d3f73e065e1
core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents:
2143
diff
changeset
|
307 def setComponent(profile_id): |
1d3f73e065e1
core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents:
2143
diff
changeset
|
308 id_ = profile_id[0][0] |
1d3f73e065e1
core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents:
2143
diff
changeset
|
309 d_comp = self.dbpool.runQuery("INSERT INTO components(profile_id, entry_point) VALUES (?, ?)", (id_, component)) |
2765
378188abe941
misc: replaced all "dummy" by the more conventional and readable "__" ("_" being used for gettext)
Goffi <goffi@goffi.org>
parents:
2747
diff
changeset
|
310 d_comp.addCallback(lambda __: profile_id) |
2144
1d3f73e065e1
core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents:
2143
diff
changeset
|
311 return d_comp |
1d3f73e065e1
core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents:
2143
diff
changeset
|
312 |
412 | 313 def profile_created(profile_id): |
2144
1d3f73e065e1
core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents:
2143
diff
changeset
|
314 id_= profile_id[0][0] |
1d3f73e065e1
core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents:
2143
diff
changeset
|
315 self.profiles[name] = id_ # we synchronise the cache |
587
952322b1d490
Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
572
diff
changeset
|
316 |
592
e5a875a3311b
Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
588
diff
changeset
|
317 d = self.dbpool.runQuery("INSERT INTO profiles(name) VALUES (?)", (name, )) |
412 | 318 d.addCallback(getProfileId) |
2144
1d3f73e065e1
core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents:
2143
diff
changeset
|
319 if component is not None: |
1d3f73e065e1
core, jp: component handling + client handling refactoring:
Goffi <goffi@goffi.org>
parents:
2143
diff
changeset
|
320 d.addCallback(setComponent) |
412 | 321 d.addCallback(profile_created) |
322 return d | |
587
952322b1d490
Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
572
diff
changeset
|
323 |
420
acd908528ef7
core: profile creation/deletion through database
Goffi <goffi@goffi.org>
parents:
416
diff
changeset
|
324 def deleteProfile(self, name): |
acd908528ef7
core: profile creation/deletion through database
Goffi <goffi@goffi.org>
parents:
416
diff
changeset
|
325 """Delete profile |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
326 |
420
acd908528ef7
core: profile creation/deletion through database
Goffi <goffi@goffi.org>
parents:
416
diff
changeset
|
327 @param name: name of the profile |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
328 @return: deferred triggered once profile is actually deleted |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
329 """ |
1961
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
330 def deletionError(failure_): |
3028 | 331 log.error(_("Can't delete profile [%s]") % name) |
1961
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
332 return failure_ |
592
e5a875a3311b
Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
588
diff
changeset
|
333 |
934
34dd9287dfe5
plugin account: bug fix profile deletion from the database + unsubscribe the contacts
souliane <souliane@mailoo.org>
parents:
853
diff
changeset
|
334 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
|
335 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
|
336 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
|
337 # 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
|
338 # 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
|
339 # 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
|
340 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
|
341 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
|
342 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
|
343 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
|
344 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
|
345 return None |
34dd9287dfe5
plugin account: bug fix profile deletion from the database + unsubscribe the contacts
souliane <souliane@mailoo.org>
parents:
853
diff
changeset
|
346 |
34dd9287dfe5
plugin account: bug fix profile deletion from the database + unsubscribe the contacts
souliane <souliane@mailoo.org>
parents:
853
diff
changeset
|
347 d = self.dbpool.runInteraction(delete) |
993
301b342c697a
core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
348 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
|
349 d.addErrback(deletionError) |
420
acd908528ef7
core: profile creation/deletion through database
Goffi <goffi@goffi.org>
parents:
416
diff
changeset
|
350 return d |
acd908528ef7
core: profile creation/deletion through database
Goffi <goffi@goffi.org>
parents:
416
diff
changeset
|
351 |
2500 | 352 ## Params |
412 | 353 def loadGenParams(self, params_gen): |
354 """Load general parameters | |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
355 |
412 | 356 @param params_gen: dictionary to fill |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
357 @return: deferred |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
358 """ |
592
e5a875a3311b
Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
588
diff
changeset
|
359 |
412 | 360 def fillParams(result): |
413
dd4caab17008
core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents:
412
diff
changeset
|
361 for param in result: |
592
e5a875a3311b
Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
588
diff
changeset
|
362 category, name, value = param |
413
dd4caab17008
core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents:
412
diff
changeset
|
363 params_gen[(category, name)] = value |
3028 | 364 log.debug(_("loading general parameters from database")) |
412 | 365 return self.dbpool.runQuery("SELECT category,name,value FROM param_gen").addCallback(fillParams) |
366 | |
367 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
|
368 """Load individual parameters |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
369 |
412 | 370 @param params_ind: dictionary to fill |
371 @param profile: a profile which *must* exist | |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
372 @return: deferred |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
373 """ |
592
e5a875a3311b
Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
588
diff
changeset
|
374 |
412 | 375 def fillParams(result): |
413
dd4caab17008
core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents:
412
diff
changeset
|
376 for param in result: |
592
e5a875a3311b
Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
588
diff
changeset
|
377 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
|
378 params_ind[(category, name)] = value |
3028 | 379 log.debug(_("loading individual parameters from database")) |
592
e5a875a3311b
Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
588
diff
changeset
|
380 d = self.dbpool.runQuery("SELECT category,name,value FROM param_ind WHERE profile_id=?", (self.profiles[profile], )) |
412 | 381 d.addCallback(fillParams) |
382 return d | |
383 | |
413
dd4caab17008
core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents:
412
diff
changeset
|
384 def getIndParam(self, category, name, profile): |
dd4caab17008
core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents:
412
diff
changeset
|
385 """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
|
386 |
413
dd4caab17008
core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents:
412
diff
changeset
|
387 @param category: category of the parameter |
dd4caab17008
core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents:
412
diff
changeset
|
388 @param name: name of the parameter |
dd4caab17008
core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents:
412
diff
changeset
|
389 @param profile: %(doc_profile)s |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
390 @return: deferred |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
391 """ |
3120 | 392 d = self.dbpool.runQuery( |
393 "SELECT value FROM param_ind WHERE category=? AND name=? AND profile_id=?", | |
394 (category, name, self.profiles[profile])) | |
413
dd4caab17008
core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents:
412
diff
changeset
|
395 d.addCallback(self.__getFirstResult) |
dd4caab17008
core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents:
412
diff
changeset
|
396 return d |
dd4caab17008
core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents:
412
diff
changeset
|
397 |
3120 | 398 async def getIndParamValues(self, category, name): |
399 """Ask database for the individual values of a parameter for all profiles | |
400 | |
401 @param category: category of the parameter | |
402 @param name: name of the parameter | |
403 @return dict: profile => value map | |
404 """ | |
405 result = await self.dbpool.runQuery( | |
406 "SELECT profiles.name, param_ind.value FROM param_ind JOIN profiles ON " | |
407 "param_ind.profile_id = profiles.id WHERE param_ind.category=? " | |
408 "and param_ind.name=?", | |
409 (category, name)) | |
410 return dict(result) | |
411 | |
412 | 412 def setGenParam(self, category, name, value): |
413 """Save the general parameters in database | |
2500 | 414 |
412 | 415 @param category: category of the parameter |
416 @param name: name of the parameter | |
417 @param value: value to set | |
418 @return: deferred""" | |
419 d = self.dbpool.runQuery("REPLACE INTO param_gen(category,name,value) VALUES (?,?,?)", (category, name, value)) | |
3028 | 420 d.addErrback(lambda ignore: log.error(_("Can't set general parameter (%(category)s/%(name)s) in database" % {"category": category, "name": name}))) |
412 | 421 return d |
422 | |
423 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
|
424 """Save the individual parameters in database |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
425 |
412 | 426 @param category: category of the parameter |
427 @param name: name of the parameter | |
428 @param value: value to set | |
429 @param profile: a profile which *must* exist | |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
430 @return: deferred |
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
431 """ |
412 | 432 d = self.dbpool.runQuery("REPLACE INTO param_ind(category,name,profile_id,value) VALUES (?,?,?,?)", (category, name, self.profiles[profile], value)) |
3028 | 433 d.addErrback(lambda ignore: log.error(_("Can't set individual parameter (%(category)s/%(name)s) for [%(profile)s] in database" % {"category": category, "name": name, "profile": profile}))) |
412 | 434 return d |
413
dd4caab17008
core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents:
412
diff
changeset
|
435 |
2500 | 436 ## History |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
437 |
2765
378188abe941
misc: replaced all "dummy" by the more conventional and readable "__" ("_" being used for gettext)
Goffi <goffi@goffi.org>
parents:
2747
diff
changeset
|
438 def _addToHistoryCb(self, __, data): |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
439 # Message metadata were successfuly added to history |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
440 # now we can add message and subject |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
441 uid = data['uid'] |
3013
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
442 d_list = [] |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
443 for key in ('message', 'subject'): |
3028 | 444 for lang, value in data[key].items(): |
3013
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
445 d = self.dbpool.runQuery( |
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
446 "INSERT INTO {key}(history_uid, {key}, language) VALUES (?,?,?)" |
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
447 .format(key=key), |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
448 (uid, value, lang or None)) |
3013
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
449 d.addErrback(lambda __: log.error( |
3028 | 450 _("Can't save following {key} in history (uid: {uid}, lang:{lang}):" |
451 " {value}").format( | |
3013
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
452 key=key, uid=uid, lang=lang, value=value))) |
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
453 d_list.append(d) |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
454 try: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
455 thread = data['extra']['thread'] |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
456 except KeyError: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
457 pass |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
458 else: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
459 thread_parent = data['extra'].get('thread_parent') |
3013
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
460 d = self.dbpool.runQuery( |
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
461 "INSERT INTO thread(history_uid, thread_id, parent_id) VALUES (?,?,?)", |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
462 (uid, thread, thread_parent)) |
3013
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
463 d.addErrback(lambda __: log.error( |
3028 | 464 _("Can't save following thread in history (uid: {uid}): thread: " |
465 "{thread}), parent:{parent}").format( | |
3013
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
466 uid=uid, thread=thread, parent=thread_parent))) |
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
467 d_list.append(d) |
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
468 return defer.DeferredList(d_list) |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
469 |
1961
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
470 def _addToHistoryEb(self, failure_, data): |
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
471 failure_.trap(sqlite3.IntegrityError) |
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
472 sqlite_msg = failure_.value.args[0] |
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
473 if "UNIQUE constraint failed" in sqlite_msg: |
3028 | 474 log.debug("message {} is already in history, not storing it again" |
3013
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
475 .format(data['uid'])) |
1961
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
476 if 'received_timestamp' not in data: |
3013
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
477 log.warning( |
3028 | 478 "duplicate message is not delayed, this is maybe a bug: data={}" |
3013
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
479 .format(data)) |
1961
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
480 # 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
|
481 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
|
482 else: |
3028 | 483 log.error("Can't store message in history: {}".format(failure_)) |
1961
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
484 |
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
485 def _logHistoryError(self, failure_, from_jid, to_jid, data): |
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
486 if failure_.check(exceptions.CancelError): |
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
487 # we propagate CancelError to avoid sending message to frontends |
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
488 raise failure_ |
3013
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
489 log.error(_( |
3028 | 490 "Can't save following message in history: from [{from_jid}] to [{to_jid}] " |
491 "(uid: {uid})") | |
3013
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
492 .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
|
493 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
494 def addToHistory(self, data, profile): |
425
e4e9187e3b5b
backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents:
423
diff
changeset
|
495 """Store a new message in history |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
496 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
497 @param data(dict): message data as build by SatMessageProtocol.onMessage |
425
e4e9187e3b5b
backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents:
423
diff
changeset
|
498 """ |
3028 | 499 extra = pickle.dumps({k: v for k, v in data['extra'].items() |
3013
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
500 if k not in NOT_IN_EXTRA}, 0) |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
501 from_jid = data['from'] |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
502 to_jid = data['to'] |
3013
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
503 d = self.dbpool.runQuery( |
3028 | 504 "INSERT INTO history(uid, stanza_id, update_uid, profile_id, source, dest, " |
505 "source_res, dest_res, timestamp, received_timestamp, type, extra) VALUES " | |
506 "(?,?,?,?,?,?,?,?,?,?,?,?)", | |
3013
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
507 (data['uid'], data['extra'].get('stanza_id'), data['extra'].get('update_uid'), |
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
508 self.profiles[profile], data['from'].userhost(), to_jid.userhost(), |
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
509 from_jid.resource, to_jid.resource, data['timestamp'], |
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
510 data.get('received_timestamp'), data['type'], sqlite3.Binary(extra))) |
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
511 d.addCallbacks(self._addToHistoryCb, |
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
512 self._addToHistoryEb, |
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
513 callbackArgs=[data], |
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
514 errbackArgs=[data]) |
1961
c73e08094a95
memory (sqlite): better handling of IntegrityError
Goffi <goffi@goffi.org>
parents:
1955
diff
changeset
|
515 d.addErrback(self._logHistoryError, from_jid, to_jid, data) |
425
e4e9187e3b5b
backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents:
423
diff
changeset
|
516 return d |
e4e9187e3b5b
backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents:
423
diff
changeset
|
517 |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
518 def sqliteHistoryToList(self, query_result): |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
519 """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
|
520 result = [] |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
521 current = {'uid': None} |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
522 for row in reversed(query_result): |
3013
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
523 (uid, stanza_id, update_uid, source, dest, source_res, dest_res, timestamp, |
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
524 received_timestamp, type_, extra, message, message_lang, subject, |
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
525 subject_lang, thread, thread_parent) = row |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
526 if uid != current['uid']: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
527 # new message |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
528 try: |
3028 | 529 extra = pickle.loads(extra or b"") |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
530 except EOFError: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
531 extra = {} |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
532 current = { |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
533 '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
|
534 '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
|
535 'uid': uid, |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
536 'message': {}, |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
537 'subject': {}, |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
538 'type': type_, |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
539 'extra': extra, |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
540 'timestamp': timestamp, |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
541 } |
2699
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
542 if stanza_id is not None: |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
543 current['extra']['stanza_id'] = stanza_id |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
544 if update_uid is not None: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
545 current['extra']['update_uid'] = update_uid |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
546 if received_timestamp is not None: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
547 current['extra']['received_timestamp'] = str(received_timestamp) |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
548 result.append(current) |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
549 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
550 if message is not None: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
551 current['message'][message_lang or ''] = message |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
552 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
553 if subject is not None: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
554 current['subject'][subject_lang or ''] = subject |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
555 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
556 if thread is not None: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
557 current_extra = current['extra'] |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
558 current_extra['thread'] = thread |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
559 if thread_parent is not None: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
560 current_extra['thread_parent'] = thread_parent |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
561 else: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
562 if thread_parent is not None: |
3013
860c550028d6
memory (sqlite): properly wait for messages to be writen in database:
Goffi <goffi@goffi.org>
parents:
2989
diff
changeset
|
563 log.error( |
3028 | 564 "Database inconsistency: thread parent without thread (uid: " |
565 "{uid}, thread_parent: {parent})" | |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
566 .format(uid=uid, parent=thread_parent)) |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
567 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
568 return result |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
569 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
570 def listDict2listTuple(self, messages_data): |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
571 """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
|
572 ret = [] |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
573 for m in messages_data: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
574 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
|
575 return ret |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
576 |
2013
b536dd121da1
backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents:
1962
diff
changeset
|
577 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
|
578 """Retrieve messages in history |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
579 |
1222
e6e0ea4dc835
memory: add Parameter "Chat history limit"
souliane <souliane@mailoo.org>
parents:
1221
diff
changeset
|
580 @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
|
581 @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
|
582 @param limit (int): maximum number of messages to get: |
e6e0ea4dc835
memory: add Parameter "Chat history limit"
souliane <souliane@mailoo.org>
parents:
1221
diff
changeset
|
583 - 0 for no message (returns the empty list) |
e6e0ea4dc835
memory: add Parameter "Chat history limit"
souliane <souliane@mailoo.org>
parents:
1221
diff
changeset
|
584 - None for unlimited |
e6e0ea4dc835
memory: add Parameter "Chat history limit"
souliane <souliane@mailoo.org>
parents:
1221
diff
changeset
|
585 @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
|
586 @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
|
587 @param profile (unicode): %(doc_profile)s |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
588 @return: list of tuple as in [messageNew] |
425
e4e9187e3b5b
backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents:
423
diff
changeset
|
589 """ |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
590 assert profile |
2013
b536dd121da1
backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents:
1962
diff
changeset
|
591 if filters is None: |
b536dd121da1
backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents:
1962
diff
changeset
|
592 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
|
593 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
|
594 return defer.succeed([]) |
592
e5a875a3311b
Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
588
diff
changeset
|
595 |
3028 | 596 query_parts = ["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
|
597 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
|
598 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
|
599 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
|
600 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
|
601 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
|
602 values = [self.profiles[profile]] |
425
e4e9187e3b5b
backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents:
423
diff
changeset
|
603 |
2699
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
604 def test_jid(type_, jid_): |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
605 values.append(jid_.userhost()) |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
606 if jid_.resource: |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
607 values.append(jid_.resource) |
3028 | 608 return '({type_}=? AND {type_}_res=?)'.format(type_=type_) |
609 return '{type_}=?'.format(type_=type_) | |
587
952322b1d490
Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
572
diff
changeset
|
610 |
2699
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
611 if not from_jid and not to_jid: |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
612 # not jid specified, we want all one2one communications |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
613 pass |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
614 elif between: |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
615 if not from_jid or not to_jid: |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
616 # 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
|
617 # from or to this jid |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
618 jid_ = from_jid or to_jid |
3028 | 619 query_parts.append("AND ({source} OR {dest})".format( |
620 source=test_jid('source', jid_), | |
621 dest=test_jid('dest' , jid_))) | |
2699
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
622 else: |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
623 # 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
|
624 # those 2 jids |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
625 query_parts.append( |
3028 | 626 "AND (({source_from} AND {dest_to}) " |
627 "OR ({source_to} AND {dest_from}))".format( | |
2699
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
628 source_from=test_jid('source', from_jid), |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
629 dest_to=test_jid('dest', to_jid), |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
630 source_to=test_jid('source', to_jid), |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
631 dest_from=test_jid('dest', from_jid))) |
425
e4e9187e3b5b
backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents:
423
diff
changeset
|
632 else: |
2699
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
633 # 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
|
634 # to somebody). |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
635 q = [] |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
636 if from_jid is not None: |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
637 q.append(test_jid('source', from_jid)) |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
638 if to_jid is not None: |
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
639 q.append(test_jid('dest', to_jid)) |
3028 | 640 query_parts.append("AND " + " AND ".join(q)) |
2699
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
641 |
2013
b536dd121da1
backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents:
1962
diff
changeset
|
642 if filters: |
3028 | 643 if 'timestamp_start' in filters: |
644 query_parts.append("AND timestamp>= ?") | |
645 values.append(float(filters['timestamp_start'])) | |
3079
f8cc88c773c8
core (memory/sqlite): added `before_uid` filter to retrieve history before a message UID
Goffi <goffi@goffi.org>
parents:
3028
diff
changeset
|
646 if 'before_uid' in filters: |
f8cc88c773c8
core (memory/sqlite): added `before_uid` filter to retrieve history before a message UID
Goffi <goffi@goffi.org>
parents:
3028
diff
changeset
|
647 query_parts.append("AND history.rowid<(select rowid from history where uid=?)") |
f8cc88c773c8
core (memory/sqlite): added `before_uid` filter to retrieve history before a message UID
Goffi <goffi@goffi.org>
parents:
3028
diff
changeset
|
648 values.append(filters['before_uid']) |
3028 | 649 if 'body' in filters: |
2013
b536dd121da1
backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents:
1962
diff
changeset
|
650 # TODO: use REGEXP (function to be defined) instead of GLOB: https://www.sqlite.org/lang_expr.html |
3028 | 651 query_parts.append("AND message LIKE ?") |
652 values.append("%{}%".format(filters['body'])) | |
653 if 'search' in filters: | |
654 query_parts.append("AND (message LIKE ? OR source_res LIKE ?)") | |
655 values.extend(["%{}%".format(filters['search'])] * 2) | |
656 if 'types' in filters: | |
2013
b536dd121da1
backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents:
1962
diff
changeset
|
657 types = filters['types'].split() |
3028 | 658 query_parts.append("AND type IN ({})".format(','.join("?"*len(types)))) |
2013
b536dd121da1
backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents:
1962
diff
changeset
|
659 values.extend(types) |
3028 | 660 if 'not_types' in filters: |
2013
b536dd121da1
backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents:
1962
diff
changeset
|
661 types = filters['not_types'].split() |
3028 | 662 query_parts.append("AND type NOT IN ({})".format(','.join("?"*len(types)))) |
2013
b536dd121da1
backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents:
1962
diff
changeset
|
663 values.extend(types) |
3028 | 664 if 'last_stanza_id' in filters: |
2699
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
665 # 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
|
666 # 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
|
667 # while we were offline, using MAM (XEP-0313). |
3028 | 668 if (filters['last_stanza_id'] is not True |
2699
310e41bd6666
core (memory/sqlite): added stanza_id:
Goffi <goffi@goffi.org>
parents:
2562
diff
changeset
|
669 or limit != 1): |
3028 | 670 raise ValueError("Unexpected values for last_stanza_id filter") |
671 query_parts.append("AND stanza_id IS NOT NULL") | |
2013
b536dd121da1
backend (memory), frontends: improved history filtering:
Goffi <goffi@goffi.org>
parents:
1962
diff
changeset
|
672 |
2715
b35c84ea73cf
plugin XEP-0045: MAM implementation for MUC
Goffi <goffi@goffi.org>
parents:
2711
diff
changeset
|
673 |
2989
c13333fcde5e
memory (sqlite): fixed order for last_stanza_id:
Goffi <goffi@goffi.org>
parents:
2964
diff
changeset
|
674 # timestamp may be identical for 2 close messages (specially when delay is |
c13333fcde5e
memory (sqlite): fixed order for last_stanza_id:
Goffi <goffi@goffi.org>
parents:
2964
diff
changeset
|
675 # used) that's why we order ties by received_timestamp |
c13333fcde5e
memory (sqlite): fixed order for last_stanza_id:
Goffi <goffi@goffi.org>
parents:
2964
diff
changeset
|
676 # We'll reverse the order in sqliteHistoryToList |
c13333fcde5e
memory (sqlite): fixed order for last_stanza_id:
Goffi <goffi@goffi.org>
parents:
2964
diff
changeset
|
677 # we use DESC here so LIMIT keep the last messages |
3028 | 678 query_parts.append("ORDER BY timestamp DESC, history.received_timestamp DESC") |
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
|
679 if limit is not None: |
3028 | 680 query_parts.append("LIMIT ?") |
425
e4e9187e3b5b
backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents:
423
diff
changeset
|
681 values.append(limit) |
587
952322b1d490
Remove trailing whitespaces.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
572
diff
changeset
|
682 |
3028 | 683 d = self.dbpool.runQuery(" ".join(query_parts), values) |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
684 d.addCallback(self.sqliteHistoryToList) |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
685 d.addCallback(self.listDict2listTuple) |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
686 return d |
425
e4e9187e3b5b
backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents:
423
diff
changeset
|
687 |
2500 | 688 ## Private values |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
689 |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
690 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
|
691 """generic errback for data queries""" |
3028 | 692 log.error(_("Can't {operation} data in database for namespace {namespace}{and_key}{for_profile}: {msg}").format( |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
693 operation = operation, |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
694 namespace = namespace, |
3028 | 695 and_key = (" and key " + key) if key is not None else "", |
696 for_profile = (' [' + profile + ']') if profile is not None else '', | |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
697 msg = failure_)) |
592
e5a875a3311b
Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
588
diff
changeset
|
698 |
3028 | 699 def _load_pickle(self, v): |
700 # FIXME: workaround for Python 3 port, some pickled data are byte while other are strings | |
701 try: | |
702 return pickle.loads(v) | |
703 except TypeError: | |
704 data = pickle.loads(v.encode('utf-8')) | |
705 log.warning(f"encoding issue in pickled data: {data}") | |
706 return data | |
707 | |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
708 def _generateDataDict(self, query_result, binary): |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
709 if binary: |
3028 | 710 return {k: self._load_pickle(v) for k,v in query_result} |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
711 else: |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
712 return dict(query_result) |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
713 |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
714 def _getPrivateTable(self, binary, profile): |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
715 """Get table to use for private values""" |
3028 | 716 table = ['private'] |
425
e4e9187e3b5b
backend, bridge: asynchronous history
Goffi <goffi@goffi.org>
parents:
423
diff
changeset
|
717 |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
718 if profile is None: |
3028 | 719 table.append('gen') |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
720 else: |
3028 | 721 table.append('ind') |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
722 |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
723 if binary: |
3028 | 724 table.append('bin') |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
725 |
3028 | 726 return '_'.join(table) |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
727 |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
728 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
|
729 """Get private value(s) from databases |
592
e5a875a3311b
Fix pep8 support in src/memory.
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
parents:
588
diff
changeset
|
730 |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
731 @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
|
732 @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
|
733 None to get all keys/values |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
734 @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
|
735 @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
|
736 None to use general values |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
737 @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
|
738 """ |
3028 | 739 log.debug(_("getting {type}{binary} private values from database for namespace {namespace}{keys}".format( |
740 type = "general" if profile is None else "individual", | |
741 binary = " binary" if binary else "", | |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
742 namespace = namespace, |
3028 | 743 keys = " with keys {}".format(", ".join(keys)) if keys is not None else ""))) |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
744 table = self._getPrivateTable(binary, profile) |
3028 | 745 query_parts = ["SELECT key,value FROM", table, "WHERE namespace=?"] |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
746 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
|
747 |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
748 if keys is not None: |
3028 | 749 placeholders = ','.join(len(keys) * '?') |
750 query_parts.append('AND key IN (' + placeholders + ')') | |
2209
ea41cf1e6d29
memory (persistent, sqlite): fixed getPrivates bug with keys arguments and its use in LazyPersistentBinaryDict
Goffi <goffi@goffi.org>
parents:
2182
diff
changeset
|
751 args.extend(keys) |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
752 |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
753 if profile is not None: |
3028 | 754 query_parts.append('AND profile_id=?') |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
755 args.append(self.profiles[profile]) |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
756 |
3028 | 757 d = self.dbpool.runQuery(" ".join(query_parts), args) |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
758 d.addCallback(self._generateDataDict, binary) |
3028 | 759 d.addErrback(self._privateDataEb, "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
|
760 return d |
31e8c48b5f5d
core: - memory refactoring (moved memory.py and sqlite.py from tools to memory)
Goffi <goffi@goffi.org>
parents:
425
diff
changeset
|
761 |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
762 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
|
763 """Set a private value in database |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
764 |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
765 @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
|
766 @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
|
767 @param value(object): value to set |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
768 @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
|
769 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
|
770 @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
|
771 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
|
772 """ |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
773 table = self._getPrivateTable(binary, profile) |
3028 | 774 query_values_names = ['namespace', 'key', 'value'] |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
775 query_values = [namespace, key] |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
776 |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
777 if binary: |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
778 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
|
779 |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
780 query_values.append(value) |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
781 |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
782 if profile is not None: |
3028 | 783 query_values_names.append('profile_id') |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
784 query_values.append(self.profiles[profile]) |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
785 |
3028 | 786 query_parts = ["REPLACE INTO", table, '(', ','.join(query_values_names), ')', |
787 "VALUES (", ",".join('?'*len(query_values_names)), ')'] | |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
788 |
3028 | 789 d = self.dbpool.runQuery(" ".join(query_parts), query_values) |
790 d.addErrback(self._privateDataEb, "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
|
791 return d |
31e8c48b5f5d
core: - memory refactoring (moved memory.py and sqlite.py from tools to memory)
Goffi <goffi@goffi.org>
parents:
425
diff
changeset
|
792 |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
793 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
|
794 """Delete private value from database |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
795 |
432
31e8c48b5f5d
core: - memory refactoring (moved memory.py and sqlite.py from tools to memory)
Goffi <goffi@goffi.org>
parents:
425
diff
changeset
|
796 @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
|
797 @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
|
798 @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
|
799 @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
|
800 if None, it's a general value |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
801 """ |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
802 table = self._getPrivateTable(binary, profile) |
3028 | 803 query_parts = ["DELETE FROM", table, "WHERE namespace=? AND key=?"] |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
804 args = [namespace, key] |
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
805 if profile is not None: |
3028 | 806 query_parts.append("AND profile_id=?") |
2182
087eec4c6c07
memory (persistent, sqlite): better private values handling + new LazyPersistentBinaryDict:
Goffi <goffi@goffi.org>
parents:
2144
diff
changeset
|
807 args.append(self.profiles[profile]) |
3028 | 808 d = self.dbpool.runQuery(" ".join(query_parts), args) |
809 d.addErrback(self._privateDataEb, "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
|
810 return d |
31e8c48b5f5d
core: - memory refactoring (moved memory.py and sqlite.py from tools to memory)
Goffi <goffi@goffi.org>
parents:
425
diff
changeset
|
811 |
2735
ba74914277cf
core (memory/sqlite): new delPrivateNamespace method to delete all data of a specific namespace for a profile.
Goffi <goffi@goffi.org>
parents:
2722
diff
changeset
|
812 def delPrivateNamespace(self, namespace, binary=False, profile=None): |
ba74914277cf
core (memory/sqlite): new delPrivateNamespace method to delete all data of a specific namespace for a profile.
Goffi <goffi@goffi.org>
parents:
2722
diff
changeset
|
813 """Delete all data from a private namespace |
ba74914277cf
core (memory/sqlite): new delPrivateNamespace method to delete all data of a specific namespace for a profile.
Goffi <goffi@goffi.org>
parents:
2722
diff
changeset
|
814 |
ba74914277cf
core (memory/sqlite): new delPrivateNamespace method to delete all data of a specific namespace for a profile.
Goffi <goffi@goffi.org>
parents:
2722
diff
changeset
|
815 Be really cautious when you use this method, as all data with given namespace are |
ba74914277cf
core (memory/sqlite): new delPrivateNamespace method to delete all data of a specific namespace for a profile.
Goffi <goffi@goffi.org>
parents:
2722
diff
changeset
|
816 removed. |
ba74914277cf
core (memory/sqlite): new delPrivateNamespace method to delete all data of a specific namespace for a profile.
Goffi <goffi@goffi.org>
parents:
2722
diff
changeset
|
817 Params are the same as for delPrivateValue |
ba74914277cf
core (memory/sqlite): new delPrivateNamespace method to delete all data of a specific namespace for a profile.
Goffi <goffi@goffi.org>
parents:
2722
diff
changeset
|
818 """ |
ba74914277cf
core (memory/sqlite): new delPrivateNamespace method to delete all data of a specific namespace for a profile.
Goffi <goffi@goffi.org>
parents:
2722
diff
changeset
|
819 table = self._getPrivateTable(binary, profile) |
3028 | 820 query_parts = ["DELETE FROM", table, "WHERE namespace=?"] |
2735
ba74914277cf
core (memory/sqlite): new delPrivateNamespace method to delete all data of a specific namespace for a profile.
Goffi <goffi@goffi.org>
parents:
2722
diff
changeset
|
821 args = [namespace] |
ba74914277cf
core (memory/sqlite): new delPrivateNamespace method to delete all data of a specific namespace for a profile.
Goffi <goffi@goffi.org>
parents:
2722
diff
changeset
|
822 if profile is not None: |
3028 | 823 query_parts.append("AND profile_id=?") |
2735
ba74914277cf
core (memory/sqlite): new delPrivateNamespace method to delete all data of a specific namespace for a profile.
Goffi <goffi@goffi.org>
parents:
2722
diff
changeset
|
824 args.append(self.profiles[profile]) |
3028 | 825 d = self.dbpool.runQuery(" ".join(query_parts), args) |
826 d.addErrback(self._privateDataEb, "delete namespace", namespace, profile=profile) | |
2735
ba74914277cf
core (memory/sqlite): new delPrivateNamespace method to delete all data of a specific namespace for a profile.
Goffi <goffi@goffi.org>
parents:
2722
diff
changeset
|
827 return d |
ba74914277cf
core (memory/sqlite): new delPrivateNamespace method to delete all data of a specific namespace for a profile.
Goffi <goffi@goffi.org>
parents:
2722
diff
changeset
|
828 |
2500 | 829 ## Files |
830 | |
831 @defer.inlineCallbacks | |
3028 | 832 def getFiles(self, client, file_id=None, version='', parent=None, type_=None, |
2500 | 833 file_hash=None, hash_algo=None, name=None, namespace=None, mime_type=None, |
834 owner=None, access=None, projection=None, unique=False): | |
835 """retrieve files with with given filters | |
836 | |
837 @param file_id(unicode, None): id of the file | |
838 None to ignore | |
839 @param version(unicode, None): version of the file | |
840 None to ignore | |
841 empty string to look for current version | |
842 @param parent(unicode, None): id of the directory containing the files | |
843 None to ignore | |
844 empty string to look for root files/directories | |
845 @param projection(list[unicode], None): name of columns to retrieve | |
846 None to retrieve all | |
847 @param unique(bool): if True will remove duplicates | |
848 other params are the same as for [setFile] | |
849 @return (list[dict]): files corresponding to filters | |
850 """ | |
851 query_parts = ["SELECT"] | |
852 if unique: | |
853 query_parts.append('DISTINCT') | |
854 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
|
855 projection = ['id', 'version', 'parent', 'type', 'file_hash', 'hash_algo', 'name', |
2500 | 856 'size', 'namespace', 'mime_type', 'created', 'modified', 'owner', |
857 'access', 'extra'] | |
858 query_parts.append(','.join(projection)) | |
859 query_parts.append("FROM files WHERE") | |
860 filters = ['profile_id=?'] | |
861 args = [self.profiles[client.profile]] | |
862 | |
863 if file_id is not None: | |
3028 | 864 filters.append('id=?') |
2500 | 865 args.append(file_id) |
866 if version is not None: | |
3028 | 867 filters.append('version=?') |
2500 | 868 args.append(version) |
869 if parent is not None: | |
3028 | 870 filters.append('parent=?') |
2500 | 871 args.append(parent) |
872 if type_ is not None: | |
3028 | 873 filters.append('type=?') |
2500 | 874 args.append(type_) |
875 if file_hash is not None: | |
3028 | 876 filters.append('file_hash=?') |
2500 | 877 args.append(file_hash) |
878 if hash_algo is not None: | |
3028 | 879 filters.append('hash_algo=?') |
2500 | 880 args.append(hash_algo) |
881 if name is not None: | |
3028 | 882 filters.append('name=?') |
2500 | 883 args.append(name) |
884 if namespace is not None: | |
3028 | 885 filters.append('namespace=?') |
2500 | 886 args.append(namespace) |
887 if mime_type is not None: | |
3028 | 888 filters.append('mime_type=?') |
2500 | 889 args.append(mime_type) |
890 if owner is not None: | |
3028 | 891 filters.append('owner=?') |
2500 | 892 args.append(owner.full()) |
893 if access is not None: | |
894 raise NotImplementedError('Access check is not implemented yet') | |
895 # a JSON comparison is needed here | |
896 | |
3028 | 897 filters = ' AND '.join(filters) |
2500 | 898 query_parts.append(filters) |
3028 | 899 query = ' '.join(query_parts) |
2500 | 900 |
901 result = yield self.dbpool.runQuery(query, args) | |
3028 | 902 files_data = [dict(list(zip(projection, row))) for row in result] |
2500 | 903 to_parse = {'access', 'extra'}.intersection(projection) |
904 to_filter = {'owner'}.intersection(projection) | |
905 if to_parse or to_filter: | |
906 for file_data in files_data: | |
907 for key in to_parse: | |
908 value = file_data[key] | |
909 file_data[key] = {} if value is None else json.loads(value) | |
910 owner = file_data.get('owner') | |
911 if owner is not None: | |
912 file_data['owner'] = jid.JID(owner) | |
913 defer.returnValue(files_data) | |
914 | |
3028 | 915 def setFile(self, client, name, file_id, version='', parent=None, type_=C.FILE_TYPE_FILE, |
2500 | 916 file_hash=None, hash_algo=None, size=None, namespace=None, mime_type=None, |
917 created=None, modified=None, owner=None, access=None, extra=None): | |
918 """set a file metadata | |
919 | |
920 @param client(SatXMPPClient): client owning the file | |
921 @param name(unicode): name of the file (must not contain "/") | |
922 @param file_id(unicode): unique id of the file | |
923 @param version(unicode): version of this file | |
924 @param parent(unicode): id of the directory containing this file | |
925 None if it is a root file/directory | |
926 @param type_(unicode): one of: | |
927 - file | |
928 - directory | |
929 @param file_hash(unicode): unique hash of the payload | |
930 @param hash_algo(unicode): algorithm used for hashing the file (usually sha-256) | |
931 @param size(int): size in bytes | |
932 @param namespace(unicode, None): identifier (human readable is better) to group files | |
933 for instance, namespace could be used to group files in a specific photo album | |
934 @param mime_type(unicode): MIME type of the file, or None if not known/guessed | |
935 @param created(int): UNIX time of creation | |
936 @param modified(int,None): UNIX time of last modification, or None to use created date | |
937 @param owner(jid.JID, None): jid of the owner of the file (mainly useful for component) | |
938 @param access(dict, None): serialisable dictionary with access rules. See [memory.memory] for details | |
939 @param extra(dict, None): serialisable dictionary of any extra data | |
940 will be encoded to json in database | |
941 """ | |
942 if extra is not None: | |
943 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
|
944 query = ('INSERT INTO files(id, version, parent, type, file_hash, hash_algo, name, size, namespace, ' |
2500 | 945 'mime_type, created, modified, owner, access, extra, profile_id) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)') |
946 d = self.dbpool.runQuery(query, (file_id, version.strip(), parent, type_, | |
947 file_hash, hash_algo, | |
948 name, size, namespace, | |
949 mime_type, created, modified, | |
950 owner.full() if owner is not None else None, | |
951 json.dumps(access) if access else None, | |
952 json.dumps(extra) if extra else None, | |
953 self.profiles[client.profile])) | |
3028 | 954 d.addErrback(lambda failure: log.error(_("Can't save file metadata for [{profile}]: {reason}".format(profile=client.profile, reason=failure)))) |
2500 | 955 return d |
956 | |
2526
35d591086974
core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents:
2507
diff
changeset
|
957 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
|
958 query = 'SELECT {column} FROM files where id=?'.format(column=column) |
3028 | 959 for i in range(5): |
2526
35d591086974
core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents:
2507
diff
changeset
|
960 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
|
961 try: |
35d591086974
core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents:
2507
diff
changeset
|
962 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
|
963 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
|
964 raise exceptions.NotFound |
2918
21cf8395616c
memory (sqlite): fixed fileUpdate when original value is not set (NULL)
Goffi <goffi@goffi.org>
parents:
2895
diff
changeset
|
965 if older_value_raw is None: |
21cf8395616c
memory (sqlite): fixed fileUpdate when original value is not set (NULL)
Goffi <goffi@goffi.org>
parents:
2895
diff
changeset
|
966 value = {} |
21cf8395616c
memory (sqlite): fixed fileUpdate when original value is not set (NULL)
Goffi <goffi@goffi.org>
parents:
2895
diff
changeset
|
967 else: |
21cf8395616c
memory (sqlite): fixed fileUpdate when original value is not set (NULL)
Goffi <goffi@goffi.org>
parents:
2895
diff
changeset
|
968 value = json.loads(older_value_raw) |
2526
35d591086974
core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents:
2507
diff
changeset
|
969 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
|
970 value_raw = json.dumps(value) |
2918
21cf8395616c
memory (sqlite): fixed fileUpdate when original value is not set (NULL)
Goffi <goffi@goffi.org>
parents:
2895
diff
changeset
|
971 if older_value_raw is None: |
21cf8395616c
memory (sqlite): fixed fileUpdate when original value is not set (NULL)
Goffi <goffi@goffi.org>
parents:
2895
diff
changeset
|
972 update_query = 'UPDATE files SET {column}=? WHERE id=? AND {column} is NULL'.format(column=column) |
21cf8395616c
memory (sqlite): fixed fileUpdate when original value is not set (NULL)
Goffi <goffi@goffi.org>
parents:
2895
diff
changeset
|
973 update_args = (value_raw, file_id) |
21cf8395616c
memory (sqlite): fixed fileUpdate when original value is not set (NULL)
Goffi <goffi@goffi.org>
parents:
2895
diff
changeset
|
974 else: |
21cf8395616c
memory (sqlite): fixed fileUpdate when original value is not set (NULL)
Goffi <goffi@goffi.org>
parents:
2895
diff
changeset
|
975 update_query = 'UPDATE files SET {column}=? WHERE id=? AND {column}=?'.format(column=column) |
21cf8395616c
memory (sqlite): fixed fileUpdate when original value is not set (NULL)
Goffi <goffi@goffi.org>
parents:
2895
diff
changeset
|
976 update_args = (value_raw, file_id, older_value_raw) |
2526
35d591086974
core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents:
2507
diff
changeset
|
977 try: |
35d591086974
core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents:
2507
diff
changeset
|
978 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
|
979 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
|
980 pass |
35d591086974
core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents:
2507
diff
changeset
|
981 else: |
35d591086974
core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents:
2507
diff
changeset
|
982 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
|
983 break; |
3028 | 984 log.warning(_("table not updated, probably due to race condition, trying again ({tries})").format(tries=i+1)) |
2526
35d591086974
core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents:
2507
diff
changeset
|
985 else: |
3028 | 986 log.error(_("Can't update file table")) |
2526
35d591086974
core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents:
2507
diff
changeset
|
987 |
35d591086974
core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents:
2507
diff
changeset
|
988 def fileUpdate(self, file_id, column, update_cb): |
2928
c0f6fd75af5f
core (memory, memory/sqlite): implemented fileDelete
Goffi <goffi@goffi.org>
parents:
2919
diff
changeset
|
989 """Update a column value using a method to avoid race conditions |
2526
35d591086974
core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents:
2507
diff
changeset
|
990 |
35d591086974
core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents:
2507
diff
changeset
|
991 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
|
992 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
|
993 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
|
994 @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
|
995 @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
|
996 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
|
997 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
|
998 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
|
999 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
|
1000 @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
|
1001 """ |
35d591086974
core (memory, sqlite): added fileUpdate method to update "extra" and "access" avoiding race condition
Goffi <goffi@goffi.org>
parents:
2507
diff
changeset
|
1002 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
|
1003 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
|
1004 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
|
1005 |
2928
c0f6fd75af5f
core (memory, memory/sqlite): implemented fileDelete
Goffi <goffi@goffi.org>
parents:
2919
diff
changeset
|
1006 def fileDelete(self, file_id): |
c0f6fd75af5f
core (memory, memory/sqlite): implemented fileDelete
Goffi <goffi@goffi.org>
parents:
2919
diff
changeset
|
1007 """Delete file metadata from the database |
c0f6fd75af5f
core (memory, memory/sqlite): implemented fileDelete
Goffi <goffi@goffi.org>
parents:
2919
diff
changeset
|
1008 |
c0f6fd75af5f
core (memory, memory/sqlite): implemented fileDelete
Goffi <goffi@goffi.org>
parents:
2919
diff
changeset
|
1009 @param file_id(unicode): id of the file to delete |
c0f6fd75af5f
core (memory, memory/sqlite): implemented fileDelete
Goffi <goffi@goffi.org>
parents:
2919
diff
changeset
|
1010 NOTE: file itself must still be removed, this method only handle metadata in |
c0f6fd75af5f
core (memory, memory/sqlite): implemented fileDelete
Goffi <goffi@goffi.org>
parents:
2919
diff
changeset
|
1011 database |
c0f6fd75af5f
core (memory, memory/sqlite): implemented fileDelete
Goffi <goffi@goffi.org>
parents:
2919
diff
changeset
|
1012 """ |
c0f6fd75af5f
core (memory, memory/sqlite): implemented fileDelete
Goffi <goffi@goffi.org>
parents:
2919
diff
changeset
|
1013 return self.dbpool.runQuery("DELETE FROM files WHERE id = ?", (file_id,)) |
c0f6fd75af5f
core (memory, memory/sqlite): implemented fileDelete
Goffi <goffi@goffi.org>
parents:
2919
diff
changeset
|
1014 |
413
dd4caab17008
core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents:
412
diff
changeset
|
1015 ##Helper methods## |
dd4caab17008
core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents:
412
diff
changeset
|
1016 |
dd4caab17008
core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents:
412
diff
changeset
|
1017 def __getFirstResult(self, result): |
dd4caab17008
core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents:
412
diff
changeset
|
1018 """Return the first result of a database query |
dd4caab17008
core: - individual parameters managed through sqlite
Goffi <goffi@goffi.org>
parents:
412
diff
changeset
|
1019 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
|
1020 return None if not result else result[0][0] |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1021 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1022 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1023 class Updater(object): |
2500 | 1024 stmnt_regex = re.compile(r"[\w/' ]+(?:\(.*?\))?[^,]*") |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1025 clean_regex = re.compile(r"^ +|(?<= ) +|(?<=,) +| +$") |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1026 CREATE_SQL = "CREATE TABLE %s (%s)" |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1027 INSERT_SQL = "INSERT INTO %s VALUES (%s)" |
2787 | 1028 INDEX_SQL = "CREATE INDEX %s ON %s(%s)" |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1029 DROP_SQL = "DROP TABLE %s" |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1030 ALTER_SQL = "ALTER TABLE %s ADD COLUMN %s" |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1031 RENAME_TABLE_SQL = "ALTER TABLE %s RENAME TO %s" |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1032 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1033 CONSTRAINTS = ('PRIMARY', 'UNIQUE', 'CHECK', 'FOREIGN') |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1034 TMP_TABLE = "tmp_sat_update" |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1035 |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1036 def __init__(self, sqlite_storage, sat_version): |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1037 self._sat_version = sat_version |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1038 self.sqlite_storage = sqlite_storage |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1039 |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1040 @property |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1041 def dbpool(self): |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1042 return self.sqlite_storage.dbpool |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1043 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1044 def getLocalVersion(self): |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1045 """ Get local database version |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
1046 |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1047 @return: version (int) |
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 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
|
1050 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1051 def _setLocalVersion(self, version): |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1052 """ Set local database version |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
1053 |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1054 @param version: version (int) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1055 @return: deferred |
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 return self.dbpool.runOperation("PRAGMA user_version=%d" % version) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1058 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1059 def getLocalSchema(self): |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1060 """ return raw local schema |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
1061 |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1062 @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
|
1063 """ |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1064 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
|
1065 d.addCallback(lambda result: [row[0] for row in result]) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1066 return d |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1067 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1068 @defer.inlineCallbacks |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1069 def checkUpdates(self): |
1030
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1070 """ 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
|
1071 |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1072 @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
|
1073 """ |
2787 | 1074 # TODO: only "table" type (i.e. "CREATE" statements) is checked, |
1075 # "index" should be checked too. | |
1076 # This may be not relevant is we move to a higher level library (alchimia?) | |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1077 local_version = yield self.getLocalVersion() |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1078 raw_local_sch = yield self.getLocalSchema() |
2500 | 1079 |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1080 local_sch = self.rawStatements2data(raw_local_sch) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1081 current_sch = DATABASE_SCHEMAS['current']['CREATE'] |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1082 local_hash = self.statementHash(local_sch) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1083 current_hash = self.statementHash(current_sch) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1084 |
1030
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1085 # 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
|
1086 force_update = local_hash == current_hash and local_version < CURRENT_DB_VERSION \ |
2787 | 1087 and {'index', 'specific'}.intersection(DATABASE_SCHEMAS[CURRENT_DB_VERSION]) |
1030
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1088 |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1089 if local_hash == current_hash and not force_update: |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1090 if local_version != CURRENT_DB_VERSION: |
993
301b342c697a
core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
1091 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
|
1092 yield self._setLocalVersion(CURRENT_DB_VERSION) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1093 else: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1094 # an update is needed |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1095 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1096 if local_version == CURRENT_DB_VERSION: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1097 # Database mismatch and we have the latest version |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1098 if self._sat_version.endswith('D'): |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1099 # we are in a development version |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1100 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
|
1101 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
|
1102 update_raw = yield self.update2raw(update_data, True) |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1103 defer.returnValue(update_raw) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1104 else: |
3028 | 1105 log.error(_("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
|
1106 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
|
1107 update_raw = yield self.update2raw(update_data) |
3028 | 1108 log.warning(_("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") % '\n'.join("%s;" % statement for statement in update_raw)) |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1109 raise exceptions.DatabaseError("Database mismatch") |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1110 else: |
2964
17c61d09a85b
memory (sqlite): exit with an error if current db version is higher than version expected in current code
Goffi <goffi@goffi.org>
parents:
2928
diff
changeset
|
1111 if local_version > CURRENT_DB_VERSION: |
17c61d09a85b
memory (sqlite): exit with an error if current db version is higher than version expected in current code
Goffi <goffi@goffi.org>
parents:
2928
diff
changeset
|
1112 log.error(_( |
3028 | 1113 "You database version is higher than the one used in this SàT " |
1114 "version, are you using several version at the same time? We " | |
1115 "can't run SàT with this database.")) | |
2964
17c61d09a85b
memory (sqlite): exit with an error if current db version is higher than version expected in current code
Goffi <goffi@goffi.org>
parents:
2928
diff
changeset
|
1116 sys.exit(1) |
17c61d09a85b
memory (sqlite): exit with an error if current db version is higher than version expected in current code
Goffi <goffi@goffi.org>
parents:
2928
diff
changeset
|
1117 |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1118 # 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
|
1119 if force_update: |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1120 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
|
1121 else: |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1122 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
|
1123 update_raw = [] |
3028 | 1124 for version in range(local_version + 1, CURRENT_DB_VERSION + 1): |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1125 try: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1126 update_data = DATABASE_SCHEMAS[version] |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1127 except KeyError: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1128 raise exceptions.InternalError("Missing update definition (version %d)" % version) |
2720
453a12ff6f51
core (memory/sqlite): do not call commitStatements if there is nothing to commit in checkUpdates
Goffi <goffi@goffi.org>
parents:
2716
diff
changeset
|
1129 if "specific" in update_data and update_raw: |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1130 # 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
|
1131 # 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
|
1132 # 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
|
1133 yield self.sqlite_storage.commitStatements(update_raw) |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1134 del update_raw[:] |
1030
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1135 update_raw_step = yield self.update2raw(update_data) |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1136 if update_raw_step is not None: |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1137 # can be None with specifics |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1138 update_raw.extend(update_raw_step) |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1139 update_raw.append("PRAGMA user_version=%d" % CURRENT_DB_VERSION) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1140 defer.returnValue(update_raw) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1141 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1142 @staticmethod |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1143 def createData2Raw(data): |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1144 """ Generate SQL statements from statements data |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
1145 |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1146 @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
|
1147 @return: list of strings with raw statements |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1148 """ |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1149 ret = [] |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1150 for table in data: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1151 defs, constraints = data[table] |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1152 assert isinstance(defs, tuple) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1153 assert isinstance(constraints, tuple) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1154 ret.append(Updater.CREATE_SQL % (table, ', '.join(defs + constraints))) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1155 return ret |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1156 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1157 @staticmethod |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1158 def insertData2Raw(data): |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1159 """ Generate SQL statements from statements data |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
1160 |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1161 @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
|
1162 @return: list of strings with raw statements |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1163 """ |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1164 ret = [] |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1165 for table in data: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1166 values_tuple = data[table] |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1167 assert isinstance(values_tuple, tuple) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1168 for values in values_tuple: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1169 assert isinstance(values, tuple) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1170 ret.append(Updater.INSERT_SQL % (table, ', '.join(values))) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1171 return ret |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1172 |
2787 | 1173 @staticmethod |
1174 def indexData2Raw(data): | |
1175 """ Generate SQL statements from statements data | |
1176 | |
1177 @param data: dictionary with table as key, and statements data in tuples as value | |
1178 @return: list of strings with raw statements | |
1179 """ | |
1180 ret = [] | |
1181 assert isinstance(data, tuple) | |
1182 for table, col_data in data: | |
3028 | 1183 assert isinstance(table, str) |
2787 | 1184 assert isinstance(col_data, tuple) |
1185 for cols in col_data: | |
1186 if isinstance(cols, tuple): | |
3028 | 1187 assert all([isinstance(c, str) for c in cols]) |
1188 indexed_cols = ','.join(cols) | |
1189 elif isinstance(cols, str): | |
2787 | 1190 indexed_cols = cols |
1191 else: | |
3028 | 1192 raise exceptions.InternalError("unexpected index columns value") |
1193 index_name = table + '__' + indexed_cols.replace(',', '_') | |
2787 | 1194 ret.append(Updater.INDEX_SQL % (index_name, table, indexed_cols)) |
1195 return ret | |
1196 | |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1197 def statementHash(self, data): |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1198 """ Generate hash of template data |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
1199 |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1200 useful to compare schemas |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1201 @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
|
1202 and tuples of (col_defs, constraints) as values |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1203 @return: hash as string |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1204 """ |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1205 hash_ = hashlib.sha1() |
3028 | 1206 tables = list(data.keys()) |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1207 tables.sort() |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1208 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1209 def stmnts2str(stmts): |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1210 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
|
1211 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1212 for table in tables: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1213 col_defs, col_constr = data[table] |
3028 | 1214 hash_.update( |
1215 ("%s:%s:%s" % (table, stmnts2str(col_defs), stmnts2str(col_constr))) | |
1216 .encode('utf-8')) | |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1217 return hash_.digest() |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1218 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1219 def rawStatements2data(self, raw_statements): |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1220 """ separate "CREATE" statements into dictionary/tuples data |
2143
c3cac21157d4
memory (sqlite): introduced component table, schema updated:
Goffi <goffi@goffi.org>
parents:
2013
diff
changeset
|
1221 |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1222 @param raw_statements: list of CREATE statements as strings |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1223 @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
|
1224 """ |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1225 schema_dict = {} |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1226 for create_statement in raw_statements: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1227 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
|
1228 log.warning("Unexpected statement, ignoring it") |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1229 continue |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1230 _create_statement = create_statement[13:] |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1231 table, raw_col_stats = _create_statement.split(' ',1) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1232 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
|
1233 log.warning("Unexpected statement structure, ignoring it") |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1234 continue |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1235 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
|
1236 col_defs = [] |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1237 constraints = [] |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1238 for col_stat in col_stats: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1239 name = col_stat.split(' ',1)[0] |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1240 if name in self.CONSTRAINTS: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1241 constraints.append(col_stat) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1242 else: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1243 col_defs.append(col_stat) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1244 schema_dict[table] = (tuple(col_defs), tuple(constraints)) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1245 return schema_dict |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1246 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1247 def generateUpdateData(self, old_data, new_data, modify=False): |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1248 """ 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
|
1249 |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1250 @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
|
1251 @param new_data: data of the current schema |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1252 @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
|
1253 @return: update data, a dictionary with: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1254 - 'create': dictionary of tables to create |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1255 - 'delete': tuple of tables to delete |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1256 - '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
|
1257 - '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
|
1258 - '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
|
1259 """ |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1260 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1261 create_tables_data = {} |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1262 create_cols_data = {} |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1263 modify_cols_data = {} |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1264 delete_cols_data = {} |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1265 old_tables = set(old_data.keys()) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1266 new_tables = set(new_data.keys()) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1267 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1268 def getChanges(set_olds, set_news): |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1269 to_create = set_news.difference(set_olds) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1270 to_delete = set_olds.difference(set_news) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1271 to_check = set_news.intersection(set_olds) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1272 return tuple(to_create), tuple(to_delete), tuple(to_check) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1273 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1274 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
|
1275 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1276 for table in tables_to_create: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1277 create_tables_data[table] = new_data[table] |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1278 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1279 for table in tables_to_check: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1280 old_col_defs, old_constraints = old_data[table] |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1281 new_col_defs, new_constraints = new_data[table] |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1282 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
|
1283 if not isinstance(obj, tuple): |
993
301b342c697a
core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
1284 raise exceptions.InternalError("Columns definitions must be tuples") |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1285 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
|
1286 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
|
1287 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
|
1288 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
|
1289 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
|
1290 (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
|
1291 # we have modified columns, we need to transfer table |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1292 # 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
|
1293 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
|
1294 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
|
1295 modify_cols_data[table] = tuple(old_names.intersection(new_names)); |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1296 else: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1297 if defs_create: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1298 create_cols_data[table] = (defs_create) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1299 if defs_delete or constraints_delete: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1300 delete_cols_data[table] = (defs_delete) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1301 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1302 return {'create': create_tables_data, |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1303 'delete': tables_to_delete, |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1304 'cols create': create_cols_data, |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1305 'cols delete': delete_cols_data, |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1306 'cols modify': modify_cols_data |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1307 } |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1308 |
1030
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1309 @defer.inlineCallbacks |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1310 def update2raw(self, update, dev_version=False): |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1311 """ 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
|
1312 |
1455
4fb3280c4568
tmp (wokkel.rsm): use of super instead of direct call in PubSubRequest
Goffi <goffi@goffi.org>
parents:
1409
diff
changeset
|
1313 @param update: update data as returned by generateUpdateData |
853
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1314 @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
|
1315 @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
|
1316 """ |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1317 ret = self.createData2Raw(update.get('create', {})) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1318 drop = [] |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1319 for table in update.get('delete', tuple()): |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1320 drop.append(self.DROP_SQL % table) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1321 if dev_version: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1322 if drop: |
993
301b342c697a
core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
1323 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
|
1324 else: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1325 ret.extend(drop) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1326 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1327 cols_create = update.get('cols create', {}) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1328 for table in cols_create: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1329 for col_def in cols_create[table]: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1330 ret.append(self.ALTER_SQL % (table, col_def)) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1331 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1332 cols_delete = update.get('cols delete', {}) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1333 for table in cols_delete: |
993
301b342c697a
core: use of the new core.log module:
Goffi <goffi@goffi.org>
parents:
936
diff
changeset
|
1334 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
|
1335 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1336 cols_modify = update.get('cols modify', {}) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1337 for table in cols_modify: |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1338 ret.append(self.RENAME_TABLE_SQL % (table, self.TMP_TABLE)) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1339 main, extra = DATABASE_SCHEMAS['current']['CREATE'][table] |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1340 ret.append(self.CREATE_SQL % (table, ', '.join(main + extra))) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1341 common_cols = ', '.join(cols_modify[table]) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1342 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
|
1343 ret.append(self.DROP_SQL % self.TMP_TABLE) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1344 |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1345 insert = update.get('insert', {}) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1346 ret.extend(self.insertData2Raw(insert)) |
c2f6ada7858f
core (sqlite): automatic database update:
Goffi <goffi@goffi.org>
parents:
839
diff
changeset
|
1347 |
2787 | 1348 index = update.get('index', tuple()) |
1349 ret.extend(self.indexData2Raw(index)) | |
1350 | |
1030
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1351 specific = update.get('specific', None) |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1352 if specific: |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1353 cmds = yield getattr(self, specific)() |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1354 ret.extend(cmds or []) |
1030
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1355 defer.returnValue(ret) |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1356 |
2787 | 1357 def update_v8(self): |
1358 """Update database from v7 to v8 (primary keys order changes + indexes)""" | |
3028 | 1359 log.info("Database update to v8") |
2787 | 1360 statements = ["PRAGMA foreign_keys = OFF"] |
1361 | |
1362 # here is a copy of create and index data, we can't use "current" table | |
1363 # because it may change in a future version, which would break the update | |
1364 # when doing v8 | |
1365 create = { | |
1366 'param_gen': ( | |
1367 ("category TEXT", "name TEXT", "value TEXT"), | |
1368 ("PRIMARY KEY (category, name)",)), | |
1369 'param_ind': ( | |
1370 ("category TEXT", "name TEXT", "profile_id INTEGER", "value TEXT"), | |
1371 ("PRIMARY KEY (profile_id, category, name)", "FOREIGN KEY(profile_id) REFERENCES profiles(id) ON DELETE CASCADE")), | |
1372 'private_ind': ( | |
1373 ("namespace TEXT", "key TEXT", "profile_id INTEGER", "value TEXT"), | |
1374 ("PRIMARY KEY (profile_id, namespace, key)", "FOREIGN KEY(profile_id) REFERENCES profiles(id) ON DELETE CASCADE")), | |
1375 'private_ind_bin': ( | |
1376 ("namespace TEXT", "key TEXT", "profile_id INTEGER", "value BLOB"), | |
1377 ("PRIMARY KEY (profile_id, namespace, key)", "FOREIGN KEY(profile_id) REFERENCES profiles(id) ON DELETE CASCADE")), | |
1378 } | |
1379 index = ( | |
1380 ('history', (('profile_id', 'timestamp'), | |
1381 ('profile_id', 'received_timestamp'))), | |
1382 ('message', ('history_uid',)), | |
1383 ('subject', ('history_uid',)), | |
1384 ('thread', ('history_uid',)), | |
1385 ('files', ('profile_id', 'mime_type', 'owner', 'parent'))) | |
1386 | |
1387 for table in ('param_gen', 'param_ind', 'private_ind', 'private_ind_bin'): | |
1388 statements.append("ALTER TABLE {0} RENAME TO {0}_old".format(table)) | |
1389 schema = {table: create[table]} | |
1390 cols = [d.split()[0] for d in schema[table][0]] | |
1391 statements.extend(Updater.createData2Raw(schema)) | |
3028 | 1392 statements.append("INSERT INTO {table}({cols}) " |
1393 "SELECT {cols} FROM {table}_old".format( | |
2787 | 1394 table=table, |
3028 | 1395 cols=','.join(cols))) |
1396 statements.append("DROP TABLE {}_old".format(table)) | |
2787 | 1397 |
1398 statements.extend(Updater.indexData2Raw(index)) | |
1399 statements.append("PRAGMA foreign_keys = ON") | |
1400 return statements | |
1401 | |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1402 @defer.inlineCallbacks |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1403 def update_v7(self): |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1404 """Update database from v6 to v7 (history unique constraint change)""" |
3028 | 1405 log.info("Database update to v7, this may be long depending on your history " |
1406 "size, please be patient.") | |
2721
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1407 |
3028 | 1408 log.info("Some cleaning first") |
2721
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1409 # we need to fix duplicate stanza_id, as it can result in conflicts with the new schema |
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1410 # normally database should not contain any, but better safe than sorry. |
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1411 rows = yield self.dbpool.runQuery( |
3028 | 1412 "SELECT stanza_id, COUNT(*) as c FROM history WHERE stanza_id is not NULL " |
1413 "GROUP BY stanza_id HAVING c>1") | |
2721
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1414 if rows: |
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1415 count = sum([r[1] for r in rows]) - len(rows) |
3028 | 1416 log.info("{count} duplicate stanzas found, cleaning".format(count=count)) |
2721
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1417 for stanza_id, count in rows: |
3028 | 1418 log.info("cleaning duplicate stanza {stanza_id}".format(stanza_id=stanza_id)) |
2721
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1419 row_uids = yield self.dbpool.runQuery( |
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1420 "SELECT uid FROM history WHERE stanza_id = ? LIMIT ?", |
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1421 (stanza_id, count-1)) |
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1422 uids = [r[0] for r in row_uids] |
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1423 yield self.dbpool.runQuery( |
3028 | 1424 "DELETE FROM history WHERE uid IN ({})".format(",".join("?"*len(uids))), |
2721
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1425 uids) |
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1426 |
2722
14e1db0c1383
core (memory/sqlite): further improvments in update_v7:
Goffi <goffi@goffi.org>
parents:
2721
diff
changeset
|
1427 def deleteInfo(txn): |
14e1db0c1383
core (memory/sqlite): further improvments in update_v7:
Goffi <goffi@goffi.org>
parents:
2721
diff
changeset
|
1428 # with foreign_keys on, the delete takes ages, so we deactivate it here |
14e1db0c1383
core (memory/sqlite): further improvments in update_v7:
Goffi <goffi@goffi.org>
parents:
2721
diff
changeset
|
1429 # the time to delete info messages from history. |
14e1db0c1383
core (memory/sqlite): further improvments in update_v7:
Goffi <goffi@goffi.org>
parents:
2721
diff
changeset
|
1430 txn.execute("PRAGMA foreign_keys = OFF") |
3028 | 1431 txn.execute("DELETE FROM message WHERE history_uid IN (SELECT uid FROM history WHERE " |
1432 "type='info')") | |
1433 txn.execute("DELETE FROM subject WHERE history_uid IN (SELECT uid FROM history WHERE " | |
1434 "type='info')") | |
1435 txn.execute("DELETE FROM thread WHERE history_uid IN (SELECT uid FROM history WHERE " | |
1436 "type='info')") | |
1437 txn.execute("DELETE FROM message WHERE history_uid IN (SELECT uid FROM history WHERE " | |
1438 "type='info')") | |
1439 txn.execute("DELETE FROM history WHERE type='info'") | |
2722
14e1db0c1383
core (memory/sqlite): further improvments in update_v7:
Goffi <goffi@goffi.org>
parents:
2721
diff
changeset
|
1440 # not sure that is is necessary to reactivate here, but in doubt… |
14e1db0c1383
core (memory/sqlite): further improvments in update_v7:
Goffi <goffi@goffi.org>
parents:
2721
diff
changeset
|
1441 txn.execute("PRAGMA foreign_keys = ON") |
14e1db0c1383
core (memory/sqlite): further improvments in update_v7:
Goffi <goffi@goffi.org>
parents:
2721
diff
changeset
|
1442 |
3028 | 1443 log.info('Deleting "info" messages (this can take a while)') |
2722
14e1db0c1383
core (memory/sqlite): further improvments in update_v7:
Goffi <goffi@goffi.org>
parents:
2721
diff
changeset
|
1444 yield self.dbpool.runInteraction(deleteInfo) |
14e1db0c1383
core (memory/sqlite): further improvments in update_v7:
Goffi <goffi@goffi.org>
parents:
2721
diff
changeset
|
1445 |
3028 | 1446 log.info("Cleaning done") |
2721
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1447 |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1448 # we have to rename table we will replace |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1449 # 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
|
1450 # 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
|
1451 # seems to be fixed in new version of Sqlite |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1452 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
|
1453 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
|
1454 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
|
1455 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
|
1456 |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1457 # history |
3028 | 1458 query = ("CREATE TABLE history (uid TEXT PRIMARY KEY, stanza_id TEXT, " |
1459 "update_uid TEXT, profile_id INTEGER, source TEXT, dest TEXT, " | |
1460 "source_res TEXT, dest_res TEXT, timestamp DATETIME NOT NULL, " | |
1461 "received_timestamp DATETIME, type TEXT, extra BLOB, " | |
1462 "FOREIGN KEY(profile_id) REFERENCES profiles(id) ON DELETE CASCADE, " | |
1463 "FOREIGN KEY(type) REFERENCES message_types(type), " | |
1464 "UNIQUE (profile_id, stanza_id, source, dest))") | |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1465 yield self.dbpool.runQuery(query) |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1466 |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1467 # message |
3028 | 1468 query = ("CREATE TABLE message (id INTEGER PRIMARY KEY ASC, history_uid INTEGER" |
1469 ", message TEXT, language TEXT, FOREIGN KEY(history_uid) REFERENCES " | |
1470 "history(uid) ON DELETE CASCADE)") | |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1471 yield self.dbpool.runQuery(query) |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1472 |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1473 # subject |
3028 | 1474 query = ("CREATE TABLE subject (id INTEGER PRIMARY KEY ASC, history_uid INTEGER" |
1475 ", subject TEXT, language TEXT, FOREIGN KEY(history_uid) REFERENCES " | |
1476 "history(uid) ON DELETE CASCADE)") | |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1477 yield self.dbpool.runQuery(query) |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1478 |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1479 # thread |
3028 | 1480 query = ("CREATE TABLE thread (id INTEGER PRIMARY KEY ASC, history_uid INTEGER" |
1481 ", thread_id TEXT, parent_id TEXT, FOREIGN KEY(history_uid) REFERENCES " | |
1482 "history(uid) ON DELETE CASCADE)") | |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1483 yield self.dbpool.runQuery(query) |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1484 |
3028 | 1485 log.info("Now transfering old data to new tables, please be patient.") |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1486 |
3028 | 1487 log.info("\nTransfering table history") |
1488 query = ("INSERT INTO history (uid, stanza_id, update_uid, profile_id, source, " | |
1489 "dest, source_res, dest_res, timestamp, received_timestamp, type, extra" | |
1490 ") SELECT uid, stanza_id, update_uid, profile_id, source, dest, " | |
1491 "source_res, dest_res, timestamp, received_timestamp, type, extra " | |
1492 "FROM history_old") | |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1493 yield self.dbpool.runQuery(query) |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1494 |
3028 | 1495 log.info("\nTransfering table message") |
1496 query = ("INSERT INTO message (id, history_uid, message, language) SELECT id, " | |
1497 "history_uid, message, language FROM message_old") | |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1498 yield self.dbpool.runQuery(query) |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1499 |
3028 | 1500 log.info("\nTransfering table subject") |
1501 query = ("INSERT INTO subject (id, history_uid, subject, language) SELECT id, " | |
1502 "history_uid, subject, language FROM subject_old") | |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1503 yield self.dbpool.runQuery(query) |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1504 |
3028 | 1505 log.info("\nTransfering table thread") |
1506 query = ("INSERT INTO thread (id, history_uid, thread_id, parent_id) SELECT id" | |
1507 ", history_uid, thread_id, parent_id FROM thread_old") | |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1508 yield self.dbpool.runQuery(query) |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1509 |
3028 | 1510 log.info("\nRemoving old tables") |
2721
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1511 # because of foreign keys, tables referencing history_old |
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1512 # must be deleted first |
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1513 yield self.dbpool.runQuery("DROP TABLE thread_old") |
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1514 yield self.dbpool.runQuery("DROP TABLE subject_old") |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1515 yield self.dbpool.runQuery("DROP TABLE message_old") |
2721
4aaa47f62d8d
core (memory/sqlite): fixed v7 update performance issue:
Goffi <goffi@goffi.org>
parents:
2720
diff
changeset
|
1516 yield self.dbpool.runQuery("DROP TABLE history_old") |
3028 | 1517 log.info("\nReducing database size (this can take a while)") |
2722
14e1db0c1383
core (memory/sqlite): further improvments in update_v7:
Goffi <goffi@goffi.org>
parents:
2721
diff
changeset
|
1518 yield self.dbpool.runQuery("VACUUM") |
3028 | 1519 log.info("Database update done :)") |
2716
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1520 |
06160b529da6
core (memory/sqlite): changed history constraint
Goffi <goffi@goffi.org>
parents:
2715
diff
changeset
|
1521 @defer.inlineCallbacks |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1522 def update_v3(self): |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1523 """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
|
1524 # 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
|
1525 # 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
|
1526 # 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
|
1527 # 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
|
1528 # messages |
3028 | 1529 log.info("Database update to v3, this may take a while") |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1530 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1531 # 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
|
1532 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
|
1533 if rows: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1534 log.info("fixing duplicate timestamp") |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1535 fixed = [] |
2765
378188abe941
misc: replaced all "dummy" by the more conventional and readable "__" ("_" being used for gettext)
Goffi <goffi@goffi.org>
parents:
2747
diff
changeset
|
1536 for timestamp, __ in rows: |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1537 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
|
1538 for idx, (id_,) in enumerate(ids_rows): |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1539 fixed.append(id_) |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1540 yield self.dbpool.runQuery("UPDATE history SET timestamp=? WHERE id=?", (float(timestamp) + idx * 0.001, id_)) |
3028 | 1541 log.info("fixed messages with ids {}".format(', '.join([str(id_) for id_ in fixed]))) |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1542 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1543 def historySchema(txn): |
3028 | 1544 log.info("History schema update") |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1545 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
|
1546 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
|
1547 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
|
1548 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1549 yield self.dbpool.runInteraction(historySchema) |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1550 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1551 def newTables(txn): |
3028 | 1552 log.info("Creating new tables") |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1553 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
|
1554 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
|
1555 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
|
1556 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1557 yield self.dbpool.runInteraction(newTables) |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1558 |
3028 | 1559 log.info("inserting new message type") |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1560 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
|
1561 |
3028 | 1562 log.info("messages update") |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1563 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
|
1564 total = len(rows) |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1565 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1566 def updateHistory(txn, queries): |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1567 for query, args in iter(queries): |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1568 txn.execute(query, args) |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1569 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1570 queries = [] |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1571 for idx, row in enumerate(rows, 1): |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1572 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
|
1573 log.info("preparing message {}/{}".format(idx, total)) |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1574 id_, timestamp, message, extra = row |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1575 try: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1576 extra = pickle.loads(str(extra or "")) |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1577 except EOFError: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1578 extra = {} |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1579 except Exception: |
3028 | 1580 log.warning("Can't handle extra data for message id {}, ignoring it".format(id_)) |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1581 extra = {} |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1582 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1583 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
|
1584 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1585 try: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1586 subject = extra.pop('subject') |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1587 except KeyError: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1588 pass |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1589 else: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1590 try: |
3028 | 1591 subject = subject |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1592 except UnicodeEncodeError: |
3028 | 1593 log.warning("Error while decoding subject, ignoring it") |
1955
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1594 del extra['subject'] |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1595 else: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1596 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
|
1597 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1598 received_timestamp = extra.pop('timestamp', None) |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1599 try: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1600 del extra['archive'] |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1601 except KeyError: |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1602 # archive was not used |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1603 pass |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1604 |
1962
a45235d8dc93
memory (sqlite): fixed handling of extra (pickled data) by using sqlite3.Binary
Goffi <goffi@goffi.org>
parents:
1961
diff
changeset
|
1605 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
|
1606 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1607 yield self.dbpool.runInteraction(updateHistory, queries) |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1608 |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1609 log.info("Dropping temporary table") |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1610 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
|
1611 log.info("Database update finished :)") |
633b5c21aefd
backend, frontend: messages refactoring (huge commit, not finished):
Goffi <goffi@goffi.org>
parents:
1934
diff
changeset
|
1612 |
1030
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1613 def update2raw_v2(self): |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1614 """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
|
1615 |
1030
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1616 - 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
|
1617 - the profile password is stored hashed |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1618 - 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
|
1619 - 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
|
1620 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
|
1621 """ |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1622 xmpp_pass_path = ('Connection', 'Password') |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1623 |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1624 def encrypt_values(values): |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1625 ret = [] |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1626 list_ = [] |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1627 |
1065
9378c80e3408
memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents:
1047
diff
changeset
|
1628 def prepare_queries(result, xmpp_password): |
9378c80e3408
memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents:
1047
diff
changeset
|
1629 try: |
9378c80e3408
memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents:
1047
diff
changeset
|
1630 id_ = result[0][0] |
9378c80e3408
memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents:
1047
diff
changeset
|
1631 except IndexError: |
3028 | 1632 log.error("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
|
1633 return defer.succeed(None) |
1065
9378c80e3408
memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents:
1047
diff
changeset
|
1634 |
9378c80e3408
memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents:
1047
diff
changeset
|
1635 sat_password = xmpp_password |
3160
330a5f1d9eea
core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
1636 sat_cipher = PasswordHasher.hash(sat_password) |
1065
9378c80e3408
memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents:
1047
diff
changeset
|
1637 personal_key = BlockCipher.getRandomKey(base64=True) |
3160
330a5f1d9eea
core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
1638 personal_cipher = BlockCipher.encrypt(sat_password, personal_key) |
330a5f1d9eea
core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
1639 xmpp_cipher = BlockCipher.encrypt(personal_key, xmpp_password) |
1030
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1640 |
3160
330a5f1d9eea
core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
1641 ret.append("INSERT INTO param_ind(category,name,profile_id,value) VALUES ('%s','%s',%s,'%s')" % |
330a5f1d9eea
core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
1642 (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
|
1643 |
3160
330a5f1d9eea
core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
1644 ret.append("INSERT INTO private_ind(namespace,key,profile_id,value) VALUES ('%s','%s',%s,'%s')" % |
330a5f1d9eea
core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
1645 (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
|
1646 |
3160
330a5f1d9eea
core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
1647 ret.append("REPLACE INTO param_ind(category,name,profile_id,value) VALUES ('%s','%s',%s,'%s')" % |
330a5f1d9eea
core (memory/crypto): replaced `PyCrypto` by `cryptography`:
Goffi <goffi@goffi.org>
parents:
3137
diff
changeset
|
1648 (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
|
1649 |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1650 |
1065
9378c80e3408
memory (sqlite): fixes upgrade to database v2
souliane <souliane@mailoo.org>
parents:
1047
diff
changeset
|
1651 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
|
1652 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
|
1653 d.addCallback(prepare_queries, xmpp_password) |
1030
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1654 list_.append(d) |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1655 |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1656 d_list = defer.DeferredList(list_) |
2765
378188abe941
misc: replaced all "dummy" by the more conventional and readable "__" ("_" being used for gettext)
Goffi <goffi@goffi.org>
parents:
2747
diff
changeset
|
1657 d_list.addCallback(lambda __: ret) |
1030
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1658 return d_list |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1659 |
1045
65fffdcb97f1
memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents:
1030
diff
changeset
|
1660 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
|
1661 try: |
65fffdcb97f1
memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents:
1030
diff
changeset
|
1662 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
|
1663 except IndexError: |
65fffdcb97f1
memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents:
1030
diff
changeset
|
1664 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
|
1665 |
65fffdcb97f1
memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents:
1030
diff
changeset
|
1666 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
|
1667 try: |
65fffdcb97f1
memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents:
1030
diff
changeset
|
1668 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
|
1669 except IndexError: |
65fffdcb97f1
memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents:
1030
diff
changeset
|
1670 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
|
1671 return |
65fffdcb97f1
memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents:
1030
diff
changeset
|
1672 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
|
1673 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
|
1674 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
|
1675 |
65fffdcb97f1
memory: auto-update configuration file with libervia's passphrase when migrating the database
souliane <souliane@mailoo.org>
parents:
1030
diff
changeset
|
1676 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
|
1677 d.addCallback(updateLiberviaConf) |
2765
378188abe941
misc: replaced all "dummy" by the more conventional and readable "__" ("_" being used for gettext)
Goffi <goffi@goffi.org>
parents:
2747
diff
changeset
|
1678 d.addCallback(lambda __: 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
|
1679 d.addCallback(encrypt_values) |
15f43b54d697
core, memory, bridge: added profile password + password encryption:
souliane <souliane@mailoo.org>
parents:
1019
diff
changeset
|
1680 return d |