Fixes #80 by carefully avoiding the implicit commit when rollback fails
This commit is contained in:
parent
6497641896
commit
b6014e824a
3 changed files with 81 additions and 10 deletions
|
|
@ -6,6 +6,7 @@ Only accretive/fixative changes will be made from now on.
|
||||||
|
|
||||||
The following changes have been committed to the **master** branch since the 1.0.11 release:
|
The following changes have been committed to the **master** branch since the 1.0.11 release:
|
||||||
|
|
||||||
|
* Fix #80 by avoiding the auto-commit restore after a failed rollback in a failed transaction.
|
||||||
* Address #78 by documenting the `:connectionInitSql` workaround for HikariCP/PostgreSQL and non-default schemas.
|
* Address #78 by documenting the `:connectionInitSql` workaround for HikariCP/PostgreSQL and non-default schemas.
|
||||||
|
|
||||||
## Stable Builds
|
## Stable Builds
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,8 @@
|
||||||
rollback-only (:rollback-only opts)
|
rollback-only (:rollback-only opts)
|
||||||
old-autocommit (.getAutoCommit con)
|
old-autocommit (.getAutoCommit con)
|
||||||
old-isolation (.getTransactionIsolation con)
|
old-isolation (.getTransactionIsolation con)
|
||||||
old-readonly (.isReadOnly con)]
|
old-readonly (.isReadOnly con)
|
||||||
|
restore-ac? (volatile! true)]
|
||||||
(io!
|
(io!
|
||||||
(when isolation
|
(when isolation
|
||||||
(.setTransactionIsolation con (isolation isolation-levels)))
|
(.setTransactionIsolation con (isolation isolation-levels)))
|
||||||
|
|
@ -37,12 +38,21 @@
|
||||||
(try
|
(try
|
||||||
(let [result (f con)]
|
(let [result (f con)]
|
||||||
(if rollback-only
|
(if rollback-only
|
||||||
|
(do
|
||||||
|
;; per #80: if the rollback operation fails, we do not
|
||||||
|
;; want to try to restore auto-commit...
|
||||||
|
(vreset! restore-ac? false)
|
||||||
(.rollback con)
|
(.rollback con)
|
||||||
|
(vreset! restore-ac? true))
|
||||||
(.commit con))
|
(.commit con))
|
||||||
result)
|
result)
|
||||||
(catch Throwable t
|
(catch Throwable t
|
||||||
(try
|
(try
|
||||||
|
;; per #80: if the rollback operation fails, we do not
|
||||||
|
;; want to try to restore auto-commit...
|
||||||
|
(vreset! restore-ac? false)
|
||||||
(.rollback con)
|
(.rollback con)
|
||||||
|
(vreset! restore-ac? true)
|
||||||
(catch Throwable rb
|
(catch Throwable rb
|
||||||
;; combine both exceptions
|
;; combine both exceptions
|
||||||
(throw (ex-info (str "Rollback failed handling \""
|
(throw (ex-info (str "Rollback failed handling \""
|
||||||
|
|
@ -56,9 +66,10 @@
|
||||||
;; want those to replace any exception currently being
|
;; want those to replace any exception currently being
|
||||||
;; handled -- and if the connection got closed, we just
|
;; handled -- and if the connection got closed, we just
|
||||||
;; want to ignore exceptions here anyway
|
;; want to ignore exceptions here anyway
|
||||||
(try
|
(when @restore-ac?
|
||||||
|
(try ; only restore auto-commit if rollback did not fail
|
||||||
(.setAutoCommit con old-autocommit)
|
(.setAutoCommit con old-autocommit)
|
||||||
(catch Exception _))
|
(catch Exception _)))
|
||||||
(when isolation
|
(when isolation
|
||||||
(try
|
(try
|
||||||
(.setTransactionIsolation con old-isolation)
|
(.setTransactionIsolation con old-isolation)
|
||||||
|
|
|
||||||
|
|
@ -171,7 +171,17 @@ VALUES ('Pear', 'green', 49, 47)
|
||||||
INSERT INTO fruit (name, appearance, cost, grade)
|
INSERT INTO fruit (name, appearance, cost, grade)
|
||||||
VALUES ('Pear', 'green', 49, 47)
|
VALUES ('Pear', 'green', 49, 47)
|
||||||
"]))))
|
"]))))
|
||||||
(is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"])))))
|
(is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"]))))
|
||||||
|
(with-open [con (jdbc/get-connection (ds))]
|
||||||
|
(let [ac (.getAutoCommit con)]
|
||||||
|
(is (= [{:next.jdbc/update-count 1}]
|
||||||
|
(jdbc/with-transaction [t con {:rollback-only true}]
|
||||||
|
(jdbc/execute! t ["
|
||||||
|
INSERT INTO fruit (name, appearance, cost, grade)
|
||||||
|
VALUES ('Pear', 'green', 49, 47)
|
||||||
|
"]))))
|
||||||
|
(is (= 4 (count (jdbc/execute! con ["select * from fruit"]))))
|
||||||
|
(is (= ac (.getAutoCommit con))))))
|
||||||
(testing "with-transaction exception"
|
(testing "with-transaction exception"
|
||||||
(is (thrown? Throwable
|
(is (thrown? Throwable
|
||||||
(jdbc/with-transaction [t (ds)]
|
(jdbc/with-transaction [t (ds)]
|
||||||
|
|
@ -180,7 +190,18 @@ INSERT INTO fruit (name, appearance, cost, grade)
|
||||||
VALUES ('Pear', 'green', 49, 47)
|
VALUES ('Pear', 'green', 49, 47)
|
||||||
"])
|
"])
|
||||||
(throw (ex-info "abort" {})))))
|
(throw (ex-info "abort" {})))))
|
||||||
(is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"])))))
|
(is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"]))))
|
||||||
|
(with-open [con (jdbc/get-connection (ds))]
|
||||||
|
(let [ac (.getAutoCommit con)]
|
||||||
|
(is (thrown? Throwable
|
||||||
|
(jdbc/with-transaction [t con]
|
||||||
|
(jdbc/execute! t ["
|
||||||
|
INSERT INTO fruit (name, appearance, cost, grade)
|
||||||
|
VALUES ('Pear', 'green', 49, 47)
|
||||||
|
"])
|
||||||
|
(throw (ex-info "abort" {})))))
|
||||||
|
(is (= 4 (count (jdbc/execute! con ["select * from fruit"]))))
|
||||||
|
(is (= ac (.getAutoCommit con))))))
|
||||||
(testing "with-transaction call rollback"
|
(testing "with-transaction call rollback"
|
||||||
(is (= [{:next.jdbc/update-count 1}]
|
(is (= [{:next.jdbc/update-count 1}]
|
||||||
(jdbc/with-transaction [t (ds)]
|
(jdbc/with-transaction [t (ds)]
|
||||||
|
|
@ -190,7 +211,19 @@ VALUES ('Pear', 'green', 49, 47)
|
||||||
"])]
|
"])]
|
||||||
(.rollback t)
|
(.rollback t)
|
||||||
result))))
|
result))))
|
||||||
(is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"])))))
|
(is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"]))))
|
||||||
|
(with-open [con (jdbc/get-connection (ds))]
|
||||||
|
(let [ac (.getAutoCommit con)]
|
||||||
|
(is (= [{:next.jdbc/update-count 1}]
|
||||||
|
(jdbc/with-transaction [t con]
|
||||||
|
(let [result (jdbc/execute! t ["
|
||||||
|
INSERT INTO fruit (name, appearance, cost, grade)
|
||||||
|
VALUES ('Pear', 'green', 49, 47)
|
||||||
|
"])]
|
||||||
|
(.rollback t)
|
||||||
|
result))))
|
||||||
|
(is (= 4 (count (jdbc/execute! con ["select * from fruit"]))))
|
||||||
|
(is (= ac (.getAutoCommit con))))))
|
||||||
(testing "with-transaction with unnamed save point"
|
(testing "with-transaction with unnamed save point"
|
||||||
(is (= [{:next.jdbc/update-count 1}]
|
(is (= [{:next.jdbc/update-count 1}]
|
||||||
(jdbc/with-transaction [t (ds)]
|
(jdbc/with-transaction [t (ds)]
|
||||||
|
|
@ -201,7 +234,20 @@ VALUES ('Pear', 'green', 49, 47)
|
||||||
"])]
|
"])]
|
||||||
(.rollback t save-point)
|
(.rollback t save-point)
|
||||||
result))))
|
result))))
|
||||||
(is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"])))))
|
(is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"]))))
|
||||||
|
(with-open [con (jdbc/get-connection (ds))]
|
||||||
|
(let [ac (.getAutoCommit con)]
|
||||||
|
(is (= [{:next.jdbc/update-count 1}]
|
||||||
|
(jdbc/with-transaction [t con]
|
||||||
|
(let [save-point (.setSavepoint t)
|
||||||
|
result (jdbc/execute! t ["
|
||||||
|
INSERT INTO fruit (name, appearance, cost, grade)
|
||||||
|
VALUES ('Pear', 'green', 49, 47)
|
||||||
|
"])]
|
||||||
|
(.rollback t save-point)
|
||||||
|
result))))
|
||||||
|
(is (= 4 (count (jdbc/execute! con ["select * from fruit"]))))
|
||||||
|
(is (= ac (.getAutoCommit con))))))
|
||||||
(testing "with-transaction with named save point"
|
(testing "with-transaction with named save point"
|
||||||
(is (= [{:next.jdbc/update-count 1}]
|
(is (= [{:next.jdbc/update-count 1}]
|
||||||
(jdbc/with-transaction [t (ds)]
|
(jdbc/with-transaction [t (ds)]
|
||||||
|
|
@ -212,7 +258,20 @@ VALUES ('Pear', 'green', 49, 47)
|
||||||
"])]
|
"])]
|
||||||
(.rollback t save-point)
|
(.rollback t save-point)
|
||||||
result))))
|
result))))
|
||||||
(is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"]))))))
|
(is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"]))))
|
||||||
|
(with-open [con (jdbc/get-connection (ds))]
|
||||||
|
(let [ac (.getAutoCommit con)]
|
||||||
|
(is (= [{:next.jdbc/update-count 1}]
|
||||||
|
(jdbc/with-transaction [t con]
|
||||||
|
(let [save-point (.setSavepoint t (name (gensym)))
|
||||||
|
result (jdbc/execute! t ["
|
||||||
|
INSERT INTO fruit (name, appearance, cost, grade)
|
||||||
|
VALUES ('Pear', 'green', 49, 47)
|
||||||
|
"])]
|
||||||
|
(.rollback t save-point)
|
||||||
|
result))))
|
||||||
|
(is (= 4 (count (jdbc/execute! con ["select * from fruit"]))))
|
||||||
|
(is (= ac (.getAutoCommit con)))))))
|
||||||
|
|
||||||
(deftest connection-tests
|
(deftest connection-tests
|
||||||
(testing "datasource via jdbcUrl"
|
(testing "datasource via jdbcUrl"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue