diff --git a/CHANGELOG.md b/CHANGELOG.md index f90aa82..511fd83 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ Only accretive/fixative changes will be made from now on. * 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]_ * Update `test-runner`. * 1.2.659 -- 2021-05-05 diff --git a/src/next/jdbc.clj b/src/next/jdbc.clj index 6ba4102..6b26784 100644 --- a/src/next/jdbc.clj +++ b/src/next/jdbc.clj @@ -67,6 +67,7 @@ [next.jdbc.prepare :as prepare] [next.jdbc.protocols :as p] [next.jdbc.result-set :as rs] + [next.jdbc.sql-logging :as logger] [next.jdbc.transaction]) (:import (java.sql PreparedStatement))) @@ -368,6 +369,24 @@ [connectable opts] (opts/->DefaultOptions connectable opts)) +(defn with-logging + "Given a connectable/transactable object and a logging function + that should be used 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: + * a symbol indicating which operation is being performed: + * `plan`, `execute-one!`, `execute!`, or `prepare` + * the vector containing the SQL string and its parameters + + 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 + object, you'll need to re-wrap the Java object `with-logging` again. See + the Datasources, Connections & Transactions section of Getting Started for + more details, and some examples of use with these functions." + [connectable opts] + (logger/->SQLLogging connectable opts)) + (def snake-kebab-opts "A hash map of options that will convert Clojure identifiers to snake_case SQL entities (`:table-fn`, `:column-fn`), and will convert diff --git a/src/next/jdbc/sql_logging.clj b/src/next/jdbc/sql_logging.clj new file mode 100644 index 0000000..1f2fdb8 --- /dev/null +++ b/src/next/jdbc/sql_logging.clj @@ -0,0 +1,48 @@ +;; copyright (c) 2021 Sean Corfield, all rights reserved + +(ns ^:no-doc next.jdbc.sql-logging + "Implementation of sql-logging logic." + (:require [next.jdbc.protocols :as p])) + +(set! *warn-on-reflection* true) + +(defrecord SQLLogging [connectable logger]) + +(extend-protocol p/Sourceable + SQLLogging + (get-datasource [this] + (p/get-datasource (:connectable this)))) + +(extend-protocol p/Connectable + SQLLogging + (get-connection [this opts] + (p/get-connection (:connectable this) + (merge (:options this) opts)))) + +(extend-protocol p/Executable + SQLLogging + (-execute [this sql-params opts] + ((:logger this) 'plan sql-params) + (p/-execute (:connectable this) sql-params + (merge (:options this) opts))) + (-execute-one [this sql-params opts] + ((:logger this) 'execute-one! sql-params) + (p/-execute-one (:connectable this) sql-params + (merge (:options this) opts))) + (-execute-all [this sql-params opts] + ((:logger this) 'execute! sql-params) + (p/-execute-all (:connectable this) sql-params + (merge (:options this) opts)))) + +(extend-protocol p/Preparable + SQLLogging + (prepare [this sql-params opts] + ((:logger this) 'prepare sql-params) + (p/prepare (:connectable this) sql-params + (merge (:options this) opts)))) + +(extend-protocol p/Transactable + SQLLogging + (-transact [this body-fn opts] + (p/-transact (:connectable this) body-fn + (merge (:options this) opts))))