Back

with-logging (clj)

(source)

function

(with-logging connectable sql-logger & [result-logger])
Given a connectable/transactable object and a sql/params logging function and an optional result 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 sql/params logging function will be called with two arguments: * a symbol indicating which operation is being performed: * `next.jdbc/plan`, `next.jdbc/execute-one!`, `next.jdbc/execute!`, or `next.jdbc/prepare` * 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. This means you can use this mechanism to provide some timing information, since your sql/params logging function can return the current system time, and your result logging function can then calculate the elapsed time. There is an example of this in the Naive Logging with Timing section of Getting Started. 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 either the result of the `execute!` or `execute-one!` call or an exception if the call failed. 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` 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.

Examples

next-jdbc
(ns next.jdbc-test
  "Basic tests for the primary API of `next.jdbc`."
  (:require [clojure.core.reducers :as r]
            [clojure.string :as str]
            [clojure.test :refer [deftest is testing use-fixtures]]
            [next.jdbc :as jdbc]
            [next.jdbc.connection :as c]
            [next.jdbc.test-fixtures
             :refer [with-test-db db ds column
                     default-options stored-proc?
                     derby? hsqldb? jtds? mssql? mysql? postgres? sqlite?]]
            [next.jdbc.prepare :as prep]
            [next.jdbc.result-set :as rs]
            [next.jdbc.specs :as specs]
            [next.jdbc.types :as types])
  (:import (com.zaxxer.hikari HikariDataSource)
           (com.mchange.v2.c3p0 ComboPooledDataSource PooledDataSource)
           (java.sql ResultSet ResultSetMetaData)))

(deftest execute-batch-connectable-tests
  (testing "simple batch insert"
    (is (= [1 1 1 1 1 1 1 1 1 13]
           (try
             (let [result (jdbc/execute-batch! (ds)
                                               "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) ["delete from fruit where id > 4"])))))
    (is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"])))))
  (testing "batch with-options"
    (is (= [1 1 1 1 1 1 1 1 1 13]
           (try
             (let [result (jdbc/execute-batch! (jdbc/with-options (ds) {})
                                               "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) ["delete from fruit where id > 4"])))))
    (is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"])))))
  (testing "batch with-logging"
    (is (= [1 1 1 1 1 1 1 1 1 13]
           (try
             (let [result (jdbc/execute-batch! (jdbc/with-logging (ds) 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) ["delete from fruit where id > 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]
           (try
             (let [result (jdbc/execute-batch! (ds)
                                               "INSERT INTO fruit (name, appearance) VALUES (?,?)"
                                               [["fruit1" "one"]
                                                ["fruit2" "two"]
                                                ["fruit3" "three"]
                                                ["fruit4" "four"]
                                                ["fruit5" "five"]
                                                ["fruit6" "six"]
                                                ["fruit7" "seven"]
                                                ["fruit8" "eight"]
                                                ["fruit9" "nine"]]
                                               {:batch-size 3})]
               (conj result (count (jdbc/execute! (ds) ["select * from fruit"]))))
             (finally
               (jdbc/execute-one! (ds) ["delete from fruit where id > 4"])))))
    (is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"])))))
  (testing "big batch insert"
    (is (= [1 1 1 1 1 1 1 1 1 13]
           (try
             (let [result (jdbc/execute-batch! (ds)
                                               "INSERT INTO fruit (name, appearance) VALUES (?,?)"
                                               [["fruit1" "one"]
                                                ["fruit2" "two"]
                                                ["fruit3" "three"]
                                                ["fruit4" "four"]
                                                ["fruit5" "five"]
                                                ["fruit6" "six"]
                                                ["fruit7" "seven"]
                                                ["fruit8" "eight"]
                                                ["fruit9" "nine"]]
                                               {:batch-size 8})]
               (conj result (count (jdbc/execute! (ds) ["select * from fruit"]))))
             (finally
               (jdbc/execute-one! (ds) ["delete from fruit where id > 4"])))))
    (is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"])))))
  (testing "large batch insert"
    (when-not (or (jtds?) (sqlite?))
      (is (= [1 1 1 1 1 1 1 1 1 13]
             (try
               (let [result (jdbc/execute-batch! (ds)
                                                 "INSERT INTO fruit (name, appearance) VALUES (?,?)"
                                                 [["fruit1" "one"]
                                                  ["fruit2" "two"]
                                                  ["fruit3" "three"]
                                                  ["fruit4" "four"]
                                                  ["fruit5" "five"]
                                                  ["fruit6" "six"]
                                                  ["fruit7" "seven"]
                                                  ["fruit8" "eight"]
                                                  ["fruit9" "nine"]]
                                                 {:batch-size 4
                                                  :large true})]
                 (conj result (count (jdbc/execute! (ds) ["select * from fruit"]))))
               (finally
                 (jdbc/execute-one! (ds) ["delete from fruit where id > 4"])))))
      (is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"]))))))
  (testing "return generated keys"
    (when-not (or (mssql?) (sqlite?))
      (let [results
            (try
              (let [result (jdbc/execute-batch! (ds)
                                                "INSERT INTO fruit (name, appearance) VALUES (?,?)"
                                                [["fruit1" "one"]
                                                 ["fruit2" "two"]
                                                 ["fruit3" "three"]
                                                 ["fruit4" "four"]
                                                 ["fruit5" "five"]
                                                 ["fruit6" "six"]
                                                 ["fruit7" "seven"]
                                                 ["fruit8" "eight"]
                                                 ["fruit9" "nine"]]
                                                ;; note: we need both :return-keys true for creating
                                                ;; the PreparedStatement and :return-generated-keys
                                                ;; true to control the way batch execution happens:
                                                {:batch-size 4 :return-keys true
                                                 :return-generated-keys true})]
                (conj result (count (jdbc/execute! (ds) ["select * from fruit"]))))
              (finally
                (jdbc/execute-one! (ds) ["delete from fruit where id > 4"])))]
        (is (= 13 (last results)))
        (is (every? map? (butlast results)))
        ;; Derby and SQLite only return one generated key per batch so there
        ;; are only three keys, plus the overall count here:
        (is (< 3 (count results))))
      (is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"])))))))
seancorfield/next-jdbc
(ns next.jdbc-test
  "Basic tests for the primary API of `next.jdbc`."
  (:require [clojure.core.reducers :as r]
            [clojure.string :as str]
            [clojure.test :refer [deftest is testing use-fixtures]]
            [next.jdbc :as jdbc]
            [next.jdbc.connection :as c]
            [next.jdbc.test-fixtures
             :refer [with-test-db db ds column
                     default-options stored-proc?
                     derby? hsqldb? jtds? mssql? mysql? postgres? sqlite?]]
            [next.jdbc.prepare :as prep]
            [next.jdbc.result-set :as rs]
            [next.jdbc.specs :as specs]
            [next.jdbc.types :as types])
  (:import (com.zaxxer.hikari HikariDataSource)
           (com.mchange.v2.c3p0 ComboPooledDataSource PooledDataSource)
           (java.sql ResultSet ResultSetMetaData)))

(deftest execute-batch-connectable-tests
  (testing "simple batch insert"
    (is (= [1 1 1 1 1 1 1 1 1 13]
           (try
             (let [result (jdbc/execute-batch! (ds)
                                               "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) ["delete from fruit where id > 4"])))))
    (is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"])))))
  (testing "batch with-options"
    (is (= [1 1 1 1 1 1 1 1 1 13]
           (try
             (let [result (jdbc/execute-batch! (jdbc/with-options (ds) {})
                                               "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) ["delete from fruit where id > 4"])))))
    (is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"])))))
  (testing "batch with-logging"
    (is (= [1 1 1 1 1 1 1 1 1 13]
           (try
             (let [result (jdbc/execute-batch! (jdbc/with-logging (ds) 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) ["delete from fruit where id > 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]
           (try
             (let [result (jdbc/execute-batch! (ds)
                                               "INSERT INTO fruit (name, appearance) VALUES (?,?)"
                                               [["fruit1" "one"]
                                                ["fruit2" "two"]
                                                ["fruit3" "three"]
                                                ["fruit4" "four"]
                                                ["fruit5" "five"]
                                                ["fruit6" "six"]
                                                ["fruit7" "seven"]
                                                ["fruit8" "eight"]
                                                ["fruit9" "nine"]]
                                               {:batch-size 3})]
               (conj result (count (jdbc/execute! (ds) ["select * from fruit"]))))
             (finally
               (jdbc/execute-one! (ds) ["delete from fruit where id > 4"])))))
    (is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"])))))
  (testing "big batch insert"
    (is (= [1 1 1 1 1 1 1 1 1 13]
           (try
             (let [result (jdbc/execute-batch! (ds)
                                               "INSERT INTO fruit (name, appearance) VALUES (?,?)"
                                               [["fruit1" "one"]
                                                ["fruit2" "two"]
                                                ["fruit3" "three"]
                                                ["fruit4" "four"]
                                                ["fruit5" "five"]
                                                ["fruit6" "six"]
                                                ["fruit7" "seven"]
                                                ["fruit8" "eight"]
                                                ["fruit9" "nine"]]
                                               {:batch-size 8})]
               (conj result (count (jdbc/execute! (ds) ["select * from fruit"]))))
             (finally
               (jdbc/execute-one! (ds) ["delete from fruit where id > 4"])))))
    (is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"])))))
  (testing "large batch insert"
    (when-not (or (jtds?) (sqlite?))
      (is (= [1 1 1 1 1 1 1 1 1 13]
             (try
               (let [result (jdbc/execute-batch! (ds)
                                                 "INSERT INTO fruit (name, appearance) VALUES (?,?)"
                                                 [["fruit1" "one"]
                                                  ["fruit2" "two"]
                                                  ["fruit3" "three"]
                                                  ["fruit4" "four"]
                                                  ["fruit5" "five"]
                                                  ["fruit6" "six"]
                                                  ["fruit7" "seven"]
                                                  ["fruit8" "eight"]
                                                  ["fruit9" "nine"]]
                                                 {:batch-size 4
                                                  :large true})]
                 (conj result (count (jdbc/execute! (ds) ["select * from fruit"]))))
               (finally
                 (jdbc/execute-one! (ds) ["delete from fruit where id > 4"])))))
      (is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"]))))))
  (testing "return generated keys"
    (when-not (or (mssql?) (sqlite?))
      (let [results
            (try
              (let [result (jdbc/execute-batch! (ds)
                                                "INSERT INTO fruit (name, appearance) VALUES (?,?)"
                                                [["fruit1" "one"]
                                                 ["fruit2" "two"]
                                                 ["fruit3" "three"]
                                                 ["fruit4" "four"]
                                                 ["fruit5" "five"]
                                                 ["fruit6" "six"]
                                                 ["fruit7" "seven"]
                                                 ["fruit8" "eight"]
                                                 ["fruit9" "nine"]]
                                                ;; note: we need both :return-keys true for creating
                                                ;; the PreparedStatement and :return-generated-keys
                                                ;; true to control the way batch execution happens:
                                                {:batch-size 4 :return-keys true
                                                 :return-generated-keys true})]
                (conj result (count (jdbc/execute! (ds) ["select * from fruit"]))))
              (finally
                (jdbc/execute-one! (ds) ["delete from fruit where id > 4"])))]
        (is (= 13 (last results)))
        (is (every? map? (butlast results)))
        ;; Derby and SQLite only return one generated key per batch so there
        ;; are only three keys, plus the overall count here:
        (is (< 3 (count results))))
      (is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"])))))))