Sketch of side-effecting builder-adapter

This commit is contained in:
Sean Corfield 2019-11-08 12:47:54 -08:00
parent e2058fb6ae
commit b2b7696973
2 changed files with 75 additions and 0 deletions

View file

@ -356,6 +356,45 @@
(with-row [this mrs row] (with-row arsb mrs row))
(rs! [this mrs] (rs! arsb mrs))))))
(defn builder-adapter
"Given a builder function (e.g., `as-lower-maps`) and a hash map of
(optional) processing functions, return a new builder function that
applies those functions as follows, _after_ the SQL operation completes:
* `:sql-params-fn` -- called on the value of `:next.jdbc/sql-params`
(which is the vector of SQL and parameters passed to `plan`, `execute!`,
or `execute-one!` that was just completed)
* `:row!-fn` -- called on each row once it is fully-realized
* `:rs!-fn` -- called on the whole result set once it is fully-realized
These functions are assumed to be side-effecting and their result is
ignored."
[builder-fn processors]
(fn [rs opts]
(when-let [f (:sql-params-fn processors)]
(when-let [sql-params (:next.jdbc/sql-params opts)]
(f sql-params)))
(let [mrsb (builder-fn rs opts)]
(reify
RowBuilder
(->row [this] (->row mrsb))
(column-count [this] (column-count mrsb))
(with-column [this row i] (with-column mrsb row i))
(row! [this row]
(let [r (row! mrsb row)]
(when-let [f (:row!-fn processors)]
(f r))
r))
ResultSetBuilder
(->rs [this] (->rs mrsb))
(with-row [this mrs row] (with-row mrsb mrs row))
(rs! [this mrs]
(let [r (rs! mrsb mrs)]
(when-let [f (:rs!-fn processors)]
(f r))
r))))))
(declare navize-row)
(defprotocol DatafiableRow

View file

@ -220,3 +220,39 @@ VALUES ('Pear', 'green', 49, 47)
(into [] (map pr-str) (jdbc/plan (ds) ["select * from fruit"]))))
(is (thrown? IllegalArgumentException
(doall (take 3 (jdbc/plan (ds) ["select * from fruit"]))))))
(deftest adapter-side-effects
(let [logging (atom [])
logger (fn [data] (swap! logging conj data))
sql-p ["select * from fruit where id in (?,?) order by id desc" 1 4]]
(jdbc/execute! (ds) sql-p
{:builder-fn (rs/builder-adapter
rs/as-lower-maps
{:sql-params-fn logger
:row!-fn logger
:rs!-fn logger})})
;; should log four things
(is (= 4 (-> @logging count)))
;; :next.jdbc/sql-params value
(is (= sql-p (-> @logging (nth 0))))
;; first row (with PK 4)
(is (= 4 (-> @logging (nth 1) :fruit/id)))
;; second row (with PK 1)
(is (= 1 (-> @logging (nth 2) :fruit/id)))
;; full result set with two rows
(is (= 2 (-> @logging (nth 3) count)))
(is (= [4 1] (-> @logging (nth 3) (->> (map :fruit/id)))))
;; now repeat without the row logging
(reset! logging [])
(jdbc/execute! (ds) sql-p
{:builder-fn (rs/builder-adapter
rs/as-lower-maps
{:sql-params-fn logger
:rs!-fn logger})})
;; should log two things
(is (= 2 (-> @logging count)))
;; :next.jdbc/sql-params value
(is (= sql-p (-> @logging (nth 0))))
;; full result set with two rows
(is (= 2 (-> @logging (nth 1) count)))
(is (= [4 1] (-> @logging (nth 1) (->> (map :fruit/id)))))))