2019-11-11 01:53:23 +00:00
|
|
|
;; copyright (c) 2019 Sean Corfield, all rights reserved
|
2019-11-10 06:59:34 +00:00
|
|
|
|
|
|
|
|
(ns next.jdbc.middleware-test
|
2019-11-13 18:52:17 +00:00
|
|
|
(:require [clojure.test :refer [deftest is testing use-fixtures]]
|
2019-11-10 06:59:34 +00:00
|
|
|
[next.jdbc :as jdbc]
|
|
|
|
|
[next.jdbc.middleware :as mw]
|
|
|
|
|
[next.jdbc.test-fixtures :refer [with-test-db db ds
|
2019-11-16 22:41:54 +00:00
|
|
|
default-options]]
|
2019-11-10 06:59:34 +00:00
|
|
|
[next.jdbc.result-set :as rs]
|
|
|
|
|
[next.jdbc.specs :as specs])
|
2019-11-18 00:00:39 +00:00
|
|
|
(:import (java.sql ResultSet)))
|
2019-11-10 06:59:34 +00:00
|
|
|
|
|
|
|
|
(set! *warn-on-reflection* true)
|
|
|
|
|
|
|
|
|
|
(use-fixtures :once with-test-db)
|
|
|
|
|
|
|
|
|
|
(specs/instrument)
|
|
|
|
|
|
|
|
|
|
(deftest logging-test
|
|
|
|
|
(let [logging (atom [])
|
2019-11-16 22:41:54 +00:00
|
|
|
logger (fn [data _] (swap! logging conj data) data)
|
|
|
|
|
log-sql (fn [sql-p opts] (logger sql-p opts) [sql-p opts])
|
2019-11-10 06:59:34 +00:00
|
|
|
sql-p ["select * from fruit where id in (?,?) order by id desc" 1 4]]
|
|
|
|
|
(jdbc/execute! (mw/wrapper (ds))
|
|
|
|
|
sql-p
|
2019-11-16 06:37:42 +00:00
|
|
|
(assoc (default-options)
|
2019-11-16 22:41:54 +00:00
|
|
|
:builder-fn rs/as-lower-maps
|
|
|
|
|
:pre-execute-fn log-sql
|
|
|
|
|
:row!-fn logger
|
|
|
|
|
:rs!-fn logger))
|
2019-11-10 06:59:34 +00:00
|
|
|
;; 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! (mw/wrapper (ds)
|
2019-11-16 22:41:54 +00:00
|
|
|
{:builder-fn rs/as-lower-maps
|
|
|
|
|
:pre-execute-fn log-sql
|
|
|
|
|
:rs!-fn logger})
|
2019-11-16 06:37:42 +00:00
|
|
|
sql-p
|
|
|
|
|
(default-options))
|
2019-11-10 06:59:34 +00:00
|
|
|
;; 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)))))))
|
|
|
|
|
|
|
|
|
|
(deftest timing-test
|
2019-11-16 22:41:54 +00:00
|
|
|
(let [start-fn (fn [sql-p opts]
|
|
|
|
|
(swap! (::timing opts) update ::calls inc)
|
|
|
|
|
[sql-p (assoc opts ::start (System/nanoTime))])
|
|
|
|
|
end-fn (fn [rs opts]
|
2019-11-10 06:59:34 +00:00
|
|
|
(let [end (System/nanoTime)]
|
2019-11-16 22:41:54 +00:00
|
|
|
(swap! (::timing opts) update ::total + (- end (::start opts)))
|
|
|
|
|
[rs opts]))
|
|
|
|
|
timing (atom {::calls 0 ::total 0.0})
|
2019-11-18 00:00:39 +00:00
|
|
|
mw-ds (mw/wrapper (ds) {::timing timing
|
|
|
|
|
:pre-execute-fn start-fn
|
|
|
|
|
:post-execute-fn end-fn})
|
2019-11-10 06:59:34 +00:00
|
|
|
sql-p ["select * from fruit where id in (?,?) order by id desc" 1 4]]
|
2019-11-18 00:00:39 +00:00
|
|
|
(jdbc/execute! mw-ds sql-p)
|
|
|
|
|
(jdbc/execute! mw-ds sql-p)
|
2019-11-16 22:41:54 +00:00
|
|
|
(printf "%20s - %d calls took %,10d nanoseconds\n"
|
|
|
|
|
(:dbtype (db)) (::calls @timing) (long (::total @timing)))))
|
2019-11-18 00:00:39 +00:00
|
|
|
|
|
|
|
|
(deftest post-execute-tests
|
|
|
|
|
(let [calls (atom 0)
|
|
|
|
|
seen-rs (atom 0)
|
|
|
|
|
rows (atom 0)
|
|
|
|
|
rss (atom 0)
|
|
|
|
|
post-fn (fn [x opts]
|
|
|
|
|
(swap! calls inc)
|
|
|
|
|
(when (instance? ResultSet x)
|
|
|
|
|
(swap! seen-rs inc))
|
|
|
|
|
[x opts])
|
|
|
|
|
mw-ds (mw/wrapper (ds) {:post-execute-fn post-fn
|
|
|
|
|
:row!-fn (fn [row _] (swap! rows inc) row)
|
|
|
|
|
:rs!-fn (fn [rs _] (swap! rss inc) rs)})]
|
|
|
|
|
;; first call, four rows, one result set
|
|
|
|
|
(jdbc/execute! mw-ds ["select * from fruit"])
|
|
|
|
|
(is (= 1 @calls))
|
|
|
|
|
(is (= 1 @seen-rs))
|
|
|
|
|
(is (= 4 @rows))
|
|
|
|
|
(is (= 1 @rss))
|
|
|
|
|
;; second call, no rows, one more result set
|
|
|
|
|
(jdbc/execute! mw-ds ["select * from fruit where id < 0"])
|
|
|
|
|
(is (= 2 @calls))
|
|
|
|
|
(is (= 2 @seen-rs))
|
|
|
|
|
(is (= 4 @rows))
|
|
|
|
|
(is (= 2 @rss))
|
|
|
|
|
;; third call, no result set
|
|
|
|
|
(jdbc/execute! mw-ds ["update fruit set name = ? where id < 0" "Plum"])
|
|
|
|
|
(is (= 3 @calls))
|
|
|
|
|
(is (= 2 @seen-rs))
|
|
|
|
|
(is (= 4 @rows))
|
|
|
|
|
(is (= 2 @rss))
|
|
|
|
|
;; fourth call, one row, one result set (but no rs!-fn)
|
|
|
|
|
(jdbc/execute-one! mw-ds ["select * from fruit"])
|
|
|
|
|
(is (= 4 @calls))
|
|
|
|
|
(is (= 3 @seen-rs))
|
|
|
|
|
(is (= 5 @rows))
|
|
|
|
|
(is (= 2 @rss))))
|
2019-11-18 01:09:14 +00:00
|
|
|
|
|
|
|
|
;; does middleware compose?
|
|
|
|
|
(deftest middleware-composition
|
|
|
|
|
(let [pre (atom 0)
|
|
|
|
|
post (atom 0)
|
|
|
|
|
rows (atom 0)
|
|
|
|
|
inner (mw/wrapper (ds) {:pre-execute-fn #(do (swap! pre inc) [%1 %2])})
|
|
|
|
|
mw-ds (mw/wrapper inner {:post-execute-fn #(do (swap! post inc) [%1 %2])})]
|
|
|
|
|
(jdbc/execute! mw-ds ["select * from fruit"]
|
|
|
|
|
{:row!-fn (fn [row _] (swap! rows inc) row)})
|
|
|
|
|
(is (= 1 @pre))
|
|
|
|
|
(is (= 1 @post))
|
|
|
|
|
(is (= 4 @rows))))
|