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.
|
||||
|
||||
* 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
|
||||
* 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.
|
||||
|
|
|
|||
|
|
@ -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})
|
||||
```
|
||||
|
||||
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
|
||||
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
|
||||
|
|
@ -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
|
||||
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`
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
"Some utility functions that make common operations easier by
|
||||
|
|
@ -43,15 +43,17 @@
|
|||
(merge {:return-keys true} opts)))))
|
||||
|
||||
(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
|
||||
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
|
||||
generated keys.
|
||||
|
||||
Also supports a sequence of hash maps with keys corresponding to column
|
||||
names.
|
||||
Given a connectable object, a table name, a sequence of hash maps of data,
|
||||
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
|
||||
for situations in which the generated keys may or may not be returned as well as
|
||||
|
|
@ -68,12 +70,15 @@
|
|||
([connectable table hash-maps]
|
||||
(insert-multi! connectable table hash-maps {}))
|
||||
([connectable table hash-maps-or-cols opts-or-rows]
|
||||
(if-not (-> hash-maps-or-cols first map?)
|
||||
(insert-multi! connectable table hash-maps-or-cols opts-or-rows {})
|
||||
(if (map? (first hash-maps-or-cols))
|
||||
(let [cols (keys (first hash-maps-or-cols))
|
||||
->row (fn ->row [m]
|
||||
(map (partial get m) cols))]
|
||||
(insert-multi! connectable table cols (map ->row hash-maps-or-cols) opts-or-rows))))
|
||||
(map #(get m %) cols))]
|
||||
(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]
|
||||
(if (seq rows)
|
||||
(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
|
||||
"Some utility functions for building SQL strings.
|
||||
|
|
@ -157,7 +157,9 @@
|
|||
(into [(str "INSERT INTO " (table-fn (safe-name table))
|
||||
" (" params ")"
|
||||
" 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)]
|
||||
(str " " suffix)))]
|
||||
(if batch? identity cat)
|
||||
|
|
|
|||
|
|
@ -199,6 +199,10 @@
|
|||
(is (thrown? clojure.lang.ExceptionInfo
|
||||
(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
|
||||
(is (thrown? clojure.lang.ExceptionInfo
|
||||
(sql/find-by-keys (ds) :fruit
|
||||
|
|
|
|||
Loading…
Reference in a new issue