hold my beer, let's remove *DB-LOCK*
- We shouldn't need it anyway because of the component data lock, and having two locks around causes deadlocks (they're taken in different orders)
This commit is contained in:
parent
3985aba03f
commit
f6561a64a3
35
sqlite.lisp
35
sqlite.lisp
|
@ -2,8 +2,6 @@
|
||||||
|
|
||||||
(defvar *db* nil
|
(defvar *db* nil
|
||||||
"Connection to the database.")
|
"Connection to the database.")
|
||||||
(defvar *db-lock* (bt:make-recursive-lock)
|
|
||||||
"Lock for *DB*.")
|
|
||||||
(defparameter *default-database-path* "data.sqlite3"
|
(defparameter *default-database-path* "data.sqlite3"
|
||||||
"Default path to the SQLite database file.")
|
"Default path to the SQLite database file.")
|
||||||
(defvar *prepared-statements* nil
|
(defvar *prepared-statements* nil
|
||||||
|
@ -20,12 +18,11 @@
|
||||||
|
|
||||||
(defun connect-database (&optional (path *default-database-path*))
|
(defun connect-database (&optional (path *default-database-path*))
|
||||||
"Establish a connection to the database."
|
"Establish a connection to the database."
|
||||||
(bt:with-recursive-lock-held (*db-lock*)
|
(setf *db* (sqlite:connect path))
|
||||||
(setf *db* (sqlite:connect path))
|
(run-pragmas)
|
||||||
(run-pragmas)
|
(loop for sym in *prepared-statements*
|
||||||
(loop for sym in *prepared-statements*
|
do (eval `(setf ,sym nil)))
|
||||||
do (eval `(setf ,sym nil)))
|
(setf *prepared-statements* nil))
|
||||||
(setf *prepared-statements* nil)))
|
|
||||||
|
|
||||||
(defmacro prepared-statement (statement)
|
(defmacro prepared-statement (statement)
|
||||||
"Caches the creation of a prepared statement with SQL text STATEMENT.
|
"Caches the creation of a prepared statement with SQL text STATEMENT.
|
||||||
|
@ -41,12 +38,11 @@ In other words, prepares STATEMENT once, then returns the prepared statement aft
|
||||||
|
|
||||||
(defmacro with-prepared-statement ((name statement) &body forms)
|
(defmacro with-prepared-statement ((name statement) &body forms)
|
||||||
"Evaluates FORMS, binding a prepared statement with SQL text STATEMENT to NAME, and ensuring it is reset when control is transferred."
|
"Evaluates FORMS, binding a prepared statement with SQL text STATEMENT to NAME, and ensuring it is reset when control is transferred."
|
||||||
`(bt:with-recursive-lock-held (*db-lock*)
|
`(let ((,name (prepared-statement ,statement)))
|
||||||
(let ((,name (prepared-statement ,statement)))
|
(multiple-value-prog1
|
||||||
(multiple-value-prog1
|
(unwind-protect
|
||||||
(unwind-protect
|
(progn ,@forms)
|
||||||
(progn ,@forms)
|
(ignore-errors (sqlite:reset-statement ,name))))))
|
||||||
(ignore-errors (sqlite:reset-statement ,name)))))))
|
|
||||||
|
|
||||||
(defmacro with-prepared-statements (statements &body forms)
|
(defmacro with-prepared-statements (statements &body forms)
|
||||||
"Like WITH-PREPARED-STATEMENT, but takes multiple statements."
|
"Like WITH-PREPARED-STATEMENT, but takes multiple statements."
|
||||||
|
@ -54,12 +50,11 @@ In other words, prepares STATEMENT once, then returns the prepared statement aft
|
||||||
collect `(,name (prepared-statement ,statement))))
|
collect `(,name (prepared-statement ,statement))))
|
||||||
(reset-forms (loop for (name statement) in statements
|
(reset-forms (loop for (name statement) in statements
|
||||||
collect `(ignore-errors (sqlite:reset-statement ,name)))))
|
collect `(ignore-errors (sqlite:reset-statement ,name)))))
|
||||||
`(bt:with-recursive-lock-held (*db-lock*)
|
`(let (,@let-forms)
|
||||||
(let (,@let-forms)
|
(multiple-value-prog1
|
||||||
(multiple-value-prog1
|
(unwind-protect
|
||||||
(unwind-protect
|
(progn ,@forms))
|
||||||
(progn ,@forms))
|
(ignore-errors (progn ,@reset-forms))))))
|
||||||
(ignore-errors (progn ,@reset-forms)))))))
|
|
||||||
|
|
||||||
(defmacro column-values (statement)
|
(defmacro column-values (statement)
|
||||||
"Returns the values in the current row of the STATEMENT."
|
"Returns the values in the current row of the STATEMENT."
|
||||||
|
|
Loading…
Reference in a new issue