expand docs/tests for #206
This commit is contained in:
parent
0bdffbc87f
commit
3ed1f4b99c
5 changed files with 75 additions and 11 deletions
|
|
@ -2,6 +2,10 @@
|
||||||
|
|
||||||
Only accretive/fixative changes will be made from now on.
|
Only accretive/fixative changes will be made from now on.
|
||||||
|
|
||||||
|
* 1.2.next in progress
|
||||||
|
* Enhance `insert-multi!` to accept a sequence of hash maps and also to support batch execution, via PR [#206](https://github.com/seancorfield/next-jdbc/pull/206) -- [@rschmukler](https://github.com/rschmukler).
|
||||||
|
* Fix HikariCP pooling example.
|
||||||
|
|
||||||
* 1.2.780 -- 2022-04-04
|
* 1.2.780 -- 2022-04-04
|
||||||
* Address [#204](https://github.com/seancorfield/next-jdbc/issues/204) by adding `next.jdbc/on-connection`.
|
* Address [#204](https://github.com/seancorfield/next-jdbc/issues/204) by adding `next.jdbc/on-connection`.
|
||||||
* Address [#203](https://github.com/seancorfield/next-jdbc/issues/203) by adding a note to the **PostgreSQL Tips & Tricks** section.
|
* Address [#203](https://github.com/seancorfield/next-jdbc/issues/203) by adding a note to the **PostgreSQL Tips & Tricks** section.
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,20 @@ Given a table name (as a keyword), a vector of column names, and a vector of row
|
||||||
"Aunt Sally" "sour@lagunitas.beer"] {:return-keys true})
|
"Aunt Sally" "sour@lagunitas.beer"] {:return-keys true})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Given a table name (as a keyword) and a vector of hash maps, this performs a multi-row insertion into the database:
|
||||||
|
|
||||||
|
```clojure
|
||||||
|
(sql/insert-multi! ds :address
|
||||||
|
[{:name "Stella", :email "stella@artois.beer"}
|
||||||
|
{:name "Waldo", :email "waldo@lagunitas.beer"}
|
||||||
|
{:name "Aunt Sally", :email "sour@lagunitas.beer"}])
|
||||||
|
;; equivalent to
|
||||||
|
(jdbc/execute! ds ["INSERT INTO address (name,email) VALUES (?,?), (?,?), (?,?)"
|
||||||
|
"Stella" "stella@artois.beer"
|
||||||
|
"Waldo" "waldo@lagunitas.beer"
|
||||||
|
"Aunt Sally" "sour@lagunitas.beer"] {:return-keys true})
|
||||||
|
```
|
||||||
|
|
||||||
> Note: this expands to a single SQL statement with placeholders for every
|
> Note: this expands to a single SQL statement with placeholders for every
|
||||||
value being inserted -- for large sets of rows, this may exceed the limits
|
value being inserted -- for large sets of rows, this may exceed the limits
|
||||||
on SQL string size and/or number of parameters for your JDBC driver or your
|
on SQL string size and/or number of parameters for your JDBC driver or your
|
||||||
|
|
@ -60,7 +74,42 @@ database. Several databases have a limit of 1,000 parameter placeholders.
|
||||||
Oracle does not support this form of multi-row insert, requiring a different
|
Oracle does not support this form of multi-row insert, requiring a different
|
||||||
syntax altogether.
|
syntax altogether.
|
||||||
|
|
||||||
You should look at [`next.jdbc/execute-batch!`](https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/api/next.jdbc#execute-batch!) for an alternative approach.
|
### Batch Insertion
|
||||||
|
|
||||||
|
As of release 1.2.next, you can specify `:batch true` in the options, which
|
||||||
|
will use `execute-batch!` under the hood, instead of `execute!`, as follows:
|
||||||
|
|
||||||
|
```clojure
|
||||||
|
(sql/insert-multi! ds :address
|
||||||
|
[:name :email]
|
||||||
|
[["Stella" "stella@artois.beer"]
|
||||||
|
["Waldo" "waldo@lagunitas.beer"]
|
||||||
|
["Aunt Sally" "sour@lagunitas.beer"]]
|
||||||
|
{:batch true})
|
||||||
|
;; equivalent to
|
||||||
|
(jdbc/execute-batch! ds
|
||||||
|
["INSERT INTO address (name,email) VALUES (?,?)"
|
||||||
|
["Stella" "stella@artois.beer"]
|
||||||
|
["Waldo" "waldo@lagunitas.beer"]
|
||||||
|
["Aunt Sally" "sour@lagunitas.beer"]]
|
||||||
|
{:return-keys true :return-generated-keys true})
|
||||||
|
;; and
|
||||||
|
(sql/insert-multi! ds :address
|
||||||
|
[:name :email]
|
||||||
|
[{:name "Stella", :email "stella@artois.beer"}
|
||||||
|
{:name "Waldo", :email "waldo@lagunitas.beer"}
|
||||||
|
{:name "Aunt Sally", :email "sour@lagunitas.beer"}]
|
||||||
|
{:batch true})
|
||||||
|
;; equivalent to
|
||||||
|
(jdbc/execute-batch! ds
|
||||||
|
["INSERT INTO address (name,email) VALUES (?,?)"
|
||||||
|
["Stella" "stella@artois.beer"]
|
||||||
|
["Waldo" "waldo@lagunitas.beer"]
|
||||||
|
["Aunt Sally" "sour@lagunitas.beer"]]
|
||||||
|
{:return-keys true :return-generated-keys true})
|
||||||
|
```
|
||||||
|
|
||||||
|
See [**Batched Parameters**](https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/doc/getting-started/prepared-statements#caveats) for caveats and possible database-specific behaviors.
|
||||||
|
|
||||||
## `query`
|
## `query`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
;; copyright (c) 2019-2021 Sean Corfield, all rights reserved
|
;; copyright (c) 2019-2022 Sean Corfield, all rights reserved
|
||||||
|
|
||||||
(ns next.jdbc.sql
|
(ns next.jdbc.sql
|
||||||
"Some utility functions that make common operations easier by
|
"Some utility functions that make common operations easier by
|
||||||
|
|
@ -43,15 +43,17 @@
|
||||||
(merge {:return-keys true} opts)))))
|
(merge {:return-keys true} opts)))))
|
||||||
|
|
||||||
(defn insert-multi!
|
(defn insert-multi!
|
||||||
"Syntactic sugar over `execute!` to make inserting columns/rows easier.
|
"Syntactic sugar over `execute!` or `execute-batch!` to make inserting
|
||||||
|
columns/rows easier.
|
||||||
|
|
||||||
Given a connectable object, a table name, a sequence of column names, and
|
Given a connectable object, a table name, a sequence of column names, and
|
||||||
a vector of rows of data (vectors of column values), inserts the data as
|
a vector of rows of data (vectors of column values), inserts the data as
|
||||||
multiple rows in the database and attempts to return a vector of maps of
|
multiple rows in the database and attempts to return a vector of maps of
|
||||||
generated keys.
|
generated keys.
|
||||||
|
|
||||||
Also supports a sequence of hash maps with keys corresponding to column
|
Given a connectable object, a table name, a sequence of hash maps of data,
|
||||||
names.
|
inserts the data as multiple rows in the database and attempts to return
|
||||||
|
a vector of maps of generated keys.
|
||||||
|
|
||||||
If called with `:batch` true will call `execute-batch!` - see its documentation
|
If called with `:batch` true will call `execute-batch!` - see its documentation
|
||||||
for situations in which the generated keys may or may not be returned as well as
|
for situations in which the generated keys may or may not be returned as well as
|
||||||
|
|
@ -68,12 +70,15 @@
|
||||||
([connectable table hash-maps]
|
([connectable table hash-maps]
|
||||||
(insert-multi! connectable table hash-maps {}))
|
(insert-multi! connectable table hash-maps {}))
|
||||||
([connectable table hash-maps-or-cols opts-or-rows]
|
([connectable table hash-maps-or-cols opts-or-rows]
|
||||||
(if-not (-> hash-maps-or-cols first map?)
|
(if (map? (first hash-maps-or-cols))
|
||||||
(insert-multi! connectable table hash-maps-or-cols opts-or-rows {})
|
|
||||||
(let [cols (keys (first hash-maps-or-cols))
|
(let [cols (keys (first hash-maps-or-cols))
|
||||||
->row (fn ->row [m]
|
->row (fn ->row [m]
|
||||||
(map (partial get m) cols))]
|
(map #(get m %) cols))]
|
||||||
(insert-multi! connectable table cols (map ->row hash-maps-or-cols) opts-or-rows))))
|
(when-not (apply = (map (comp set keys) hash-maps-or-cols))
|
||||||
|
(throw (IllegalArgumentException.
|
||||||
|
"insert-multi! hash maps must all have the same keys")))
|
||||||
|
(insert-multi! connectable table cols (map ->row hash-maps-or-cols) opts-or-rows))
|
||||||
|
(insert-multi! connectable table hash-maps-or-cols opts-or-rows {})))
|
||||||
([connectable table cols rows opts]
|
([connectable table cols rows opts]
|
||||||
(if (seq rows)
|
(if (seq rows)
|
||||||
(let [opts (merge (:options connectable) opts)
|
(let [opts (merge (:options connectable) opts)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
;; copyright (c) 2019-2021 Sean Corfield, all rights reserved
|
;; copyright (c) 2019-2022 Sean Corfield, all rights reserved
|
||||||
|
|
||||||
(ns next.jdbc.sql.builder
|
(ns next.jdbc.sql.builder
|
||||||
"Some utility functions for building SQL strings.
|
"Some utility functions for building SQL strings.
|
||||||
|
|
@ -157,7 +157,9 @@
|
||||||
(into [(str "INSERT INTO " (table-fn (safe-name table))
|
(into [(str "INSERT INTO " (table-fn (safe-name table))
|
||||||
" (" params ")"
|
" (" params ")"
|
||||||
" VALUES "
|
" VALUES "
|
||||||
(str/join ", " (repeat (if batch? 1 (count rows)) (str "(" places ")")))
|
(if batch?
|
||||||
|
(str "(" places ")")
|
||||||
|
(str/join ", " (repeat (count rows) (str "(" places ")"))))
|
||||||
(when-let [suffix (:suffix opts)]
|
(when-let [suffix (:suffix opts)]
|
||||||
(str " " suffix)))]
|
(str " " suffix)))]
|
||||||
(if batch? identity cat)
|
(if batch? identity cat)
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,10 @@
|
||||||
(is (thrown? clojure.lang.ExceptionInfo
|
(is (thrown? clojure.lang.ExceptionInfo
|
||||||
(sql/insert-multi! (ds) :fruit [] [[] [] []]))))
|
(sql/insert-multi! (ds) :fruit [] [[] [] []]))))
|
||||||
|
|
||||||
|
(deftest no-mismatched-columns
|
||||||
|
(is (thrown? IllegalArgumentException
|
||||||
|
(sql/insert-multi! (ds) :fruit [{:name "Apple"} {:cost 1.23}]))))
|
||||||
|
|
||||||
(deftest no-empty-order-by
|
(deftest no-empty-order-by
|
||||||
(is (thrown? clojure.lang.ExceptionInfo
|
(is (thrown? clojure.lang.ExceptionInfo
|
||||||
(sql/find-by-keys (ds) :fruit
|
(sql/find-by-keys (ds) :fruit
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue