AtlatestRepositoryfolio
1
;;; FTS replacement must remove every literal-name row, including legacy rows.2
(import (sigil test)3
(sigil fs)4
(sigil path)5
(sigil sqlite)6
(folio store)7
(folio index))9
(test-group "literal FTS replacement"10
(test "updates and removal preserve unrelated names, arbitrary rowids and tokenless names"11
(call-with-temp-directory12
(lambda (root)13
(let* ((store (make-folio-store root))14
(idx (make-folio-index store))15
(db (folio-index-db idx)))16
(for-each17
(lambda (name)18
(let* ((path (path-join (store-notes-dir store)19
(string-append name ".md")))20
(sibling (string-append "guard-" name)))21
(write-file-string path "# Before\nbeforeword\n")22
(index-note! idx path)23
;; Standalone FTS rowids are unrelated to notes_meta rowids.24
;; Old/concurrent versions can leave more than one FTS row.25
(assert-true26
(sqlite-run db27
"INSERT INTO notes_fts (name, title, tags, content) VALUES (?, ?, '', 'staleword')"28
name name))29
(assert-true30
(sqlite-run db31
"INSERT INTO notes_fts (name, title, tags, content) VALUES (?, ?, '', 'guardword')"32
sibling name))33
(write-file-string path "# After\nafterword\n")34
(index-note! idx path)35
(let ((rows (sqlite-query db36
"SELECT content FROM notes_fts WHERE name = ?" name)))37
(assert-equal 1 (length rows))38
(assert-equal "# After\nafterword\n" (cdr (assoc 'content (car rows)))))39
(assert-equal 140
(length (sqlite-query db "SELECT rowid FROM notes_fts WHERE name = ?" sibling)))41
(remove-note-from-index! idx name)42
(assert-equal '()43
(sqlite-query db "SELECT rowid FROM notes_fts WHERE name = ?" name))44
(assert-equal 145
(length (sqlite-query db "SELECT rowid FROM notes_fts WHERE name = ?" sibling)))))46
'("normal" "a\"quoted" "中文" "---" "😀" "Case-Fold" "a.b" "with space"))47
(sqlite-close db)))))49
(test "a failed indexed lookup falls back to literal-name replacement"50
(call-with-temp-directory51
(lambda (root)52
(let* ((store (make-folio-store root))53
(idx (make-folio-index store))54
(db (folio-index-db idx))55
(path (path-join (store-notes-dir store) "one.md")))56
;; This table accepts the old literal DELETE but cannot run MATCH.57
;; It injects a lookup failure independently of note tokenization.58
(assert-true (sqlite-exec db "DROP TABLE notes_fts"))59
(assert-true60
(sqlite-exec db61
"CREATE TABLE notes_fts (name TEXT, title TEXT, tags TEXT, content TEXT)"))62
(assert-true63
(sqlite-run db64
"INSERT INTO notes_fts VALUES ('one', 'Old', '', 'staleword')"))65
(write-file-string path "# One\nafterword\n")66
(index-note! idx path)67
(let ((rows (sqlite-query db "SELECT content FROM notes_fts WHERE name = 'one'")))68
(assert-equal 1 (length rows))69
(assert-equal "# One\nafterword\n" (cdr (assoc 'content (car rows)))))70
(sqlite-close db))))))