Files
2025-12-24 20:10:38 -08:00

66 lines
1.9 KiB
Python

"""
SQLite FTS5 search backend - search and flush operations.
This module provides the search interface for the SQLite FTS backend.
Environment variables:
SQLITEFTS_DB: Database filename (default: search.sqlite3)
FTS_SEPARATE_DATABASE: Use separate database file (default: true)
FTS_TOKENIZERS: FTS5 tokenizer config (default: porter unicode61 remove_diacritics 2)
"""
import os
import sqlite3
from pathlib import Path
from typing import List, Iterable
from django.conf import settings
# Config with old var names for backwards compatibility
SQLITEFTS_DB = os.environ.get('SQLITEFTS_DB', 'search.sqlite3').strip()
FTS_SEPARATE_DATABASE = os.environ.get('FTS_SEPARATE_DATABASE', 'true').lower() in ('true', '1', 'yes')
FTS_TOKENIZERS = os.environ.get('FTS_TOKENIZERS', 'porter unicode61 remove_diacritics 2').strip()
def get_db_path() -> Path:
"""Get path to the search index database."""
return Path(settings.DATA_DIR) / SQLITEFTS_DB
def search(query: str) -> List[str]:
"""Search for snapshots matching the query."""
db_path = get_db_path()
if not db_path.exists():
return []
conn = sqlite3.connect(str(db_path))
try:
cursor = conn.execute(
'SELECT DISTINCT snapshot_id FROM search_index WHERE search_index MATCH ?',
(query,)
)
return [row[0] for row in cursor.fetchall()]
except sqlite3.OperationalError:
# Table doesn't exist yet
return []
finally:
conn.close()
def flush(snapshot_ids: Iterable[str]) -> None:
"""Remove snapshots from the index."""
db_path = get_db_path()
if not db_path.exists():
return
conn = sqlite3.connect(str(db_path))
try:
for snapshot_id in snapshot_ids:
conn.execute('DELETE FROM search_index WHERE snapshot_id = ?', (snapshot_id,))
conn.commit()
except sqlite3.OperationalError:
pass # Table doesn't exist
finally:
conn.close()