newdb: Optimize setting the same value as before for author data

Do not mark books as dirty if the same value as before is set for
author_sort or author_link.
This commit is contained in:
Kovid Goyal 2013-08-27 09:18:36 +05:30
parent f542b8babe
commit c281600581
3 changed files with 30 additions and 6 deletions

View File

@ -1531,11 +1531,11 @@ class Cache(object):
@write_api @write_api
def set_sort_for_authors(self, author_id_to_sort_map, update_books=True): def set_sort_for_authors(self, author_id_to_sort_map, update_books=True):
self.fields['authors'].table.set_sort_names(author_id_to_sort_map, self.backend) sort_map = self.fields['authors'].table.set_sort_names(author_id_to_sort_map, self.backend)
changed_books = set() changed_books = set()
if update_books: if update_books:
val_map = {} val_map = {}
for author_id in author_id_to_sort_map: for author_id in sort_map:
books = self._books_for_field('authors', author_id) books = self._books_for_field('authors', author_id)
changed_books |= books changed_books |= books
for book_id in books: for book_id in books:
@ -1545,16 +1545,18 @@ class Cache(object):
val_map[book_id] = ' & '.join(sorts) val_map[book_id] = ' & '.join(sorts)
if val_map: if val_map:
self._set_field('author_sort', val_map) self._set_field('author_sort', val_map)
self._mark_as_dirty(changed_books) if changed_books:
self._mark_as_dirty(changed_books)
return changed_books return changed_books
@write_api @write_api
def set_link_for_authors(self, author_id_to_link_map): def set_link_for_authors(self, author_id_to_link_map):
self.fields['authors'].table.set_links(author_id_to_link_map, self.backend) link_map = self.fields['authors'].table.set_links(author_id_to_link_map, self.backend)
changed_books = set() changed_books = set()
for author_id in author_id_to_link_map: for author_id in link_map:
changed_books |= self._books_for_field('authors', author_id) changed_books |= self._books_for_field('authors', author_id)
self._mark_as_dirty(changed_books) if changed_books:
self._mark_as_dirty(changed_books)
return changed_books return changed_books
@read_api @read_api

View File

@ -366,15 +366,19 @@ class AuthorsTable(ManyToManyTable):
def set_sort_names(self, aus_map, db): def set_sort_names(self, aus_map, db):
aus_map = {aid:(a or '').strip() for aid, a in aus_map.iteritems()} aus_map = {aid:(a or '').strip() for aid, a in aus_map.iteritems()}
aus_map = {aid:a for aid, a in aus_map.iteritems() if a != self.asort_map.get(aid, None)}
self.asort_map.update(aus_map) self.asort_map.update(aus_map)
db.conn.executemany('UPDATE authors SET sort=? WHERE id=?', db.conn.executemany('UPDATE authors SET sort=? WHERE id=?',
[(v, k) for k, v in aus_map.iteritems()]) [(v, k) for k, v in aus_map.iteritems()])
return aus_map
def set_links(self, link_map, db): def set_links(self, link_map, db):
link_map = {aid:(l or '').strip() for aid, l in link_map.iteritems()} link_map = {aid:(l or '').strip() for aid, l in link_map.iteritems()}
link_map = {aid:l for aid, l in link_map.iteritems() if l != self.alink_map.get(aid, None)}
self.alink_map.update(link_map) self.alink_map.update(link_map)
db.conn.executemany('UPDATE authors SET link=? WHERE id=?', db.conn.executemany('UPDATE authors SET link=? WHERE id=?',
[(v, k) for k, v in link_map.iteritems()]) [(v, k) for k, v in link_map.iteritems()])
return link_map
def remove_books(self, book_ids, db): def remove_books(self, book_ids, db):
clean = ManyToManyTable.remove_books(self, book_ids, db) clean = ManyToManyTable.remove_books(self, book_ids, db)

View File

@ -607,3 +607,21 @@ class WritingTest(BaseTest):
cache = self.init_cache() cache = self.init_cache()
self.assertEqual(cache.all_book_ids(), all_ids, 'dump and restore broke database') self.assertEqual(cache.all_book_ids(), all_ids, 'dump and restore broke database')
# }}} # }}}
def test_set_author_data(self): # {{{
cache = self.init_cache()
adata = cache.author_data()
ldata = {aid:str(aid) for aid in adata}
self.assertEqual({1,2,3}, cache.set_link_for_authors(ldata))
for c in (cache, self.init_cache()):
self.assertEqual(ldata, {aid:d['link'] for aid, d in c.author_data().iteritems()})
self.assertEqual({3}, cache.set_link_for_authors({aid:'xxx' if aid == max(adata) else str(aid) for aid in adata}),
'Setting the author link to the same value as before, incorrectly marked some books as dirty')
sdata = {aid:'%s, changed' % aid for aid in adata}
self.assertEqual({1,2,3}, cache.set_sort_for_authors(sdata))
for bid in (1, 2, 3):
self.assertIn(', changed', cache.field_for('author_sort', bid))
sdata = {aid:'%s, changed' % (aid*2 if aid == max(adata) else aid) for aid in adata}
self.assertEqual({3}, cache.set_sort_for_authors(sdata),
'Setting the author sort to the same value as before, incorrectly marked some books as dirty')
# }}}