Add optional MySQL testing
This commit is contained in:
parent
8fbd0837ab
commit
774e08236f
7 changed files with 118 additions and 102 deletions
|
|
@ -6,7 +6,9 @@ Only accretive/fixative changes will be made from now on.
|
||||||
|
|
||||||
The following changes have been committed to the **master** branch since the 1.0.10 release:
|
The following changes have been committed to the **master** branch since the 1.0.10 release:
|
||||||
|
|
||||||
* None.
|
* Add testing against MySQL (run tests with environment variables `NEXT_JDBC_TEST_MYSQL=yes` and `MYSQL_ROOT_PASSWORD` set to your local MySQL `root` user password; assumes you have already created an empty database called `clojure_test`).
|
||||||
|
* Bump several JDBC driver versions for up-to-date testing.
|
||||||
|
* Minor documentation fixes.
|
||||||
|
|
||||||
## Stable Builds
|
## Stable Builds
|
||||||
|
|
||||||
|
|
|
||||||
16
deps.edn
16
deps.edn
|
|
@ -5,21 +5,21 @@
|
||||||
{:test {:extra-paths ["test"]
|
{:test {:extra-paths ["test"]
|
||||||
:extra-deps {org.clojure/test.check {:mvn/version "0.10.0"}
|
:extra-deps {org.clojure/test.check {:mvn/version "0.10.0"}
|
||||||
;; connection pooling
|
;; connection pooling
|
||||||
com.zaxxer/HikariCP {:mvn/version "3.3.1"}
|
com.zaxxer/HikariCP {:mvn/version "3.4.1"}
|
||||||
com.mchange/c3p0 {:mvn/version "0.9.5.4"}
|
com.mchange/c3p0 {:mvn/version "0.9.5.4"}
|
||||||
;; JDBC drivers
|
;; JDBC drivers
|
||||||
org.apache.derby/derby {:mvn/version "10.14.2.0"} ; behind
|
org.apache.derby/derby {:mvn/version "10.14.2.0"} ; behind
|
||||||
org.hsqldb/hsqldb {:mvn/version "2.5.0"}
|
org.hsqldb/hsqldb {:mvn/version "2.5.0"}
|
||||||
com.h2database/h2 {:mvn/version "1.4.199"}
|
com.h2database/h2 {:mvn/version "1.4.200"}
|
||||||
net.sourceforge.jtds/jtds {:mvn/version "1.3.1"}
|
net.sourceforge.jtds/jtds {:mvn/version "1.3.1"}
|
||||||
mysql/mysql-connector-java {:mvn/version "5.1.41"} ; behind
|
mysql/mysql-connector-java {:mvn/version "8.0.18"}
|
||||||
org.postgresql/postgresql {:mvn/version "42.2.6"}
|
org.postgresql/postgresql {:mvn/version "42.2.8"}
|
||||||
com.opentable.components/otj-pg-embedded {:mvn/version "0.13.1"}
|
com.opentable.components/otj-pg-embedded {:mvn/version "0.13.3"}
|
||||||
com.impossibl.pgjdbc-ng/pgjdbc-ng {:mvn/version "0.8.2"}
|
com.impossibl.pgjdbc-ng/pgjdbc-ng {:mvn/version "0.8.3"}
|
||||||
org.xerial/sqlite-jdbc {:mvn/version "3.28.0"}
|
org.xerial/sqlite-jdbc {:mvn/version "3.28.0"}
|
||||||
com.microsoft.sqlserver/mssql-jdbc {:mvn/version "7.2.2.jre8"}
|
com.microsoft.sqlserver/mssql-jdbc {:mvn/version "7.4.1.jre8"}
|
||||||
;; supplementary test stuff
|
;; supplementary test stuff
|
||||||
org.slf4j/slf4j-nop {:mvn/version "1.7.28"}}}
|
org.slf4j/slf4j-nop {:mvn/version "1.7.29"}}}
|
||||||
:runner
|
:runner
|
||||||
{:extra-deps {com.cognitect/test-runner
|
{:extra-deps {com.cognitect/test-runner
|
||||||
{:git/url "https://github.com/cognitect-labs/test-runner"
|
{:git/url "https://github.com/cognitect-labs/test-runner"
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
[clojure.test :refer [deftest is testing use-fixtures]]
|
[clojure.test :refer [deftest is testing use-fixtures]]
|
||||||
[next.jdbc.optional :as opt]
|
[next.jdbc.optional :as opt]
|
||||||
[next.jdbc.protocols :as p]
|
[next.jdbc.protocols :as p]
|
||||||
[next.jdbc.test-fixtures :refer [with-test-db ds postgres?]])
|
[next.jdbc.test-fixtures :refer [with-test-db ds column]])
|
||||||
(:import (java.sql ResultSet ResultSetMetaData)))
|
(:import (java.sql ResultSet ResultSetMetaData)))
|
||||||
|
|
||||||
(set! *warn-on-reflection* true)
|
(set! *warn-on-reflection* true)
|
||||||
|
|
@ -19,17 +19,17 @@
|
||||||
["select * from fruit where id = ?" 1]
|
["select * from fruit where id = ?" 1]
|
||||||
{:builder-fn opt/as-maps})]
|
{:builder-fn opt/as-maps})]
|
||||||
(is (map? row))
|
(is (map? row))
|
||||||
(is (not (contains? row (if (postgres?) :fruit/grade :FRUIT/GRADE))))
|
(is (not (contains? row (column :FRUIT/GRADE))))
|
||||||
(is (= 1 ((if (postgres?) :fruit/id :FRUIT/ID) row)))
|
(is (= 1 ((column :FRUIT/ID) row)))
|
||||||
(is (= "Apple" ((if (postgres?) :fruit/name :FRUIT/NAME) row)))))
|
(is (= "Apple" ((column :FRUIT/NAME) row)))))
|
||||||
(testing "unqualified row builder"
|
(testing "unqualified row builder"
|
||||||
(let [row (p/-execute-one (ds)
|
(let [row (p/-execute-one (ds)
|
||||||
["select * from fruit where id = ?" 2]
|
["select * from fruit where id = ?" 2]
|
||||||
{:builder-fn opt/as-unqualified-maps})]
|
{:builder-fn opt/as-unqualified-maps})]
|
||||||
(is (map? row))
|
(is (map? row))
|
||||||
(is (not (contains? row (if (postgres?) :cost :COST))))
|
(is (not (contains? row (column :COST))))
|
||||||
(is (= 2 ((if (postgres?) :id :ID) row)))
|
(is (= 2 ((column :ID) row)))
|
||||||
(is (= "Banana" ((if (postgres?) :name :NAME) row)))))
|
(is (= "Banana" ((column :NAME) row)))))
|
||||||
(testing "lower-case row builder"
|
(testing "lower-case row builder"
|
||||||
(let [row (p/-execute-one (ds)
|
(let [row (p/-execute-one (ds)
|
||||||
["select * from fruit where id = ?" 3]
|
["select * from fruit where id = ?" 3]
|
||||||
|
|
@ -52,9 +52,9 @@
|
||||||
:label-fn str/lower-case
|
:label-fn str/lower-case
|
||||||
:qualifier-fn identity})]
|
:qualifier-fn identity})]
|
||||||
(is (map? row))
|
(is (map? row))
|
||||||
(is (not (contains? row (if (postgres?) :fruit/appearance :FRUIT/appearance))))
|
(is (not (contains? row (column :FRUIT/appearance))))
|
||||||
(is (= 3 ((if (postgres?) :fruit/id :FRUIT/id) row)))
|
(is (= 3 ((column :FRUIT/id) row)))
|
||||||
(is (= "Peach" ((if (postgres?) :fruit/name :FRUIT/name) row))))))
|
(is (= "Peach" ((column :FRUIT/name) row))))))
|
||||||
|
|
||||||
(defn- default-column-reader
|
(defn- default-column-reader
|
||||||
[^ResultSet rs ^ResultSetMetaData rsmeta ^Integer i]
|
[^ResultSet rs ^ResultSetMetaData rsmeta ^Integer i]
|
||||||
|
|
@ -68,9 +68,9 @@
|
||||||
opt/as-maps
|
opt/as-maps
|
||||||
default-column-reader)})]
|
default-column-reader)})]
|
||||||
(is (map? row))
|
(is (map? row))
|
||||||
(is (not (contains? row (if (postgres?) :fruit/grade :FRUIT/GRADE))))
|
(is (not (contains? row (column :FRUIT/GRADE))))
|
||||||
(is (= 1 ((if (postgres?) :fruit/id :FRUIT/ID) row)))
|
(is (= 1 ((column :FRUIT/ID) row)))
|
||||||
(is (= "Apple" ((if (postgres?) :fruit/name :FRUIT/NAME) row)))))
|
(is (= "Apple" ((column :FRUIT/NAME) row)))))
|
||||||
(testing "unqualified row builder"
|
(testing "unqualified row builder"
|
||||||
(let [row (p/-execute-one (ds)
|
(let [row (p/-execute-one (ds)
|
||||||
["select * from fruit where id = ?" 2]
|
["select * from fruit where id = ?" 2]
|
||||||
|
|
@ -78,9 +78,9 @@
|
||||||
opt/as-unqualified-maps
|
opt/as-unqualified-maps
|
||||||
default-column-reader)})]
|
default-column-reader)})]
|
||||||
(is (map? row))
|
(is (map? row))
|
||||||
(is (not (contains? row (if (postgres?) :cost :COST))))
|
(is (not (contains? row (column :COST))))
|
||||||
(is (= 2 ((if (postgres?) :id :ID) row)))
|
(is (= 2 ((column :ID) row)))
|
||||||
(is (= "Banana" ((if (postgres?) :name :NAME) row)))))
|
(is (= "Banana" ((column :NAME) row)))))
|
||||||
(testing "lower-case row builder"
|
(testing "lower-case row builder"
|
||||||
(let [row (p/-execute-one (ds)
|
(let [row (p/-execute-one (ds)
|
||||||
["select * from fruit where id = ?" 3]
|
["select * from fruit where id = ?" 3]
|
||||||
|
|
@ -109,6 +109,6 @@
|
||||||
:label-fn str/lower-case
|
:label-fn str/lower-case
|
||||||
:qualifier-fn identity})]
|
:qualifier-fn identity})]
|
||||||
(is (map? row))
|
(is (map? row))
|
||||||
(is (not (contains? row (if (postgres?) :fruit/appearance :FRUIT/appearance))))
|
(is (not (contains? row (column :FRUIT/appearance))))
|
||||||
(is (= 3 ((if (postgres?) :fruit/id :FRUIT/id) row)))
|
(is (= 3 ((column :FRUIT/id) row)))
|
||||||
(is (= "Peach" ((if (postgres?) :fruit/name :FRUIT/name) row))))))
|
(is (= "Peach" ((column :FRUIT/name) row))))))
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@
|
||||||
[clojure.test :refer [deftest is testing use-fixtures]]
|
[clojure.test :refer [deftest is testing use-fixtures]]
|
||||||
[next.jdbc.protocols :as p]
|
[next.jdbc.protocols :as p]
|
||||||
[next.jdbc.result-set :as rs]
|
[next.jdbc.result-set :as rs]
|
||||||
[next.jdbc.test-fixtures :refer [with-test-db ds postgres?]])
|
[next.jdbc.test-fixtures :refer [with-test-db ds column
|
||||||
|
mysql? postgres?]])
|
||||||
(:import (java.sql ResultSet ResultSetMetaData)))
|
(:import (java.sql ResultSet ResultSetMetaData)))
|
||||||
|
|
||||||
(set! *warn-on-reflection* true)
|
(set! *warn-on-reflection* true)
|
||||||
|
|
@ -28,8 +29,8 @@
|
||||||
(is (= 1 v))
|
(is (= 1 v))
|
||||||
(let [object (d/nav data :table/fruit_id v)]
|
(let [object (d/nav data :table/fruit_id v)]
|
||||||
;; check nav produces a single map with the expected key/value data
|
;; check nav produces a single map with the expected key/value data
|
||||||
(is (= 1 ((if (postgres?) :fruit/id :FRUIT/ID) object)))
|
(is (= 1 ((column :FRUIT/ID) object)))
|
||||||
(is (= "Apple" ((if (postgres?) :fruit/name :FRUIT/NAME) object))))))
|
(is (= "Apple" ((column :FRUIT/NAME) object))))))
|
||||||
(testing "custom schema *-to-1"
|
(testing "custom schema *-to-1"
|
||||||
(let [connectable (ds)
|
(let [connectable (ds)
|
||||||
test-row (rs/datafiable-row {:foo/bar 2} connectable
|
test-row (rs/datafiable-row {:foo/bar 2} connectable
|
||||||
|
|
@ -40,8 +41,8 @@
|
||||||
(is (= 2 v))
|
(is (= 2 v))
|
||||||
(let [object (d/nav data :foo/bar v)]
|
(let [object (d/nav data :foo/bar v)]
|
||||||
;; check nav produces a single map with the expected key/value data
|
;; check nav produces a single map with the expected key/value data
|
||||||
(is (= 2 ((if (postgres?) :fruit/id :FRUIT/ID) object)))
|
(is (= 2 ((column :FRUIT/ID) object)))
|
||||||
(is (= "Banana" ((if (postgres?) :fruit/name :FRUIT/NAME) object))))))
|
(is (= "Banana" ((column :FRUIT/NAME) object))))))
|
||||||
(testing "custom schema *-to-many"
|
(testing "custom schema *-to-many"
|
||||||
(let [connectable (ds)
|
(let [connectable (ds)
|
||||||
test-row (rs/datafiable-row {:foo/bar 3} connectable
|
test-row (rs/datafiable-row {:foo/bar 3} connectable
|
||||||
|
|
@ -53,8 +54,8 @@
|
||||||
(let [object (d/nav data :foo/bar v)]
|
(let [object (d/nav data :foo/bar v)]
|
||||||
;; check nav produces a result set with the expected key/value data
|
;; check nav produces a result set with the expected key/value data
|
||||||
(is (vector? object))
|
(is (vector? object))
|
||||||
(is (= 3 ((if (postgres?) :fruit/id :FRUIT/ID) (first object))))
|
(is (= 3 ((column :FRUIT/ID) (first object))))
|
||||||
(is (= "Peach" ((if (postgres?) :fruit/name :FRUIT/NAME) (first object)))))))
|
(is (= "Peach" ((column :FRUIT/NAME) (first object)))))))
|
||||||
(testing "legacy schema tuples"
|
(testing "legacy schema tuples"
|
||||||
(let [connectable (ds)
|
(let [connectable (ds)
|
||||||
test-row (rs/datafiable-row {:foo/bar 2} connectable
|
test-row (rs/datafiable-row {:foo/bar 2} connectable
|
||||||
|
|
@ -65,8 +66,8 @@
|
||||||
(is (= 2 v))
|
(is (= 2 v))
|
||||||
(let [object (d/nav data :foo/bar v)]
|
(let [object (d/nav data :foo/bar v)]
|
||||||
;; check nav produces a single map with the expected key/value data
|
;; check nav produces a single map with the expected key/value data
|
||||||
(is (= 2 ((if (postgres?) :fruit/id :FRUIT/ID) object)))
|
(is (= 2 ((column :FRUIT/ID) object)))
|
||||||
(is (= "Banana" ((if (postgres?) :fruit/name :FRUIT/NAME) object)))))
|
(is (= "Banana" ((column :FRUIT/NAME) object)))))
|
||||||
(let [connectable (ds)
|
(let [connectable (ds)
|
||||||
test-row (rs/datafiable-row {:foo/bar 3} connectable
|
test-row (rs/datafiable-row {:foo/bar 3} connectable
|
||||||
{:schema {:foo/bar [:fruit :id :many]}})
|
{:schema {:foo/bar [:fruit :id :many]}})
|
||||||
|
|
@ -77,8 +78,8 @@
|
||||||
(let [object (d/nav data :foo/bar v)]
|
(let [object (d/nav data :foo/bar v)]
|
||||||
;; check nav produces a result set with the expected key/value data
|
;; check nav produces a result set with the expected key/value data
|
||||||
(is (vector? object))
|
(is (vector? object))
|
||||||
(is (= 3 ((if (postgres?) :fruit/id :FRUIT/ID) (first object))))
|
(is (= 3 ((column :FRUIT/ID) (first object))))
|
||||||
(is (= "Peach" ((if (postgres?) :fruit/name :FRUIT/NAME) (first object))))))))
|
(is (= "Peach" ((column :FRUIT/NAME) (first object))))))))
|
||||||
|
|
||||||
(deftest test-map-row-builder
|
(deftest test-map-row-builder
|
||||||
(testing "default row builder"
|
(testing "default row builder"
|
||||||
|
|
@ -86,27 +87,27 @@
|
||||||
["select * from fruit where id = ?" 1]
|
["select * from fruit where id = ?" 1]
|
||||||
{})]
|
{})]
|
||||||
(is (map? row))
|
(is (map? row))
|
||||||
(is (contains? row (if (postgres?) :fruit/grade :FRUIT/GRADE)))
|
(is (contains? row (column :FRUIT/GRADE)))
|
||||||
(is (nil? ((if (postgres?) :fruit/grade :FRUIT/GRADE) row)))
|
(is (nil? ((column :FRUIT/GRADE) row)))
|
||||||
(is (= 1 ((if (postgres?) :fruit/id :FRUIT/ID) row)))
|
(is (= 1 ((column :FRUIT/ID) row)))
|
||||||
(is (= "Apple" ((if (postgres?) :fruit/name :FRUIT/NAME) row))))
|
(is (= "Apple" ((column :FRUIT/NAME) row))))
|
||||||
(let [rs (p/-execute-all (ds)
|
(let [rs (p/-execute-all (ds)
|
||||||
["select * from fruit order by id"]
|
["select * from fruit order by id"]
|
||||||
{})]
|
{})]
|
||||||
(is (every? map? rs))
|
(is (every? map? rs))
|
||||||
(is (= 1 ((if (postgres?) :fruit/id :FRUIT/ID) (first rs))))
|
(is (= 1 ((column :FRUIT/ID) (first rs))))
|
||||||
(is (= "Apple" ((if (postgres?) :fruit/name :FRUIT/NAME) (first rs))))
|
(is (= "Apple" ((column :FRUIT/NAME) (first rs))))
|
||||||
(is (= 4 ((if (postgres?) :fruit/id :FRUIT/ID) (last rs))))
|
(is (= 4 ((column :FRUIT/ID) (last rs))))
|
||||||
(is (= "Orange" ((if (postgres?) :fruit/name :FRUIT/NAME) (last rs))))))
|
(is (= "Orange" ((column :FRUIT/NAME) (last rs))))))
|
||||||
(testing "unqualified row builder"
|
(testing "unqualified row builder"
|
||||||
(let [row (p/-execute-one (ds)
|
(let [row (p/-execute-one (ds)
|
||||||
["select * from fruit where id = ?" 2]
|
["select * from fruit where id = ?" 2]
|
||||||
{:builder-fn rs/as-unqualified-maps})]
|
{:builder-fn rs/as-unqualified-maps})]
|
||||||
(is (map? row))
|
(is (map? row))
|
||||||
(is (contains? row (if (postgres?) :cost :COST)))
|
(is (contains? row (column :COST)))
|
||||||
(is (nil? ((if (postgres?) :cost :COST) row)))
|
(is (nil? ((column :COST) row)))
|
||||||
(is (= 2 ((if (postgres?) :id :ID) row)))
|
(is (= 2 ((column :ID) row)))
|
||||||
(is (= "Banana" ((if (postgres?) :name :NAME) row)))))
|
(is (= "Banana" ((column :NAME) row)))))
|
||||||
(testing "lower-case row builder"
|
(testing "lower-case row builder"
|
||||||
(let [row (p/-execute-one (ds)
|
(let [row (p/-execute-one (ds)
|
||||||
["select * from fruit where id = ?" 3]
|
["select * from fruit where id = ?" 3]
|
||||||
|
|
@ -130,10 +131,10 @@
|
||||||
:label-fn str/lower-case
|
:label-fn str/lower-case
|
||||||
:qualifier-fn identity})]
|
:qualifier-fn identity})]
|
||||||
(is (map? row))
|
(is (map? row))
|
||||||
(is (contains? row (if (postgres?) :fruit/appearance :FRUIT/appearance)))
|
(is (contains? row (column :FRUIT/appearance)))
|
||||||
(is (nil? ((if (postgres?) :fruit/appearance :FRUIT/appearance) row)))
|
(is (nil? ((column :FRUIT/appearance) row)))
|
||||||
(is (= 3 ((if (postgres?) :fruit/id :FRUIT/id) row)))
|
(is (= 3 ((column :FRUIT/id) row)))
|
||||||
(is (= "Peach" ((if (postgres?) :fruit/name :FRUIT/name) row)))))
|
(is (= "Peach" ((column :FRUIT/name) row)))))
|
||||||
(testing "adapted row builder"
|
(testing "adapted row builder"
|
||||||
(let [row (p/-execute-one (ds)
|
(let [row (p/-execute-one (ds)
|
||||||
["select * from fruit where id = ?" 3]
|
["select * from fruit where id = ?" 3]
|
||||||
|
|
@ -151,10 +152,10 @@
|
||||||
:label-fn str/lower-case
|
:label-fn str/lower-case
|
||||||
:qualifier-fn identity})]
|
:qualifier-fn identity})]
|
||||||
(is (map? row))
|
(is (map? row))
|
||||||
(is (contains? row (if (postgres?) :fruit/appearance :FRUIT/appearance)))
|
(is (contains? row (column :FRUIT/appearance)))
|
||||||
(is (nil? ((if (postgres?) :fruit/appearance :FRUIT/appearance) row)))
|
(is (nil? ((column :FRUIT/appearance) row)))
|
||||||
(is (= 3 ((if (postgres?) :fruit/id :FRUIT/id) row)))
|
(is (= 3 ((column :FRUIT/id) row)))
|
||||||
(is (= "Peach" ((if (postgres?) :fruit/name :FRUIT/name) row))))))
|
(is (= "Peach" ((column :FRUIT/name) row))))))
|
||||||
|
|
||||||
(deftest test-mapify
|
(deftest test-mapify
|
||||||
(testing "no row builder is used"
|
(testing "no row builder is used"
|
||||||
|
|
@ -202,17 +203,11 @@
|
||||||
nil
|
nil
|
||||||
(p/-execute (ds) ["select * from fruit"] {})))))
|
(p/-execute (ds) ["select * from fruit"] {})))))
|
||||||
(is (map? (reduce (fn [_ row] (reduced
|
(is (map? (reduce (fn [_ row] (reduced
|
||||||
(dissoc row
|
(dissoc row (column :FRUIT/NAME))))
|
||||||
(if (postgres?)
|
|
||||||
:fruit/name
|
|
||||||
:FRUIT/NAME))))
|
|
||||||
nil
|
nil
|
||||||
(p/-execute (ds) ["select * from fruit"] {}))))
|
(p/-execute (ds) ["select * from fruit"] {}))))
|
||||||
(is (= 4 (count (reduce (fn [_ row] (reduced
|
(is (= 4 (count (reduce (fn [_ row] (reduced
|
||||||
(dissoc row
|
(dissoc row (column :FRUIT/NAME))))
|
||||||
(if (postgres?)
|
|
||||||
:fruit/name
|
|
||||||
:FRUIT/NAME))))
|
|
||||||
nil
|
nil
|
||||||
(p/-execute (ds) ["select * from fruit"] {})))))
|
(p/-execute (ds) ["select * from fruit"] {})))))
|
||||||
(is (seq? (reduce (fn [_ row] (reduced (seq row)))
|
(is (seq? (reduce (fn [_ row] (reduced (seq row)))
|
||||||
|
|
@ -291,7 +286,7 @@
|
||||||
metadata))))
|
metadata))))
|
||||||
|
|
||||||
(deftest clob-reading
|
(deftest clob-reading
|
||||||
(when-not (postgres?) ; embedded postgres does not support clob
|
(when-not (or (mysql?) (postgres?)) ; no clob in mysql or embedded postgres
|
||||||
(with-open [con (p/get-connection (ds) {})]
|
(with-open [con (p/get-connection (ds) {})]
|
||||||
(try
|
(try
|
||||||
(p/-execute-one con ["DROP TABLE CLOBBER"] {})
|
(p/-execute-one con ["DROP TABLE CLOBBER"] {})
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
[next.jdbc.specs :as specs]
|
[next.jdbc.specs :as specs]
|
||||||
[next.jdbc.sql :as sql]
|
[next.jdbc.sql :as sql]
|
||||||
[next.jdbc.test-fixtures
|
[next.jdbc.test-fixtures
|
||||||
:refer [with-test-db ds derby? postgres? sqlite?]]))
|
:refer [with-test-db ds column derby? mysql? postgres? sqlite?]]))
|
||||||
|
|
||||||
(set! *warn-on-reflection* true)
|
(set! *warn-on-reflection* true)
|
||||||
|
|
||||||
|
|
@ -82,8 +82,8 @@
|
||||||
(is (= 4 (count rs)))
|
(is (= 4 (count rs)))
|
||||||
(is (every? map? rs))
|
(is (every? map? rs))
|
||||||
(is (every? meta rs))
|
(is (every? meta rs))
|
||||||
(is (= 1 ((if (postgres?) :fruit/id :FRUIT/ID) (first rs))))
|
(is (= 1 ((column :FRUIT/ID) (first rs))))
|
||||||
(is (= 4 ((if (postgres?) :fruit/id :FRUIT/ID) (last rs))))))
|
(is (= 4 ((column :FRUIT/ID) (last rs))))))
|
||||||
|
|
||||||
(deftest test-find-by-keys
|
(deftest test-find-by-keys
|
||||||
(let [rs (sql/find-by-keys (ds) :fruit {:appearance "neon-green"})]
|
(let [rs (sql/find-by-keys (ds) :fruit {:appearance "neon-green"})]
|
||||||
|
|
@ -93,26 +93,26 @@
|
||||||
(is (= 1 (count rs)))
|
(is (= 1 (count rs)))
|
||||||
(is (every? map? rs))
|
(is (every? map? rs))
|
||||||
(is (every? meta rs))
|
(is (every? meta rs))
|
||||||
(is (= 2 ((if (postgres?) :fruit/id :FRUIT/ID) (first rs))))))
|
(is (= 2 ((column :FRUIT/ID) (first rs))))))
|
||||||
|
|
||||||
(deftest test-get-by-id
|
(deftest test-get-by-id
|
||||||
(is (nil? (sql/get-by-id (ds) :fruit -1)))
|
(is (nil? (sql/get-by-id (ds) :fruit -1)))
|
||||||
(let [row (sql/get-by-id (ds) :fruit 3)]
|
(let [row (sql/get-by-id (ds) :fruit 3)]
|
||||||
(is (map? row))
|
(is (map? row))
|
||||||
(is (= "Peach" ((if (postgres?) :fruit/name :FRUIT/NAME) row))))
|
(is (= "Peach" ((column :FRUIT/NAME) row))))
|
||||||
(let [row (sql/get-by-id (ds) :fruit "juicy" :appearance {})]
|
(let [row (sql/get-by-id (ds) :fruit "juicy" :appearance {})]
|
||||||
(is (map? row))
|
(is (map? row))
|
||||||
(is (= 4 ((if (postgres?) :fruit/id :FRUIT/ID) row)))
|
(is (= 4 ((column :FRUIT/ID) row)))
|
||||||
(is (= "Orange" ((if (postgres?) :fruit/name :FRUIT/NAME) row))))
|
(is (= "Orange" ((column :FRUIT/NAME) row))))
|
||||||
(let [row (sql/get-by-id (ds) :fruit "Banana" :FRUIT/NAME {})]
|
(let [row (sql/get-by-id (ds) :fruit "Banana" :FRUIT/NAME {})]
|
||||||
(is (map? row))
|
(is (map? row))
|
||||||
(is (= 2 ((if (postgres?) :fruit/id :FRUIT/ID) row)))))
|
(is (= 2 ((column :FRUIT/ID) row)))))
|
||||||
|
|
||||||
(deftest test-update!
|
(deftest test-update!
|
||||||
(try
|
(try
|
||||||
(is (= {:next.jdbc/update-count 1}
|
(is (= {:next.jdbc/update-count 1}
|
||||||
(sql/update! (ds) :fruit {:appearance "brown"} {:id 2})))
|
(sql/update! (ds) :fruit {:appearance "brown"} {:id 2})))
|
||||||
(is (= "brown" ((if (postgres?) :fruit/appearance :FRUIT/APPEARANCE)
|
(is (= "brown" ((column :FRUIT/APPEARANCE)
|
||||||
(sql/get-by-id (ds) :fruit 2))))
|
(sql/get-by-id (ds) :fruit 2))))
|
||||||
(finally
|
(finally
|
||||||
(sql/update! (ds) :fruit {:appearance "yellow"} {:id 2})))
|
(sql/update! (ds) :fruit {:appearance "yellow"} {:id 2})))
|
||||||
|
|
@ -120,13 +120,14 @@
|
||||||
(is (= {:next.jdbc/update-count 1}
|
(is (= {:next.jdbc/update-count 1}
|
||||||
(sql/update! (ds) :fruit {:appearance "green"}
|
(sql/update! (ds) :fruit {:appearance "green"}
|
||||||
["name = ?" "Banana"])))
|
["name = ?" "Banana"])))
|
||||||
(is (= "green" ((if (postgres?) :fruit/appearance :FRUIT/APPEARANCE)
|
(is (= "green" ((column :FRUIT/APPEARANCE)
|
||||||
(sql/get-by-id (ds) :fruit 2))))
|
(sql/get-by-id (ds) :fruit 2))))
|
||||||
(finally
|
(finally
|
||||||
(sql/update! (ds) :fruit {:appearance "yellow"} {:id 2}))))
|
(sql/update! (ds) :fruit {:appearance "yellow"} {:id 2}))))
|
||||||
|
|
||||||
(deftest test-insert-delete
|
(deftest test-insert-delete
|
||||||
(let [new-key (cond (derby?) :1
|
(let [new-key (cond (derby?) :1
|
||||||
|
(mysql?) :GENERATED_KEY
|
||||||
(postgres?) :fruit/id
|
(postgres?) :fruit/id
|
||||||
(sqlite?) (keyword "last_insert_rowid()")
|
(sqlite?) (keyword "last_insert_rowid()")
|
||||||
:else :FRUIT/ID)]
|
:else :FRUIT/ID)]
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@
|
||||||
|
|
||||||
(ns next.jdbc.test-fixtures
|
(ns next.jdbc.test-fixtures
|
||||||
"Multi-database testing fixtures."
|
"Multi-database testing fixtures."
|
||||||
(:require [next.jdbc :as jdbc]
|
(:require [clojure.string :as str]
|
||||||
|
[next.jdbc :as jdbc]
|
||||||
[next.jdbc.sql :as sql])
|
[next.jdbc.sql :as sql])
|
||||||
(:import (com.opentable.db.postgres.embedded EmbeddedPostgres)
|
(:import (com.opentable.db.postgres.embedded EmbeddedPostgres)
|
||||||
(javax.sql DataSource)))
|
(javax.sql DataSource)))
|
||||||
|
|
@ -24,17 +25,33 @@
|
||||||
;; it takes a while to spin up so we kick it off at startup
|
;; it takes a while to spin up so we kick it off at startup
|
||||||
(defonce embedded-pg (future (EmbeddedPostgres/start)))
|
(defonce embedded-pg (future (EmbeddedPostgres/start)))
|
||||||
|
|
||||||
|
(def ^:private test-mysql
|
||||||
|
(when (System/getenv "NEXT_JDBC_TEST_MYSQL")
|
||||||
|
{:dbtype "mysql" :dbname "clojure_test" :useSSL false
|
||||||
|
:user "root" :password (System/getenv "MYSQL_ROOT_PASSWORD")}))
|
||||||
|
|
||||||
(def ^:private test-db-specs
|
(def ^:private test-db-specs
|
||||||
[test-derby test-h2-mem test-h2 test-hsql test-sqlite test-postgres])
|
(cond-> [test-derby test-h2-mem test-h2 test-hsql test-sqlite test-postgres]
|
||||||
|
test-mysql (conj test-mysql)))
|
||||||
|
|
||||||
(def ^:private test-db-spec (atom nil))
|
(def ^:private test-db-spec (atom nil))
|
||||||
|
|
||||||
(defn derby? [] (= "derby" (:dbtype @test-db-spec)))
|
(defn derby? [] (= "derby" (:dbtype @test-db-spec)))
|
||||||
|
|
||||||
|
(defn mysql? [] (= "mysql" (:dbtype @test-db-spec)))
|
||||||
|
|
||||||
(defn postgres? [] (= "embedded-postgres" (:dbtype @test-db-spec)))
|
(defn postgres? [] (= "embedded-postgres" (:dbtype @test-db-spec)))
|
||||||
|
|
||||||
(defn sqlite? [] (= "sqlite" (:dbtype @test-db-spec)))
|
(defn sqlite? [] (= "sqlite" (:dbtype @test-db-spec)))
|
||||||
|
|
||||||
|
(defn column [k]
|
||||||
|
(let [n (namespace k)]
|
||||||
|
(keyword (when n (cond (postgres?) (str/lower-case n)
|
||||||
|
(mysql?) (str/lower-case n)
|
||||||
|
:else n))
|
||||||
|
(cond (postgres?) (str/lower-case (name k))
|
||||||
|
:else (name k)))))
|
||||||
|
|
||||||
(def ^:private test-datasource (atom nil))
|
(def ^:private test-datasource (atom nil))
|
||||||
|
|
||||||
(defn db
|
(defn db
|
||||||
|
|
@ -60,7 +77,8 @@
|
||||||
(reset! test-datasource
|
(reset! test-datasource
|
||||||
(.getPostgresDatabase ^EmbeddedPostgres @embedded-pg))
|
(.getPostgresDatabase ^EmbeddedPostgres @embedded-pg))
|
||||||
(reset! test-datasource (jdbc/get-datasource db)))
|
(reset! test-datasource (jdbc/get-datasource db)))
|
||||||
(let [auto-inc-pk
|
(let [fruit (if (mysql?) "fruit" "FRUIT") ; MySQL is case sensitive!
|
||||||
|
auto-inc-pk
|
||||||
(cond (or (derby?) (= "hsqldb" (:dbtype db)))
|
(cond (or (derby?) (= "hsqldb" (:dbtype db)))
|
||||||
(str "GENERATED ALWAYS AS IDENTITY"
|
(str "GENERATED ALWAYS AS IDENTITY"
|
||||||
" (START WITH 1, INCREMENT BY 1)"
|
" (START WITH 1, INCREMENT BY 1)"
|
||||||
|
|
@ -74,10 +92,10 @@
|
||||||
"AUTO_INCREMENT PRIMARY KEY")]
|
"AUTO_INCREMENT PRIMARY KEY")]
|
||||||
(with-open [con (jdbc/get-connection (ds))]
|
(with-open [con (jdbc/get-connection (ds))]
|
||||||
(try
|
(try
|
||||||
(jdbc/execute-one! con ["DROP TABLE FRUIT"])
|
(jdbc/execute-one! con [(str "DROP TABLE " fruit)])
|
||||||
(catch Exception _))
|
(catch Exception _))
|
||||||
(jdbc/execute-one! con [(str "
|
(jdbc/execute-one! con [(str "
|
||||||
CREATE TABLE FRUIT (
|
CREATE TABLE " fruit " (
|
||||||
ID INTEGER " auto-inc-pk ",
|
ID INTEGER " auto-inc-pk ",
|
||||||
NAME VARCHAR(32),
|
NAME VARCHAR(32),
|
||||||
APPEARANCE VARCHAR(32) DEFAULT NULL,
|
APPEARANCE VARCHAR(32) DEFAULT NULL,
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@
|
||||||
[clojure.test :refer [deftest is testing use-fixtures]]
|
[clojure.test :refer [deftest is testing use-fixtures]]
|
||||||
[next.jdbc :as jdbc]
|
[next.jdbc :as jdbc]
|
||||||
[next.jdbc.connection :as c]
|
[next.jdbc.connection :as c]
|
||||||
[next.jdbc.test-fixtures :refer [with-test-db db ds
|
[next.jdbc.test-fixtures :refer [with-test-db db ds column
|
||||||
derby? postgres?]]
|
derby? mysql? postgres?]]
|
||||||
[next.jdbc.prepare :as prep]
|
[next.jdbc.prepare :as prep]
|
||||||
[next.jdbc.result-set :as rs]
|
[next.jdbc.result-set :as rs]
|
||||||
[next.jdbc.specs :as specs])
|
[next.jdbc.specs :as specs])
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
(is (nil? (jdbc/execute-one!
|
(is (nil? (jdbc/execute-one!
|
||||||
(ds)
|
(ds)
|
||||||
["select * from fruit where appearance = ?" "neon-green"])))
|
["select * from fruit where appearance = ?" "neon-green"])))
|
||||||
(is (= "Apple" ((if (postgres?) :fruit/name :FRUIT/NAME)
|
(is (= "Apple" ((column :FRUIT/NAME)
|
||||||
(jdbc/execute-one!
|
(jdbc/execute-one!
|
||||||
(ds)
|
(ds)
|
||||||
["select * from fruit where appearance = ?" "red"])))))
|
["select * from fruit where appearance = ?" "red"])))))
|
||||||
|
|
@ -45,7 +45,7 @@
|
||||||
(ds)
|
(ds)
|
||||||
["select * from fruit where appearance = ?" "red"])]
|
["select * from fruit where appearance = ?" "red"])]
|
||||||
(is (= 1 (count rs)))
|
(is (= 1 (count rs)))
|
||||||
(is (= 1 ((if (postgres?) :fruit/id :FRUIT/ID) (first rs)))))
|
(is (= 1 ((column :FRUIT/ID) (first rs)))))
|
||||||
(let [rs (jdbc/execute!
|
(let [rs (jdbc/execute!
|
||||||
(ds)
|
(ds)
|
||||||
["select * from fruit order by id"]
|
["select * from fruit order by id"]
|
||||||
|
|
@ -53,8 +53,8 @@
|
||||||
(is (every? map? rs))
|
(is (every? map? rs))
|
||||||
(is (every? meta rs))
|
(is (every? meta rs))
|
||||||
(is (= 4 (count rs)))
|
(is (= 4 (count rs)))
|
||||||
(is (= 1 ((if (postgres?) :fruit/id :FRUIT/ID) (first rs))))
|
(is (= 1 ((column :FRUIT/ID) (first rs))))
|
||||||
(is (= 4 ((if (postgres?) :fruit/id :FRUIT/ID) (last rs)))))
|
(is (= 4 ((column :FRUIT/ID) (last rs)))))
|
||||||
(let [rs (jdbc/execute!
|
(let [rs (jdbc/execute!
|
||||||
(ds)
|
(ds)
|
||||||
["select * from fruit order by id"]
|
["select * from fruit order by id"]
|
||||||
|
|
@ -65,7 +65,7 @@
|
||||||
;; columns come first
|
;; columns come first
|
||||||
(is (every? qualified-keyword? (first rs)))
|
(is (every? qualified-keyword? (first rs)))
|
||||||
;; :FRUIT/ID should be first column
|
;; :FRUIT/ID should be first column
|
||||||
(is (= (if (postgres?) :fruit/id :FRUIT/ID) (ffirst rs)))
|
(is (= (column :FRUIT/ID) (ffirst rs)))
|
||||||
;; and all its corresponding values should be ints
|
;; and all its corresponding values should be ints
|
||||||
(is (every? int? (map first (rest rs))))
|
(is (every? int? (map first (rest rs))))
|
||||||
(is (every? string? (map second (rest rs)))))
|
(is (every? string? (map second (rest rs)))))
|
||||||
|
|
@ -93,8 +93,8 @@
|
||||||
(is (every? map? rs))
|
(is (every? map? rs))
|
||||||
(is (every? meta rs))
|
(is (every? meta rs))
|
||||||
(is (= 4 (count rs)))
|
(is (= 4 (count rs)))
|
||||||
(is (= 1 ((if (postgres?) :id :ID) (first rs))))
|
(is (= 1 ((column :ID) (first rs))))
|
||||||
(is (= 4 ((if (postgres?) :id :ID) (last rs)))))
|
(is (= 4 ((column :ID) (last rs)))))
|
||||||
(let [rs (jdbc/execute!
|
(let [rs (jdbc/execute!
|
||||||
(ds)
|
(ds)
|
||||||
["select * from fruit order by id"]
|
["select * from fruit order by id"]
|
||||||
|
|
@ -105,7 +105,7 @@
|
||||||
;; columns come first
|
;; columns come first
|
||||||
(is (every? simple-keyword? (first rs)))
|
(is (every? simple-keyword? (first rs)))
|
||||||
;; :ID should be first column
|
;; :ID should be first column
|
||||||
(is (= (if (postgres?) :id :ID) (ffirst rs)))
|
(is (= (column :ID) (ffirst rs)))
|
||||||
;; and all its corresponding values should be ints
|
;; and all its corresponding values should be ints
|
||||||
(is (every? int? (map first (rest rs))))
|
(is (every? int? (map first (rest rs))))
|
||||||
(is (every? string? (map second (rest rs))))))
|
(is (every? string? (map second (rest rs))))))
|
||||||
|
|
@ -118,8 +118,8 @@
|
||||||
(is (every? map? rs))
|
(is (every? map? rs))
|
||||||
(is (every? meta rs))
|
(is (every? meta rs))
|
||||||
(is (= 4 (count rs)))
|
(is (= 4 (count rs)))
|
||||||
(is (= 1 ((if (postgres?) :fruit/id :FRUIT/ID) (first rs))))
|
(is (= 1 ((column :FRUIT/ID) (first rs))))
|
||||||
(is (= 4 ((if (postgres?) :fruit/id :FRUIT/ID) (last rs)))))
|
(is (= 4 ((column :FRUIT/ID) (last rs)))))
|
||||||
(let [rs (with-open [con (jdbc/get-connection (ds))
|
(let [rs (with-open [con (jdbc/get-connection (ds))
|
||||||
ps (jdbc/prepare
|
ps (jdbc/prepare
|
||||||
con
|
con
|
||||||
|
|
@ -128,7 +128,7 @@
|
||||||
(is (every? map? rs))
|
(is (every? map? rs))
|
||||||
(is (every? meta rs))
|
(is (every? meta rs))
|
||||||
(is (= 1 (count rs)))
|
(is (= 1 (count rs)))
|
||||||
(is (= 4 ((if (postgres?) :fruit/id :FRUIT/ID) (first rs))))))
|
(is (= 4 ((column :FRUIT/ID) (first rs))))))
|
||||||
(testing "statement"
|
(testing "statement"
|
||||||
(let [rs (with-open [con (jdbc/get-connection (ds))]
|
(let [rs (with-open [con (jdbc/get-connection (ds))]
|
||||||
(jdbc/execute! (.createStatement con)
|
(jdbc/execute! (.createStatement con)
|
||||||
|
|
@ -136,15 +136,15 @@
|
||||||
(is (every? map? rs))
|
(is (every? map? rs))
|
||||||
(is (every? meta rs))
|
(is (every? meta rs))
|
||||||
(is (= 4 (count rs)))
|
(is (= 4 (count rs)))
|
||||||
(is (= 1 ((if (postgres?) :fruit/id :FRUIT/ID) (first rs))))
|
(is (= 1 ((column :FRUIT/ID) (first rs))))
|
||||||
(is (= 4 ((if (postgres?) :fruit/id :FRUIT/ID) (last rs)))))
|
(is (= 4 ((column :FRUIT/ID) (last rs)))))
|
||||||
(let [rs (with-open [con (jdbc/get-connection (ds))]
|
(let [rs (with-open [con (jdbc/get-connection (ds))]
|
||||||
(jdbc/execute! (.createStatement con)
|
(jdbc/execute! (.createStatement con)
|
||||||
["select * from fruit where id = 4"]))]
|
["select * from fruit where id = 4"]))]
|
||||||
(is (every? map? rs))
|
(is (every? map? rs))
|
||||||
(is (every? meta rs))
|
(is (every? meta rs))
|
||||||
(is (= 1 (count rs)))
|
(is (= 1 (count rs)))
|
||||||
(is (= 4 ((if (postgres?) :fruit/id :FRUIT/ID) (first rs))))))
|
(is (= 4 ((column :FRUIT/ID) (first rs))))))
|
||||||
(testing "transact"
|
(testing "transact"
|
||||||
(is (= [{:next.jdbc/update-count 1}]
|
(is (= [{:next.jdbc/update-count 1}]
|
||||||
(jdbc/transact (ds)
|
(jdbc/transact (ds)
|
||||||
|
|
@ -209,9 +209,9 @@ VALUES ('Pear', 'green', 49, 47)
|
||||||
(when-not (postgres?)
|
(when-not (postgres?)
|
||||||
(let [[url etc] (#'c/spec->url+etc (db))
|
(let [[url etc] (#'c/spec->url+etc (db))
|
||||||
ds (jdbc/get-datasource (assoc etc :jdbcUrl url))]
|
ds (jdbc/get-datasource (assoc etc :jdbcUrl url))]
|
||||||
(if (derby?)
|
(cond (derby?) (is (= {:create true} etc))
|
||||||
(is (= {:create true} etc))
|
(mysql?) (is (= #{:user :password :useSSL} (set (keys etc))))
|
||||||
(is (= {} etc)))
|
:else (is (= {} etc)))
|
||||||
(is (instance? javax.sql.DataSource ds))
|
(is (instance? javax.sql.DataSource ds))
|
||||||
(is (str/index-of (pr-str ds) (str "jdbc:" (:dbtype (db)))))
|
(is (str/index-of (pr-str ds) (str "jdbc:" (:dbtype (db)))))
|
||||||
;; checks get-datasource on a DataSource is identity
|
;; checks get-datasource on a DataSource is identity
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue