b06bf9ef8322facf1d48f562744ee5be85b20f88
[tiramisu.git] / tiramisu / storage / sqlite3 / value.py
1 # -*- coding: utf-8 -*-
2 "default plugin for value: set it in a simple dictionary"
3 # Copyright (C) 2013-2017 Team tiramisu (see AUTHORS for all contributors)
4 #
5 # This program is free software: you can redistribute it and/or modify it
6 # under the terms of the GNU Lesser General Public License as published by the
7 # Free Software Foundation, either version 3 of the License, or (at your
8 # option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
13 # details.
14 #
15 # You should have received a copy of the GNU Lesser General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 # ____________________________________________________________
18
19 from .sqlite3db import Sqlite3DB
20 from .storage import delete_session
21 from ...setting import undefined, owners
22 from ...i18n import _
23
24
25 class Values(Sqlite3DB):
26     __slots__ = ('__weakref__',)
27
28     def __init__(self, storage):
29         """init plugin means create values storage
30         """
31         # should init cache too
32         super(Values, self).__init__(storage)
33         values_table = 'CREATE TABLE IF NOT EXISTS value(path TEXT, '
34         values_table += 'value TEXT, owner TEXT, idx INTEGER, session_id TEXT NOT NULL, '\
35                         'PRIMARY KEY (path, idx, session_id))'
36         self._storage.execute(values_table, commit=False)
37         informations_table = 'CREATE TABLE IF NOT EXISTS information(key TEXT PRIMARY '
38         informations_table += 'KEY, value TEXT, session_id TEXT NOT NULL)'
39         self._storage.execute(informations_table)
40
41     def getsession(self):
42         pass
43
44     # sqlite
45     def _sqlite_select(self, path, index):
46         request = "SELECT value FROM value WHERE path = ? AND session_id = ?"
47         params = (path, self._session_id)
48         if index is not None:
49             request += " and idx = ?"
50             params = (path, self._session_id, index)
51         return self._storage.select(request, params)
52
53     # value
54     def setvalue(self, path, value, owner, index, session):
55         """set value for an option
56         a specified value must be associated to an owner
57         """
58         path = self._sqlite_encode_path(path)
59         if index is not None:
60             self._storage.execute("DELETE FROM value WHERE path = ? AND idx = ? AND "
61                                   "session_id = ?", (path, index, self._session_id),
62                                   commit=False)
63             self._storage.execute("INSERT INTO value(path, value, owner, idx, session_id) VALUES "
64                                   "(?, ?, ?, ?, ?)", (path, self._sqlite_encode(value),
65                                                       self._sqlite_encode(str(owner)),
66                                                       index,
67                                                       self._session_id),
68                                   commit=True)
69         else:
70             self._storage.execute("DELETE FROM value WHERE path = ? AND session_id = ?",
71                                   (path, self._session_id),
72                                   commit=False)
73             self._storage.execute("INSERT INTO value(path, value, owner, session_id) VALUES "
74                                   "(?, ?, ?, ?)", (path, self._sqlite_encode(value),
75                                                    self._sqlite_encode(str(owner)),
76                                                    self._session_id),
77                                   commit=True)
78
79     def getvalue(self, path, session, index=None):
80         """get value for an option
81         return: only value, not the owner
82         """
83         path = self._sqlite_encode_path(path)
84         values = self._sqlite_select(path, index)
85         if values is None:
86             return values
87         return self._sqlite_decode(values[0])
88
89     def hasvalue(self, path, index=None):
90         """if opt has a value
91         return: boolean
92         """
93         path = self._sqlite_encode_path(path)
94         return self._sqlite_select(path, index) is not None
95
96     def resetvalue(self, path, session):
97         """remove value means delete value in storage
98         """
99         path = self._sqlite_encode_path(path)
100         self._storage.execute("DELETE FROM value WHERE path = ? AND session_id = ?", (path, self._session_id))
101
102     def get_modified_values(self):
103         """return all values in a dictionary
104         example: {option1: (owner, 'value1'), option2: (owner, 'value2')}
105         """
106         ret = {}
107         for path, value, owner, index, _ in self._storage.select("SELECT * FROM value WHERE "
108                                                                  "session_id = ?",
109                                                                  (self._session_id,),
110                                                                  only_one=False):
111             path = self._sqlite_decode_path(path)
112             owner = getattr(owners, self._sqlite_decode(owner))
113
114             value = self._sqlite_decode(value)
115             if isinstance(value, list):
116                 value = tuple(value)
117             if index is None:
118                 ret[path] = (owner, value)
119             else:
120                 if path in ret:
121                     ret[path][0][str(index)] = owner
122                     ret[path][1][str(index)] = value
123                 else:
124                     ret[path] = ({str(index): owner}, {str(index): value})
125         return ret
126
127     # owner
128     def setowner(self, path, owner, session, index=None):
129         """change owner for an option
130         """
131         path = self._sqlite_encode_path(path)
132         if index is None:
133             self._storage.execute("UPDATE value SET owner = ? WHERE path = ? AND session_id = ?",
134                                  (self._sqlite_encode(str(owner)), path, self._session_id))
135         else:
136             self._storage.execute("UPDATE value SET owner = ? WHERE path = ? and idx = ? AND session_id = ?",
137                                  (self._sqlite_encode(str(owner)), path, index, self._session_id))
138
139     def getowner(self, path, default, session, index=None, only_default=False):
140         """get owner for an option
141         return: owner object
142         """
143         path = self._sqlite_encode_path(path)
144         request = "SELECT owner FROM value WHERE path = ? AND session_id = ?"
145         if index is not None:
146             request += " AND idx = ?"
147             params = (path, self._session_id, index)
148         else:
149             params = (path, self._session_id)
150         owner = self._storage.select(request, params)
151         if owner is None:
152             return default
153         else:
154             owner = self._sqlite_decode(owner[0])
155             # autocreate owners
156             try:
157                 return getattr(owners, owner)
158             except AttributeError:
159                 owners.addowner(owner)
160                 return getattr(owners, owner)
161
162     def set_information(self, key, value):
163         """updates the information's attribute
164         (which is a dictionary)
165
166         :param key: information's key (ex: "help", "doc"
167         :param value: information's value (ex: "the help string")
168         """
169         self._storage.execute("DELETE FROM information WHERE key = ? AND session_id = ?",
170                              (key, self._session_id),
171                              False)
172         self._storage.execute("INSERT INTO information(key, value, session_id) VALUES "
173                              "(?, ?, ?)", (key, self._sqlite_encode(value), self._session_id))
174
175     def get_information(self, key, default):
176         """retrieves one information's item
177
178         :param key: the item string (ex: "help")
179         """
180         value = self._storage.select("SELECT value FROM information WHERE key = ? AND "
181                                      "session_id = ?",
182                                     (key, self._session_id))
183         if value is None:
184             if default is undefined:
185                 raise ValueError(_("information's item"
186                                    " not found: {0}").format(key))
187             return default
188         else:
189             return self._sqlite_decode(value[0])
190
191     def del_information(self, key, raises):
192         if raises and self._storage.select("SELECT value FROM information WHERE key = ? "
193                                            "AND session_id = ?",
194                                            (key, self._session_id)) is None:
195             raise ValueError(_("information's item not found {0}").format(key))
196         self._storage.execute("DELETE FROM information WHERE key = ? AND session_id = ?",
197                               (key, self._session_id))
198
199     def exportation(self, session, fake=False):
200         rows = self._storage.select("SELECT path, value, owner, idx FROM value WHERE "
201                                     "session_id = ?;", (self._session_id,), only_one=False)
202         ret = [[], [], [], []]
203         for row in rows:
204             path = row[0]
205             value = self._sqlite_decode(row[1])
206             owner = self._sqlite_decode(row[2])
207             index = row[3]
208             if index is None:
209                 ret[0].append(path)
210                 ret[1].append(index)
211                 ret[2].append(value)
212                 ret[3].append(owner)
213             else:
214                 if path in ret[0]:
215                     path_idx = ret[0].index(path)
216                     ret[1][path_idx].append(index)
217                     ret[2][path_idx].append(value)
218                 else:
219                     ret[0].append(path)
220                     ret[1].append([index])
221                     ret[2].append([value])
222                     ret[3].append(owner)
223
224         return ret
225
226     def importation(self, export):
227         self._storage.execute("DELETE FROM value WHERE session_id = ?", (self._session_id,),
228                               commit=False)
229         for idx, path in enumerate(export[0]):
230             index = export[1][idx]
231             value = export[2][idx]
232             owner = export[3][idx]
233             self._storage.execute("INSERT INTO value(path, value, owner, idx, session_id) VALUES "
234                                   "(?, ?, ?, ?, ?)", (path, self._sqlite_encode(value),
235                                                       self._sqlite_encode(str(owner)), index,
236                                                       self._session_id))
237         self._storage._conn.commit()
238
239     def get_max_length(self, path, session):
240         val_max = self._storage.select("SELECT max(idx) FROM value WHERE path = ? AND session_id = ?",
241                                        (path, self._session_id), False)
242         if val_max[0][0] is None:
243             return 0
244         return val_max[0][0] + 1