Fixes #117 by providing control over nested transactions
This commit is contained in:
parent
fbbd2b5d4d
commit
e9c1bda637
2 changed files with 36 additions and 7 deletions
|
|
@ -2,11 +2,10 @@
|
||||||
|
|
||||||
Only accretive/fixative changes will be made from now on.
|
Only accretive/fixative changes will be made from now on.
|
||||||
|
|
||||||
* WIP: nested transaction support!
|
|
||||||
|
|
||||||
Changes made since the 1.0.478 release:
|
Changes made since the 1.0.478 release:
|
||||||
* Address #125 by making the result of `plan` foldable (in the `clojure.core.reducers` sense).
|
* Address #125 by making the result of `plan` foldable (in the `clojure.core.reducers` sense).
|
||||||
* Address #124 by extending `next.jdbc.sql.builder/for-query` to support `:top` (SQL Server), `:limit` / `:offset` (MySQL/PostgreSQL), `:offset` / `:fetch` (SQL Standard).
|
* Address #124 by extending `next.jdbc.sql.builder/for-query` to support `:top` (SQL Server), `:limit` / `:offset` (MySQL/PostgreSQL), `:offset` / `:fetch` (SQL Standard).
|
||||||
|
* Address #117 by adding `next.jdbc.transaction/*nested-tx*` to provide control over how attempts to create nested transactions should be handled.
|
||||||
* Address #116 by adding a `:multi-rs` option to `execute!` to retrieve multiple result sets, for example from stored procedure calls or T-SQL scripts.
|
* Address #116 by adding a `:multi-rs` option to `execute!` to retrieve multiple result sets, for example from stored procedure calls or T-SQL scripts.
|
||||||
* Allow `:all` to be passed into `find-by-keys` instead of an example hash map or a where clause vector so all rows will be returned (expected to be used with `:offset` etc to support simple pagination of an entire table).
|
* Allow `:all` to be passed into `find-by-keys` instead of an example hash map or a where clause vector so all rows will be returned (expected to be used with `:offset` etc to support simple pagination of an entire table).
|
||||||
* Add `:columns` option to `find-by-keys` (and `get-by-id`) to specify a subset of columns to be returned in each row. This can also specify an alias for the column and allows for computed expressions to be selected with an alias.
|
* Add `:columns` option to `find-by-keys` (and `get-by-id`) to specify a subset of columns to be returned in each row. This can also specify an alias for the column and allows for computed expressions to be selected with an alias.
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,45 @@
|
||||||
;; copyright (c) 2018-2020 Sean Corfield, all rights reserved
|
;; copyright (c) 2018-2020 Sean Corfield, all rights reserved
|
||||||
|
|
||||||
(ns ^:no-doc next.jdbc.transaction
|
(ns next.jdbc.transaction
|
||||||
"Implementation of SQL transaction logic."
|
"Implementation of SQL transaction logic.
|
||||||
|
|
||||||
|
In general, you cannot nest transactions. `clojure.java.jdbc` would
|
||||||
|
ignore any attempt to create a nested transaction, even tho' some
|
||||||
|
databases do support it. `next.jdbc` allows you to call `with-transaction`
|
||||||
|
even while you are inside an active transaction, but the behavior may
|
||||||
|
vary across databases and the commit or rollback boundaries may not be
|
||||||
|
what you expect. In order to avoid two transactions constructed on the
|
||||||
|
same connection from interfering with each other, `next.jdbc` locks on
|
||||||
|
the `Connection` object (this prevents concurrent transactions on separate
|
||||||
|
threads from interfering but will cause deadlock on a single thread --
|
||||||
|
so beware).
|
||||||
|
|
||||||
|
Consequently, this namespace exposes a dynamic variable, `*nested-tx*`,
|
||||||
|
which can be used to vary the behavior when an attempt is made to start
|
||||||
|
a transaction when you are already inside a transaction."
|
||||||
(:require [next.jdbc.protocols :as p])
|
(:require [next.jdbc.protocols :as p])
|
||||||
(:import (java.sql Connection)))
|
(:import (java.sql Connection)))
|
||||||
|
|
||||||
(set! *warn-on-reflection* true)
|
(set! *warn-on-reflection* true)
|
||||||
|
|
||||||
|
(defonce ^:dynamic
|
||||||
|
^{:doc "Controls the behavior when a nested transaction is attempted.
|
||||||
|
|
||||||
|
Possible values are:
|
||||||
|
* `:allow` -- the default: assumes you know what you are doing!
|
||||||
|
* `:ignore` -- the same behavior as `clojure.java.jdbc`: the nested
|
||||||
|
transaction is simply ignored and any SQL operations inside it are
|
||||||
|
executed in the context of the outer transaction.
|
||||||
|
* `:prohibit` -- any attempt to create a nested transaction will throw
|
||||||
|
an exception: this is the safest but most restrictive approach so
|
||||||
|
that you can make sure you don't accidentally have any attempts
|
||||||
|
to create nested transactions (since that might be a bug in your code)."}
|
||||||
|
*nested-tx*
|
||||||
|
:allow)
|
||||||
|
|
||||||
|
(defonce ^:private ^:dynamic ^{:doc "Used to detect nested transactions."}
|
||||||
|
*active-tx* false)
|
||||||
|
|
||||||
(def ^:private isolation-levels
|
(def ^:private isolation-levels
|
||||||
"Transaction isolation levels."
|
"Transaction isolation levels."
|
||||||
{:none Connection/TRANSACTION_NONE
|
{:none Connection/TRANSACTION_NONE
|
||||||
|
|
@ -79,9 +112,6 @@
|
||||||
(.setReadOnly con old-readonly)
|
(.setReadOnly con old-readonly)
|
||||||
(catch Exception _))))))))
|
(catch Exception _))))))))
|
||||||
|
|
||||||
(defonce ^:dynamic ^{:doc ""} *nested-tx* :allow)
|
|
||||||
(defonce ^:private ^:dynamic ^{:doc ""} *active-tx* false)
|
|
||||||
|
|
||||||
(extend-protocol p/Transactable
|
(extend-protocol p/Transactable
|
||||||
java.sql.Connection
|
java.sql.Connection
|
||||||
(-transact [this body-fn opts]
|
(-transact [this body-fn opts]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue