From e855246ff35e83af3e49d70464b3577b96eb5af9 Mon Sep 17 00:00:00 2001 From: Sean Corfield Date: Wed, 20 May 2020 15:07:15 -0700 Subject: [PATCH] Add example of execute-batch! with :return-keys --- CHANGELOG.md | 1 + doc/all-the-options.md | 2 +- doc/prepared-statements.md | 17 +++++++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55e75e4..75c9ab9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Only accretive/fixative changes will be made from now on. The following changes have been made on **master** since the 1.0.424 release: * Support for Stuart Sierra's Component library, via `next.jdbc.connection/component`. See updated **Getting Started** guide for usage. +* Add example of getting generated keys from `execute-batch!`. * Add MySQL-specific result set streaming tip. * Add array handling example to PostgreSQL **Tips & Tricks**. PR #108 from @maxp. * Investigate possible solutions for #106 (mutable transaction thread safety) -- experimental `locking` on `Connection` object. diff --git a/doc/all-the-options.md b/doc/all-the-options.md index c941c82..43fad29 100644 --- a/doc/all-the-options.md +++ b/doc/all-the-options.md @@ -73,7 +73,7 @@ Not all databases or drivers support all of these options, or all values for any > Note: If `plan`, `execute!`, or `execute-one!` are passed a `DataSource`, a "db spec" hash map, or a JDBC URI string, they will call `prepare` to create a `PreparedStatement`, so they will accept the above options in those cases. -In addition the the above, `next.jdbc.prepare/execute-batch!` accepts an options hash map that can also contain the following: +In addition the the above, `next.jdbc.prepare/execute-batch!` (which does **not** create a `PreparedStatement`) accepts an options hash map that can also contain the following: * `:batch-size` -- an integer that determines how to partition the parameter groups for submitting to the database in batches, * `:large` -- a Boolean flag that indicates whether the batch will produce large update counts (`long` rather than `int` values). diff --git a/doc/prepared-statements.md b/doc/prepared-statements.md index 5051c80..28e8169 100644 --- a/doc/prepared-statements.md +++ b/doc/prepared-statements.md @@ -101,6 +101,23 @@ Both of those are somewhat ugly and contain a fair bit of boilerplate and Java i By default, this adds all the parameter groups and executes one batched command. It returns a (Clojure) vector of update counts (rather than `int[]`). If you provide an options hash map, you can specify a `:batch-size` and the parameter groups will be partitioned and executed as multiple batched commands. This is intended to allow very large sequences of parameter groups to be executed without running into limitations that may apply to a single batched command. If you expect the update counts to be very large (more than `Integer/MAX_VALUE`), you can specify `:large true` so that `.executeLargeBatch` is called instead of `.executeBatch`. Note: not all databases support `.executeLargeBatch`. +If you want to get the generated keys from an `insert` done via `execute-batch!`, you need a couple of extras, compared to the above: + +```clojure +(with-open [con (jdbc/get-connection ds) + ;; ensure the PreparedStatement will return the keys: + ps (jdbc/prepare con ["insert into status (id,name) values (?,?)"] + {:return-keys true})] + ;; this returns update counts (which we'll ignore) + (p/execute-batch! ps [[1 "Approved"] [2 "Rejected"] [3 "New"]]) + ;; this produces the generated keys as a (datafiable) Clojure data structure: + (rs/datafiable-result-set (.getGeneratedKeys ps) con {})) +``` + +The call to `rs/datafiable-result-set` can be passed a `:builder-fn` option if you want something other than qualified as-is hash maps. + +> Note: not all databases support calling `.getGeneratedKeys` here (everything I test against seems to, except MS SQL Server). + ### Caveats There are several caveats around using batched parameters. Some JDBC drivers need a "hint" in order to perform the batch operation as a single command for the database. In particular, PostgreSQL requires the `:reWriteBatchedInserts true` option and MySQL requires `:rewriteBatchedStatement true` (both non-standard JDBC options, of course!). These should be provided as part of the db-spec hash map when the datasource is created.