Normalize FTS match expression for search

This commit is contained in:
Jordan Wages 2025-09-18 22:49:06 -05:00
commit d723b57b31

View file

@ -914,9 +914,28 @@
$q.focus(); $q.focus();
} }
function buildSearchMatchExpression(rawInput) {
const trimmed = String(rawInput || '').trim();
if (!trimmed) return '';
// Preserve power user syntax (field scoping, phrase searches, boolean ops)
if (/["':*()^+-]/.test(trimmed)) {
return trimmed;
}
const tokens = trimmed
.split(/\s+/)
.map((token) => token.replace(/[^0-9a-z]/gi, '').toLowerCase())
.filter(Boolean);
if (!tokens.length) return '';
return tokens.map((token) => `${token}*`).join(' ');
}
function runSearchImmediate() { function runSearchImmediate() {
const term = state.query.trim(); const matchExpr = buildSearchMatchExpression(state.query);
if (!term) { if (!matchExpr) {
table.clear(); table.clear();
listState.showIdle('Type to search…'); listState.showIdle('Type to search…');
return; return;
@ -931,10 +950,11 @@
try { try {
console.debug('[Search] Preparing count query', { console.debug('[Search] Preparing count query', {
sql: countSql.trim(), sql: countSql.trim(),
params: [term], params: [matchExpr],
chars: Array.from(matchExpr).map((ch) => ch.codePointAt(0)),
}); });
const countStmt = db.prepare(countSql); const countStmt = db.prepare(countSql);
countStmt.bind([term]); countStmt.bind([matchExpr]);
if (countStmt.step()) { if (countStmt.step()) {
const row = countStmt.getAsObject(); const row = countStmt.getAsObject();
total = Number(row.count) || 0; total = Number(row.count) || 0;
@ -951,10 +971,11 @@
state.page = Math.max(1, Math.ceil(total / state.pageSize)); state.page = Math.max(1, Math.ceil(total / state.pageSize));
} }
const searchParams = [term, state.pageSize, (state.page - 1) * state.pageSize]; const searchParams = [matchExpr, state.pageSize, (state.page - 1) * state.pageSize];
console.debug('[Search] Preparing row query', { console.debug('[Search] Preparing row query', {
sql: effectiveSearchSql.trim(), sql: effectiveSearchSql.trim(),
params: searchParams, params: searchParams,
chars: Array.from(matchExpr).map((ch) => ch.codePointAt(0)),
}); });
const searchStmt = db.prepare(effectiveSearchSql); const searchStmt = db.prepare(effectiveSearchSql);
searchStmt.bind(searchParams); searchStmt.bind(searchParams);