Clean up DB code from previous PR

Note that string literals in SQLITE should be single quoted.
https://sqlite.org/quirks.html#dblquote
This commit is contained in:
Kovid Goyal 2023-03-30 08:37:17 +05:30
parent b3aafddf5a
commit aabd29c571
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 33 additions and 29 deletions

View File

@ -97,6 +97,7 @@ CREATE TABLE identifiers ( id INTEGER PRIMARY KEY,
); );
CREATE TABLE languages ( id INTEGER PRIMARY KEY, CREATE TABLE languages ( id INTEGER PRIMARY KEY,
lang_code TEXT NOT NULL COLLATE NOCASE, lang_code TEXT NOT NULL COLLATE NOCASE,
link TEXT NOT NULL DEFAULT '',
UNIQUE(lang_code) UNIQUE(lang_code)
); );
CREATE TABLE library_id ( id INTEGER PRIMARY KEY, CREATE TABLE library_id ( id INTEGER PRIMARY KEY,
@ -116,19 +117,23 @@ CREATE TABLE preferences(id INTEGER PRIMARY KEY,
CREATE TABLE publishers ( id INTEGER PRIMARY KEY, CREATE TABLE publishers ( id INTEGER PRIMARY KEY,
name TEXT NOT NULL COLLATE NOCASE, name TEXT NOT NULL COLLATE NOCASE,
sort TEXT COLLATE NOCASE, sort TEXT COLLATE NOCASE,
link TEXT NOT NULL DEFAULT '',
UNIQUE(name) UNIQUE(name)
); );
CREATE TABLE ratings ( id INTEGER PRIMARY KEY, CREATE TABLE ratings ( id INTEGER PRIMARY KEY,
rating INTEGER CHECK(rating > -1 AND rating < 11), rating INTEGER CHECK(rating > -1 AND rating < 11),
link TEXT NOT NULL DEFAULT '',
UNIQUE (rating) UNIQUE (rating)
); );
CREATE TABLE series ( id INTEGER PRIMARY KEY, CREATE TABLE series ( id INTEGER PRIMARY KEY,
name TEXT NOT NULL COLLATE NOCASE, name TEXT NOT NULL COLLATE NOCASE,
sort TEXT COLLATE NOCASE, sort TEXT COLLATE NOCASE,
link TEXT NOT NULL DEFAULT '',
UNIQUE (name) UNIQUE (name)
); );
CREATE TABLE tags ( id INTEGER PRIMARY KEY, CREATE TABLE tags ( id INTEGER PRIMARY KEY,
name TEXT NOT NULL COLLATE NOCASE, name TEXT NOT NULL COLLATE NOCASE,
link TEXT NOT NULL DEFAULT '',
UNIQUE (name) UNIQUE (name)
); );
CREATE TABLE last_read_positions ( id INTEGER PRIMARY KEY, CREATE TABLE last_read_positions ( id INTEGER PRIMARY KEY,
@ -633,4 +638,4 @@ CREATE TRIGGER series_update_trg
BEGIN BEGIN
UPDATE series SET sort=title_sort(NEW.name) WHERE id=NEW.id; UPDATE series SET sort=title_sort(NEW.name) WHERE id=NEW.id;
END; END;
pragma user_version=25; pragma user_version=26;

View File

@ -2341,10 +2341,7 @@ class Cache:
@read_api @read_api
def has_link_map(self, field): def has_link_map(self, field):
if field not in self.fields: return hasattr(getattr(self.fields.get(field), 'table', None), 'link_map')
raise ValueError(f'Lookup name {field} is not a valid name')
table = self.fields[field].table
return hasattr(table, 'link_map')
@read_api @read_api
def get_link_map(self, for_field): def get_link_map(self, for_field):
@ -2358,11 +2355,12 @@ class Cache:
if for_field not in self.fields: if for_field not in self.fields:
raise ValueError(f'Lookup name {for_field} is not a valid name') raise ValueError(f'Lookup name {for_field} is not a valid name')
table = self.fields[for_field].table table = self.fields[for_field].table
if not hasattr(table, 'link_map'): lm = getattr(table, 'link_map', None)
if lm is None:
raise ValueError(f"Lookup name {for_field} doesn't have a link map") raise ValueError(f"Lookup name {for_field} doesn't have a link map")
lm = table.link_map lm = table.link_map
vm = table.id_map vm = table.id_map
return dict({vm.get(fid, None):v for fid,v in lm.items() if v}) return {vm.get(fid):v for fid,v in lm.items() if v}
@read_api @read_api
def get_all_link_maps_for_book(self, book_id): def get_all_link_maps_for_book(self, book_id):
@ -2381,21 +2379,22 @@ class Cache:
If book 2's author is neither A nor B and has no tags, this If book 2's author is neither A nor B and has no tags, this
method returns {} method returns {}
''' '''
if book_id in self.link_maps_cache: cached = self.link_maps_cache.get(book_id)
return self.link_maps_cache[book_id] if cached is not None:
return cached
links = {} links = {}
def add_links_for_field(f): def add_links_for_field(f):
field_ids = frozenset(self.field_ids_for(f, book_id)) field_ids = frozenset(self.field_ids_for(f, book_id))
table = self.fields[f].table table = self.fields[f].table
lm = table.link_map lm = table.link_map
vm = table.id_map vm = table.id_map
d = dict({vm.get(fid, None):v for fid,v in lm.items() if v and fid in field_ids}) d = {vm.get(fid):v for fid,v in lm.items() if v and fid in field_ids}
if d: if d:
links[f] = d links[f] = d
for field in ('authors', 'publisher', 'series', 'tags'): for field in ('authors', 'publisher', 'series', 'tags'):
add_links_for_field(field) add_links_for_field(field)
for field in self.field_metadata.custom_field_keys(include_composites=False): for field in self.field_metadata.custom_field_keys(include_composites=False):
if self.has_link_map(field): if self._has_link_map(field):
add_links_for_field(field) add_links_for_field(field)
self.link_maps_cache[book_id] = links self.link_maps_cache[book_id] = links
return links return links
@ -2415,8 +2414,8 @@ class Cache:
''' '''
if field not in self.fields: if field not in self.fields:
raise ValueError(f'Lookup name {field} is not a valid name') raise ValueError(f'Lookup name {field} is not a valid name')
table = self.fields[field].table table = getattr(self.fields[field], 'table', None)
if not hasattr(table, 'link_map'): if table is None:
raise ValueError(f"Lookup name {field} doesn't have a link map") raise ValueError(f"Lookup name {field} doesn't have a link map")
# Clear the links for book cache as we don't know what will be affected # Clear the links for book cache as we don't know what will be affected
self.link_maps_cache = {} self.link_maps_cache = {}

View File

@ -810,14 +810,13 @@ CREATE TRIGGER fkc_annot_update
} }
if data['normalized']: if data['normalized']:
tn = 'custom_column_{}'.format(data['num']) tn = 'custom_column_{}'.format(data['num'])
alters.append(f'ALTER TABLE {tn} ADD COLUMN link TEXT NOT NULL DEFAULT "";') alters.append(f"ALTER TABLE {tn} ADD COLUMN link TEXT NOT NULL DEFAULT '';")
alters.append('ALTER TABLE publishers ADD COLUMN link TEXT NOT NULL DEFAULT "";') alters.append("ALTER TABLE publishers ADD COLUMN link TEXT NOT NULL DEFAULT '';")
alters.append('ALTER TABLE series ADD COLUMN link TEXT NOT NULL DEFAULT "";') alters.append("ALTER TABLE series ADD COLUMN link TEXT NOT NULL DEFAULT '';")
alters.append('ALTER TABLE tags ADD COLUMN link TEXT NOT NULL DEFAULT "";') alters.append("ALTER TABLE tags ADD COLUMN link TEXT NOT NULL DEFAULT '';")
# These aren't necessary in that there is no UI to set links, but having them # These aren't necessary in that there is no UI to set links, but having them
# makes the code uniform # makes the code uniform
alters.append('ALTER TABLE languages ADD COLUMN link TEXT NOT NULL DEFAULT "";') alters.append("ALTER TABLE languages ADD COLUMN link TEXT NOT NULL DEFAULT '';")
alters.append('ALTER TABLE ratings ADD COLUMN link TEXT NOT NULL DEFAULT "";') alters.append("ALTER TABLE ratings ADD COLUMN link TEXT NOT NULL DEFAULT '';")
self.db.execute('\n'.join(alters)) self.db.execute('\n'.join(alters))

View File

@ -16,6 +16,9 @@ from calibre_extensions.speedup import parse_date as _c_speedup
from polyglot.builtins import iteritems, itervalues from polyglot.builtins import iteritems, itervalues
def identity(x):
return x
def c_parse(val): def c_parse(val):
try: try:
year, month, day, hour, minutes, seconds, tzsecs = _c_speedup(val) year, month, day, hour, minutes, seconds, tzsecs = _c_speedup(val)
@ -208,10 +211,7 @@ class ManyToOneTable(Table):
def read_id_maps(self, db): def read_id_maps(self, db):
query = db.execute('SELECT id, {}, link FROM {}'.format( query = db.execute('SELECT id, {}, link FROM {}'.format(
self.metadata['column'], self.metadata['table'])) self.metadata['column'], self.metadata['table']))
if self.unserialize is None: us = identity if self.unserialize is None else self.unserialize
us = lambda x: x
else:
us = self.unserialize
for id_, val, link in query: for id_, val, link in query:
self.id_map[id_] = us(val) self.id_map[id_] = us(val)
self.link_map[id_] = link self.link_map[id_] = link
@ -347,11 +347,12 @@ class ManyToOneTable(Table):
return affected_books, new_id return affected_books, new_id
def set_links(self, link_map, db): def set_links(self, link_map, db):
link_map = {id_:(l or '').strip() for id_, l in iteritems(link_map)} link_map = {id_:(l or '').strip() for id_, l in link_map.items()}
link_map = {id_:l for id_, l in iteritems(link_map) if l != self.link_map.get(id_)} link_map = {id_:l for id_, l in link_map.items() if l != self.link_map.get(id_)}
self.link_map.update(link_map) if link_map:
db.executemany(f'UPDATE {self.metadata["table"]} SET link=? WHERE id=?', self.link_map.update(link_map)
[(v, k) for k, v in iteritems(link_map)]) db.executemany(f'UPDATE {self.metadata["table"]} SET link=? WHERE id=?',
tuple((v, k) for k, v in link_map.items()))
return link_map return link_map

Binary file not shown.