From 1c9c2daf83546619f36c7309d46a44fce2806848 Mon Sep 17 00:00:00 2001 From: Matt Westcott <matt@west.co.tt> Date: Wed, 12 Jan 2022 11:57:03 +0000 Subject: [PATCH] Warn and use fallback backend if fts5 is available but the index table is missing This scenario will happen if sqlite has been upgraded to a version with fts5 support since wagtailsearch migration 0006 was run. --- wagtail/search/backends/database/__init__.py | 25 +++++++++++++++++-- .../search/backends/database/sqlite/utils.py | 13 ++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/wagtail/search/backends/database/__init__.py b/wagtail/search/backends/database/__init__.py index 6e181b2b31..255eda268b 100644 --- a/wagtail/search/backends/database/__init__.py +++ b/wagtail/search/backends/database/__init__.py @@ -1,6 +1,11 @@ +import warnings + from django.db import connection +USE_SQLITE_FTS = None # True if sqlite FTS is available, False if not, None if untested + + def SearchBackend(params): """ Returns the appropriate search backend for the current 'default' database system @@ -12,8 +17,24 @@ def SearchBackend(params): from .mysql.mysql import MySQLSearchBackend return MySQLSearchBackend(params) elif connection.vendor == 'sqlite': - from .sqlite.utils import fts5_available - if fts5_available(): + global USE_SQLITE_FTS + + if USE_SQLITE_FTS is None: + from .sqlite.utils import fts5_available, fts_table_exists + if not fts5_available(): + USE_SQLITE_FTS = False + elif not fts_table_exists(): + USE_SQLITE_FTS = False + warnings.warn( + "The installed SQLite library supports full-text search, but the table for storing " + "searchable content is missing. This probably means SQLite was upgraded after the " + "migration was applied. To enable full-text search, reapply wagtailsearch migration 0006 " + "or create the table manually." + ) + else: + USE_SQLITE_FTS = True + + if USE_SQLITE_FTS: from .sqlite.sqlite import SQLiteSearchBackend return SQLiteSearchBackend(params) else: diff --git a/wagtail/search/backends/database/sqlite/utils.py b/wagtail/search/backends/database/sqlite/utils.py index fb4e0326f3..cb9a75171c 100644 --- a/wagtail/search/backends/database/sqlite/utils.py +++ b/wagtail/search/backends/database/sqlite/utils.py @@ -20,3 +20,16 @@ def fts5_available(): tmp_db.close() return True + + +def fts_table_exists(): + from wagtail.search.models import SQLiteFTSIndexEntry + + try: + # ignore result of query; we are only interested in the query failing, + # not the presence of index entries + SQLiteFTSIndexEntry.objects.exists() + except OperationalError: + return False + + return True