3 # Copyright (C) 2013 Simo Sorce <simo@redhat.com>
5 # see file 'COPYING' for use and warranty information
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
23 from ipsilon.util.log import Log
27 OPTIONS_COLUMNS = ['name', 'option', 'value']
28 UNIQUE_DATA_COLUMNS = ['uuid', 'name', 'value']
33 def __init__(self, name):
36 def _build_where(self, kvfilter, kvout):
41 kvout[mk] = kvfilter[k]
42 where += "%s %s=:%s" % (sep, k, mk)
46 def _build_select(self, table, kvfilter=None, kvout=None, columns=None):
47 SELECT = "SELECT %(cols)s FROM %(table)s %(where)s"
50 cols = ",".join(columns)
52 if kvfilter is not None:
53 where = self._build_where(kvfilter, kvout)
54 return SELECT % {'table': table, 'cols': cols, 'where': where}
56 def _select(self, cursor, table, kvfilter=None, columns=None):
58 select = self._build_select(table, kvfilter, kv, columns)
59 cursor.execute(select, kv)
60 return cursor.fetchall()
62 def _create(self, cursor, table, columns):
63 CREATE = "CREATE TABLE IF NOT EXISTS %(table)s(%(cols)s)"
64 cols = ",".join(columns)
65 create = CREATE % {'table': table, 'cols': cols}
66 cursor.execute(create)
68 def _update(self, cursor, table, values, kvfilter):
69 UPDATE = "UPDATE %(table)s SET %(setval)s %(where)s"
77 setval += "%s%s=:%s" % (sep, k, mk)
80 where = self._build_where(kvfilter, kv)
82 update = UPDATE % {'table': table, 'setval': setval, 'where': where}
83 cursor.execute(update, kv)
85 def _insert(self, cursor, table, values):
86 INSERT = "INSERT INTO %(table)s VALUES(%(values)s)"
92 insert = INSERT % {'table': table, 'values': vals}
93 cursor.execute(insert, values)
95 def _delete(self, cursor, table, kvfilter):
96 DELETE = "DELETE FROM %(table)s %(where)s"
98 where = self._build_where(kvfilter, kv)
99 delete = DELETE % {'table': table, 'where': where}
100 cursor.execute(delete, kv)
102 def _row_to_dict_tree(self, data, row):
108 self._row_to_dict_tree(d2, row[1:])
112 if data[name] is list:
113 data[name].append(value)
116 data[name] = [v, value]
120 def _rows_to_dict_tree(self, rows):
123 self._row_to_dict_tree(data, r)
126 def _load_data(self, table, columns, kvfilter=None):
130 con = sqlite3.connect(self._dbname)
132 self._create(cur, table, columns)
133 rows = self._select(cur, table, kvfilter)
135 except sqlite3.Error, e:
138 self.error("Failed to load data for table %s: [%s]" % (table, e))
143 return self._rows_to_dict_tree(rows)
145 def load_config(self):
147 columns = ['name', 'value']
148 return self._load_data(table, columns)
150 def load_options(self, table, name=None):
153 kvfilter['name'] = name
154 options = self._load_data(table, OPTIONS_COLUMNS, kvfilter)
155 if name and name in options:
159 def save_options(self, table, name, options):
163 con = sqlite3.connect(self._dbname)
165 self._create(cur, table, OPTIONS_COLUMNS)
166 rows = self._select(cur, table, {'name': name},
169 curvals[row[0]] = row[1]
173 self._update(cur, table,
174 {'value': options[opt]},
175 {'name': name, 'option': opt})
177 self._insert(cur, table, (name, opt, options[opt]))
180 except sqlite3.Error, e:
183 self.error("Failed to store config: [%s]" % e)
189 def delete_options(self, table, name, options=None):
190 kvfilter = {'name': name}
192 con = sqlite3.connect(self._dbname)
194 self._create(cur, table, OPTIONS_COLUMNS)
196 self._delete(cur, table, kvfilter)
199 kvfilter['option'] = opt
200 self._delete(cur, table, kvfilter)
202 except sqlite3.Error, e:
205 self.error("Failed to delete from %s: [%s]" % (table, e))
211 def new_unique_data(self, table, data):
214 con = sqlite3.connect(self._dbname)
216 self._create(cur, table, UNIQUE_DATA_COLUMNS)
217 newid = str(uuid.uuid4())
219 self._insert(cur, table, (newid, name, data[name]))
221 except sqlite3.Error, e:
224 cherrypy.log.error("Failed to store %s data: [%s]" % (table, e))
231 def get_unique_data(self, table, uuidval=None, name=None, value=None):
234 kvfilter['uuid'] = uuidval
236 kvfilter['name'] = name
238 kvfilter['value'] = value
239 return self._load_data(table, UNIQUE_DATA_COLUMNS, kvfilter)
241 def save_unique_data(self, table, data):
245 con = sqlite3.connect(self._dbname)
247 self._create(cur, table, UNIQUE_DATA_COLUMNS)
250 rows = self._select(cur, table, {'uuid': uid},
258 self._update(cur, table,
259 {'value': datum[name]},
260 {'uuid': uid, 'name': name})
262 self._insert(cur, table, (uid, name, datum[name]))
265 except sqlite3.Error, e:
268 self.error("Failed to store data in %s: [%s]" % (table, e))
274 def del_unique_data(self, table, uuidval):
275 kvfilter = {'uuid': uuidval}
278 con = sqlite3.connect(self._dbname)
280 self._delete(cur, table, kvfilter)
281 except sqlite3.Error, e:
282 self.error("Failed to delete data from %s: [%s]" % (table, e))
288 class AdminStore(Store):
290 def __init__(self, path=None):
292 self._path = os.getcwd()
296 if 'admin.config.db' in cherrypy.config:
297 self._name = cherrypy.config['admin.config.db']
299 self._name = os.path.join(self._path, 'adminconfig.sqlite')
300 super(AdminStore, self).__init__(self._name)
302 def get_data(self, plugin, idval=None, name=None, value=None):
303 return self.get_unique_data(plugin+"_data", idval, name, value)
305 def save_data(self, plugin, data):
306 return self.save_unique_data(plugin+"_data", data)
308 def new_datum(self, plugin, datum):
309 table = plugin+"_data"
310 return self.new_unique_data(table, datum)
312 def del_datum(self, plugin, idval):
313 table = plugin+"_data"
314 return self.del_unique_data(table, idval)
316 def wipe_data(self, plugin):
317 table = plugin+"_data"
318 # Try to backup old data first, just in case
320 con = sqlite3.connect(self._dbname)
322 cur.execute("DROP TABLE IF EXISTS " + table)
323 self._create(cur, table, UNIQUE_DATA_COLUMNS)
325 except sqlite3.Error, e:
328 cherrypy.log.error("Failed to wipe %s data: [%s]" % (plugin, e))
335 class UserStore(Store):
337 def __init__(self, path=None):
339 self._path = os.getcwd()
343 if 'user.prefs.db' in cherrypy.config:
344 self._name = cherrypy.config['user.prefs.db']
346 self._name = os.path.join(self._path, 'userprefs.sqlite')
347 super(UserStore, self).__init__(self._name)
349 def save_user_preferences(self, user, options):
350 return self.save_options('users', user, options)