unofficial mirror of guix-patches@gnu.org 
 help / color / mirror / code / Atom feed
blob b6bf5325ad6fb149968f371322fa268a8a12fb83 3790 bytes (raw)
name: gnu/packages/patches/guile-sqlite3-reset-on-sqlite-finalize.patch 	 # note: path name is non-authoritative(*)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
 
From c59db66f9ac754b40463c6788ab9bad4f045cc92 Mon Sep 17 00:00:00 2001
From: Caleb Ristvedt <caleb.ristvedt@cune.org>
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


debug log:

solving b6bf5325ad ...
found b6bf5325ad in https://yhetil.org/guix-patches/87o8pu5cjx.fsf@cune.org/

applying [1/1] https://yhetil.org/guix-patches/87o8pu5cjx.fsf@cune.org/
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

1:75: trailing whitespace.
 
1:78: trailing whitespace.
-- 
Checking patch gnu/packages/patches/guile-sqlite3-reset-on-sqlite-finalize.patch...
1:80: new blank line at EOF.
+
Applied patch gnu/packages/patches/guile-sqlite3-reset-on-sqlite-finalize.patch cleanly.
warning: 3 lines add whitespace errors.

index at:
100644 b6bf5325ad6fb149968f371322fa268a8a12fb83	gnu/packages/patches/guile-sqlite3-reset-on-sqlite-finalize.patch

(*) Git path names are given by the tree(s) the blob belongs to.
    Blobs themselves have no identifier aside from the hash of its contents.^

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/guix.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).