(use-modules (gnu packages) (guix packages) (ice-9 match) (sqlite3) (srfi srfi-26)) (define db (sqlite-open "/tmp/index.sqlite")) (define schema "CREATE VIRTUAL TABLE packages USING fts5(name, description)") (define (build-sqlite-database) (sqlite-exec db schema) (sqlite-exec db "BEGIN") (fold-packages (lambda (package _) (let ((statement (sqlite-prepare db "INSERT INTO packages(name, description) VALUES(:name, :description)"))) (sqlite-bind-arguments statement #:name (package-name package) #:description (package-description package)) (sqlite-fold cons '() statement) (sqlite-finalize statement))) #f) (sqlite-exec db "COMMIT;")) (define (sqlite-retrieve query) (let ((statement (sqlite-prepare db "SELECT name FROM packages WHERE description MATCH :query"))) (sqlite-bind-arguments statement #:query query) (let ((result (sqlite-fold (lambda (v result) (match v (#(name) (cons name result)))) '() statement))) (sqlite-finalize statement) result))) (define (brute-force-retrieve query) "Return names of all packages whose descriptions contain the string QUERY. Search brute force by folding over all packages." (fold-packages (lambda (package result) (if (string-contains (package-description package) query) (cons package result) result)) '())) (define (time-us thunk) (define pair->sec (match-lambda ((sec . usec) (+ sec (/ usec 1e6))))) (let ((start (gettimeofday))) (thunk) (let ((stop (gettimeofday))) (- (pair->sec stop) (pair->sec start))))) (format #t "Sqlite database populated in ~a seconds Brute force search took ~a seconds Sqlite search took ~a seconds " (time-us build-sqlite-database) (time-us (cut brute-force-retrieve "strategy")) (time-us (cut sqlite-retrieve "strategy"))) (sqlite-close db)