Use a unique table name for restriction book ids.

Makes the search atomic allowing multiple searches to be run in parallel
This commit is contained in:
Kovid Goyal 2022-08-02 19:55:49 +05:30
parent 64ea016aa1
commit 9e34ba665f
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C

View File

@ -10,6 +10,7 @@ import os
import sys import sys
from contextlib import suppress from contextlib import suppress
from threading import Lock from threading import Lock
from itertools import count
from calibre.db import FTSQueryError from calibre.db import FTSQueryError
from calibre.db.annotations import unicode_normalize from calibre.db.annotations import unicode_normalize
@ -30,6 +31,7 @@ class FTS:
self.dbref = dbref self.dbref = dbref
self.pool = Pool(dbref) self.pool = Pool(dbref)
self.init_lock = Lock() self.init_lock = Lock()
self.temp_table_counter = count()
def initialize(self, conn): def initialize(self, conn):
needs_dirty = False needs_dirty = False
@ -169,13 +171,17 @@ class FTS:
query += ' WHERE ' query += ' WHERE '
data = [] data = []
conn = self.get_connection() conn = self.get_connection()
temp_table_name = ''
if restrict_to_book_ids: if restrict_to_book_ids:
conn.execute('CREATE TABLE IF NOT EXISTS temp.restrict_fts_items(x INTEGER); DELETE FROM temp.restrict_fts_items;') temp_table_name = f'fts_restrict_search_{next(self.temp_table_counter)}'
conn.executemany('INSERT INTO temp.restrict_fts_items VALUES (?)', tuple((x,) for x in restrict_to_book_ids)) conn.execute(f'CREATE TABLE temp.{temp_table_name}(x INTEGER)')
query += ' fts_db.books_text.book IN temp.restrict_fts_items AND ' conn.executemany(f'INSERT INTO temp.{temp_table_name} VALUES (?)', tuple((x,) for x in restrict_to_book_ids))
query += f' fts_db.books_text.book IN temp.{temp_table_name} AND '
query += f' "{fts_table}" MATCH ?' query += f' "{fts_table}" MATCH ?'
data.append(fts_engine_query) data.append(fts_engine_query)
query += f' ORDER BY {fts_table}.rank ' query += f' ORDER BY {fts_table}.rank '
if temp_table_name:
query += f'; DROP TABLE temp.{temp_table_name}'
try: try:
for record in conn.execute(query, tuple(data)): for record in conn.execute(query, tuple(data)):
ret = yield { ret = yield {