Save upddate in bee files

This commit is contained in:
Rebecca Breu 2024-05-28 22:10:33 +02:00
parent caed5c3801
commit c251bb8159
3 changed files with 75 additions and 5 deletions

View file

@ -1,4 +1,4 @@
USER_VERSION = 2
USER_VERSION = 3
APPLICATION_ID = 2060242126
@ -30,12 +30,20 @@ SCHEMA = [
ON UPDATE NO ACTION
)
""",
"""CREATE TABLE info (
key TEXT PRIMARY KEY,
value TEXT
)
""",
]
MIGRATIONS = {
2: [
2: (
"ALTER TABLE items ADD COLUMN data JSON",
"UPDATE items SET data = json_object('filename', filename)",
],
),
3: (
"CREATE TABLE info (key TEXT PRIMARY KEY, value TEXT)",
),
}

View file

@ -23,6 +23,7 @@ https://www.sqlite.org/appfileformat.html
https://www.sqlite.org/sqlar.html
"""
import datetime
import json
import logging
import os
@ -51,7 +52,7 @@ def is_bee_file(path):
def handle_sqlite_errors(func):
def wrapper(self, *args, **kwargs):
try:
func(self, *args, **kwargs)
return func(self, *args, **kwargs)
except Exception as e:
logger.exception(f'Error while reading/writing {self.filename}')
try:
@ -187,6 +188,22 @@ class SQLiteIO:
for schema in SCHEMA:
self.ex(schema)
@handle_sqlite_errors
def read_info_value(self, key, default=None):
"""Reads a value from the info table."""
rows = self.fetchone('SELECT value FROM info WHERE key=?', (key,))
return rows[0] if rows else default
@handle_sqlite_errors
def write_info_value(self, key, value):
"""Writes a value into the info table."""
self.ex(
'INSERT INTO info (key, value) VALUES (?, ?) '
'ON CONFLICT(key) DO UPDATE SET value=excluded.value',
(key, value))
@handle_sqlite_errors
def read(self):
rows = self.fetchall(
@ -283,6 +300,10 @@ class SQLiteIO:
if self.worker.canceled:
break
self.delete_items(to_delete)
timestamp = datetime.datetime.now(datetime.timezone.utc).isoformat()
self.write_info_value('upddate', timestamp)
self.connection.commit()
self.ex('VACUUM')
self.connection.commit()
if self.worker:

View file

@ -1,3 +1,4 @@
import datetime
import json
import os
import os.path
@ -120,6 +121,36 @@ def test_all_migrations(tmpfile):
assert result[3] == b'bla'
def test_sqliteio_read_info_value_when_exists(tmpfile):
io = SQLiteIO(tmpfile, MagicMock(), create_new=True)
io.create_schema_on_new()
io.ex('INSERT INTO info (key, value) VALUES ("foo", "bar")')
io.read_info_value('foo') == 'bar'
def test_sqliteio_read_info_value_returns_default_when_doesnt_exists(tmpfile):
io = SQLiteIO(tmpfile, MagicMock(), create_new=True)
io.create_schema_on_new()
io.read_info_value('foo', 'baz') == 'baz'
def test_sqliteio_write_info_value_when_doesnt_exist(tmpfile):
io = SQLiteIO(tmpfile, MagicMock(), create_new=True)
io.create_schema_on_new()
io.write_info_value('foo', 'bar')
io.read_info_value('foo') == 'bar'
def test_sqliteio_write_info_value_when_exist_updates(tmpfile):
io = SQLiteIO(tmpfile, MagicMock(), create_new=True)
io.create_schema_on_new()
io.ex('INSERT INTO info (key, value) VALUES ("foo", "bar")')
io.write_info_value('foo', 'baz')
io.read_info_value('foo') == 'baz'
row = io.fetchone('SELECT COUNT(*) FROM info WHERE key="foo"')
assert row[0] == 1
def test_sqliteio_write_meta_application_id(tmpfile):
io = SQLiteIO(tmpfile, MagicMock(), create_new=True)
io.write_meta()
@ -148,7 +179,7 @@ def test_sqliteio_create_schema_on_new_when_create_new(tmpfile):
result = io.fetchone(
'SELECT COUNT(*) FROM sqlite_master '
'WHERE type="table" AND name NOT LIKE "sqlite_%"')
assert result[0] == 2
assert result[0] == 3
scene_mock.clear_save_ids.assert_called_once()
@ -196,6 +227,16 @@ def test_sqliteio_write_calls_write_meta(tmpfile, view):
metamock.assert_called_once()
def test_sqliteio_write_writes_upddate(tmpfile, view):
item = BeeTextItem(text='foo bar')
view.scene.addItem(item)
io = SQLiteIO(tmpfile, view.scene, create_new=True)
io.write()
year = datetime.datetime.utcnow().year
upddate = io.read_info_value('upddate')
assert upddate.startswith(str(year))
def test_sqliteio_write_inserts_new_text_item(tmpfile, view):
item = BeeTextItem(text='foo bar')
view.scene.addItem(item)