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