diff --git a/script.js b/script.js index 67c3fc6..c06bdc5 100644 --- a/script.js +++ b/script.js @@ -282,16 +282,6 @@ return `${hz.toLocaleString()} Hz`; } - function escapeSqlText(value) { - return `'${String(value).replace(/'/g, "''")}'`; - } - - function applyFtsMatch(sql, matchExpr) { - const placeholder = 'MATCH ?'; - if (!sql.includes(placeholder)) throw new Error('Expected FTS MATCH placeholder'); - return sql.replace(placeholder, `MATCH ${escapeSqlText(matchExpr)}`); - } - async function unzipSqlite(zipBytes) { loader.setStep('Unpacking database…'); loader.setDetail('Decompressing ZIP'); @@ -960,10 +950,11 @@ try { console.debug('[Search] Preparing count query', { sql: countSql.trim(), - ftsExpr: matchExpr, + params: [matchExpr], chars: Array.from(matchExpr).map((ch) => ch.codePointAt(0)), }); - const countStmt = db.prepare(applyFtsMatch(countSql, matchExpr)); + const countStmt = db.prepare(countSql); + countStmt.bind([matchExpr]); if (countStmt.step()) { const row = countStmt.getAsObject(); total = Number(row.count) || 0; @@ -980,14 +971,13 @@ state.page = Math.max(1, Math.ceil(total / state.pageSize)); } - const searchParams = [state.pageSize, (state.page - 1) * state.pageSize]; + const searchParams = [matchExpr, state.pageSize, (state.page - 1) * state.pageSize]; console.debug('[Search] Preparing row query', { sql: effectiveSearchSql.trim(), - ftsExpr: matchExpr, params: searchParams, chars: Array.from(matchExpr).map((ch) => ch.codePointAt(0)), }); - const searchStmt = db.prepare(applyFtsMatch(effectiveSearchSql, matchExpr)); + const searchStmt = db.prepare(effectiveSearchSql); searchStmt.bind(searchParams); const nextRows = []; while (searchStmt.step()) { @@ -1194,14 +1184,15 @@ try { if (ftsMatch) { - const ftsCountStmt = db.prepare(applyFtsMatch(ftsCountSql, ftsMatch)); + const ftsCountStmt = db.prepare(ftsCountSql); + ftsCountStmt.bind([ftsMatch]); if (ftsCountStmt.step()) total = Number(ftsCountStmt.getAsObject().count) || 0; ftsCountStmt.free(); if (total > 0) { if (offset >= total) state.page = Math.max(1, Math.ceil(total / state.pageSize)); - const ftsRowsStmt = db.prepare(applyFtsMatch(ftsRowsSql, ftsMatch)); - ftsRowsStmt.bind([state.pageSize, (state.page - 1) * state.pageSize]); + const ftsRowsStmt = db.prepare(ftsRowsSql); + ftsRowsStmt.bind([ftsMatch, state.pageSize, (state.page - 1) * state.pageSize]); while (ftsRowsStmt.step()) rows.push(ftsRowsStmt.getAsObject()); ftsRowsStmt.free(); usedFts = true;