Fix #50 by testing against (embedded) PostgreSQL

This is the first database that returns lowercase columns in results so 
there are a lot of conditionals in the tests now. It also returns entire 
rows on inserts instead of just the generated key.
This commit is contained in:
Sean Corfield 2019-07-24 17:32:58 -07:00
parent 097cdf7d28
commit 9372ce11cd
9 changed files with 138 additions and 121 deletions

View file

@ -6,7 +6,7 @@ Only accretive/fixative changes will be made from now on.
The following changes have been committed to the **master** branch since the 1.0.3 release: The following changes have been committed to the **master** branch since the 1.0.3 release:
* None. * Fix #50 by adding machinery to test against (embedded) PostgreSQL!
## Stable Builds ## Stable Builds

View file

@ -14,6 +14,7 @@
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 "5.1.41"} ; behind
org.postgresql/postgresql {:mvn/version "42.2.6"} org.postgresql/postgresql {:mvn/version "42.2.6"}
com.opentable.components/otj-pg-embedded {:mvn/version "0.13.1"}
com.impossibl.pgjdbc-ng/pgjdbc-ng {:mvn/version "0.8.2"} com.impossibl.pgjdbc-ng/pgjdbc-ng {:mvn/version "0.8.2"}
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.2.2.jre8"}}}

View file

@ -18,7 +18,7 @@ for `deps.edn` or:
``` ```
for `project.clj` or `build.boot`. for `project.clj` or `build.boot`.
In addition, you will need to add dependencies for the JDBC drivers you wish to use for whatever databases you are using. You can see the drivers and versions that `next.jdbc` is tested against in [the project's `deps.edn` file](https://github.com/seancorfield/next-jdbc/blob/master/deps.edn#L11-L19), but many other JDBC drivers for other databases should also work (e.g., Oracle, Red Shift). In addition, you will need to add dependencies for the JDBC drivers you wish to use for whatever databases you are using. You can see the drivers and versions that `next.jdbc` is tested against in [the project's `deps.edn` file](https://github.com/seancorfield/next-jdbc/blob/master/deps.edn#L11-L20), but many other JDBC drivers for other databases should also work (e.g., Oracle, Red Shift).
## An Example REPL Session ## An Example REPL Session

View file

@ -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]])) [next.jdbc.test-fixtures :refer [with-test-db ds postgres?]]))
(set! *warn-on-reflection* true) (set! *warn-on-reflection* true)
@ -18,17 +18,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 :FRUIT/GRADE))) (is (not (contains? row (if (postgres?) :fruit/grade :FRUIT/GRADE))))
(is (= 1 (:FRUIT/ID row))) (is (= 1 ((if (postgres?) :fruit/id :FRUIT/ID) row)))
(is (= "Apple" (:FRUIT/NAME row))))) (is (= "Apple" ((if (postgres?) :fruit/name :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 :COST))) (is (not (contains? row (if (postgres?) :cost :COST))))
(is (= 2 (:ID row))) (is (= 2 ((if (postgres?) :id :ID) row)))
(is (= "Banana" (:NAME row))))) (is (= "Banana" ((if (postgres?) :name :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]
@ -51,6 +51,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 :FRUIT/appearance))) (is (not (contains? row (if (postgres?) :fruit/appearance :FRUIT/appearance))))
(is (= 3 (:FRUIT/id row))) (is (= 3 ((if (postgres?) :fruit/id :FRUIT/id) row)))
(is (= "Peach" (:FRUIT/name row)))))) (is (= "Peach" ((if (postgres?) :fruit/name :FRUIT/name) row))))))

View file

@ -8,7 +8,7 @@
`execute-batch!` here." `execute-batch!` here."
(:require [clojure.test :refer [deftest is testing use-fixtures]] (:require [clojure.test :refer [deftest is testing use-fixtures]]
[next.jdbc :as jdbc] [next.jdbc :as jdbc]
[next.jdbc.test-fixtures :refer [with-test-db ds sqlite?]] [next.jdbc.test-fixtures :refer [with-test-db ds postgres? sqlite?]]
[next.jdbc.prepare :as prep] [next.jdbc.prepare :as prep]
[next.jdbc.specs :as specs])) [next.jdbc.specs :as specs]))
@ -73,7 +73,7 @@ INSERT INTO fruit (name, appearance) VALUES (?,?)
(conj result (count (jdbc/execute! t ["select * from fruit"])))))))) (conj result (count (jdbc/execute! t ["select * from fruit"]))))))))
(is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"]))))) (is (= 4 (count (jdbc/execute! (ds) ["select * from fruit"])))))
(testing "large batch insert" (testing "large batch insert"
(when-not (sqlite?) (when-not (or (postgres?) (sqlite?))
(is (= [1 1 1 1 1 1 1 1 1 13] (is (= [1 1 1 1 1 1 1 1 1 13]
(jdbc/with-transaction [t (ds) {:rollback-only true}] (jdbc/with-transaction [t (ds) {:rollback-only true}]
(with-open [ps (jdbc/prepare t [" (with-open [ps (jdbc/prepare t ["

View file

@ -11,7 +11,7 @@
[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]]) [next.jdbc.test-fixtures :refer [with-test-db ds postgres?]])
(:import (java.sql ResultSet ResultSetMetaData))) (:import (java.sql ResultSet ResultSetMetaData)))
(set! *warn-on-reflection* true) (set! *warn-on-reflection* true)
@ -28,9 +28,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
;; and remember H2 is all UPPERCASE! (is (= 1 ((if (postgres?) :fruit/id :FRUIT/ID) object)))
(is (= 1 (:FRUIT/ID object))) (is (= "Apple" ((if (postgres?) :fruit/name :FRUIT/NAME) object))))))
(is (= "Apple" (:FRUIT/NAME object))))))
(testing "custom schema :one" (testing "custom schema :one"
(let [connectable (ds) (let [connectable (ds)
test-row (rs/datafiable-row {:foo/bar 2} connectable test-row (rs/datafiable-row {:foo/bar 2} connectable
@ -41,9 +40,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
;; and remember H2 is all UPPERCASE! (is (= 2 ((if (postgres?) :fruit/id :FRUIT/ID) object)))
(is (= 2 (:FRUIT/ID object))) (is (= "Banana" ((if (postgres?) :fruit/name :FRUIT/NAME) object))))))
(is (= "Banana" (:FRUIT/NAME object))))))
(testing "custom schema :many" (testing "custom schema :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
@ -54,10 +52,9 @@
(is (= 3 v)) (is (= 3 v))
(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
;; and remember H2 is all UPPERCASE!
(is (vector? object)) (is (vector? object))
(is (= 3 (:FRUIT/ID (first object)))) (is (= 3 ((if (postgres?) :fruit/id :FRUIT/ID) (first object))))
(is (= "Peach" (:FRUIT/NAME (first object)))))))) (is (= "Peach" ((if (postgres?) :fruit/name :FRUIT/NAME) (first object))))))))
(deftest test-map-row-builder (deftest test-map-row-builder
(testing "default row builder" (testing "default row builder"
@ -65,27 +62,27 @@
["select * from fruit where id = ?" 1] ["select * from fruit where id = ?" 1]
{})] {})]
(is (map? row)) (is (map? row))
(is (contains? row :FRUIT/GRADE)) (is (contains? row (if (postgres?) :fruit/grade :FRUIT/GRADE)))
(is (nil? (:FRUIT/GRADE row))) (is (nil? ((if (postgres?) :fruit/grade :FRUIT/GRADE) row)))
(is (= 1 (:FRUIT/ID row))) (is (= 1 ((if (postgres?) :fruit/id :FRUIT/ID) row)))
(is (= "Apple" (:FRUIT/NAME row)))) (is (= "Apple" ((if (postgres?) :fruit/name :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 (:FRUIT/ID (first rs)))) (is (= 1 ((if (postgres?) :fruit/id :FRUIT/ID) (first rs))))
(is (= "Apple" (:FRUIT/NAME (first rs)))) (is (= "Apple" ((if (postgres?) :fruit/name :FRUIT/NAME) (first rs))))
(is (= 4 (:FRUIT/ID (last rs)))) (is (= 4 ((if (postgres?) :fruit/id :FRUIT/ID) (last rs))))
(is (= "Orange" (:FRUIT/NAME (last rs)))))) (is (= "Orange" ((if (postgres?) :fruit/name :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 :COST)) (is (contains? row (if (postgres?) :cost :COST)))
(is (nil? (:COST row))) (is (nil? ((if (postgres?) :cost :COST) row)))
(is (= 2 (:ID row))) (is (= 2 ((if (postgres?) :id :ID) row)))
(is (= "Banana" (:NAME row))))) (is (= "Banana" ((if (postgres?) :name :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,10 +106,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 :FRUIT/appearance)) (is (contains? row (if (postgres?) :fruit/appearance :FRUIT/appearance)))
(is (nil? (:FRUIT/appearance row))) (is (nil? ((if (postgres?) :fruit/appearance :FRUIT/appearance) row)))
(is (= 3 (:FRUIT/id row))) (is (= 3 ((if (postgres?) :fruit/id :FRUIT/id) row)))
(is (= "Peach" (:FRUIT/name row)))))) (is (= "Peach" ((if (postgres?) :fruit/name :FRUIT/name) row))))))
(deftest test-mapify (deftest test-mapify
(testing "no row builder is used" (testing "no row builder is used"

View file

@ -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? sqlite?]])) :refer [with-test-db ds derby? postgres? sqlite?]]))
(set! *warn-on-reflection* true) (set! *warn-on-reflection* true)
@ -82,33 +82,33 @@
(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 (:FRUIT/ID (first rs)))) (is (= 1 ((if (postgres?) :fruit/id :FRUIT/ID) (first rs))))
(is (= 4 (:FRUIT/ID (last rs)))))) (is (= 4 ((if (postgres?) :fruit/id :FRUIT/ID) (last rs))))))
(deftest test-find-by-keys (deftest test-find-by-keys
(let [rs (sql/find-by-keys (ds) :fruit {:appearance "yellow"})] (let [rs (sql/find-by-keys (ds) :fruit {:appearance "yellow"})]
(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 (:FRUIT/ID (first rs)))))) (is (= 2 ((if (postgres?) :fruit/id :FRUIT/ID) (first rs))))))
(deftest test-get-by-id (deftest test-get-by-id
(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" (:FRUIT/NAME row)))) (is (= "Peach" ((if (postgres?) :fruit/name :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 (:FRUIT/ID row))) (is (= 4 ((if (postgres?) :fruit/id :FRUIT/ID) row)))
(is (= "Orange" (:FRUIT/NAME row)))) (is (= "Orange" ((if (postgres?) :fruit/name :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 (:FRUIT/ID row))))) (is (= 2 ((if (postgres?) :fruit/id :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" (:FRUIT/APPEARANCE (is (= "brown" ((if (postgres?) :fruit/appearance :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})))
@ -116,68 +116,69 @@
(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" (:FRUIT/APPEARANCE (is (= "green" ((if (postgres?) :fruit/appearance :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
(testing "single insert/delete" (let [new-key (cond (derby?) :1
(is (= (cond (derby?) (postgres?) :fruit/id
{:1 5M} (sqlite?) (keyword "last_insert_rowid()")
(sqlite?) :else :FRUIT/ID)]
{(keyword "last_insert_rowid()") 5} (testing "single insert/delete"
:else (is (= (if (derby?) 5M 5)
{:FRUIT/ID 5}) (new-key (sql/insert! (ds) :fruit
(sql/insert! (ds) :fruit {:name "Kiwi" :appearance "green & fuzzy"
{:name "Kiwi" :appearance "green & fuzzy" :cost 100 :grade 99.9}))))
:cost 100 :grade 99.9}))) (is (= 5 (count (sql/query (ds) ["select * from fruit"]))))
(is (= 5 (count (sql/query (ds) ["select * from fruit"])))) (is (= {:next.jdbc/update-count 1}
(is (= {:next.jdbc/update-count 1} (sql/delete! (ds) :fruit {:id 5})))
(sql/delete! (ds) :fruit {:id 5}))) (is (= 4 (count (sql/query (ds) ["select * from fruit"])))))
(is (= 4 (count (sql/query (ds) ["select * from fruit"]))))) (testing "multiple insert/delete"
(testing "multiple insert/delete" (is (= (cond (derby?)
(is (= (cond (derby?) [nil] ; WTF Apache Derby?
[{:1 nil}] ; WTF Apache Derby? (sqlite?)
(sqlite?) [8]
[{(keyword "last_insert_rowid()") 8}] :else
:else [6 7 8])
[{:FRUIT/ID 6} {:FRUIT/ID 7} {:FRUIT/ID 8}]) (mapv new-key
(sql/insert-multi! (ds) :fruit (sql/insert-multi! (ds) :fruit
[:name :appearance :cost :grade] [:name :appearance :cost :grade]
[["Kiwi" "green & fuzzy" 100 99.9] [["Kiwi" "green & fuzzy" 100 99.9]
["Grape" "black" 10 50] ["Grape" "black" 10 50]
["Lemon" "yellow" 20 9.9]]))) ["Lemon" "yellow" 20 9.9]]))))
(is (= 7 (count (sql/query (ds) ["select * from fruit"])))) (is (= 7 (count (sql/query (ds) ["select * from fruit"]))))
(is (= {:next.jdbc/update-count 1} (is (= {:next.jdbc/update-count 1}
(sql/delete! (ds) :fruit {:id 6}))) (sql/delete! (ds) :fruit {:id 6})))
(is (= 6 (count (sql/query (ds) ["select * from fruit"])))) (is (= 6 (count (sql/query (ds) ["select * from fruit"]))))
(is (= {:next.jdbc/update-count 2} (is (= {:next.jdbc/update-count 2}
(sql/delete! (ds) :fruit ["id > ?" 4]))) (sql/delete! (ds) :fruit ["id > ?" 4])))
(is (= 4 (count (sql/query (ds) ["select * from fruit"]))))) (is (= 4 (count (sql/query (ds) ["select * from fruit"])))))
(testing "multiple insert/delete with sequential cols/rows" ; per #43 (testing "multiple insert/delete with sequential cols/rows" ; per #43
(is (= (cond (derby?) (is (= (cond (derby?)
[{:1 nil}] ; WTF Apache Derby? [nil] ; WTF Apache Derby?
(sqlite?) (sqlite?)
[{(keyword "last_insert_rowid()") 11}] [11]
:else :else
[{:FRUIT/ID 9} {:FRUIT/ID 10} {:FRUIT/ID 11}]) [9 10 11])
(sql/insert-multi! (ds) :fruit (mapv new-key
'(:name :appearance :cost :grade) (sql/insert-multi! (ds) :fruit
'(("Kiwi" "green & fuzzy" 100 99.9) '(:name :appearance :cost :grade)
("Grape" "black" 10 50) '(("Kiwi" "green & fuzzy" 100 99.9)
("Lemon" "yellow" 20 9.9))))) ("Grape" "black" 10 50)
(is (= 7 (count (sql/query (ds) ["select * from fruit"])))) ("Lemon" "yellow" 20 9.9))))))
(is (= {:next.jdbc/update-count 1} (is (= 7 (count (sql/query (ds) ["select * from fruit"]))))
(sql/delete! (ds) :fruit {:id 9}))) (is (= {:next.jdbc/update-count 1}
(is (= 6 (count (sql/query (ds) ["select * from fruit"])))) (sql/delete! (ds) :fruit {:id 9})))
(is (= {:next.jdbc/update-count 2} (is (= 6 (count (sql/query (ds) ["select * from fruit"]))))
(sql/delete! (ds) :fruit ["id > ?" 4]))) (is (= {:next.jdbc/update-count 2}
(is (= 4 (count (sql/query (ds) ["select * from fruit"]))))) (sql/delete! (ds) :fruit ["id > ?" 4])))
(testing "empty insert-multi!" ; per #44 (is (= 4 (count (sql/query (ds) ["select * from fruit"])))))
(is (= [] (sql/insert-multi! (ds) :fruit (testing "empty insert-multi!" ; per #44
[:name :appearance :cost :grade] (is (= [] (sql/insert-multi! (ds) :fruit
[]))))) [:name :appearance :cost :grade]
[]))))))
(deftest no-empty-example-maps (deftest no-empty-example-maps
(is (thrown? clojure.lang.ExceptionInfo (is (thrown? clojure.lang.ExceptionInfo

View file

@ -3,7 +3,9 @@
(ns next.jdbc.test-fixtures (ns next.jdbc.test-fixtures
"Multi-database testing fixtures." "Multi-database testing fixtures."
(:require [next.jdbc :as jdbc] (:require [next.jdbc :as jdbc]
[next.jdbc.sql :as sql])) [next.jdbc.sql :as sql])
(:import (com.opentable.db.postgres.embedded EmbeddedPostgres)
(javax.sql DataSource)))
(set! *warn-on-reflection* true) (set! *warn-on-reflection* true)
@ -17,12 +19,19 @@
(def ^:private test-sqlite {:dbtype "sqlite" :dbname "clojure_test_sqlite"}) (def ^:private test-sqlite {:dbtype "sqlite" :dbname "clojure_test_sqlite"})
(def ^:private test-db-specs [test-derby test-h2-mem test-h2 test-hsql test-sqlite]) ;; this is just a dummy db-spec -- it's handled in with-test-db below
(def ^:private test-postgres {:dbtype "embedded-postgres"})
(defonce embedded-pg (atom nil))
(def ^:private test-db-specs
[test-derby test-h2-mem test-h2 test-hsql test-sqlite test-postgres])
(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 postgres? [] (= "embedded-postgres" (:dbtype @test-db-spec)))
(defn sqlite? [] (= "sqlite" (:dbtype @test-db-spec))) (defn sqlite? [] (= "sqlite" (:dbtype @test-db-spec)))
(def ^:private test-datasource (atom nil)) (def ^:private test-datasource (atom nil))
@ -41,12 +50,21 @@
[t] [t]
(doseq [db test-db-specs] (doseq [db test-db-specs]
(reset! test-db-spec db) (reset! test-db-spec db)
(reset! test-datasource (jdbc/get-datasource db)) (if (= "embedded-postgres" (:dbtype db))
(do
(when-not @embedded-pg
(reset! embedded-pg (EmbeddedPostgres/start)))
(reset! test-datasource
(.getPostgresDatabase ^EmbeddedPostgres @embedded-pg)))
(reset! test-datasource (jdbc/get-datasource db)))
(let [auto-inc-pk (let [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)"
" PRIMARY KEY") " PRIMARY KEY")
(postgres?)
(str "GENERATED ALWAYS AS IDENTITY"
" PRIMARY KEY")
(sqlite?) (sqlite?)
"PRIMARY KEY AUTOINCREMENT" "PRIMARY KEY AUTOINCREMENT"
:else :else

View file

@ -4,7 +4,7 @@
"Not exactly a test suite -- more a series of examples." "Not exactly a test suite -- more a series of examples."
(:require [clojure.test :refer [deftest is testing use-fixtures]] (:require [clojure.test :refer [deftest is testing use-fixtures]]
[next.jdbc :as jdbc] [next.jdbc :as jdbc]
[next.jdbc.test-fixtures :refer [with-test-db ds]] [next.jdbc.test-fixtures :refer [with-test-db ds 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])
@ -25,7 +25,7 @@
(ds) (ds)
["select * from fruit where appearance = ?" "red"]))))) ["select * from fruit where appearance = ?" "red"])))))
(testing "execute-one!" (testing "execute-one!"
(is (= "Apple" (:FRUIT/NAME (is (= "Apple" ((if (postgres?) :fruit/name :FRUIT/NAME)
(jdbc/execute-one! (jdbc/execute-one!
(ds) (ds)
["select * from fruit where appearance = ?" "red"]))))) ["select * from fruit where appearance = ?" "red"])))))
@ -34,7 +34,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 (:FRUIT/ID (first rs))))) (is (= 1 ((if (postgres?) :fruit/id :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"]
@ -42,8 +42,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 (:FRUIT/ID (first rs)))) (is (= 1 ((if (postgres?) :fruit/id :FRUIT/ID) (first rs))))
(is (= 4 (:FRUIT/ID (last rs))))) (is (= 4 ((if (postgres?) :fruit/id :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"]
@ -54,7 +54,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 (= :FRUIT/ID (ffirst rs))) (is (= (if (postgres?) :fruit/id :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)))))
@ -65,8 +65,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 (:ID (first rs)))) (is (= 1 ((if (postgres?) :id :ID) (first rs))))
(is (= 4 (:ID (last rs))))) (is (= 4 ((if (postgres?) :id :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"]
@ -77,7 +77,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 (= :ID (ffirst rs))) (is (= (if (postgres?) :id :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))))))
@ -90,8 +90,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 (:FRUIT/ID (first rs)))) (is (= 1 ((if (postgres?) :fruit/id :FRUIT/ID) (first rs))))
(is (= 4 (:FRUIT/ID (last rs))))) (is (= 4 ((if (postgres?) :fruit/id :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
@ -100,7 +100,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 (:FRUIT/ID (first rs)))))) (is (= 4 ((if (postgres?) :fruit/id :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)