Provide a way to force builder construction in plan
This still won't catch the empty result set or lack of result set cases (e.g., update count only).
This commit is contained in:
parent
bebcf0af17
commit
bb6eb02cbc
3 changed files with 27 additions and 1 deletions
|
|
@ -7,6 +7,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.10 release:
|
The following changes have been committed to the **master** branch since the 1.0.10 release:
|
||||||
|
|
||||||
* Add `next.jdbc.middleware` containing a `wrapper` for connectable objects that can offer default options, as well as four "hooks" for pre- and post-processing functions that make it easier to add logging and timing code to your `next.jdbc`-based application.
|
* Add `next.jdbc.middleware` containing a `wrapper` for connectable objects that can offer default options, as well as four "hooks" for pre- and post-processing functions that make it easier to add logging and timing code to your `next.jdbc`-based application.
|
||||||
|
* Make the "mapified" result set object implement `clojure.lang.IDeref` so you can "force" the result set builder to be constructed so that the `:post-execute-fn` hook will run in middleware.
|
||||||
* Add testing against Microsoft SQL Server (run tests with environment variables `NEXT_JDBC_TEST_MSSQL=yes` and `MSSQL_SA_PASSWORD` set to your local -- `127.0.0.1:1433` -- SQL Server `sa` user password; assumes that it can create and drop `fruit` and `fruit_time` tables in the `model` database).
|
* Add testing against Microsoft SQL Server (run tests with environment variables `NEXT_JDBC_TEST_MSSQL=yes` and `MSSQL_SA_PASSWORD` set to your local -- `127.0.0.1:1433` -- SQL Server `sa` user password; assumes that it can create and drop `fruit` and `fruit_time` tables in the `model` database).
|
||||||
* Add testing against MySQL (run tests with environment variables `NEXT_JDBC_TEST_MYSQL=yes` and `MYSQL_ROOT_PASSWORD` set to your local -- `127.0.0.1:3306` -- MySQL `root` user password; assumes you have already created an empty database called `clojure_test`).
|
* Add testing against MySQL (run tests with environment variables `NEXT_JDBC_TEST_MYSQL=yes` and `MYSQL_ROOT_PASSWORD` set to your local -- `127.0.0.1:3306` -- 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.
|
* Bump several JDBC driver versions for up-to-date testing.
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,28 @@ As you can see, both `:pre-process-fn` and `:post-process-fn` can return updated
|
||||||
|
|
||||||
Any of the hook functions may execute side-effects (such as logging) but must still return the expected data.
|
Any of the hook functions may execute side-effects (such as logging) but must still return the expected data.
|
||||||
|
|
||||||
|
## Middleware and `plan`
|
||||||
|
|
||||||
|
Because `next.jdbc/plan` tries to avoid realizing a result set, it is possible to perform reductions that do not even cause the result set builder to be constructed -- the `:post-execute-fn` hook will not executed in such cases. For example:
|
||||||
|
|
||||||
|
```clojure
|
||||||
|
user=> (into [] (map :name) ; does not construct the builder!
|
||||||
|
(jdbc/plan db-spec ["select * from fruit"]))
|
||||||
|
["Apple" "Banana" "Peach" "Orange"]
|
||||||
|
```
|
||||||
|
|
||||||
|
You can force the result set builder to be constructed by calling `deref` on any row:
|
||||||
|
|
||||||
|
```clojure
|
||||||
|
user=> (into [] (map (comp :name deref))
|
||||||
|
(jdbc/plan db-spec ["select * from fruit"]))
|
||||||
|
["Apple" "Banana" "Peach" "Orange"]
|
||||||
|
```
|
||||||
|
|
||||||
|
That will ensure that the result set builder _is_ constructed and it will execute the `:post-execute-fn` hook, but it will not cause rows (or the overall result set) to be realized. Thus, the only overhead of calling `deref` on each row is the one-off cost of constructing the result set builder for the first row, and the cost of derefencing a realized delay object for each row (and throwing that value away).
|
||||||
|
|
||||||
|
*Note: If your SQL operation produces no rows, or no `ResultSet` at all (only an update count), then there is no way to force the result set builder to be constructed and no way for the `:post-execute-fn` hook to be executed.*
|
||||||
|
|
||||||
## Examples of Middleware Usage
|
## Examples of Middleware Usage
|
||||||
|
|
||||||
The usage for providing default options should be clear from the overview above
|
The usage for providing default options should be clear from the overview above
|
||||||
|
|
|
||||||
|
|
@ -462,7 +462,10 @@
|
||||||
|
|
||||||
clojure.lang.IDeref
|
clojure.lang.IDeref
|
||||||
(deref [this]
|
(deref [this]
|
||||||
(deref builder))
|
;; force the builder to be created but return the row
|
||||||
|
;; without actually building anything
|
||||||
|
(deref builder)
|
||||||
|
this)
|
||||||
|
|
||||||
;; from java.lang.Object:
|
;; from java.lang.Object:
|
||||||
(toString [_]
|
(toString [_]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue