resplite 1.4.12 → 1.4.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -154,7 +154,11 @@ export function addDocument(db, idx, docId, score, replace, fields) {
|
|
|
154
154
|
let ftsRowid;
|
|
155
155
|
if (existing) {
|
|
156
156
|
if (!replace) throw new Error('ERR document exists');
|
|
157
|
-
|
|
157
|
+
// FTS5 contentless bug: INSERT OR REPLACE doesn't remove old tokens.
|
|
158
|
+
// Solution: assign a new fts_rowid to avoid token pollution.
|
|
159
|
+
const maxRow = db.prepare(`SELECT COALESCE(MAX(fts_rowid), 0) AS m FROM ${docmapT}`).get();
|
|
160
|
+
ftsRowid = maxRow.m + 1;
|
|
161
|
+
db.prepare(`UPDATE ${docmapT} SET fts_rowid = ? WHERE doc_id = ?`).run(ftsRowid, docId);
|
|
158
162
|
} else {
|
|
159
163
|
const maxRow = db.prepare(`SELECT COALESCE(MAX(fts_rowid), 0) AS m FROM ${docmapT}`).get();
|
|
160
164
|
ftsRowid = maxRow.m + 1;
|
|
@@ -172,12 +176,12 @@ export function addDocument(db, idx, docId, score, replace, fields) {
|
|
|
172
176
|
).run(docId, score, fieldsJson, now, now);
|
|
173
177
|
}
|
|
174
178
|
|
|
175
|
-
// FTS5 contentless:
|
|
179
|
+
// FTS5 contentless: insert with new rowid (old rowid becomes orphaned and won't match via docmap join).
|
|
176
180
|
const ftsColumns = ['rowid', ...fieldNames.sort()];
|
|
177
181
|
const ftsValues = [ftsRowid, ...fieldNames.sort().map((f) => fields[f] ?? '')];
|
|
178
182
|
const placeholders = ftsValues.map(() => '?').join(', ');
|
|
179
183
|
const colList = ftsColumns.join(', ');
|
|
180
|
-
db.prepare(`INSERT
|
|
184
|
+
db.prepare(`INSERT INTO ${ftsT}(${colList}) VALUES (${placeholders})`).run(...ftsValues);
|
|
181
185
|
});
|
|
182
186
|
|
|
183
187
|
run();
|
|
@@ -196,6 +196,40 @@ describe('Search integration', () => {
|
|
|
196
196
|
const err = v?.error ?? v;
|
|
197
197
|
assert.ok(String(err).includes('Unknown index name'));
|
|
198
198
|
});
|
|
199
|
+
|
|
200
|
+
it('FT.SEARCH prefix query should not match unrelated terms', async () => {
|
|
201
|
+
// Create a fresh index for this test
|
|
202
|
+
await sendCommand(port, argv('FT.CREATE', 'bugtest', 'SCHEMA', 'payload', 'TEXT'));
|
|
203
|
+
|
|
204
|
+
// Add document with "gorge" first
|
|
205
|
+
await sendCommand(port, argv('FT.ADD', 'bugtest', 'DOC1', '1', 'REPLACE', 'FIELDS', 'payload', 'gorge'));
|
|
206
|
+
|
|
207
|
+
// Verify it matches gorge*
|
|
208
|
+
const gorge1 = await sendCommand(port, argv('FT.SEARCH', 'bugtest', 'gorge*', 'NOCONTENT', 'LIMIT', '0', '10'));
|
|
209
|
+
const g1 = tryParseValue(gorge1, 0).value;
|
|
210
|
+
assert.equal(g1[0], 1, 'gorge* should match gorge');
|
|
211
|
+
assert.equal(g1[1].toString?.('utf8') ?? g1[1], 'DOC1');
|
|
212
|
+
|
|
213
|
+
// Replace with "martan"
|
|
214
|
+
await sendCommand(port, argv('FT.ADD', 'bugtest', 'DOC1', '1', 'REPLACE', 'FIELDS', 'payload', 'martan'));
|
|
215
|
+
|
|
216
|
+
// Verify FT.GET shows only martan
|
|
217
|
+
const get = await sendCommand(port, argv('FT.GET', 'bugtest', 'DOC1'));
|
|
218
|
+
const getArr = tryParseValue(get, 0).value;
|
|
219
|
+
assert.equal(getArr[0].toString?.('utf8') ?? getArr[0], 'payload');
|
|
220
|
+
assert.equal(getArr[1].toString?.('utf8') ?? getArr[1], 'martan');
|
|
221
|
+
|
|
222
|
+
// martan* should match
|
|
223
|
+
const martan = await sendCommand(port, argv('FT.SEARCH', 'bugtest', 'martan*', 'NOCONTENT', 'LIMIT', '0', '10'));
|
|
224
|
+
const m = tryParseValue(martan, 0).value;
|
|
225
|
+
assert.equal(m[0], 1, 'martan* should match martan');
|
|
226
|
+
assert.equal(m[1].toString?.('utf8') ?? m[1], 'DOC1');
|
|
227
|
+
|
|
228
|
+
// gorge* should NOT match martan
|
|
229
|
+
const gorge2 = await sendCommand(port, argv('FT.SEARCH', 'bugtest', 'gorge*', 'NOCONTENT', 'LIMIT', '0', '10'));
|
|
230
|
+
const g2 = tryParseValue(gorge2, 0).value;
|
|
231
|
+
assert.equal(g2[0], 0, 'gorge* should NOT match martan - this is the bug');
|
|
232
|
+
});
|
|
199
233
|
});
|
|
200
234
|
|
|
201
235
|
describe('Search persistence', () => {
|