Add optional result logging and state passthru

This commit is contained in:
Sean Corfield 2021-05-20 18:37:42 -07:00
parent 92db8477bf
commit b961ef0451
3 changed files with 37 additions and 18 deletions

View file

@ -3,7 +3,7 @@
Only accretive/fixative changes will be made from now on. Only accretive/fixative changes will be made from now on.
* 1.2.next in progress * 1.2.next in progress
* Add `next.jdbc/with-logging` to create a wrapped connectable that will invoke a logging function with the SQL and parameters for each operation. _[needs docs and tests]_ * _[Experimental! Will change in response to feedback!]_ Add `next.jdbc/with-logging` to create a wrapped connectable that will invoke logging functions with the SQL/parameters and optionally the result for each operation. _[needs docs and tests]_
* Update `test-runner`. * Update `test-runner`.
* 1.2.659 -- 2021-05-05 * 1.2.659 -- 2021-05-05

View file

@ -370,22 +370,33 @@
(opts/->DefaultOptions connectable opts)) (opts/->DefaultOptions connectable opts))
(defn with-logging (defn with-logging
"Given a connectable/transactable object and a logging function "Given a connectable/transactable object and a sql/params logging
that should be used on all operations on that object, return a new function and an optional result logging function that should be used
wrapper object that can be used in its place. on all operations on that object, return a new wrapper object that can
be used in its place.
The logging function will be called with two arguments: The sql/params logging function will be called with two arguments:
* a symbol indicating which operation is being performed: * a symbol indicating which operation is being performed:
* `plan`, `execute-one!`, `execute!`, or `prepare` * `next.jdbc/plan`, `next.jdbc/execute-one!`, `next.jdbc/execute!`,
or `next.jdbc/prepare`
* the vector containing the SQL string and its parameters * the vector containing the SQL string and its parameters
Whatever the sql/params logging function returns will be passed as a
`state` argument to the optional result logging function.
The result logging function, if provided, will be called with the
same symbol passed to the sql/params logging function, the `state`
returned by the sql/params logging function, and the result of the
`execute!` or `execute-one!` call. The result logging function is
not called for the `plan` or `prepare` call (since they do not produce
result sets directly).
Bear in mind that `get-datasource`, `get-connection`, and `with-transaction` Bear in mind that `get-datasource`, `get-connection`, and `with-transaction`
return plain Java objects, so if you call any of those on this wrapped return plain Java objects, so if you call any of those on this wrapped
object, you'll need to re-wrap the Java object `with-logging` again. See object, you'll need to re-wrap the Java object `with-logging` again. See
the Datasources, Connections & Transactions section of Getting Started for the Datasources, Connections & Transactions section of Getting Started for
more details, and some examples of use with these functions." more details, and some examples of use with these functions."
[connectable opts] [connectable sql-logger & [result-logger]]
(logger/->SQLLogging connectable opts)) (logger/->SQLLogging connectable sql-logger result-logger))
(def snake-kebab-opts (def snake-kebab-opts
"A hash map of options that will convert Clojure identifiers to "A hash map of options that will convert Clojure identifiers to

View file

@ -6,7 +6,7 @@
(set! *warn-on-reflection* true) (set! *warn-on-reflection* true)
(defrecord SQLLogging [connectable logger]) (defrecord SQLLogging [connectable sql-logger result-logger])
(extend-protocol p/Sourceable (extend-protocol p/Sourceable
SQLLogging SQLLogging
@ -19,25 +19,33 @@
(p/get-connection (:connectable this) (p/get-connection (:connectable this)
(merge (:options this) opts)))) (merge (:options this) opts))))
(defn- result-logger-helper [result this sym state]
(when-let [logger (:result-logger this)]
(logger sym state result)))
(extend-protocol p/Executable (extend-protocol p/Executable
SQLLogging SQLLogging
(-execute [this sql-params opts] (-execute [this sql-params opts]
((:logger this) 'plan sql-params) ;; no result-logger call possible:
((:sql-logger this) 'next.jdbc/plan sql-params)
(p/-execute (:connectable this) sql-params (p/-execute (:connectable this) sql-params
(merge (:options this) opts))) (merge (:options this) opts)))
(-execute-one [this sql-params opts] (-execute-one [this sql-params opts]
((:logger this) 'execute-one! sql-params) (let [state ((:sql-logger this) 'next.jdbc/execute-one! sql-params)]
(p/-execute-one (:connectable this) sql-params (doto (p/-execute-one (:connectable this) sql-params
(merge (:options this) opts))) (merge (:options this) opts))
(result-logger-helper this 'next.jdbc/execute-one! state))))
(-execute-all [this sql-params opts] (-execute-all [this sql-params opts]
((:logger this) 'execute! sql-params) (let [state ((:sql-logger this) 'next.jdbc/execute! sql-params)]
(p/-execute-all (:connectable this) sql-params (doto (p/-execute-all (:connectable this) sql-params
(merge (:options this) opts)))) (merge (:options this) opts))
(result-logger-helper this 'next.jdbc/execute! state)))))
(extend-protocol p/Preparable (extend-protocol p/Preparable
SQLLogging SQLLogging
(prepare [this sql-params opts] (prepare [this sql-params opts]
((:logger this) 'prepare sql-params) ;; no result-logger call possible:
((:sql-logger this) 'next.jdbc/prepare sql-params)
(p/prepare (:connectable this) sql-params (p/prepare (:connectable this) sql-params
(merge (:options this) opts)))) (merge (:options this) opts))))