Implement retiring of notes when setting a field on a book causes an item to be deleted

This commit is contained in:
Kovid Goyal 2023-08-17 20:22:28 +05:30
parent 45f7599eee
commit 1ae94801e6
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 33 additions and 7 deletions

View File

@ -949,9 +949,12 @@ class DB:
from .notes.connect import Notes from .notes.connect import Notes
self.notes = Notes(self) self.notes = Notes(self)
def delete_category_items(self, field_name, table_name, item_map, link_table_name='', link_col_name=''): def clear_notes_for_category_items(self, field_name, item_map):
for item_id, item_val in item_map.items(): for item_id, item_val in item_map.items():
self.notes.set_note(self.conn, field_name, item_id, item_val or '') self.notes.set_note(self.conn, field_name, item_id, item_val or '')
def delete_category_items(self, field_name, table_name, item_map, link_table_name='', link_col_name=''):
self.clear_notes_for_category_items(field_name, item_map)
bindings = tuple((x,) for x in item_map) bindings = tuple((x,) for x in item_map)
if link_table_name and link_col_name: if link_table_name and link_col_name:
self.executemany(f'DELETE FROM {link_table_name} WHERE {link_col_name}=?', bindings) self.executemany(f'DELETE FROM {link_table_name} WHERE {link_col_name}=?', bindings)

View File

@ -58,13 +58,37 @@ def test_notes_api(self: 'NotesTest'):
def test_cache_api(self): def test_cache_api(self):
cache, notes = self.create_notes_db() cache, notes = self.create_notes_db()
authors = cache.field_for('authors', 1)
author_id = cache.get_item_id('authors', authors[0])
doc = 'simple notes for an author'
h1 = cache.add_notes_resource(b'resource1', 'r1.jpg')
h2 = cache.add_notes_resource(b'resource2', 'r1.jpg')
cache.set_notes_for('authors', author_id, doc, resource_ids=(h1, h2))
# test renaming to a new author preserves notes
cache.rename_items('authors', {author_id: 'renamed author'})
raid = cache.get_item_id('authors', 'renamed author')
self.ae(cache.notes_resources_used_by('authors', raid), frozenset({h1, h2}))
self.ae(cache.get_notes_resource(h1)['data'], b'resource1')
self.ae(cache.get_notes_resource(h2)['data'], b'resource2')
# test renaming to an existing author preserves notes
cache.rename_items('authors', {raid: 'Author One'})
raid = cache.get_item_id('authors', 'Author One')
self.ae(cache.notes_resources_used_by('authors', raid), frozenset({h1, h2}))
self.ae(cache.get_notes_resource(h1)['data'], b'resource1')
self.ae(cache.get_notes_resource(h2)['data'], b'resource2')
# test removing author from db retires notes
cache.set_field('authors', {bid:('New Author',) for bid in cache.all_book_ids()})
self.ae(len(cache.all_field_ids('authors')), 1)
before = os.listdir(notes.retired_dir)
self.ae(len(before), 1)
class NotesTest(BaseTest): class NotesTest(BaseTest):
ae = BaseTest.assertEqual ae = BaseTest.assertEqual
def create_notes_db(self): def create_notes_db(self):
cache = self.init_cache() cache = self.init_cache(self.cloned_library)
cache.backend.notes.max_retired_items = 1 cache.backend.notes.max_retired_items = 1
return cache, cache.backend.notes return cache, cache.backend.notes

View File

@ -378,9 +378,9 @@ def many_one(book_id_val_map, db, field, allow_case_change, *args):
iteritems(updated))) iteritems(updated)))
# Remove no longer used items # Remove no longer used items
remove = {item_id for item_id in table.id_map if not remove = {item_id:item_val for item_id, item_val in table.id_map.items() if not table.col_book_map.get(item_id, False)}
table.col_book_map.get(item_id, False)}
if remove: if remove:
db.clear_notes_for_category_items(table.name, remove)
db.executemany('DELETE FROM %s WHERE id=?'%m['table'], db.executemany('DELETE FROM %s WHERE id=?'%m['table'],
((item_id,) for item_id in remove)) ((item_id,) for item_id in remove))
for item_id in remove: for item_id in remove:
@ -482,9 +482,9 @@ def many_many(book_id_val_map, db, field, allow_case_change, *args):
field.author_sort_field.writer.set_books(aus_map, db) field.author_sort_field.writer.set_books(aus_map, db)
# Remove no longer used items # Remove no longer used items
remove = {item_id for item_id in table.id_map if not remove = {item_id:item_val for item_id, item_val in table.id_map.items() if not table.col_book_map.get(item_id, False)}
table.col_book_map.get(item_id, False)}
if remove: if remove:
db.clear_notes_for_category_items(table.name, remove)
db.executemany('DELETE FROM %s WHERE id=?'%m['table'], db.executemany('DELETE FROM %s WHERE id=?'%m['table'],
((item_id,) for item_id in remove)) ((item_id,) for item_id in remove))
for item_id in remove: for item_id in remove:
@ -494,7 +494,6 @@ def many_many(book_id_val_map, db, field, allow_case_change, *args):
table.asort_map.pop(item_id, None) table.asort_map.pop(item_id, None)
if hasattr(table, 'link_map'): if hasattr(table, 'link_map'):
table.link_map.pop(item_id, None) table.link_map.pop(item_id, None)
return dirtied return dirtied
# }}} # }}}