store: database: Stop finalizing prepared statements.

Especially since we're asking for these to be cached.

Management of prepared statements isn't trivial, since you don't want to keep
them forever as this can lead to poor query performance, but I don't think
that finalizing them immediately is the right solution.

Change-Id: I61706b4d09d771835bb8f074b8f6a6ee871f5e2d

* guix/store/database.scm (sqlite-step-and-reset): New procedure.
(last-insert-row, path-id, update-or-insert, add-references): Don't finalize
prepared statements.

Change-Id: I2a2c6deb43935d67df9e43000a5105343d72b3e6
This commit is contained in:
Christopher Baines 2024-02-18 13:38:17 +00:00
parent cdd4a0c3c9
commit 511d68c71d
No known key found for this signature in database
GPG Key ID: 5E28A33B0B84F577
1 changed files with 18 additions and 22 deletions

View File

@ -167,16 +167,19 @@ If FILE doesn't exist, create it and initialize it as a new database. Pass
((_ file db exp ...) ((_ file db exp ...)
(call-with-database file (lambda (db) exp ...))))) (call-with-database file (lambda (db) exp ...)))))
(define (sqlite-step-and-reset statement)
(let ((val (sqlite-step statement)))
(sqlite-reset statement)
val))
(define (last-insert-row-id db) (define (last-insert-row-id db)
;; XXX: (sqlite3) currently lacks bindings for 'sqlite3_last_insert_rowid'. ;; XXX: (sqlite3) currently lacks bindings for 'sqlite3_last_insert_rowid'.
;; Work around that. ;; Work around that.
(let* ((stmt (sqlite-prepare db "SELECT last_insert_rowid();" (let ((stmt (sqlite-prepare db
#:cache? #t)) "SELECT last_insert_rowid();"
(result (sqlite-fold cons '() stmt))) #:cache? #t)))
(sqlite-finalize stmt) (vector-ref (sqlite-step-and-reset stmt)
(match result 0)))
((#(id)) id)
(_ #f))))
(define* (path-id db path) (define* (path-id db path)
"If PATH exists in the 'ValidPaths' table, return its numerical "If PATH exists in the 'ValidPaths' table, return its numerical
@ -187,11 +190,9 @@ identifier. Otherwise, return #f."
SELECT id FROM ValidPaths WHERE path = :path" SELECT id FROM ValidPaths WHERE path = :path"
#:cache? #t))) #:cache? #t)))
(sqlite-bind-arguments stmt #:path path) (sqlite-bind-arguments stmt #:path path)
(let ((result (sqlite-fold cons '() stmt))) (match (sqlite-step-and-reset stmt)
(sqlite-finalize stmt) (#(id) id)
(match result (#f #f))))
((#(id) . _) id)
(_ #f)))))
(define-inlinable (assert-integer proc in-range? key number) (define-inlinable (assert-integer proc in-range? key number)
(unless (integer? number) (unless (integer? number)
@ -225,9 +226,8 @@ WHERE id = :id"
(sqlite-bind-arguments stmt #:id id (sqlite-bind-arguments stmt #:id id
#:deriver deriver #:deriver deriver
#:hash hash #:size nar-size #:time time) #:hash hash #:size nar-size #:time time)
(sqlite-fold cons '() stmt) (sqlite-step-and-reset stmt)
(sqlite-finalize stmt) id)
(last-insert-row-id db))
(let ((stmt (sqlite-prepare (let ((stmt (sqlite-prepare
db db
" "
@ -237,8 +237,7 @@ VALUES (:path, :hash, :time, :deriver, :size)"
(sqlite-bind-arguments stmt (sqlite-bind-arguments stmt
#:path path #:deriver deriver #:path path #:deriver deriver
#:hash hash #:size nar-size #:time time) #:hash hash #:size nar-size #:time time)
(sqlite-fold cons '() stmt) ;execute it (sqlite-step-and-reset stmt)
(sqlite-finalize stmt)
(last-insert-row-id db))))) (last-insert-row-id db)))))
(define (add-references db referrer references) (define (add-references db referrer references)
@ -251,13 +250,10 @@ INSERT OR REPLACE INTO Refs (referrer, reference)
VALUES (:referrer, :reference)" VALUES (:referrer, :reference)"
#:cache? #t))) #:cache? #t)))
(for-each (lambda (reference) (for-each (lambda (reference)
(sqlite-reset stmt)
(sqlite-bind-arguments stmt #:referrer referrer (sqlite-bind-arguments stmt #:referrer referrer
#:reference reference) #:reference reference)
(sqlite-fold cons '() stmt) ;execute it (sqlite-step-and-reset stmt))
(last-insert-row-id db)) references)))
references)
(sqlite-finalize stmt)))
(define (timestamp) (define (timestamp)
"Return a timestamp, either the current time of SOURCE_DATE_EPOCH." "Return a timestamp, either the current time of SOURCE_DATE_EPOCH."