address #181 (again!)

Signed-off-by: Sean Corfield <sean@corfield.org>
This commit is contained in:
Sean Corfield 2025-02-13 17:41:27 -08:00
parent e6d1abf3ec
commit 9ed335dc8d
No known key found for this signature in database
6 changed files with 82 additions and 29 deletions

View file

@ -4,6 +4,7 @@ Only accretive/fixative changes will be made from now on.
* 1.3.next in progress
* Address [#295](https://github.com/seancorfield/next-jdbc/issues/295) by providing a way to tell `next.jdbc` that certain options should be passed "as-is" in the `Properties` object when creating a `Connection`.
* Fix [#181](https://github.com/seancorfield/next-jdbc/issues/181) (again!) by adding `Wrapped` protocol as a way for `DefaultOptions` and `SQLLogging` to consistently expose the underlying connectable, even when nested.
* 1.3.994 -- 2025-01-28
* Fix [#293](https://github.com/seancorfield/next-jdbc/issues/293) by no longer `locking` on the `Connection` retrieved from a `DataSource`.

View file

@ -1,4 +1,4 @@
;; copyright (c) 2018-2024 Sean Corfield, all rights reserved
;; copyright (c) 2018-2025 Sean Corfield, all rights reserved
(ns next.jdbc
"The public API of the next generation java.jdbc library.
@ -336,13 +336,14 @@
result))))
params)))
([connectable sql param-groups opts]
(if (or (instance? java.sql.Connection connectable)
(and (satisfies? p/Connectable connectable)
(instance? java.sql.Connection (:connectable connectable))))
(with-open [ps (prepare connectable [sql] opts)]
(let [conn (p/unwrap connectable)]
(if (instance? java.sql.Connection conn)
(with-open [ps (prepare conn [sql] (if-let [opts' (:options connectable)]
(merge opts' opts)
opts))]
(execute-batch! ps param-groups opts))
(with-open [con (get-connection connectable)]
(execute-batch! con sql param-groups opts)))))
(execute-batch! con sql param-groups opts))))))
(defmacro on-connection
"Given a connectable object, gets a connection and binds it to `sym`,
@ -365,13 +366,10 @@
executes the body, and automatically closes it for you."
[[sym connectable] & body]
(let [con-sym (vary-meta sym assoc :tag 'java.sql.Connection)]
`(let [con-obj# ~connectable]
(cond (instance? java.sql.Connection con-obj#)
((^{:once true} fn* [~con-sym] ~@body) con-obj#)
(and (satisfies? p/Connectable con-obj#)
(instance? java.sql.Connection (:connectable con-obj#)))
((^{:once true} fn* [~con-sym] ~@body) (:connectable con-obj#))
:else
`(let [con-obj# ~connectable
bare-con# (p/unwrap con-obj#)]
(if (instance? java.sql.Connection bare-con#)
((^{:once true} fn* [~con-sym] ~@body) bare-con#)
(with-open [con# (get-connection con-obj#)]
((^{:once true} fn* [~con-sym] ~@body) con#))))))
@ -403,12 +401,8 @@
with `on-connection`."
[[sym connectable] & body]
`(let [con-obj# ~connectable]
(cond (instance? java.sql.Connection con-obj#)
(if (instance? java.sql.Connection (p/unwrap con-obj#))
((^{:once true} fn* [~sym] ~@body) con-obj#)
(and (satisfies? p/Connectable con-obj#)
(instance? java.sql.Connection (:connectable con-obj#)))
((^{:once true} fn* [~sym] ~@body) con-obj#)
:else
(with-open [con# (get-connection con-obj#)]
((^{:once true} fn* [~sym] ~@body)
(with-options con# (:options con-obj# {})))))))

View file

@ -1,4 +1,4 @@
;; copyright (c) 2020-2024 Sean Corfield, all rights reserved
;; copyright (c) 2020-2025 Sean Corfield, all rights reserved
(ns ^:no-doc next.jdbc.default-options
"Implementation of default options logic."
@ -8,6 +8,10 @@
(defrecord DefaultOptions [connectable options])
(extend-protocol p/Wrapped
DefaultOptions
(unwrap [this] (p/unwrap (:connectable this))))
(extend-protocol p/Sourceable
DefaultOptions
(get-datasource [this]

View file

@ -1,4 +1,4 @@
;; copyright (c) 2018-2024 Sean Corfield, all rights reserved
;; copyright (c) 2018-2025 Sean Corfield, all rights reserved
(ns next.jdbc.protocols
"This is the extensible core of the next generation java.jdbc library.
@ -63,3 +63,15 @@
:extend-via-metadata true
(-transact [this body-fn opts]
"Run the `body-fn` inside a transaction."))
(defprotocol Wrapped
"Protocol for (un)wrapping a `next.jdbc` connectable.
Implementations are provided for `Object` (identity) and `DefaultOptions`
and SQLLogging."
(unwrap [this]
"Unwrap the connectable to get the underlying connectable."))
(extend-protocol Wrapped
Object
(unwrap [this] this))

View file

@ -1,4 +1,4 @@
;; copyright (c) 2021-2024 Sean Corfield, all rights reserved
;; copyright (c) 2021-2025 Sean Corfield, all rights reserved
(ns ^:no-doc next.jdbc.sql-logging
"Implementation of sql-logging logic."
@ -8,6 +8,10 @@
(defrecord SQLLogging [connectable sql-logger result-logger options])
(extend-protocol p/Wrapped
SQLLogging
(unwrap [this] (p/unwrap (:connectable this))))
(extend-protocol p/Sourceable
SQLLogging
(get-datasource [this]

View file

@ -749,6 +749,44 @@ INSERT INTO fruit (name, appearance) VALUES (?,?)
(conj result (count (jdbc/execute! (ds) ["select * from fruit"]))))
(finally
(jdbc/execute-one! (ds) [(str "delete from fruit where " (index) " > 4")])))))
(is (= [1 1 1 1 1 1 1 1 1 13]
(try
(let [result (jdbc/execute-batch! (jdbc/with-options
(jdbc/with-logging (ds) println println)
{:ignore "me"})
"INSERT INTO fruit (name, appearance) VALUES (?,?)"
[["fruit1" "one"]
["fruit2" "two"]
["fruit3" "three"]
["fruit4" "four"]
["fruit5" "five"]
["fruit6" "six"]
["fruit7" "seven"]
["fruit8" "eight"]
["fruit9" "nine"]]
{})]
(conj result (count (jdbc/execute! (ds) ["select * from fruit"]))))
(finally
(jdbc/execute-one! (ds) [(str "delete from fruit where " (index) " > 4")])))))
(is (= [1 1 1 1 1 1 1 1 1 13]
(try
(let [result (jdbc/execute-batch! (jdbc/with-logging
(jdbc/with-options (ds) {:ignore "me"})
println println)
"INSERT INTO fruit (name, appearance) VALUES (?,?)"
[["fruit1" "one"]
["fruit2" "two"]
["fruit3" "three"]
["fruit4" "four"]
["fruit5" "five"]
["fruit6" "six"]
["fruit7" "seven"]
["fruit8" "eight"]
["fruit9" "nine"]]
{})]
(conj result (count (jdbc/execute! (ds) ["select * from fruit"]))))
(finally
(jdbc/execute-one! (ds) [(str "delete from fruit where " (index) " > 4")])))))
(is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"])))))
(testing "small batch insert"
(is (= [1 1 1 1 1 1 1 1 1 13]