aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/sqlite.el
diff options
context:
space:
mode:
authorEli Zaretskii2023-11-21 15:36:22 +0200
committerEli Zaretskii2023-11-21 15:36:22 +0200
commitd72a4ed65ce23581ff8b3bf4340caecf31c18f43 (patch)
treee29b9e83e4e9eeccfac0019eb268c8ce1d84eca1 /lisp/sqlite.el
parenta7b3c92373373f956234349fe6b792e1396e293e (diff)
downloademacs-d72a4ed65ce23581ff8b3bf4340caecf31c18f43.tar.gz
emacs-d72a4ed65ce23581ff8b3bf4340caecf31c18f43.zip
Fix 'with-sqlite-transaction' when BODY fails
* lisp/sqlite.el (with-sqlite-transaction): Don't commit changes if BODY errors out. Roll back the transaction if committing fails. (Bug#67142) * etc/NEWS: * doc/lispref/text.texi (Database): Document the error handling in 'with-sqlite-transaction'.
Diffstat (limited to 'lisp/sqlite.el')
-rw-r--r--lisp/sqlite.el21
1 files changed, 15 insertions, 6 deletions
diff --git a/lisp/sqlite.el b/lisp/sqlite.el
index aad0aa40fa4..8a525739c9a 100644
--- a/lisp/sqlite.el
+++ b/lisp/sqlite.el
@@ -24,19 +24,28 @@
24;;; Code: 24;;; Code:
25 25
26(defmacro with-sqlite-transaction (db &rest body) 26(defmacro with-sqlite-transaction (db &rest body)
27 "Execute BODY while holding a transaction for DB." 27 "Execute BODY while holding a transaction for DB.
28If BODY completes normally, commit the changes and return
29the value of BODY.
30If BODY signals an error, or transaction commit fails, roll
31back the transaction changes."
28 (declare (indent 1) (debug (form body))) 32 (declare (indent 1) (debug (form body)))
29 (let ((db-var (gensym)) 33 (let ((db-var (gensym))
30 (func-var (gensym))) 34 (func-var (gensym))
35 (res-var (gensym))
36 (commit-var (gensym)))
31 `(let ((,db-var ,db) 37 `(let ((,db-var ,db)
32 (,func-var (lambda () ,@body))) 38 (,func-var (lambda () ,@body))
39 ,res-var ,commit-var)
33 (if (sqlite-available-p) 40 (if (sqlite-available-p)
34 (unwind-protect 41 (unwind-protect
35 (progn 42 (progn
36 (sqlite-transaction ,db-var) 43 (sqlite-transaction ,db-var)
37 (funcall ,func-var)) 44 (setq ,res-var (funcall ,func-var))
38 (sqlite-commit ,db-var)) 45 (setq ,commit-var (sqlite-commit ,db-var))
39 (funcall ,func-var))))) 46 ,res-var)
47 (or ,commit-var (sqlite-rollback ,db-var))))
48 (funcall ,func-var))))
40 49
41(provide 'sqlite) 50(provide 'sqlite)
42 51