173
173
def __init__(self, path=None):
174
174
self.db_path = path
176
self.db_path = os.path.join(
177
os.environ.get('CHARM_DIR', ''), '.unit-state.db')
176
if 'UNIT_STATE_DB' in os.environ:
177
self.db_path = os.environ['UNIT_STATE_DB']
179
self.db_path = os.path.join(
180
os.environ.get('CHARM_DIR', ''), '.unit-state.db')
178
181
self.conn = sqlite3.connect('%s' % self.db_path)
179
182
self.cursor = self.conn.cursor()
180
183
self.revision = None
206
202
return json.loads(result[0])
208
204
def getrange(self, key_prefix, strip=False):
209
stmt = "select key, data from kv where key like '%s%%'" % key_prefix
210
self.cursor.execute(*self._scoped_query(stmt))
206
Get a range of keys starting with a common prefix as a mapping of
209
:param str key_prefix: Common prefix among all keys
210
:param bool strip: Optionally strip the common prefix from the key
211
names in the returned dict
212
:return dict: A (possibly empty) dict of key-value mappings
214
self.cursor.execute("select key, data from kv where key like ?",
215
['%s%%' % key_prefix])
211
216
result = self.cursor.fetchall()
218
223
(k[len(key_prefix):], json.loads(v)) for k, v in result])
220
225
def update(self, mapping, prefix=""):
227
Set the values of multiple keys at once.
229
:param dict mapping: Mapping of keys to values
230
:param str prefix: Optional prefix to apply to all keys in `mapping`
221
233
for k, v in mapping.items():
222
234
self.set("%s%s" % (prefix, k), v)
224
236
def unset(self, key):
238
Remove a key from the database entirely.
225
240
self.cursor.execute('delete from kv where key=?', [key])
226
241
if self.revision and self.cursor.rowcount:
227
242
self.cursor.execute(
228
243
'insert into kv_revisions values (?, ?, ?)',
229
244
[key, self.revision, json.dumps('DELETED')])
246
def unsetrange(self, keys=None, prefix=""):
248
Remove a range of keys starting with a common prefix, from the database
251
:param list keys: List of keys to remove.
252
:param str prefix: Optional prefix to apply to all keys in ``keys``
256
keys = ['%s%s' % (prefix, key) for key in keys]
257
self.cursor.execute('delete from kv where key in (%s)' % ','.join(['?'] * len(keys)), keys)
258
if self.revision and self.cursor.rowcount:
260
'insert into kv_revisions values %s' % ','.join(['(?, ?, ?)'] * len(keys)),
261
list(itertools.chain.from_iterable((key, self.revision, json.dumps('DELETED')) for key in keys)))
263
self.cursor.execute('delete from kv where key like ?',
265
if self.revision and self.cursor.rowcount:
267
'insert into kv_revisions values (?, ?, ?)',
268
['%s%%' % prefix, self.revision, json.dumps('DELETED')])
231
270
def set(self, key, value):
272
Set a value in the database.
274
:param str key: Key to set the value for
275
:param value: Any JSON-serializable value to be set
232
277
serialized = json.dumps(value)
235
'select data from kv where key=?', [key])
279
self.cursor.execute('select data from kv where key=?', [key])
236
280
exists = self.cursor.fetchone()
238
282
# Skip mutations to the same value