diff options
author | Lars Wirzenius <liw@liw.fi> | 2017-10-09 15:49:58 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2017-10-09 21:03:25 +0300 |
commit | c3ee93ad6eea2460bf8128d2120c415544538224 (patch) | |
tree | 416a4a59c927b5734e05dbc09fd620bde8384b21 | |
parent | 2e101cf1813806b5315947ef13c1d77507a65813 (diff) | |
download | qvisqve-c3ee93ad6eea2460bf8128d2120c415544538224.tar.gz |
Add: support for blobs to Postgres
-rw-r--r-- | qvarn/objstore.py | 51 | ||||
-rw-r--r-- | qvarn/sql.py | 5 |
2 files changed, 43 insertions, 13 deletions
diff --git a/qvarn/objstore.py b/qvarn/objstore.py index aeab6bc..90d4e84 100644 --- a/qvarn/objstore.py +++ b/qvarn/objstore.py @@ -187,9 +187,7 @@ class PostgresObjectStore(ObjectStoreInterface): # pragma: no cover _table = '_objects' _auxtable = '_aux' - _strtable = '_strings' - _inttable = '_ints' - _booltable = '_bools' + _blobtable = '_blobs' def __init__(self, sql): self._sql = sql @@ -208,9 +206,12 @@ class PostgresObjectStore(ObjectStoreInterface): # pragma: no cover # Create main table for objects. self._create_table(self._table, self._keys, '_obj', dict) - # Create helper tables for fields at all depths. + # Create helper table for fields at all depths. Needed by searches. self._create_table(self._auxtable, self._keys, '_field', dict) + # Create helper table for blobs. + self._create_table(self._blobtable, self._keys, '_blob', bytes) + def _create_table(self, name, col_dict, col_name, col_type): columns = dict(col_dict) columns[col_name] = col_type @@ -305,14 +306,44 @@ class PostgresObjectStore(ObjectStoreInterface): # pragma: no cover obj = row.pop('_obj') return keys, obj - def create_blob(self, blob, subpath=None, **keys): - raise NotImplementedError() + def create_blob(self, blob, **keys): + qvarn.log.log('trace', msg_text='Creating blob', keys=keys) - def get_blob(self, subpath=None, **keys): - raise NotImplementedError() + self.check_all_keys_are_allowed(**keys) + self.check_value_types(**keys) + if not self.get_objects(**keys): + raise NoSuchObject(keys) - def remove_blob(self, blob, subpath=None, **keys): - raise NotImplementedError() + with self._sql.transaction() as t: + column_names = list(keys.keys()) + ['_blob'] + query = t.insert_object(self._blobtable, *column_names) + + values = dict(keys) + values['_blob'] = blob + + t.execute(query, values) + + def get_blob(self, **keys): + self.check_all_keys_are_allowed(**keys) + self.check_value_types(**keys) + + column_names = list(keys.keys()) + + with self._sql.transaction() as t: + query = t.select_objects(self._blobtable, '_blob', *column_names) + blobs = [bytes(row['_blob']) for row in t.execute(query, keys)] + if len(blobs) == 0: + raise NoSuchObject(keys) + return blobs + + def remove_blob(self, **keys): + self.check_all_keys_are_allowed(**keys) + self.check_value_types(**keys) + + column_names = list(keys.keys()) + with self._sql.transaction() as t: + query = t.remove_objects(self._blobtable, *column_names) + t.execute(query, keys) class KeyCollision(Exception): diff --git a/qvarn/sql.py b/qvarn/sql.py index 5f14876..604272b 100644 --- a/qvarn/sql.py +++ b/qvarn/sql.py @@ -66,9 +66,7 @@ class Transaction: self._conn = None def execute(self, query, values): - qvarn.log.log( - 'trace', msg_text='executing SQL query', query=query, - values=values) + qvarn.log.log('trace', msg_text='executing SQL query', query=query) c = self._conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) c.execute(query, values) return c @@ -92,6 +90,7 @@ class Transaction: (int, 'BIGINT'), (bool, 'BOOL'), (dict, 'JSONB'), + (bytes, 'BYTEA'), ] for t, n in types: if col_type == t: |