Merge branch 'master' into multi-rs

# Conflicts:
#	test/next/jdbc/test_fixtures.clj
This commit is contained in:
Sean Corfield 2020-06-07 10:05:33 -07:00
commit 92f7923a2a
7 changed files with 56 additions and 19 deletions

View file

@ -5,6 +5,9 @@ Only accretive/fixative changes will be made from now on.
Changes made on master since 1.0.462: Changes made on master since 1.0.462:
* Add tests for `"jtds"` database driver (against MS SQL Server), making it officially supported. * Add tests for `"jtds"` database driver (against MS SQL Server), making it officially supported.
* Switch from OpenTable Embedded PostgreSQL to Zonky's version, so that testing can move forward from PostgreSQL 10.11 to 12.2.0. * Switch from OpenTable Embedded PostgreSQL to Zonky's version, so that testing can move forward from PostgreSQL 10.11 to 12.2.0.
* Fix potential reflection warnings caused by `next.jdbc.prepare/statement` being incorrectly type-hinted.
* Address #119 by clarifying realization actions in the docstrings for `row-number`, `column-names`, and `metadata`.
* Address #115 by adding equivalent of `db-do-commands` in the `clojure.java.jdbc` migration guide.
* Add log4j2 as a test dependency so that I have better control over logging (which makes debugging easier!). * Add log4j2 as a test dependency so that I have better control over logging (which makes debugging easier!).
* WIP: support for stored procedures and multiple result sets! * WIP: support for stored procedures and multiple result sets!

View file

@ -55,6 +55,18 @@ The `next.jdbc.sql` namespace contains several functions with similarities to `c
* `update!` -- similar to `clojure.java.jdbc/update!` but will also accept a hash map of column name/value pairs instead of a partial where clause (vector), * `update!` -- similar to `clojure.java.jdbc/update!` but will also accept a hash map of column name/value pairs instead of a partial where clause (vector),
* `delete!` -- similar to `clojure.java.jdbc/delete!` but will also accept a hash map of column name/value pairs instead of a partial where clause (vector). * `delete!` -- similar to `clojure.java.jdbc/delete!` but will also accept a hash map of column name/value pairs instead of a partial where clause (vector).
If you were using `db-do-commands` in `clojure.java.jdbc` to execute DDL, the following is the equivalent in `next.jdbc`:
```clojure
(defn do-commands [connectable commands]
(if (instance? java.sql.Connection connectable)
(with-open [stmt (next.jdbc.prepare/statement connectable)]
(run! #(.addBatch stmt %) commands)
(into [] (.executeBatch stmt)))
(with-open [conn (next.jdbc/get-connection connectable)]
(do-commands conn commands))))
```
### `:identifiers` and `:qualifier` ### `:identifiers` and `:qualifier`
If you are using `:identifiers`, you will need to change to the appropriate `:builder-fn` option with one of `next.jdbc.result-set`'s `as-*` functions. If you are using `:identifiers`, you will need to change to the appropriate `:builder-fn` option with one of `next.jdbc.result-set`'s `as-*` functions.

View file

@ -149,12 +149,13 @@
(defn statement (defn statement
"Given a `Connection` and some options, return a `Statement`." "Given a `Connection` and some options, return a `Statement`."
^java.sql.Statement (^java.sql.Statement
([con] (statement con {})) [con] (statement con {}))
([^Connection con (^java.sql.Statement
{:keys [result-type concurrency cursors [^Connection con
fetch-size max-rows timeout] {:keys [result-type concurrency cursors
:as opts}] fetch-size max-rows timeout]
:as opts}]
(let [^Statement stmt (let [^Statement stmt
(cond (cond
(and result-type concurrency) (and result-type concurrency)

View file

@ -396,16 +396,23 @@
to realize a row by calling `datafiable-row` but still wants to call to realize a row by calling `datafiable-row` but still wants to call
these functions on the (realized) row." these functions on the (realized) row."
(row-number [this] (row-number [this]
"Return the current 1-based row number, if available.") "Return the current 1-based row number, if available.
Should not cause any row realization.")
(column-names [this] (column-names [this]
"Return a vector of the column names from the result set.") "Return a vector of the column names from the result set.
Reifies the result builder, in order to construct column names,
but should not cause any row realization.")
(metadata [this] (metadata [this]
"Return the raw `ResultSetMetaData` object from the result set. "Return the raw `ResultSetMetaData` object from the result set.
If `next.jdbc.datafy` has been required, this will be fully-realized Should not cause any row realization.
as a Clojure data structure, otherwise this should not be allowed to
'leak' outside of the reducing function as it may depend on the If `next.jdbc.datafy` has been required, this metadata will be
connection remaining open, in order to be valid.")) fully-realized as a Clojure data structure, otherwise this should
not be allowed to 'leak' outside of the reducing function as it may
depend on the connection remaining open, in order to be valid."))
(defn- mapify-result-set (defn- mapify-result-set
"Given a `ResultSet`, return an object that wraps the current row as a hash "Given a `ResultSet`, return an object that wraps the current row as a hash
@ -428,7 +435,7 @@
InspectableMapifiedResultSet InspectableMapifiedResultSet
(row-number [this] (.getRow rs)) (row-number [this] (.getRow rs))
(column-names [this] (:cols @builder)) (column-names [this] (:cols @builder))
(metadata [this] (d/datafy (:rsmeta @builder))) (metadata [this] (d/datafy (.getMetaData rs)))
clojure.lang.IPersistentMap clojure.lang.IPersistentMap
(assoc [this k v] (assoc [this k v]
@ -510,7 +517,7 @@
;; that they can be thrown when the actual functions are called ;; that they can be thrown when the actual functions are called
(let [row (try (.getRow rs) (catch Throwable t t)) (let [row (try (.getRow rs) (catch Throwable t t))
cols (try (:cols @builder) (catch Throwable t t)) cols (try (:cols @builder) (catch Throwable t t))
meta (try (d/datafy (:rsmeta @builder)) (catch Throwable t t))] meta (try (d/datafy (.getMetaData rs)) (catch Throwable t t))]
(with-meta (with-meta
(row-builder @builder) (row-builder @builder)
{`core-p/datafy {`core-p/datafy

View file

@ -40,7 +40,8 @@
:schema/exception))) :schema/exception)))
data (set (keys (d/datafy con)))] data (set (keys (d/datafy con)))]
(when-let [diff (seq (set/difference data reference-keys))] (when-let [diff (seq (set/difference data reference-keys))]
(println (:dbtype (db)) :connection (sort diff))) (println (format "%6s :%-10s %s"
(:dbtype (db)) "connection" (str (sort diff)))))
(is (= reference-keys (is (= reference-keys
(set/intersection reference-keys data))))))) (set/intersection reference-keys data)))))))
@ -87,7 +88,8 @@
:rowIdLifetime/exception))) :rowIdLifetime/exception)))
data (set (keys (d/datafy (.getMetaData con))))] data (set (keys (d/datafy (.getMetaData con))))]
(when-let [diff (seq (set/difference data reference-keys))] (when-let [diff (seq (set/difference data reference-keys))]
(println (:dbtype (db)) :db-meta (sort diff))) (println (format "%6s :%-10s %s"
(:dbtype (db)) "db-meta" (str (sort diff)))))
(is (= reference-keys (is (= reference-keys
(set/intersection reference-keys data)))))) (set/intersection reference-keys data))))))
(testing "nav to catalogs yields object" (testing "nav to catalogs yields object"

View file

@ -72,4 +72,5 @@
:sql-params-fn start-fn :sql-params-fn start-fn
:execute-fn exec-fn}) :execute-fn exec-fn})
sql-p) sql-p)
(println (:dbtype (db)) (:calls @timing) "calls took" (long (:total @timing)) "nanoseconds"))) (println (format "%6s %d calls took %,10d nanoseconds"
(:dbtype (db)) (:calls @timing) (long (:total @timing))))))

View file

@ -4,6 +4,7 @@
"Multi-database testing fixtures." "Multi-database testing fixtures."
(:require [clojure.string :as str] (:require [clojure.string :as str]
[next.jdbc :as jdbc] [next.jdbc :as jdbc]
[next.jdbc.prepare :as prep]
[next.jdbc.sql :as sql]) [next.jdbc.sql :as sql])
(:import (io.zonky.test.db.postgres.embedded EmbeddedPostgres))) (:import (io.zonky.test.db.postgres.embedded EmbeddedPostgres)))
@ -94,6 +95,16 @@
[] []
@test-datasource) @test-datasource)
(defn- do-commands
"Example from migration docs: this serves as a test for it."
[connectable commands]
(if (instance? java.sql.Connection connectable)
(with-open [stmt (prep/statement connectable)]
(run! #(.addBatch stmt %) commands)
(into [] (.executeBatch stmt)))
(with-open [conn (jdbc/get-connection connectable)]
(do-commands conn commands))))
(defn with-test-db (defn with-test-db
"Given a test function (or suite), run it in the context of an in-memory "Given a test function (or suite), run it in the context of an in-memory
H2 database set up with a simple fruit table containing four rows of data. H2 database set up with a simple fruit table containing four rows of data.
@ -128,9 +139,9 @@
(jdbc/execute-one! con ["DROP PROCEDURE FRUITP"]) (jdbc/execute-one! con ["DROP PROCEDURE FRUITP"])
(catch Throwable _))) (catch Throwable _)))
(try (try
(jdbc/execute-one! con [(str "DROP TABLE " fruit)]) (do-commands con [(str "DROP TABLE " fruit)])
(catch Throwable _)) (catch Throwable _))
(jdbc/execute-one! con [(str " (do-commands con [(str "
CREATE TABLE " fruit " ( CREATE TABLE " fruit " (
ID INTEGER " auto-inc-pk ", ID INTEGER " auto-inc-pk ",
NAME VARCHAR(32), NAME VARCHAR(32),