Auto clear dirtied_formats with a trigger

This commit is contained in:
Kovid Goyal 2022-02-08 10:57:48 +05:30
parent 2ecdbfb194
commit b66c72cc15
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 26 additions and 2 deletions

View File

@ -6,12 +6,13 @@ CREATE TABLE fts_db.dirtied_formats ( id INTEGER PRIMARY KEY,
CREATE TABLE fts_db.books_text ( id INTEGER PRIMARY KEY, CREATE TABLE fts_db.books_text ( id INTEGER PRIMARY KEY,
book INTEGER NOT NULL, book INTEGER NOT NULL,
format TEXT NOT NULL COLLATE NOCASE,
timestamp REAL NOT NULL, timestamp REAL NOT NULL,
format TEXT NOT NULL COLLATE NOCASE,
format_hash TEXT NOT NULL COLLATE NOCASE, format_hash TEXT NOT NULL COLLATE NOCASE,
format_size INTEGER NOT NULL, format_size INTEGER NOT NULL,
text_hash TEXT NOT NULL COLLATE NOCASE,
searchable_text TEXT NOT NULL DEFAULT "", searchable_text TEXT NOT NULL DEFAULT "",
text_size INTEGER NOT NULL,
text_hash TEXT NOT NULL COLLATE NOCASE,
UNIQUE(book, format) UNIQUE(book, format)
); );
@ -23,6 +24,7 @@ CREATE TRIGGER fts_db.books_fts_insert_trg AFTER INSERT ON fts_db.books_text
BEGIN BEGIN
INSERT INTO books_fts(rowid, searchable_text) VALUES (NEW.id, NEW.searchable_text); INSERT INTO books_fts(rowid, searchable_text) VALUES (NEW.id, NEW.searchable_text);
INSERT INTO books_fts_stemmed(rowid, searchable_text) VALUES (NEW.id, NEW.searchable_text); INSERT INTO books_fts_stemmed(rowid, searchable_text) VALUES (NEW.id, NEW.searchable_text);
DELETE FROM dirtied_formats WHERE book=NEW.book AND format=NEW.format;
END; END;
CREATE TRIGGER fts_db.books_fts_delete_trg AFTER DELETE ON fts_db.books_text CREATE TRIGGER fts_db.books_fts_delete_trg AFTER DELETE ON fts_db.books_text
@ -37,6 +39,7 @@ BEGIN
INSERT INTO books_fts(rowid, searchable_text) VALUES (NEW.id, NEW.searchable_text); INSERT INTO books_fts(rowid, searchable_text) VALUES (NEW.id, NEW.searchable_text);
INSERT INTO books_fts_stemmed(books_fts_stemmed, rowid, searchable_text) VALUES('delete', OLD.id, OLD.searchable_text); INSERT INTO books_fts_stemmed(books_fts_stemmed, rowid, searchable_text) VALUES('delete', OLD.id, OLD.searchable_text);
INSERT INTO books_fts_stemmed(rowid, searchable_text) VALUES (NEW.id, NEW.searchable_text); INSERT INTO books_fts_stemmed(rowid, searchable_text) VALUES (NEW.id, NEW.searchable_text);
DELETE FROM dirtied_formats WHERE book=NEW.book AND format=NEW.format;
END; END;
PRAGMA fts_db.user_version=1; PRAGMA fts_db.user_version=1;

View File

@ -7,6 +7,8 @@ import builtins
import os import os
import sys import sys
from calibre.utils.date import EPOCH, utcnow
from .schema_upgrade import SchemaUpgrade from .schema_upgrade import SchemaUpgrade
# TODO: db dump+restore # TODO: db dump+restore
@ -43,3 +45,16 @@ class FTS:
def clear_all_dirty(self): def clear_all_dirty(self):
conn = self.get_connection() conn = self.get_connection()
conn.execute('DELETE FROM fts_db.dirtied_formats') conn.execute('DELETE FROM fts_db.dirtied_formats')
def add_text(self, book_id, fmt, text, text_hash='', fmt_size=0, fmt_hash=''):
conn = self.get_connection()
ts = (utcnow() - EPOCH).total_seconds()
fmt = fmt.upper()
if text:
conn.execute(
'INSERT OR REPLACE INTO fts_db.books_text '
'(book, timestamp, format, format_size, format_hash, searchable_text, text_size, text_hash) VALUES '
'(?, ?, ?, ?, ?, ?, ?, ?)', (
book_id, ts, fmt, fmt_size, fmt_hash, text, len(text), text_hash))
else:
conn.execute('DELETE FROM fts_db.dirtied_formats WHERE book=? and format=?', (book_id, fmt))

View File

@ -43,6 +43,12 @@ class FTSAPITest(BaseTest):
self.ae(fts.all_currently_dirty(), []) self.ae(fts.all_currently_dirty(), [])
cache.add_format(2, 'ADDED', BytesIO(b'data2')) cache.add_format(2, 'ADDED', BytesIO(b'data2'))
self.ae(fts.all_currently_dirty(), [(2, 'ADDED')]) self.ae(fts.all_currently_dirty(), [(2, 'ADDED')])
fts.add_text(2, 'ADDED', 'data2')
self.ae(fts.all_currently_dirty(), [])
cache.add_format(2, 'ADDED', BytesIO(b'data2'))
self.ae(fts.all_currently_dirty(), [(2, 'ADDED')])
fts.add_text(2, 'ADDED', 'data2')
self.ae(fts.all_currently_dirty(), [])
def find_tests(): def find_tests():