From e3cf7be4491f465d3041933596d3caad1ea64e83 Mon Sep 17 00:00:00 2001 From: Caleb Ristvedt Date: Sun, 7 Jun 2020 22:30:41 -0500 Subject: [PATCH 2/5] gnu: guile-sqlite3: add patch to fix sqlite-finalize bug Adds patch that fixes https://notabug.org/guile-sqlite3/guile-sqlite3/issues/12. This can be discarded once the patch is integrated into the next guile-sqlite3 release. Note that the patch is identical to the pull request at https://notabug.org/guile-sqlite3/guile-sqlite3/pulls/13. * gnu/packages/patches/guile-sqlite3-reset-on-sqlite-finalize.patch: new patch. * gnu/packages/guile.scm (guile-sqlite3): use it. * gnu/local.mk (dist_patch_DATA): add it. --- gnu/local.mk | 1 + gnu/packages/guile.scm | 3 +- ...ile-sqlite3-reset-on-sqlite-finalize.patch | 74 +++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 gnu/packages/patches/guile-sqlite3-reset-on-sqlite-finalize.patch diff --git a/gnu/local.mk b/gnu/local.mk index ae8a2275f7..d382205a03 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -1059,6 +1059,7 @@ dist_patch_DATA = \ %D%/packages/patches/guile-rsvg-pkgconfig.patch \ %D%/packages/patches/guile-emacs-fix-configure.patch \ %D%/packages/patches/guile-sqlite3-fix-cross-compilation.patch \ + %D%/packages/patches/guile-sqlite3-reset-on-sqlite-finalize.patch \ %D%/packages/patches/gtk2-respect-GUIX_GTK2_PATH.patch \ %D%/packages/patches/gtk2-respect-GUIX_GTK2_IM_MODULE_FILE.patch \ %D%/packages/patches/gtk2-theme-paths.patch \ diff --git a/gnu/packages/guile.scm b/gnu/packages/guile.scm index c2dc7f6d5f..63cd91a1cb 100644 --- a/gnu/packages/guile.scm +++ b/gnu/packages/guile.scm @@ -645,7 +645,8 @@ Guile's foreign function interface.") "1nv8j7wk6b5n4p22szyi8lv8fs31rrzxhzz16gyj8r38c1fyp9qp")) (file-name (string-append name "-" version "-checkout")) (patches - (search-patches "guile-sqlite3-fix-cross-compilation.patch")) + (search-patches "guile-sqlite3-fix-cross-compilation.patch" + "guile-sqlite3-reset-on-sqlite-finalize.patch")) (modules '((guix build utils))) (snippet '(begin diff --git a/gnu/packages/patches/guile-sqlite3-reset-on-sqlite-finalize.patch b/gnu/packages/patches/guile-sqlite3-reset-on-sqlite-finalize.patch new file mode 100644 index 0000000000..b6bf5325ad --- /dev/null +++ b/gnu/packages/patches/guile-sqlite3-reset-on-sqlite-finalize.patch @@ -0,0 +1,74 @@ +From c59db66f9ac754b40463c6788ab9bad4f045cc92 Mon Sep 17 00:00:00 2001 +From: Caleb Ristvedt +Date: Sun, 7 Jun 2020 18:27:44 -0500 +Subject: [PATCH] Reset statement when sqlite-finalize is called on cached + statement + +Automatically-started transactions only end when a statement finishes, which is +normally either when sqlite-reset or sqlite-finalize is called for that +statement. Consequently, transactions automatically started by cached +statements won't end until the statement is next reused by sqlite-prepare or +sqlite-reset is called on it. This changes sqlite-finalize so that it preserves +the statement-finishing (and thus transaction-finishing) behavior of +sqlite_finalize. +--- + sqlite3.scm.in | 43 ++++++++++++++++++++++++++++++++++--------- + 1 file changed, 34 insertions(+), 9 deletions(-) + +diff --git a/sqlite3.scm.in b/sqlite3.scm.in +index 77b5032..19241dc 100644 +--- a/sqlite3.scm.in ++++ b/sqlite3.scm.in +@@ -274,15 +274,40 @@ statements, into DB. The result is unspecified." + (dynamic-func "sqlite3_finalize" libsqlite3) + (list '*)))) + (lambda (stmt) +- ;; Note: When STMT is cached, this is a no-op. This ensures caching +- ;; actually works while still separating concerns: users can turn +- ;; caching on and off without having to change the rest of their code. +- (when (and (stmt-live? stmt) +- (not (stmt-cached? stmt))) +- (let ((p (stmt-pointer stmt))) +- (sqlite-remove-statement! (stmt->db stmt) stmt) +- (set-stmt-live?! stmt #f) +- (f p)))))) ++ ;; Note: When STMT is cached, this merely resets. This ensures caching ++ ;; actually works while still separating concerns: users can turn caching ++ ;; on and off without having to change the rest of their code. ++ (if (and (stmt-live? stmt) ++ (not (stmt-cached? stmt))) ++ (let ((p (stmt-pointer stmt))) ++ (sqlite-remove-statement! (stmt->db stmt) stmt) ++ (set-stmt-live?! stmt #f) ++ (f p)) ++ ;; It's necessary to reset cached statements due to the following: ++ ;; ++ ;; "An implicit transaction (a transaction that is started ++ ;; automatically, not a transaction started by BEGIN) is committed ++ ;; automatically when the last active statement finishes. A statement ++ ;; finishes when its last cursor closes, which is guaranteed to happen ++ ;; when the prepared statement is reset or finalized. Some statements ++ ;; might "finish" for the purpose of transaction control prior to ++ ;; being reset or finalized, but there is no guarantee of this." ++ ;; ++ ;; (see https://www.sqlite.org/lang_transaction.html) ++ ;; ++ ;; Thus, it's possible for an implicitly-started transaction to hang ++ ;; around until sqlite-reset is called when the cached statement is ++ ;; next used. Because the transaction is committed automatically only ++ ;; when the *last active statement* finishes, the implicitly-started ++ ;; transaction may later be upgraded to a write transaction (!) and ++ ;; this non-reset statement will still be keeping the transaction from ++ ;; committing until it is next used or the database connection is ++ ;; closed. This has the potential to make (exclusive) write access to ++ ;; the database necessary for much longer than it should be. ++ ;; ++ ;; So it's necessary to preserve the statement-finishing behavior of ++ ;; sqlite_finalize here, which we do by calling sqlite-reset. ++ (sqlite-reset stmt))))) + + (define *stmt-map* (make-weak-key-hash-table)) + (define (stmt->db stmt) +-- +2.26.2 + -- 2.26.2