diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE
deleted file mode 100644
index 686625a4..00000000
--- a/.github/PULL_REQUEST_TEMPLATE
+++ /dev/null
@@ -1,14 +0,0 @@
-Hi! Thanks for your interest in contributing to this project.
-
-Clojure contrib projects do not use GitHub issues or pull requests, and
-require a signed Contributor Agreement. If you would like to contribute,
-please read more about the CA and sign that first (this can be done online).
-
-Then go to this project's issue tracker in JIRA to create tickets, update
-tickets, or submit patches. For help in creating tickets and patches,
-please see:
-
-- Signing the CA: https://clojure.org/community/contributing
-- Creating Tickets: https://clojure.org/community/creating_tickets
-- Developing Patches: https://clojure.org/community/developing_patches
-- Contributing FAQ: https://clojure.org/community/contributing
diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml
deleted file mode 100644
index 685f14ea..00000000
--- a/.github/workflows/doc-build.yml
+++ /dev/null
@@ -1,10 +0,0 @@
-name: Build API Docs
-
-on:
-  workflow_dispatch:
-
-jobs:
-  call-doc-build-workflow:
-    uses: clojure/build.ci/.github/workflows/doc-build.yml@master
-    with:
-      project: clojure/java.jdbc
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
deleted file mode 100644
index e2718bd3..00000000
--- a/.github/workflows/release.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-name: Release on demand
-
-on:
-  workflow_dispatch:
-    inputs:
-      releaseVersion:
-        description: "Version to release"
-        required: true
-      snapshotVersion:
-        description: "Snapshot version after release"
-        required: true
-
-jobs:
-  call-release:
-    uses: clojure/build.ci/.github/workflows/release.yml@master
-    with:
-      releaseVersion: ${{ github.event.inputs.releaseVersion }}
-      snapshotVersion: ${{ github.event.inputs.snapshotVersion }}
-    secrets: inherit
\ No newline at end of file
diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml
deleted file mode 100644
index 24729578..00000000
--- a/.github/workflows/snapshot.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-name: Snapshot on demand
-
-on: [workflow_dispatch]
-
-jobs:
-  call-snapshot:
-    uses: clojure/build.ci/.github/workflows/snapshot.yml@master
-    secrets: inherit
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
deleted file mode 100644
index 1fa127c9..00000000
--- a/.github/workflows/test.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-name: Test
-
-on: [push]
-
-jobs:
-  call-test:
-    uses: clojure/build.ci/.github/workflows/test.yml@master
diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index 81f14885..00000000
--- a/.gitignore
+++ /dev/null
@@ -1,21 +0,0 @@
-.calva/repl.calva-repl
-.classpath
-.clj-kondo/.cache
-.cpcache
-.lsp/.cache
-.portal
-.project
-.rebl
-.settings
-*.jar
-/.lein-failures
-/.lein-repl-history
-/.nrepl-port
-/build.boot
-/clojure_test_*
-bin
-classes
-derby.log
-settings.xml
-target
-test-all.sh
diff --git a/CHANGES.md b/CHANGES.md
deleted file mode 100644
index d6d50aab..00000000
--- a/CHANGES.md
+++ /dev/null
@@ -1,487 +0,0 @@
-Changes not yet released
-* Update most testing dependencies (and update a couple of tests to match).
-* Drop support for Clojure 1.7 & 1.8. Test against 1.9, 1.10, 1.11, and 1.12.
-
-Changes in 0.7.12
-
-* Make the protocols `ISQLValue`, `ISQLParameter`, and `IResultSetReadColumn` extensible via metadata.
-
-Changes in 0.7.11
-
-* Address edge case in transaction rollback failure [JDBC-179](https://clojure.atlassian.net/browse/JDBC-179).
-
-Changes in 0.7.10
-
-* Use a US-locale `lower-case` function to avoid problems in certain locales (e.g., Turkish). A similar issue has been fixed recently in both HoneySQL and `next.jdbc`.
-* Clean up `db-spec` options that are passed to the JDBC connection manager as properties [JDBC-178](https://clojure.atlassian.net/browse/JDBC-178).
-* Relax restriction on `create-table-ddl` column specs to allow numbers (as well as keywords and strings) [JDBC-177](https://clojure.atlassian.net/browse/JDBC-177).
-
-Changes in 0.7.9
-
-* Fix behavior of multi-inserts when database does not support generated keys [JDBC-176](https://clojure.atlassian.net/browse/JDBC-176).
-* Added _highly experimental_ support for `datafy`/`nav` (in `clojure.java.jdbc.datafy` namespace). This includes a convention-based approach to foreign keys with some assistance from a `:schema` option. This is subject to change and is provided mostly for informational purposes, as an example of the new functionality in Clojure 1.10. This includes a fix for the conventions from [JDBC-175](https://clojure.atlassian.net/browse/JDBC-175).
-* Add note about rewriting batched operations to `insert-multi!` for some drivers [JDBC-174](https://clojure.atlassian.net/browse/JDBC-174).
-* Support Oracle SID style URLs (`dbtype` can be `oracle:sid` which maps to `oracle:thin` and uses `:` as the separator before the `dbname` value) [JDBC-173](https://clojure.atlassian.net/browse/JDBC-173).
-
-Changes in 0.7.8
-
-* Support multiple JDBC driver class names (MySQL introduced a new driver class name with its 6.x connector) [JDBC-172](https://clojure.atlassian.net/browse/JDBC-172).
-* Allow `with-db-connection` and `with-db-metadata` to nest [JDBC-171](https://clojure.atlassian.net/browse/JDBC-171).
-
-Changes in 0.7.7
-
-* Support `:as-arrays?`, `:result-set-fn`, and `:row-fn` in operations that return generated keys as a result set (`execute!`, `insert!`, and `insert-multi!`) [JDBC-169](https://clojure.atlassian.net/browse/JDBC-169).
-* `get-connection` provides much better feedback if you accidentally call a function that expects a `db-spec` but pass a `java.sql.Connection` object instead (which is only required for `prepare-statement`).
-
-Changes in 0.7.6
-
-* `execute!` now supports `:return-keys` as a vector of column names, rather than just a simple Boolean value, for drivers that support that [JDBC-166](https://clojure.atlassian.net/browse/JDBC-166).
-* Add built-in support for H2 in-memory database (`:dbtype "h2:mem"`).
-* Add missing spec for `db-spec` being a `java.net.URI` object.
-* Fix `add-connection` handling of string `db-spec` (becomes `:connection-uri`, not `:connection-string`).
-* Fix specs for `with-db-*` functions, to support options in the binding form [JDBC-165](https://clojure.atlassian.net/browse/JDBC-165).
-* Update tests so they work properly with string `db-spec` test databases.
-* Ensure no reflection warnings are present.
-* Switched local test infrastructure over to CLI and `deps.edn` (from Leiningen) as an example of multi-version testing without a "build tool".
-
-Changes in 0.7.5
-
-* Add support for `:return-keys` in `execute!` and `:multi?` in `db-do-prepared-return-keys` [JDBC-163](https://clojure.atlassian.net/browse/JDBC-163).
-
-Changes in 0.7.4
-
-* Improved discoverability of other `java.jdbc` documentation [JDBC-160](https://clojure.atlassian.net/browse/JDBC-160).
-* Optional specs updated with `:keywordize?` and `:connection-uri` changes from 0.7.2 and 0.7.3 releases.
-* Performance improvements, primarily in `query` and `reducible-query`.
-* Experimental `:raw?` result set handling in `reducible-query`.
-* `modify-connection` is more robust in the face of `null` connections and bad option values.
-
-Changes in 0.7.3
-
-* Added `:keywordize?` option alongside `:identifiers` that defaults to `true` but can be set to `false` to opt-out of converting identifiers to keywords (so column names etc will only be processed by the function passed as `:identifiers`) [JDBC-159](https://clojure.atlassian.net/browse/JDBC-159).
-* If an exception occurs during a transaction, and then rollback fails with another exception, both exceptions will now be combined into an `ex-info`. Previously the rollback exception obscured the transaction exception [JDBC-158](https://clojure.atlassian.net/browse/JDBC-158).
-
-Changes in 0.7.2
-
-* `connection-uri` was incorrectly spec'd as a `java.net.URI` but should be `string?` [JDBC-156](https://clojure.atlassian.net/browse/JDBC-156).
-* Allow for `:user` and `:password` to be passed with `:connection-uri`, so credentials can be omitted from the connection string.
-* Clarified docstring for `get-connection` to show where `:user` and `:password` can be passed.
-
-Changes in 0.7.1
-
-* Connection strings with empty values were not parsed correctly [JDBC-155](https://clojure.atlassian.net/browse/JDBC-155).
-
-Changes in 0.7.0
-
-* `:conditional?` option for `create-table-ddl` and `drop-table-ddl` to provide for existence check (or a function to manipulate the generated DDL).
-* Add better support for Oracle connections (default port to `1521`, support `:dbtype "oracle"` -- as `"oracle:thin"` -- and `:dbtype "oracle:oci"`, with `@` instead of `//` before host).
-
-Changes in 0.7.0-beta5
-
-* `get-connection` now accepts an `opts` map with `:auto-commit?` and `:read-only?` options. If present, the appropriate methods will be called on the connection obtained. These options are valid in any function call that may call `get-connection` under the hood. This should allow for streaming results in a query for most databases [JDBC-153](https://clojure.atlassian.net/browse/JDBC-153).
-* Additional validation of options is performed in `prepared-statement` to avoid silently ignoring invalid combinations of `:concurrency`, `:cursors`, `:result-type`, and `:return-keys`.
-
-Changes in 0.7.0-beta4
-
-* `opts` are now correctly passed from `reducible-query` to `db-query-with-resultset`.
-* Updated the `::query-options` spec to make it clear that `::prepare-options` are also acceptable there.
-
-Changes in 0.7.0-beta3
-
-* Reflection warnings removed in `reducible-result-set` [JDBC-152](https://clojure.atlassian.net/browse/JDBC-152).
-
-Changes in 0.7.0-beta2
-
-* Support for Clojure 1.6.0 and earlier has been dropped -- breaking change.
-* Or, put another way, `clojure.java.jdbc` now requires Clojure 1.7 or later!
-* All public functions now have specs in the optional `clojure.java.jdbc.spec` namespace (requires `clojure.spec.alpha`).
-* `reducible-query` and `reducible-result-set` use `IReduce` and correctly support the no-`init` arity of `reduce` by using the first row of the `ResultSet`, if present, as the (missing) `init` value, and only calling `f` with no arguments if the `ResultSet` is empty. The `init` arity of `reduce` only ever calls `f` with two arguments.
-
-Changes in 0.7.0-beta1
-
-* Support for Clojure 1.4.0 has been dropped -- breaking change.
-* Optional spec support now uses `clojure.spec.alpha`.
-* `reducible-query` accepts a `db-spec` and a SQL/parameters vector and returns a reducible (`IReduce` on Clojure 1.7 or later; `CollReduce` on Clojure 1.5/1.6): when reduced, it runs the query, obtains a reducible result set, and then reduces that. A reducible query will run the query each time it is reduced. The helper function `reducible-result-set` is public: it accepts a `ResultSet` and produces a reducible that offers a single pass reduce over the rows. Both functions honor `reduced` values to short-circuit the process [JDBC-99](https://clojure.atlassian.net/browse/JDBC-99).
-
-Changes in 0.7.0-alpha3
-
-* `classname` is now accepted with `dbtype` / `dbname` so you can easily specify a JDBC driver class name for a database type that is not known [JDBC-151](https://clojure.atlassian.net/browse/JDBC-151).
-* `redshift` has been added as a `dbtype` with `com.amazon.redshift.jdbc.Driver` as the driver name.
-
-Changes in 0.7.0-alpha2
-
-* `pgsql` and the Impossibl PostgresSQL 'NG' driver are now supported (note that `:max-rows` does not work with this driver!); also, providing unknown `dbtype` or `subprotocol` in a `db-spec` should now throw a better exception [JDBC-150](https://clojure.atlassian.net/browse/JDBC-150).
-* `quoted` now accepts keywords for database / dialect (`:ansi` (including PostgresSQL), `:mysql`, `:oracle`, `:sqlserver` -- these match the keywords used in HoneySQL which is the recommended third party SQL DSL for java.jdbc) [JDBC-149](https://clojure.atlassian.net/browse/JDBC-149).
-* Reorder `get-connection` clauses to make it easier to combine keys in a `db-spec` [JDBC-148](https://clojure.atlassian.net/browse/JDBC-148).
-* Force load `DriverManager` before `classForName` call on drivers to avoid potential race condition on initialization [JDBC-145](https://clojure.atlassian.net/browse/JDBC-145).
-
-Changes in 0.7.0-alpha1 -- potentially breaking changes
-
-* The signatures of `as-sql-name` and `quoted` have changed slightly: the former no longer has the curried (single argument) version, and the latter no longer has the two argument version. This change came out of a discussion on Slack which indicated curried functions are non-idiomatic. If you relied on the curried version of `as-sql-name`, you will not need to use `partial`. If you relied on the two argument version of `quoted`, you will need to add an extra `( )` for the one argument call. I'd be fairly surprised if anyone is using `as-sql-name` at all since it is really an implementation detail. I'd also be surprised if anyone was using the two argument version of `quoted` since the natural usage is `:entities (quoted [\[ \]])` to create a naming strategy (that provides SQL entity quoting).
-* Clarified that `insert-multi!` with a sequence of row maps may be substantially slower than with a sequence of row value vectors (the former performs an insert for each row, the latter performs a single insert for all the data together) [JDBC-147](https://clojure.atlassian.net/browse/JDBC-147).
-* All options are passed through all function calls, expanding the range of options you can pass into high-level functions such as `insert!` and `update!` [JDBC-144](https://clojure.atlassian.net/browse/JDBC-144).
-* Added `get-isolation-level` to return the current transaction's isolation level, if any [JDBC-141](https://clojure.atlassian.net/browse/JDBC-141).
-* Added support for `read-columns` option to allow more flexible customization of reading column values from a result set (particularly in a multi-database application). Also expands `set-parameters` support to options (previously it was just part of the db-spec) [JDBC-137](https://clojure.atlassian.net/browse/JDBC-137).
-* Expanded optional `clojure.spec` coverage to almost the whole library API.
-
-Changes in 0.6.2-alpha3
-
-* Fixed bad interaction between `:qualifier` and existing `:identifiers` functionality [JDBC-140](https://clojure.atlassian.net/browse/JDBC-140).
-* Updated the README and docstrings to reflect that `:dbtype` is the easiest / preferred way to write `db-spec` maps [JDBC-139](https://clojure.atlassian.net/browse/JDBC-139).
-* Fixed postgres / postgresql alias support [JDBC-138](https://clojure.atlassian.net/browse/JDBC-138).
-  This also adds aliases for mssql (sqlserver), jtds (jtds:sqlserver), oracle (oracle:thin), and hsql (hsqldb).
-
-Changes in 0.6.2-alpha2
-
-* Updates to `clojure.spec` support to work properly with Clojure 1.9.0 Alpha 10.
-
-Changes in 0.6.2-alpha1
-
-* Experimental support for `clojure.spec` via the new `clojure.java.jdbc.spec` namespace. Requires Clojure 1.9.0 Alpha 8 (or later).
-* All options to all functions can now have defaults within the `db-spec` itself [JDBC-136](https://clojure.atlassian.net/browse/JDBC-136).
-* `query` (and by extension `find-by-keys` and `get-by-id`) now support `:explain?` and `:explain-fn` options to help support basic performance analysis [JDBC-135](https://clojure.atlassian.net/browse/JDBC-135).
-* `insert!` and `insert-multi!` now respect `:identifiers` and `:qualifier` because inserting rows on PostgreSQL returns full rows, not just the newly inserted keys [JDBC-134](https://clojure.atlassian.net/browse/JDBC-134).
-* In addition to the `:identifiers` option, you can now use `:qualifier` to specify a namespace qualifier (string) to be used when constructing keywords from SQL column names [JDBC-133](https://clojure.atlassian.net/browse/JDBC-133).
-
-Changes in 0.6.1
-
-* `insert!` and `insert-multi!` now default `:transaction?` to `true` (as they should have done in 0.6.0!) [JDBC-128](https://clojure.atlassian.net/browse/JDBC-128). These two functions also have improved docstrings to clarify the difference in behavior between inserting rows as maps compared to inserting rows as a series of column values.
-* PostgreSQL support has been improved: java.jdbc is now tested against PostgreSQL locally (as well as SQLite, Apache Derby, HSQLDB, H2, MySQL, MS SQL Server (both MS Type 4 driver and jTDS driver). [JDBC-127](https://clojure.atlassian.net/browse/JDBC-127) and [JDBC-129](https://clojure.atlassian.net/browse/JDBC-129).
-
-Changes in 0.6.0
-
-* `find-by-keys` now correctly handles `nil` values [JDBC-126](https://clojure.atlassian.net/browse/JDBC-126).
-* `find-by-keys` calls `seq` on `:order-by` to treat `[]` as no `ORDER BY` clause.
-
-Changes in 0.6.0-rc2
-
-* `db-query-with-resultset` now accepts an options map and passes it to `prepare-statement` [JDBC-125](https://clojure.atlassian.net/browse/JDBC-125).
-  - Passing the `prepare-statement` options map as the first element of the `[sql & params]` vector is no longer supported and will throw an `IllegalArgumentException`. It was always very poorly documented and almost never used, as far as I can tell.
-* `db-query-with-resultset` no longer requires the `sql-params` argument to be a vector: a sequence is acceptable. This is in line with other functions that accept a sequence.
-* `db-query-with-resultset` now accepts a bare SQL string or `PreparedStatement` as the `sql-params` argument, when there are no parameters needed. This is in line with other functions that accept SQL or a `PreparedStatement`.
-* `query`'s options map now is passed to `db-query-with-resultset` and thus can contain options to be used to construct the `PreparedStatement` [JDBC-125](https://clojure.atlassian.net/browse/JDBC-125).
-* `find-by-keys` now accepts an `:order-by` option that specifies a sequence of orderings; an ordering is either a column (to sort ascending) or a map from column name to direct (`:asc` or `:desc`).
-
-Changes in 0.6.0-rc1
-
-* Adds `get-by-id` and `find-by-keys` convenience functions (these were easy to add after the API changes in 0.6.0 and we rely very heavily on them at World Singles so putting them in the core for everyone seemed reasonable).
-* REMINDER: ALL DEPRECATED FUNCTIONALITY HAS BEEN REMOVED! [JDBC-118](https://clojure.atlassian.net/browse/JDBC-118).
-  - See alpha2 / alpha1 below for more details.
-
-Changes in 0.6.0-alpha2
-
-* ALL DEPRECATED FUNCTIONALITY HAS BEEN REMOVED! [JDBC-118](https://clojure.atlassian.net/browse/JDBC-118).
-  - This removes deprecated functionality from db-do-commands and `db-do-prepared*` which should have been removed in Alpha 1.
-* Ensures SQL / params are actually vectors prior to destructuring (this addresses an interop edge case from other languages) [JDBC-124](https://clojure.atlassian.net/browse/JDBC-124).
-* Fix typo in `insert-multi!` argument validation exception [JDBC-123](https://clojure.atlassian.net/browse/JDBC-123).
-
-Changes in 0.6.0-alpha1
-
-* (ALMOST) ALL DEPRECATED FUNCTIONALITY HAS BEEN REMOVED! [JDBC-118](https://clojure.atlassian.net/browse/JDBC-118).
-  - See changes described in versions 0.5.5 through 0.5.8 for what was deprecated
-  - Use version 0.5.8 as a bridge to identify any deprecated API calls on which your code relies!
-  - `db-transaction` (deprecated in version 0.3.0) has been removed
-  - The `java.jdbc.deprecated` namespace has been removed
-
-Changes in 0.5.8
-
-* `db-do-commands` now expects multiple commands to be be wrapped in a vector [JDBC-122](https://clojure.atlassian.net/browse/JDBC-123). The single command form is unchanged (but may be wrapped in a vector). Calling `db-do-commands` with multiple commands (not wrapped in a single vector) will produce a "DEPRECATED" warning printed to the console.
-* `db-do-prepared` and `db-do-prepared-return-keys` now expect to receive a `db-spec`, an optional `transaction?` boolean, a `sql-params` argument, and an optional options map. `sql-params` is a vector containing a SQL string or `PreparedStatement` followed by parameters -- like other APIs in this library. In addition, like the `:multi? true` version of `execute!`, `db-do-prepared` can accept a vector that has parameter groups: multiple vectors containing groups of parameter values [JDBC-122](https://clojure.atlassian.net/browse/JDBC-123). Calling `db-do-prepared` with unrolled arguments -- the SQL string / statement followed by parameter groups -- is deprecated and will produce "DEPRECATED" warnings printed to the console.
-
-Changes in 0.5.7
-
-* `(insert! db table [:col] ["val"] {})` syntax, introduced in 0.5.6, threw an exception [JDBC-121](https://clojure.atlassian.net/browse/JDBC-121).
-
-Changes in 0.5.6
-
-* `create-table-ddl` now expects the column specs to be wrapped in a single vector and no longer needs the `:options` delimiter to specify the options map [JDBC-120](https://clojure.atlassian.net/browse/JDBC-120). If column specs are not wrapped in a vector, you will get a "DEPRECATED" warning printed to the console.
-* `insert!` now supports only single row insertion; multi-row insertion is deprecated. `insert-multi!` has been added for multi-row insertion. `:options` is no longer needed as a delimiter for the options map [JDBC-119](https://clojure.atlassian.net/browse/JDBC-119). If `insert!` is called with multiple rows, or `:options` is specified, you will get a "DEPRECATED" warning printed to the console.
-* NOTE: all deprecated functionality will go away in version 0.6.0!
-
-Changes in 0.5.5
-
-* Allow options map in all calls that previously took optional keyword arguments [JDBC-117](https://clojure.atlassian.net/browse/JDBC-117). The unrolled keyword argument forms of call are deprecated -- and print a "DEPRECATED" message to the console! -- and will go away in 0.6.0.
-
-Changes in 0.5.0
-
-* Allow PreparedStatement in db-do-prepared-return-keys [JDBC-115](https://clojure.atlassian.net/browse/JDBC-115).
-* Remove exception wrapping [JDBC-114](https://clojure.atlassian.net/browse/JDBC-114).
-* Drop Clojure 1.3 compatibility.
-
-Changes in 0.4.2
-
-* Remove redundant type hints [JDBC-113](https://clojure.atlassian.net/browse/JDBC-113) - Michael Blume.
-* Avoid reflection on `.prepareStatement` [JDBC-112](https://clojure.atlassian.net/browse/JDBC-112) - Michael Blume.
-* Add `metadata-query` macro to make metadata query / results easier to work with for [JDBC-107](https://clojure.atlassian.net/browse/JDBC-107).
-* `prepare-statement` `:return-keys` may now be a vector of (auto-generated) column names to return, in addition to just being truthy or falsey. This allows keys to be returned for more databases. [JDBC-104](https://clojure.atlassian.net/browse/JDBC-104).
-* Officially support H2 (and test against it) to support [JDBC-91](https://clojure.atlassian.net/browse/JDBC-91) and clarify docstrings to improve debugging driver-specific restrictions on SQL.
-
-Changes in 0.4.0 / 0.4.1
-
-* `db-do-prepared` now allows `transaction?` to be omitted when a `PreparedStatement` is passed as the second argument [JDBC-111](https://clojure.atlassian.net/browse/JDBC-111) - Stefan Kamphausen.
-* Nested transaction checks isolation level is the same [JDBC-110](https://clojure.atlassian.net/browse/JDBC-110) - Donald Ball.
-* Default PostgreSQL port; Support more dbtype/dbname variants [JDBC-109](https://clojure.atlassian.net/browse/JDBC-109).
-* Drop Clojure 1.2 compatibility.
-
-Changes in 0.3.7
-
-* Bump all driver versions in `project.clj` and re-test.
-* Remove duplicate `count` calls in `insert-sql` [JDBC-108](https://clojure.atlassian.net/browse/JDBC-108) - Earl St Sauver.
-* Remove driver versions from README and link to Maven Central [JDBC-106](https://clojure.atlassian.net/browse/JDBC-106).
-* Fix links in CHANGES and README [JDBC-103](https://clojure.atlassian.net/browse/JDBC-103) - John Walker.
-
-Changes in 0.3.6
-
-* Arbitrary values allowed for `:cursors`, `:concurrency`, `:result-type` arguments to `prepare-statement` [JDBC-102](https://clojure.atlassian.net/browse/JDBC-102).
-* Allow `:as-arrays? :cols-as-is` to omit column name uniqueness when returning result sets as arrrays [JDBC-101](https://clojure.atlassian.net/browse/JDBC-101).
-* Add `:timeout` argument to `prepare-statement` [JDBC-100](https://clojure.atlassian.net/browse/JDBC-100).
-
-Changes in 0.3.5
-
-* Reflection warnings on executeUpdate addressed.
-* HSQLDB and SQLite in-memory strings are now accepted [JDBC-94](https://clojure.atlassian.net/browse/JDBC-94).
-* Add support for readonly transactions via :read-only? [JDBC-93](https://clojure.atlassian.net/browse/JDBC-93).
-
-Changes in 0.3.4
-
-* execute! can now accept a PreparedStatement [JDBC-96](https://clojure.atlassian.net/browse/JDBC-96).
-* Support simpler db-spec with :dbtype and :dbname (and optional :host and :port etc) [JDBC-92](https://clojure.atlassian.net/browse/JDBC-92).
-* Support oracle:oci and oracle:thin subprotocols [JDBC-90](https://clojure.atlassian.net/browse/JDBC-90).
-
-Changes in 0.3.3
-
-* Prevent exception/crash when query called with bare SQL string [JDBC-89](https://clojure.atlassian.net/browse/JDBC-89).
-* Add :row-fn and :result-set-fn to metadata-result function [JDBC-87](https://clojure.atlassian.net/browse/JDBC-87).
-* Support key/value configuration from URI (Phil Hagelberg).
-
-Changes in 0.3.2
-
-* Add nil protocol implementation to ISQLParameter.
-
-Changes in 0.3.1 (broken)
-
-* Improve docstrings and add :arglists for better auto-generated documentation.
-* Make insert-sql private - technically a breaking change but it should never have been public: sorry folks!
-* Provide better protocol for setting parameters in prepared statements [JDBC-86](https://clojure.atlassian.net/browse/JDBC-86).
-* Fix parens in two deprecated tests [JDBC-85](https://clojure.atlassian.net/browse/JDBC-85).
-* Made create-table-ddl less aggressive about applying as-sql-name so only first name in a column spec is affected.
-
-Changes in 0.3.0
-
-* Ensure canonical Boolean to workaround strange behavior in some JDBC drivers [JDBC-84](https://clojure.atlassian.net/browse/JDBC-84).
-* Rename recently introduced test to ensure unique names [JDBC-83](https://clojure.atlassian.net/browse/JDBC-83).
-* Rename unused arguments in protocol implementation to support Android [JDBC-82](https://clojure.atlassian.net/browse/JDBC-82).
-* Correctly handle empty param group sequence in execute! (which only seemed to affect SQLite) [JDBC-65](https://clojure.atlassian.net/browse/JDBC-65).
-
-Changes in 0.3.0-rc1
-
-* Deprecate db-transaction (new in 0.3.0) in favor of with-db-transaction [JDBC-81](https://clojure.atlassian.net/browse/JDBC-81).
-* Add with-db-metadata macro and metadata-result function to make it easier to work with SQL metadata [JDBC-80](https://clojure.atlassian.net/browse/JDBC-80).
-* Add with-db-connection macro to make it easier to run groups of operations against a single open connection [JDBC-79](https://clojure.atlassian.net/browse/JDBC-79).
-* Add ISQLValue protocol to make it easier to support custom SQL types for parameters in SQL statements [JDBC-77](https://clojure.atlassian.net/browse/JDBC-77).
-* Add support for :isolation in with-db-transaction [JDBC-75](https://clojure.atlassian.net/browse/JDBC-75).
-* Add :user as an alias for :username for DataSource connections [JDBC-74](https://clojure.atlassian.net/browse/JDBC-74).
-
-Changes in 0.3.0-beta2
-
-* The DSL namespaces introduced in 0.3.0-alpha1 have been retired - see [java-jdbc/dsl](https://github.com/seancorfield/jsql) for a migration path if you wish to continue using the DSL (although it is recommended you switch to another, more expressive DSL).
-* The older API (0.2.3) which was deprecated in earlier 0.3.0 builds has moved to `clojure.java.jdbc.deprecated` to help streamline the API for 0.3.0 and clean up the documentation.
-
-Changes in 0.3.0-beta1
-
-* query as-arrays? now allows you to leverage lazy result fetching [JDBC-72](https://clojure.atlassian.net/browse/JDBC-72).
-* "h2" is recognized as a protocol shorthand for org.h2.Driver
-* Tests no longer use :1 literal [JDBC-71](https://clojure.atlassian.net/browse/JDBC-71).
-* Conditional use of javax.naming.InitialContext so it can be compiled on Android [JDBC-69](https://clojure.atlassian.net/browse/JDBC-69).
-* New db-query-with-resultset function replaces private `db-with-query-results*` and processes a raw ResultSet object [JDBC-63](https://clojure.atlassian.net/browse/JDBC-63).
-* Allow :set-parameters in db-spec to override set-parameters internal function to allow per-DB special handling of SQL parameters values (such as null for Teradata) [JDBC-40](https://clojure.atlassian.net/browse/JDBC-40).
-
-Changes in 0.3.0-alpha5
-
-* DDL now supports entities naming strategy [JDBC-53](https://clojure.atlassian.net/browse/JDBC-53).
-* Attempt to address potential memory leaks due to closures - see [Christophe Grand's blog post on Macros, closures and unexpected object retention](http://clj-me.cgrand.net/2013/09/11/macros-closures-and-unexpected-object-retention/).
-* Documentation has moved to [Using java.jdbc on Clojure-Doc.org](http://clojure-doc.org/articles/ecosystem/java_jdbc/home.html)
-* Added Leiningen support for easier development/testing (Maven is still the primary build tool).
-* Added create-index / drop-index DDL [JDBC-62](https://clojure.atlassian.net/browse/JDBC-62) - moquist
-* Make transaction? boolean optional in various `db-do-*` functions
-* Create clojure.java.jdbc.ddl namespace
-* Add create-table, drop-table, create-index and drop-index
-* Deprecate create-table, create-table-ddl and drop-table in main namespace
-* Update README to clarify PostgreSQL instructions.
-* Fix test suite for PostgreSQL [JDBC-59](https://clojure.atlassian.net/browser/JDBC-59)
-* Improve hooks for Oracle data type handling [JDBC-57](https://clojure.atlassian.net/browser/JDBC-57)
-* Fix reflection warnings [JDBC-55](https://clojure.atlassian.net/browser/JDBC-55)
-
-* DDL now supports entities naming strategy [JDBC-53](https://clojure.atlassian.net/browse/JDBC-53).
-* Attempt to address potential memory leaks due to closures - see [Christophe Grand's blog post on Macros, closures and unexpected object retention](http://clj-me.cgrand.net/2013/09/11/macros-closures-and-unexpected-object-retention/).
-* Documentation has moved to [Using java.jdbc on Clojure-Doc.org](http://clojure-doc.org/articles/ecosystem/java_jdbc/home.html)
-* Added Leiningen support for easier development/testing (Maven is still the primary build tool).
-* Added create-index / drop-index DDL [JDBC-62](https://clojure.atlassian.net/browse/JDBC-62) - moquist
-* Make transaction? boolean optional in various `db-do-*` functions
-  * It will ultimately change to a function argument I think when [JDBC-37](https://clojure.atlassian.net/browser/JDBC-37) is dealt with
-* Create clojure.java.jdbc.ddl namespace
-  * Add create-table and drop-table
-  * Deprecate create-table, create-table-ddl and drop-table in main namespace
-  * More DDL is coming soon
-* Update README to clarify PostgreSQL instructions.
-* Fix test suite for PostgreSQL [JDBC-59](https://clojure.atlassian.net/browser/JDBC-59)
-* Improve hooks for Oracle data type handling [JDBC-57](https://clojure.atlassian.net/browser/JDBC-57)
-* Fix reflection warnings [JDBC-55](https://clojure.atlassian.net/browser/JDBC-55)
-
-Changes in 0.3.0-alpha4
-
-* Fix connection leaks [JDBC-54](https://clojure.atlassian.net/browser/JDBC-54)
-* Allow order-by to accept empty sequence (and return empty string)
-
-Changes in 0.3.0-alpha3
-
-* Fix macro / import interaction by fully qualifying Connection type.
-
-Changes in 0.3.0-alpha2
-
-* Address [JDBC-51](https://clojure.atlassian.net/browse/JDBC-51) by declaring get-connection returns java.sql.Connection
-* Add IResultSetReadColumn protocol extension point for custom read conversions [JDBC-46](https://clojure.atlassian.net/browse/JDBC-46)
-* Add :multi? to execute! so it can be used for repeated operations [JDBC-52](https://clojure.atlassian.net/browse/JDBC-52)
-* Reverted specialized handling of NULL values (reopens [JDBC-40](https://clojure.atlassian.net/browse/JDBC-40))
-* Rename :as-arrays to :as-arrays? since it is boolean
-* Add curried version of clojure.java.jdbc.sql/as-quoted-str
-* Officially deprecate resultset-seq
-
-Changes in 0.3.0-alpha1
-
-Major overhaul of the API and deprecation of most of the old API!
-
-* Add insert!, query, update!, delete! and execute! high-level API
-  [JDBC-20](https://clojure.atlassian.net/browse/JDBC-20)
-* Add optional SQL-generating DSL in clojure.java.jdbc.sql (implied by JDBC-20)
-* Add db- prefixed versions of low-level API
-* Add db-transaction macro:
-
-```
-  (db-transaction [t-con db-spec]
-    (query t-con (select * :user (where {:id 42}))))
-```
-
-* Add result-set-seq as replacement for resultset-seq (which will be deprecated)
-* Transaction now correctly rollback on non-Exception Throwables
-  [JDBC-43](https://clojure.atlassian.net/browse/JDBC-43)
-* Rewrite old API functions in terms of new API, and deprecate old API
-  [JDBC-43](https://clojure.atlassian.net/browse/JDBC-43)
-* Add :as-arrays to query / result-set-seq
-  [JDBC-41](https://clojure.atlassian.net/browse/JDBC-41)
-* Better handling of NULL values [JDBC-40](https://clojure.atlassian.net/browse/JDBC-40)
-  and [JDBC-18](https://clojure.atlassian.net/browse/JDBC-18)
-  Note: JDBC-40 has been reverted in 0.3.0-alpha2 because it introduced regressions for PostgreSQL
-* db-do-commands allows you to execute SQL without a transaction wrapping it
-  [JDBC-38](https://clojure.atlassian.net/browse/JDBC-38)
-* Remove reflection warning from execute-batch
-* Add notes to README about 3rd party database driver dependencies
-* Add optional :identifiers argument to resultset-seq so you can explicitly pass in the naming strategy
-
-Changes in 0.2.3:
-
-* as-str now treats a.b as two identifiers separated by . so quoting produces [a].[b] instead of [a.b]
-* Add :connection-uri option [JDBC-34](https://clojure.atlassian.net/browse/JDBC-34)
-
-Changes in 0.2.2:
-
-* Handle Oracle unknown row count affected [JDBC-33](https://clojure.atlassian.net/browse/JDBC-33)
-* Handle jdbc: prefix in string db-specs [JDBC-32](https://clojure.atlassian.net/browse/JDBC-32)
-* Handle empty columns in make column unique (Juergen Hoetzel) [JDBC-31](https://clojure.atlassian.net/browse/JDBC-31)
-
-Changes in 0.2.1:
-
-* Result set performance enhancement (Juergen Hoetzel) [JDBC-29](https://clojure.atlassian.net/browse/JDBC-29)
-* Make do-prepared-return-keys (for Korma team) [JDBC-30](https://clojure.atlassian.net/browse/JDBC-30)
-
-Changes in 0.2.0:
-
-* Merge internal namespace into main jdbc namespace and update symbol visibility / naming.
-
-Changes in 0.1.4:
-
-* Unwrap RTE for nested transaction exception (we already unwrapped top-level transaction RTEs).
-* Remove reflection warning unwrapping RunTimeException (Alan Malloy)
-
-Changes in 0.1.3:
-
-* Fix JDBC-26 (fully) by adding transaction/generated keys support for SQLite3 (based on patch from Nelson Morris)
-
-Changes in 0.1.2:
-
-* Fix JDBC-23 by handling prepared statement params correctly (Ghadi Shayban)
-* Fix JDBC-26 by adding support for SQLite3 (based on patch from Nelson Morris)
-* Fix JDBC-27 by replacing replicate with repeat (Jonas Enlund)
-* Ensure MS SQL Server passes tests with both Microsoft and jTDS drivers
-* Build server now tests derby, hsqldb and sqlite by default
-* Update README per Stuart Sierra's outline for contrib projects
-
-Changes in 0.1.1:
-
-* Fix JDBC-21 by adding support for db-spec as URI (Phil Hagelberg).
-* Fix JDBC-22 by deducing driver class name from subprotocol (Phil Hagelberg).
-* Add Postgres dependency so tests can be automcated (Phil Hagelberg).
-* Add ability to specify test databases via TEST_DBS environment variable (Phil Hagelberg).
-
-Changes in 0.1.0:
-
-* Fix JDBC-15 by removing dependence on deprecated structmap.
-
-Changes in 0.0.7:
-
-* Fix JDBC-9 by renaming duplicate columns instead of throwing an exception.
-  - thanx to Peter Siewert!
-* Fix JDBC-16 by ensuring do-prepared works with no param-groups provided.
-* Fix JDBC-17 by adding type hints to remove more reflection warnings.
-  - thanx to Stuart Sierra!
-Documentation:
-* Address JDBC-4 by documenting how to do connection pooling.
-
-Changes in 0.0.6:
-
-* Move former tests to test-utilities namespace - these do not touch a database
-* Convert old "test" examples into real tests against real databases
-  - tested locally against MySQL, Apache Derby, HSQLDB
-  - build system should run against Apache Derby, HSQLSB
-  - will add additional databases later
-* Fix JDBC-12 by removing batch when doing a single update
-* Remove wrapping of exceptions in transactions to make it easier to work with SQLExceptions
-
-Changes in 0.0.5:
-
-* Add prepare-statement function to ease creation of PreparedStatement with common options:
-  - see docstring for details
-* with-query-results now allows the SQL/params vector to be:
-  - a PreparedStatement object, followed by any parameters the SQL needs
-  - a SQL query string, followed by any parameters it needs
-  - options (for prepareStatement), a SQL query string, followed by any parameters it needs
-* Add support for databases that cannot return generated keys (e.g., HSQLDB)
-  - insert operations silently return the insert counts instead of generated keys
-  - it is the user's responsibility to handle this if you're using such a database!
-
-Changes in 0.0.4:
-
-* Fix JDBC-2 by allowing :table-spec {string} at the end of create-table arguments:
-  (sql/create-table :foo [:col1 "int"] ["col2" :int] :table-spec "ENGINE=MyISAM")
-* Fix JDBC-8 by removing all reflection warnings
-* Fix JDBC-11 by no longer committing the transaction when an Error occurs
-* Clean up as-... functions to reduce use of (binding)
-* Refactor `do-prepared*`, separating out return keys logic and parameter setting logic
-  - in preparation for exposing more hooks in PreparedStatement creation / manipulation
-
-Changes in 0.0.3:
-
-* Fix JDBC-10 by using .executeUpdate when generating keys (MS SQL Server, PostgreSQL compatibility issue)
-
-Changes in 0.0.2:
-
-* Fix JDBC-7 Clojure 1.2 compatibility (thanx to Aaron Bedra!)
-
-Changes in 0.0.1 (compared to clojure.contrib.sql):
-
-* Exposed print-... functions for exception printing; no longer writes exceptions to `*out*`
-* Add clojure.java.jdbc/resultset-seq (to replace clojure.core/resultset-seq which should be deprecated)
-* Add support for naming and quoting strategies - see https://clojure.github.io/java.jdbc/doc/clojure/java/jdbc/NameMapping.html
-  - The formatting is a bit borked, Tom F knows about this and is working on an enhancement to auto-doc to improve it
-* Add ability to return generated keys from single insert operations, add insert-record function
-* Clojure 1.3 compatibility
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index d1017074..00000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,12 +0,0 @@
-This is a [Clojure contrib] project.
-
-Under the Clojure contrib [guidelines], this project cannot accept
-pull requests. All patches must be submitted via [JIRA].
-
-See [Contributing] on the Clojure website for
-more information on how to contribute.
-
-[Clojure contrib]: https://clojure.org/community/contrib_libs
-[Contributing]: https://clojure.org/community/contributing
-[JIRA]: http://clojure.atlassian.net/browse/JDBC
-[guidelines]: https://clojure.org/community/contrib_howto
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index e246f6a2..00000000
--- a/LICENSE
+++ /dev/null
@@ -1,205 +0,0 @@
-Eclipse Public License - v 1.0
-
-THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
-LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
-CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
-
-1. DEFINITIONS
-
-"Contribution" means:
-
-a) in the case of the initial Contributor, the initial code and documentation
-   distributed under this Agreement, and
-b) in the case of each subsequent Contributor:
-    i) changes to the Program, and
-   ii) additions to the Program;
-
-   where such changes and/or additions to the Program originate from and are
-   distributed by that particular Contributor. A Contribution 'originates'
-   from a Contributor if it was added to the Program by such Contributor
-   itself or anyone acting on such Contributor's behalf. Contributions do not
-   include additions to the Program which: (i) are separate modules of
-   software distributed in conjunction with the Program under their own
-   license agreement, and (ii) are not derivative works of the Program.
-
-"Contributor" means any person or entity that distributes the Program.
-
-"Licensed Patents" mean patent claims licensable by a Contributor which are
-necessarily infringed by the use or sale of its Contribution alone or when
-combined with the Program.
-
-"Program" means the Contributions distributed in accordance with this
-Agreement.
-
-"Recipient" means anyone who receives the Program under this Agreement,
-including all Contributors.
-
-2. GRANT OF RIGHTS
-  a) Subject to the terms of this Agreement, each Contributor hereby grants
-     Recipient a non-exclusive, worldwide, royalty-free copyright license to
-     reproduce, prepare derivative works of, publicly display, publicly
-     perform, distribute and sublicense the Contribution of such Contributor,
-     if any, and such derivative works, in source code and object code form.
-  b) Subject to the terms of this Agreement, each Contributor hereby grants
-     Recipient a non-exclusive, worldwide, royalty-free patent license under
-     Licensed Patents to make, use, sell, offer to sell, import and otherwise
-     transfer the Contribution of such Contributor, if any, in source code and
-     object code form. This patent license shall apply to the combination of
-     the Contribution and the Program if, at the time the Contribution is
-     added by the Contributor, such addition of the Contribution causes such
-     combination to be covered by the Licensed Patents. The patent license
-     shall not apply to any other combinations which include the Contribution.
-     No hardware per se is licensed hereunder.
-  c) Recipient understands that although each Contributor grants the licenses
-     to its Contributions set forth herein, no assurances are provided by any
-     Contributor that the Program does not infringe the patent or other
-     intellectual property rights of any other entity. Each Contributor
-     disclaims any liability to Recipient for claims brought by any other
-     entity based on infringement of intellectual property rights or
-     otherwise. As a condition to exercising the rights and licenses granted
-     hereunder, each Recipient hereby assumes sole responsibility to secure
-     any other intellectual property rights needed, if any. For example, if a
-     third party patent license is required to allow Recipient to distribute
-     the Program, it is Recipient's responsibility to acquire that license
-     before distributing the Program.
-  d) Each Contributor represents that to its knowledge it has sufficient
-     copyright rights in its Contribution, if any, to grant the copyright
-     license set forth in this Agreement.
-
-3. REQUIREMENTS
-
-A Contributor may choose to distribute the Program in object code form under
-its own license agreement, provided that:
-
-  a) it complies with the terms and conditions of this Agreement; and
-  b) its license agreement:
-      i) effectively disclaims on behalf of all Contributors all warranties
-         and conditions, express and implied, including warranties or
-         conditions of title and non-infringement, and implied warranties or
-         conditions of merchantability and fitness for a particular purpose;
-     ii) effectively excludes on behalf of all Contributors all liability for
-         damages, including direct, indirect, special, incidental and
-         consequential damages, such as lost profits;
-    iii) states that any provisions which differ from this Agreement are
-         offered by that Contributor alone and not by any other party; and
-     iv) states that source code for the Program is available from such
-         Contributor, and informs licensees how to obtain it in a reasonable
-         manner on or through a medium customarily used for software exchange.
-
-When the Program is made available in source code form:
-
-  a) it must be made available under this Agreement; and
-  b) a copy of this Agreement must be included with each copy of the Program.
-     Contributors may not remove or alter any copyright notices contained
-     within the Program.
-
-Each Contributor must identify itself as the originator of its Contribution,
-if
-any, in a manner that reasonably allows subsequent Recipients to identify the
-originator of the Contribution.
-
-4. COMMERCIAL DISTRIBUTION
-
-Commercial distributors of software may accept certain responsibilities with
-respect to end users, business partners and the like. While this license is
-intended to facilitate the commercial use of the Program, the Contributor who
-includes the Program in a commercial product offering should do so in a manner
-which does not create potential liability for other Contributors. Therefore,
-if a Contributor includes the Program in a commercial product offering, such
-Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
-every other Contributor ("Indemnified Contributor") against any losses,
-damages and costs (collectively "Losses") arising from claims, lawsuits and
-other legal actions brought by a third party against the Indemnified
-Contributor to the extent caused by the acts or omissions of such Commercial
-Contributor in connection with its distribution of the Program in a commercial
-product offering. The obligations in this section do not apply to any claims
-or Losses relating to any actual or alleged intellectual property
-infringement. In order to qualify, an Indemnified Contributor must:
-a) promptly notify the Commercial Contributor in writing of such claim, and
-b) allow the Commercial Contributor to control, and cooperate with the
-Commercial Contributor in, the defense and any related settlement
-negotiations. The Indemnified Contributor may participate in any such claim at
-its own expense.
-
-For example, a Contributor might include the Program in a commercial product
-offering, Product X. That Contributor is then a Commercial Contributor. If
-that Commercial Contributor then makes performance claims, or offers
-warranties related to Product X, those performance claims and warranties are
-such Commercial Contributor's responsibility alone. Under this section, the
-Commercial Contributor would have to defend claims against the other
-Contributors related to those performance claims and warranties, and if a
-court requires any other Contributor to pay any damages as a result, the
-Commercial Contributor must pay those damages.
-
-5. NO WARRANTY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
-IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
-NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
-Recipient is solely responsible for determining the appropriateness of using
-and distributing the Program and assumes all risks associated with its
-exercise of rights under this Agreement , including but not limited to the
-risks and costs of program errors, compliance with applicable laws, damage to
-or loss of data, programs or equipment, and unavailability or interruption of
-operations.
-
-6. DISCLAIMER OF LIABILITY
-
-EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
-CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
-LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
-EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGES.
-
-7. GENERAL
-
-If any provision of this Agreement is invalid or unenforceable under
-applicable law, it shall not affect the validity or enforceability of the
-remainder of the terms of this Agreement, and without further action by the
-parties hereto, such provision shall be reformed to the minimum extent
-necessary to make such provision valid and enforceable.
-
-If Recipient institutes patent litigation against any entity (including a
-cross-claim or counterclaim in a lawsuit) alleging that the Program itself
-(excluding combinations of the Program with other software or hardware)
-infringes such Recipient's patent(s), then such Recipient's rights granted
-under Section 2(b) shall terminate as of the date such litigation is filed.
-
-All Recipient's rights under this Agreement shall terminate if it fails to
-comply with any of the material terms or conditions of this Agreement and does
-not cure such failure in a reasonable period of time after becoming aware of
-such noncompliance. If all Recipient's rights under this Agreement terminate,
-Recipient agrees to cease use and distribution of the Program as soon as
-reasonably practicable. However, Recipient's obligations under this Agreement
-and any licenses granted by Recipient relating to the Program shall continue
-and survive.
-
-Everyone is permitted to copy and distribute copies of this Agreement, but in
-order to avoid inconsistency the Agreement is copyrighted and may only be
-modified in the following manner. The Agreement Steward reserves the right to
-publish new versions (including revisions) of this Agreement from time to
-time. No one other than the Agreement Steward has the right to modify this
-Agreement. The Eclipse Foundation is the initial Agreement Steward. The
-Eclipse Foundation may assign the responsibility to serve as the Agreement
-Steward to a suitable separate entity. Each new version of the Agreement will
-be given a distinguishing version number. The Program (including
-Contributions) may always be distributed subject to the version of the
-Agreement under which it was received. In addition, after a new version of the
-Agreement is published, Contributor may elect to distribute the Program
-(including its Contributions) under the new version. Except as expressly
-stated in Sections 2(a) and 2(b) above, Recipient receives no rights or
-licenses to the intellectual property of any Contributor under this Agreement,
-whether expressly, by implication, estoppel or otherwise. All rights in the
-Program not expressly granted under this Agreement are reserved.
-
-This Agreement is governed by the laws of the State of New York and the
-intellectual property laws of the United States of America. No party to this
-Agreement will bring a legal action under this Agreement more than one year
-after the cause of action arose. Each party waives its rights to a jury trial in
-any resulting litigation.
-
-
diff --git a/README.md b/README.md
deleted file mode 100644
index b36cbaf9..00000000
--- a/README.md
+++ /dev/null
@@ -1,514 +0,0 @@
-clojure.java.jdbc
-========================================
-
-A low-level Clojure wrapper for JDBC-based access to databases. This project is "Inactive". It has effectively been superseded by [seancorfield/next.jdbc](https://github.com/seancorfield/next-jdbc).
-
-For higher level DSLs and migration libraries that are compatible, see the [documentation](https://clojure-doc.org/articles/ecosystem/java_jdbc/home).
-
-Formerly known as `clojure.contrib.sql`.
-
-This library is mature and stable. It is widely used and its use is described in many books and tutorials. It will continue to get bug fixes and minor releases. Based on my experience using and maintaining this library, I've created a faster, more modern JDBC wrapper called [next.jdbc](https://github.com/seancorfield/next-jdbc). I consider it to be the "next generation" of `clojure.java.jdbc` but it exposes a different API -- a better API, I think.
-
-Documentation
-========================================
-* [API Reference](https://clojure.github.io/java.jdbc/) (Autogenerated)
-* [Overview](https://clojure-doc.org/articles/ecosystem/java_jdbc/home)
-* [Manipulating Data with SQL](https://clojure-doc.org/articles/ecosystem/java_jdbc/using_sql)
-* [How to Reuse Database Connections](https://clojure-doc.org/articles/ecosystem/java_jdbc/reusing_connections)
-* [Using DDL and Metadata](https://clojure-doc.org/articles/ecosystem/java_jdbc/using_ddl)
-
-Support
-========================================
-* [Mailing List](https://groups.google.com/forum/#!forum/clojure-java-jdbc)
-* #sql on [Clojurians Slack](http://clojurians.net/)
-
-Releases and Dependency Information
-========================================
-
-Latest stable release: 0.7.12 -- requires Clojure 1.7 or later!
-
-* [All Released Versions](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.clojure%22%20AND%20a%3A%22java.jdbc%22)
-* [Development Snapshot Versions](https://oss.sonatype.org/index.html#nexus-search;gav~org.clojure~java.jdbc~~~)
-
-[CLI/`deps.edn`](https://clojure.org/reference/deps_and_cli) dependency information:
-```clojure
-org.clojure/java.jdbc {:mvn/version "0.7.12"}
-```
-[Leiningen](https://github.com/technomancy/leiningen) dependency information:
-```clojure
-[org.clojure/java.jdbc "0.7.12"]
-```
-[Maven](https://maven.apache.org/) dependency information:
-```xml
-<dependency>
-  <groupId>org.clojure</groupId>
-  <artifactId>java.jdbc</artifactId>
-  <version>0.7.12</version>
-</dependency>
-```
-_Note: Earlier versions of Clojure are supported by older versions of `clojure.java.jdbc`: e.g., version 0.6.1 supports Clojure 1.4 and later._
-
-You will also need to add dependencies for the JDBC driver you intend to use. Here are links (to Maven Central) for each of the common database drivers that clojure.java.jdbc is known to be used with:
-
-* [Apache Derby](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.apache.derby%22%20AND%20a%3A%22derby%22)
-* [H2](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.h2database%22%20AND%20a%3A%22h2%22)
-* [HSQLDB](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22hsqldb%22%20AND%20a%3A%22hsqldb%22)
-* [Microsoft SQL Server jTDS](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22net.sourceforge.jtds%22%20AND%20a%3A%22jtds%22)
-* [Microsoft SQL Server -- Official MS Version](https://search.maven.org/#search%7Cga%7C1%7Cg%3A%22com.microsoft.sqlserver%22%20AND%20a%3A%22mssql-jdbc%22)
-* [MySQL](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22mysql%22%20AND%20a%3A%22mysql-connector-java%22)
-* [PostgreSQL](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.postgresql%22%20AND%20a%3A%22postgresql%22)
-* [SQLite](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.xerial%22%20AND%20a%3A%22sqlite-jdbc%22)
-
-Note: different versions of various database drivers have different Java/JVM version requirements. In particular, recent versions of Apache Derby require at least Java 8 and recent versions of H2 require at least Java 7. Clojure's Continuous Integration system uses older versions so tests can be run on Java 6 (see `pom.xml`); local testing is done with more recent versions on Java 8.
-
-Example Usage
-========================================
-```clojure
-(require '[clojure.java.jdbc :as j])
-
-;; there are many ways to write a db-spec but the easiest way is to
-;; use :dbtype and then provide the :dbname and any of :user, :password,
-;; :host, :port, and other options as needed:
-(def mysql-db {:dbtype "mysql"
-               :dbname "clojure_test"
-               :user "clojure_test"
-               :password "clojure_test"})
-
-(def pg-db {:dbtype "postgresql"
-            :dbname "mypgdatabase"
-            :host "mydb.server.com"
-            :user "myuser"
-            :password "secret"
-            :ssl true
-            :sslfactory "org.postgresql.ssl.NonValidatingFactory"})
-
-;; if the dbtype is not known to clojure.java.jdbc, or you want to override the
-;; default choice of JDBC driver class name, you can provide :classname and the
-;; name of the class to use:
-
-(def redshift42 {:dbtype "redshift"
-                 :dbname "myredstore"
-                 :classname "com.amazon.redshift.jdbc42.Driver"
-                 ...})
-
-;; you can also specify a full connection string if you'd prefer:
-(def pg-uri
-  {:connection-uri (str "postgresql://myuser:secret@mydb.server.com:5432/mypgdatabase"
-                        "?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory")})
-
-(j/insert-multi! mysql-db :fruit
-  [{:name "Apple" :appearance "rosy" :cost 24}
-   {:name "Orange" :appearance "round" :cost 49}])
-;; ({:generated_key 1} {:generated_key 2})
-
-(j/query mysql-db
-  ["select * from fruit where appearance = ?" "rosy"]
-  {:row-fn :cost})
-;; (24)
-```
-For more detail see the [API reference](https://clojure.github.io/java.jdbc/) or [documentation](https://clojure-doc.org/articles/ecosystem/java_jdbc/home).
-
-Developer Information
-========================================
-
-* [GitHub project](https://github.com/clojure/java.jdbc)
-* [Bug Tracker](https://clojure.atlassian.net/browse/JDBC)
-* [Continuous Integration](https://github.com/clojure/java.jdbc/actions/workflows/test.yml)
-
-* Testing:
-  * Currently by default tests run only against Derby and HSQLDB, the in-process databases.
-
-* To test against PostgreSQL, first create the user and database:
-
-        $ sudo -u postgres createuser clojure_test -P clojure_test
-        $ sudo -u postgres createdb clojure_test -O clojure_test
-
-* Or similarly with MySQL:
-
-        $ mysql -u root
-        mysql> create database clojure_test;
-        mysql> grant all on clojure_test.* to clojure_test identified by "clojure_test";
-
-* Then run the tests with the <tt>TEST_DBS</tt> environment variable:
-
-        $ TEST_DBS="mysql postgres" mvn test
-
-* Also see the `run-tests.sh` shell script which uses the `clj` CLI and `deps.edn` for multi-version testing!
-
-Change Log
-====================
-
-* Release 0.7.12 on 2021-02-01
-  * Make the protocols `ISQLValue`, `ISQLParameter`, and `IResultSetReadColumn` extensible via metadata.
-
-* Release 0.7.11 on 2019-12-24
-  * Address edge case in transaction rollback failure [JDBC-179](https://clojure.atlassian.net/browse/JDBC-179).
-
-* Release 0.7.10 on 2019-08-24
-  * Use a US-locale `lower-case` function to avoid problems in certain locales (e.g., Turkish). A similar issue has been fixed recently in both HoneySQL and `next.jdbc`.
-  * Clean up `db-spec` options that are passed to the JDBC connection manager as properties [JDBC-178](https://clojure.atlassian.net/browse/JDBC-178).
-  * Relax restriction on `create-table-ddl` column specs to allow numbers (as well as keywords and strings) [JDBC-177](https://clojure.atlassian.net/browse/JDBC-177).
-
-* Release 0.7.9 on 2019-02-21
-  * Fix behavior of multi-inserts when database does not support generated keys [JDBC-176](https://clojure.atlassian.net/browse/JDBC-176).
-  * Added _highly experimental_ support for `datafy`/`nav` (in `clojure.java.jdbc.datafy` namespace). This includes a convention-based approach to foreign keys with some assistance from a `:schema` option. This is subject to change and is provided mostly for informational purposes, as an example of the new functionality in Clojure 1.10. This includes a fix for the conventions from [JDBC-175](https://clojure.atlassian.net/browse/JDBC-175).
-  * Add note about rewriting batched operations to `insert-multi!` for some drivers [JDBC-174](https://clojure.atlassian.net/browse/JDBC-174).
-  * Support Oracle SID style URLs (`dbtype` can be `oracle:sid` which maps to `oracle:thin` and uses `:` as the separator before the `dbname` value) [JDBC-173](https://clojure.atlassian.net/browse/JDBC-173).
-
-* Release 0.7.8 on 2018-08-13
-  * Support multiple JDBC driver class names (MySQL introduced a new driver class name with its 6.x connector) [JDBC-172](https://clojure.atlassian.net/browse/JDBC-172).
-  * Allow `with-db-connection` and `with-db-metadata` to nest [JDBC-171](https://clojure.atlassian.net/browse/JDBC-171).
-
-* Release 0.7.7 on 2018-06-23
-  * Support `:as-arrays?`, `:result-set-fn`, and `:row-fn` in operations that return generated keys as a result set (`execute!`, `insert!`, and `insert-multi!`) [JDBC-169](https://clojure.atlassian.net/browse/JDBC-169).
-  * `get-connection` provides much better feedback if you accidentally call a function that expects a `db-spec` but pass a `java.sql.Connection` object instead (which is only required for `prepare-statement`).
-
-* Release 0.7.6 on 2018-04-24
-  * `execute!` now supports `:return-keys` as a vector of column names, rather than just a simple Boolean value, for drivers that support that [JDBC-166](https://clojure.atlassian.net/browse/JDBC-166).
-  * Add built-in support for H2 in-memory database (`:dbtype "h2:mem"`).
-  * Add missing spec for `db-spec` being a `java.net.URI` object.
-  * Fix `add-connection` handling of string `db-spec` (becomes `:connection-uri`, not `:connection-string`).
-  * Fix specs for `with-db-*` functions, to support options in the binding form [JDBC-165](https://clojure.atlassian.net/browse/JDBC-165).
-  * Update tests so they work properly with string `db-spec` test databases.
-  * Ensure no reflection warnings are present.
-  * Switched local test infrastructure over to CLI and `deps.edn` (from Leiningen) as an example of multi-version testing without a "build tool".
-
-* Release 0.7.5 on 2017-12-29
-  * Add support for `:return-keys` in `execute!` and `:multi?` in `db-do-prepared-return-keys` [JDBC-163](https://clojure.atlassian.net/browse/JDBC-163).
-
-* Release 0.7.4 on 2017-12-14
-  * Improved discoverability of other `java.jdbc` documentation [JDBC-160](https://clojure.atlassian.net/browse/JDBC-160).
-  * Optional specs updated with `:keywordize?` and `:connection-uri` changes from 0.7.2 and 0.7.3 releases.
-  * Performance improvements, primarily in `query` and `reducible-query`.
-  * Experimental `:raw?` result set handling in `reducible-query`.
-  * `modify-connection` is more robust in the face of `null` connections and bad option values.
-
-* Release 0.7.3 on 2017-10-05
-  * Added `:keywordize?` option alongside `:identifiers` that defaults to `true` but can be set to `false` to opt-out of converting identifiers to keywords (so column names etc will only be processed by the function passed as `:identifiers`) [JDBC-159](https://clojure.atlassian.net/browse/JDBC-159).
-  * If an exception occurs during a transaction, and then rollback fails with another exception, both exceptions will now be combined into an `ex-info`. Previously the rollback exception obscured the transaction exception [JDBC-158](https://clojure.atlassian.net/browse/JDBC-158).
-
-* Release 0.7.2 on 2017-10-02
-  * `connection-uri` was incorrectly spec'd as a `java.net.URI` but should be `string?` [JDBC-156](https://clojure.atlassian.net/browse/JDBC-156).
-  * Allow for `:user` and `:password` to be passed with `:connection-uri`, so credentials can be omitted from the connection string.
-  * Clarified docstring for `get-connection` to show where `:user` and `:password` can be passed.
-
-* Release 0.7.1 on 2017-08-30
-  * Connection strings with empty values were not parsed correctly [JDBC-155](https://clojure.atlassian.net/browse/JDBC-155).
-
-* Release 0.7.0 on 2017-07-16
-  * `:conditional?` option for `create-table-ddl` and `drop-table-ddl` to provide for existence check (or a function to manipulate the generated DDL).
-  * Add better support for Oracle connections (default port to `1521`, support `:dbtype "oracle"` -- as `"oracle:thin"` -- and `:dbtype "oracle:oci"`, with `@` instead of `//` before host).
-
-* Release 0.7.0-beta5 on 2017-07-05
-  * `get-connection` now accepts an `opts` map with `:auto-commit?` and `:read-only?` options. If present, the appropriate methods will be called on the connection obtained. These options are valid in any function call that may call `get-connection` under the hood. This should allow for streaming results in a query for most databases [JDBC-153](https://clojure.atlassian.net/browse/JDBC-153).
-  * Additional validation of options is performed in `prepared-statement` to avoid silently ignoring invalid combinations of `:concurrency`, `:cursors`, `:result-type`, and `:return-keys`.
-
-* Release 0.7.0-beta4 on 2017-07-04
-  * `opts` are now correctly passed from `reducible-query` to `db-query-with-resultset`.
-  * Updated the `::query-options` spec to make it clear that `::prepare-options` are also acceptable there.
-
-* Release 0.7.0-beta3 on 2017-07-04
-  * Reflection warnings removed in `reducible-result-set` [JDBC-152](https://clojure.atlassian.net/browse/JDBC-152).
-
-* Release 0.7.0-beta2 on 2017-06-30 (a.k.a The Reducible Saga, Part 2)
-  * Support for Clojure 1.5 and 1.6 has been dropped -- breaking change.
-  * Or, put another way, `clojure.java.jdbc` now requires Clojure 1.7 or later!
-  * All public functions now have specs in the optional `clojure.java.jdbc.spec` namespace (requires `clojure.spec.alpha`).
-  * `reducible-query` and `reducible-result-set` use `IReduce` and correctly support the no-`init` arity of `reduce` by using the first row of the `ResultSet`, if present, as the (missing) `init` value, and only calling `f` with no arguments if the `ResultSet` is empty. The `init` arity of `reduce` only ever calls `f` with two arguments.
-
-* Release 0.7.0-beta1 on 2017-06-29
-  * Support for Clojure 1.4.0 has been dropped -- breaking change.
-  * Optional spec support now uses `clojure.spec.alpha`.
-  * `reducible-query` accepts a `db-spec` and a SQL/parameters vector and returns a reducible (`IReduce` on Clojure 1.7 or later; `CollReduce` on Clojure 1.5/1.6): when reduced, it runs the query, obtains a reducible result set, and then reduces that. A reducible query will run the query each time it is reduced. The helper function `reducible-result-set` is public: it accepts a `ResultSet` and produces a reducible that offers a single pass reduce over the rows. Both functions honor `reduced` values to short-circuit the process [JDBC-99](https://clojure.atlassian.net/browse/JDBC-99).
-
-* Release 0.7.0-alpha3 on 2017-03-23
-  * `classname` is now accepted with `dbtype` / `dbname` so you can easily specify a JDBC driver class name for a database type that is not known [JDBC-151](https://clojure.atlassian.net/browse/JDBC-151).
-  * `redshift` has been added as a `dbtype` with `com.amazon.redshift.jdbc.Driver` as the driver name.
-
-* Release 0.7.0-alpha2 on 2017-03-01
-  * `pgsql` and the Impossibl PostgresSQL 'NG' driver are now supported (note that `:max-rows` does not work with this driver!); also, providing unknown `dbtype` or `subprotocol` in a `db-spec` should now throw a better exception [JDBC-150](https://clojure.atlassian.net/browse/JDBC-150).
-  * `quoted` now accepts keywords for database / dialect (`:ansi` (including PostgresSQL), `:mysql`, `:oracle`, `:sqlserver` -- these match the keywords used in HoneySQL which is the recommended third party SQL DSL for java.jdbc) [JDBC-149](https://clojure.atlassian.net/browse/JDBC-149).
-  * Reorder `get-connection` clauses to make it easier to combine keys in a `db-spec` [JDBC-148](https://clojure.atlassian.net/browse/JDBC-148).
-  * Force load `DriverManager` before `classForName` call on drivers to avoid potential race condition on initialization [JDBC-145](https://clojure.atlassian.net/browse/JDBC-145).
-
-* Release 0.7.0-alpha1 on 2016-11-12 -- potentially breaking changes
-  * The signatures of `as-sql-name` and `quoted` have changed slightly: the former no longer has the curried (single argument) version, and the latter no longer has the two argument version. This change came out of a discussion on Slack which indicated curried functions are non-idiomatic. If you relied on the curried version of `as-sql-name`, you will not need to use `partial`. If you relied on the two argument version of `quoted`, you will need to add an extra `( )` for the one argument call. I'd be fairly surprised if anyone is using `as-sql-name` at all since it is really an implementation detail. I'd also be surprised if anyone was using the two argument version of `quoted` since the natural usage is `:entities (quoted [\[ \]])` to create a naming strategy (that provides SQL entity quoting).
-  * Clarified that `insert-multi!` with a sequence of row maps may be substantially slower than with a sequence of row value vectors (the former performs an insert for each row, the latter performs a single insert for all the data together) [JDBC-147](https://clojure.atlassian.net/browse/JDBC-147).
-  * All options are passed through all function calls, expanding the range of options you can pass into high-level functions such as `insert!` and `update!` [JDBC-144](https://clojure.atlassian.net/browse/JDBC-144).
-  * Added `get-isolation-level` to return the current transaction's isolation level, if any [JDBC-141](https://clojure.atlassian.net/browse/JDBC-141).
-  * Added support for `read-columns` option to allow more flexible customization of reading column values from a result set (particularly in a multi-database application). Also expands `set-parameters` support to options (previously it was just part of the db-spec) [JDBC-137](https://clojure.atlassian.net/browse/JDBC-137).
-  * Expanded optional `clojure.spec` coverage to almost the whole library API.
-
-* Release 0.6.2-alpha3 on 2016-08-25
-  * Fixed bad interaction between `:qualifier` and existing `:identifiers` functionality [JDBC-140](https://clojure.atlassian.net/browse/JDBC-140).
-  * Updated the README and docstrings to reflect that `:dbtype` is the easiest / preferred way to write `db-spec` maps [JDBC-139](https://clojure.atlassian.net/browse/JDBC-139).
-  * Fixed postgres / postgresql alias support [JDBC-138](https://clojure.atlassian.net/browse/JDBC-138).
-    This also adds aliases for mssql (sqlserver), jtds (jtds:sqlserver), oracle (oracle:thin), and hsql (hsqldb).
-
-* Release 0.6.2-alpha2 on 2016-07-21
-  * Update `clojure.spec` support to work with Clojure 1.9.0 Alpha 10.
-
-* Release 0.6.2-alpha1 on 2016-07-05
-  * Experimental support for `clojure.spec` via the new `clojure.java.jdbc.spec` namespace. Requires Clojure 1.9.0 Alpha 8 (or later).
-  * All options to all functions can now have defaults within the `db-spec` itself [JDBC-136](https://clojure.atlassian.net/browse/JDBC-136).
-  * `query` (and by extension `find-by-keys` and `get-by-id`) now support `:explain?` and `:explain-fn` options to help support basic performance analysis [JDBC-135](https://clojure.atlassian.net/browse/JDBC-135).
-  * `insert!` and `insert-multi!` now respect `:identifiers` and `:qualifier` because inserting rows on PostgreSQL returns full rows, not just the newly inserted keys [JDBC-134](https://clojure.atlassian.net/browse/JDBC-134).
-  * In addition to the `:identifiers` option, you can now use `:qualifier` to specify a namespace qualifier (string) to be used when constructing keywords from SQL column names [JDBC-133](https://clojure.atlassian.net/browse/JDBC-133).
-
-* Release 0.6.1 on 2016-05-12 -- **IMPORTANT BUG FIX!**
-  * `insert!` and `insert-multi!` now default `:transaction?` to `true` (as they should have done in 0.6.0!) [JDBC-128](https://clojure.atlassian.net/browse/JDBC-128). These two functions also have improved docstrings to clarify the difference in behavior between inserting rows as maps compared to inserting rows as a series of column values.
-  * PostgreSQL support has been improved: java.jdbc is now tested against PostgreSQL locally (as well as SQLite, Apache Derby, HSQLDB, H2, MySQL, MS SQL Server (both MS Type 4 driver and jTDS driver). [JDBC-127](https://clojure.atlassian.net/browse/JDBC-127) and [JDBC-129](https://clojure.atlassian.net/browse/JDBC-129).
-
-
-* Release 0.6.0 on 2016-05-11 -- **BREAKING RELEASE! DEPRECATED FUNCTIONALITY REMOVED!**
-  * `find-by-keys` now correctly handles `nil` values [JDBC-126](https://clojure.atlassian.net/browse/JDBC-126). 0.6.0 / 2016-05-11.
-  * `find-by-keys` calls `seq` on `:order-by` to treat `[]` as no `ORDER BY` clause. 0.6.0 / 2016-05-11.
-  * `db-query-with-resultset` now accepts an options map and passes it to `prepare-statement` [JDBC-125](https://clojure.atlassian.net/browse/JDBC-125). 0.6.0-rc2 / 2016-05-07.
-    - Passing the `prepare-statement` options map as the first element of the `[sql & params]` vector is no longer supported and will throw an `IllegalArgumentException`. It was always very poorly documented and almost never used, as far as I can tell.
-  * `db-query-with-resultset` no longer requires the `sql-params` argument to be a vector: a sequence is acceptable. This is in line with other functions that accept a sequence. 0.6.0-rc2 / 2016-05-07.
-  * `db-query-with-resultset` now accepts a bare SQL string or `PreparedStatement` as the `sql-params` argument, when there are no parameters needed. This is in line with other functions that accept SQL or a `PreparedStatement`. 0.6.0-rc2 / 2016-05-07.
-  * `query`'s options map now is passed to `db-query-with-resultset` and thus can contain options to be used to construct the `PreparedStatement` [JDBC-125](https://clojure.atlassian.net/browse/JDBC-125). 0.6.0-rc2 / 2016-05-07.
-  * Adds `get-by-id` and `find-by-keys` convenience functions (these were easy to add after the API changes in 0.6.0 and we rely very heavily on them at World Singles so putting them in the core for everyone seemed reasonable). 0.6.0-rc1 / 2016-05-04.
-    - `find-by-keys` accepts an `:order-by` option that expects a sequence of orderings; an ordering is a column name (keyword) or a map from column name (keyword) to direction (`:asc` or `:desc`). 0.6.0-rc2 / 2016-05-07.
-  * Ensures SQL / params are actually vectors prior to destructuring (this addresses an interop edge case from other languages) [JDBC-124](https://clojure.atlassian.net/browse/JDBC-124). 0.6.0-alpha2 / 2016-04-18.
-  * Fix typo in `insert-multi!` argument validation exception [JDBC-123](https://clojure.atlassian.net/browse/JDBC-123). 0.6.0-alpha2 / 2016-04-18.
-  * ALL DEPRECATED FUNCTIONALITY HAS BEEN REMOVED! [JDBC-118](https://clojure.atlassian.net/browse/JDBC-118). 0.6.0-alpha1 / 2016-04-13
-    - See changes described in versions 0.5.5 through 0.5.8 for what was deprecated
-    - Use version 0.5.8 as a bridge to identify any deprecated API calls on which your code relies!
-    - `db-transaction` (deprecated in version 0.3.0) has been removed
-    - The `java.jdbc.deprecated` namespace has been removed
-
-* Release 0.5.8 on 2016-04-12
-  * `db-do-commands` now expects multiple commands to be be wrapped in a vector [JDBC-122](https://clojure.atlassian.net/browse/JDBC-123). The single command form is unchanged (but may be wrapped in a vector). Calling `db-do-commands` with multiple commands (not wrapped in a single vector) will produce a "DEPRECATED" warning printed to the console.
-  * `db-do-prepared` and `db-do-prepared-return-keys` now expect to receive a `db-spec`, an optional `transaction?` boolean, a `sql-params` argument, and an optional options map. `sql-params` is a vector containing a SQL string or `PreparedStatement` followed by parameters -- like other APIs in this library. In addition, like the `:multi? true` version of `execute!`, `db-do-prepared` can accept a vector that has parameter groups: multiple vectors containing groups of parameter values [JDBC-122](https://clojure.atlassian.net/browse/JDBC-123). Calling `db-do-prepared` with unrolled arguments -- the SQL string / statement followed by parameter groups -- is deprecated and will produce "DEPRECATED" warnings printed to the console.
-
-* Release 0.5.7 on 2016-04-10
-  * `(insert! db table [:col] ["val"] {})` syntax, introduced in 0.5.6, threw an exception [JDBC-121](https://clojure.atlassian.net/browse/JDBC-121).
-
-* Release 0.5.6 on 2016-04-10
-  * `create-table-ddl` now expects the column specs to be wrapped in a single vector and no longer needs the `:options` delimiter to specify the options map [JDBC-120](https://clojure.atlassian.net/browse/JDBC-120).
-    - If column specs are not wrapped in a vector, you will get a "DEPRECATED" warning printed to the console.
-  * `insert!` now supports only single row insertion; multi-row insertion is deprecated. `insert-multi!` has been added for multi-row insertion. `:options` is no longer needed as a delimiter for the options map [JDBC-119](https://clojure.atlassian.net/browse/JDBC-119).
-    - If `insert!` is called with multiple rows, or `:options` is specified, you will get a "DEPRECATED" warning printed to the console.
-  * NOTE: all deprecated functionality will go away in version 0.6.0!
-
-* Release 0.5.5 on 2016-04-09
-  * Allow options map in all calls that previously took optional keyword arguments [JDBC-117](https://clojure.atlassian.net/browse/JDBC-117).
-    - The unrolled keyword argument forms of call are deprecated -- and print a "DEPRECATED" message to the console! -- and will go away in 0.6.0.
-
-* Release 0.5.0 on 2016-03-27
-  * Allow PreparedStatement in db-do-prepared-return-keys [JDBC-115](https://clojure.atlassian.net/browse/JDBC-115).
-  * Remove exception wrapping [JDBC-114](https://clojure.atlassian.net/browse/JDBC-114).
-  * Drop Clojure 1.3 compatibility.
-
-* Release 0.4.2 on 2015-09-15
-  * Remove redundant type hints [JDBC-113](https://clojure.atlassian.net/browse/JDBC-113) - Michael Blume.
-  * Avoid reflection on `.prepareStatement` [JDBC-112](https://clojure.atlassian.net/browse/JDBC-112) - Michael Blume.
-  * Add `metadata-query` macro to make metadata query / results easier to work with for [JDBC-107](https://clojure.atlassian.net/browse/JDBC-107).
-  * `prepare-statement` `:return-keys` may now be a vector of (auto-generated) column names to return, in addition to just being truthy or falsey. This allows keys to be returned for more databases. [JDBC-104](https://clojure.atlassian.net/browse/JDBC-104).
-  * Officially support H2 (and test against it) to support [JDBC-91](https://clojure.atlassian.net/browse/JDBC-91) and clarify docstrings to improve debugging driver-specific restrictions on SQL.
-
-* Release 0.4.0 / 0.4.1 on 2015-07-26
-  * `db-do-prepared` now allows `transaction?` to be omitted when a `PreparedStatement` is passed as the second argument [JDBC-111](https://clojure.atlassian.net/browse/JDBC-111) - Stefan Kamphausen.
-  * Nested transaction checks isolation level is the same [JDBC-110](https://clojure.atlassian.net/browse/JDBC-110) - Donald Ball.
-  * Default PostgreSQL port; Support more dbtype/dbname variants [JDBC-109](https://clojure.atlassian.net/browse/JDBC-109).
-  * Drop Clojure 1.2 compatibility.
-
-* Release 0.3.7 on 2015-05-18
-  * Bump all driver versions in `project.clj` and re-test.
-  * Remove duplicate `count` calls in `insert-sql` [JDBC-108](https://clojure.atlassian.net/browse/JDBC-108) - Earl St Sauver.
-  * Remove driver versions from README and link to Maven Central [JDBC-106](https://clojure.atlassian.net/browse/JDBC-106).
-  * Fix links in CHANGES and README [JDBC-103](https://clojure.atlassian.net/browse/JDBC-103) - John Walker.
-
-* Release 0.3.6 on 2014-10-28
-  * Arbitrary values allowed for `:cursors`, `:concurrency`, `:result-type` arguments to `prepare-statement` [JDBC-102](https://clojure.atlassian.net/browse/JDBC-102).
-  * Allow `:as-arrays? :cols-as-is` to omit column name uniqueness when returning result sets as arrrays [JDBC-101](https://clojure.atlassian.net/browse/JDBC-101).
-  * Add `:timeout` argument to `prepare-statement` [JDBC-100](https://clojure.atlassian.net/browse/JDBC-100).
-
-* Release 0.3.5 on 2014-08-01
-  * Reflection warnings on executeUpdate addressed.
-  * HSQLDB and SQLite in-memory strings are now accepted [JDBC-94](https://clojure.atlassian.net/browse/JDBC-94).
-  * Add support for readonly transactions via :read-only? [JDBC-93](https://clojure.atlassian.net/browse/JDBC-93).
-
-* Release 0.3.4 on 2014-06-30
-  * execute! can now accept a PreparedStatement [JDBC-96](https://clojure.atlassian.net/browse/JDBC-96).
-  * Support simpler db-spec with :dbtype and :dbname (and optional :host and :port etc) [JDBC-92](https://clojure.atlassian.net/browse/JDBC-92).
-  * Support oracle:oci and oracle:thin subprotocols [JDBC-90](https://clojure.atlassian.net/browse/JDBC-90).
-
-* Release 0.3.3 on 2014-01-30
-  * Prevent exception/crash when query called with bare SQL string [JDBC-89](https://clojure.atlassian.net/browse/JDBC-89).
-  * Add :row-fn and :result-set-fn to metadata-result function [JDBC-87](https://clojure.atlassian.net/browse/JDBC-87).
-  * Support key/value configuration from URI (Phil Hagelberg).
-
-* Release 0.3.2 on 2013-12-30
-  * Add nil protocol implementation to ISQLParameter
-
-* Release 0.3.1 on 2013-12-29 (broken; use 0.3.2 instead)
-  * Improve docstrings and add :arglists for better auto-generated documentation.
-  * Make insert-sql private - technically a breaking change but it should never have been public: sorry folks!
-  * Provide better protocol for setting parameters in prepared statements [JDBC-86](https://clojure.atlassian.net/browse/JDBC-86).
-  * Fix parens in two deprecated tests [JDBC-85](https://clojure.atlassian.net/browse/JDBC-85).
-  * Made create-table-ddl less aggressive about applying as-sql-name so only first name in a column spec is affected.
-
-* Release 0.3.0 on 2013-12-16
-  * Ensure canonical Boolean to workaround strange behavior in some JDBC drivers [JDBC-84](https://clojure.atlassian.net/browse/JDBC-84).
-  * Rename recently introduced test to ensure unique names [JDBC-83](https://clojure.atlassian.net/browse/JDBC-83).
-  * Rename unused arguments in protocol implementation to support Android [JDBC-82](https://clojure.atlassian.net/browse/JDBC-82).
-  * Correctly handle empty param group sequence in execute! (which only seemed to affect SQLite) [JDBC-65](https://clojure.atlassian.net/browse/JDBC-65).
-
-* Release 0.3.0-rc1 on 2013-12-12
-  * Deprecate db-transaction (new in 0.3.0) in favor of with-db-transaction [JDBC-81](https://clojure.atlassian.net/browse/JDBC-81).
-  * Add with-db-metadata macro and metadata-result function to make it easier to work with SQL metadata [JDBC-80](https://clojure.atlassian.net/browse/JDBC-80).
-  * Add with-db-connection macro to make it easier to run groups of operations against a single open connection [JDBC-79](https://clojure.atlassian.net/browse/JDBC-79).
-  * Add ISQLValue protocol to make it easier to support custom SQL types for parameters in SQL statements [JDBC-77](https://clojure.atlassian.net/browse/JDBC-77).
-  * Add support for :isolation in with-db-transaction [JDBC-75](https://clojure.atlassian.net/browse/JDBC-75).
-  * Add :user as an alias for :username for DataSource connections [JDBC-74](https://clojure.atlassian.net/browse/JDBC-74).
-
-* Release 0.3.0-beta2 on 2013-11-24
-  * **BREAKING CHANGES!**
-  * The DSL namespaces introduced in 0.3.0-alpha1 have been retired - see [java-jdbc/dsl](https://github.com/seancorfield/jsql) for a migration path if you wish to continue using the DSL (although it is recommended you switch to another, more expressive DSL).
-  * The older API (0.2.3) which was deprecated in earlier 0.3.0 builds has moved to `clojure.java.jdbc.deprecated` to help streamline the API for 0.3.0 and clean up the documentation.
-
-* Release 0.3.0-beta1 on 2013-11-03
-  * query as-arrays? now allows you to leverage lazy result fetching [JDBC-72](https://clojure.atlassian.net/browse/JDBC-72).
-  * "h2" is recognized as a protocol shorthand for org.h2.Driver
-  * Tests no longer use :1 literal [JDBC-71](https://clojure.atlassian.net/browse/JDBC-71).
-  * Conditional use of javax.naming.InitialContext so it can be compiled on Android [JDBC-69](https://clojure.atlassian.net/browse/JDBC-69).
-  * New db-query-with-resultset function replaces private `db-with-query-results*` and processes a raw ResultSet object [JDBC-63](https://clojure.atlassian.net/browse/JDBC-63).
-  * Allow :set-parameters in db-spec to override set-parameters internal function to allow per-DB special handling of SQL parameters values (such as null for Teradata) [JDBC-40](https://clojure.atlassian.net/browse/JDBC-40).
-
-* Release 0.3.0-alpha5 on 2013-09-15
-  * DDL now supports entities naming strategy [JDBC-53](https://clojure.atlassian.net/browse/JDBC-53).
-  * Attempt to address potential memory leaks due to closures - see [Christophe Grand's blog post on Macros, closures and unexpected object retention](https://clj-me.cgrand.net/2013/09/11/macros-closures-and-unexpected-object-retention/).
-  * Documentation has moved to [Using java.jdbc on Clojure-Doc.org](https://clojure-doc.org/articles/ecosystem/java_jdbc/home.html)
-  * Added Leiningen support for easier development/testing (Maven is still the primary build tool).
-  * Added create-index / drop-index DDL [JDBC-62](https://clojure.atlassian.net/browse/JDBC-62) - moquist
-  * Make transaction? boolean optional in various `db-do-*` functions
-  * Create clojure.java.jdbc.ddl namespace
-  * Add create-table, drop-table, create-index and drop-index
-  * Deprecate create-table, create-table-ddl and drop-table in main namespace
-  * Update README to clarify PostgreSQL instructions.
-  * Fix test suite for PostgreSQL [JDBC-59](https://clojure.atlassian.net/browser/JDBC-59)
-  * Improve hooks for Oracle data type handling [JDBC-57](https://clojure.atlassian.net/browser/JDBC-57)
-  * Fix reflection warnings [JDBC-55](https://clojure.atlassian.net/browser/JDBC-55)
-
-* Release 0.3.0-alpha4 on 2013-05-11
-  * Fix connection leaks [JDBC-54](https://clojure.atlassian.net/browser/JDBC-54)
-  * Allow order-by to accept empty sequence (and return empty string)
-
-* Release 0.3.0-alpha3 on 2013-05-04
-  * Fix macro / import interaction by fully qualifying Connection type.
-
-* Release 0.3.0-alpha2 on 2013-05-03
-  * Address [JDBC-51](https://clojure.atlassian.net/browse/JDBC-51) by declaring get-connection returns java.sql.Connection
-  * Add IResultSetReadColumn protocol extension point for custom read conversions [JDBC-46](https://clojure.atlassian.net/browse/JDBC-46)
-  * Add :multi? to execute! so it can be used for repeated operations [JDBC-52](https://clojure.atlassian.net/browse/JDBC-52)
-  * Reverted specialized handling of NULL values (reopens [JDBC-40](https://clojure.atlassian.net/browse/JDBC-40))
-  * Rename :as-arrays to :as-arrays? since it is boolean
-  * Add curried version of clojure.java.jdbc.sql/as-quoted-str
-  * Officially deprecate resultset-seq
-
-* Release 0.3.0-alpha1 on 2013-04-07
-  * MAJOR API OVERHAUL!
-  * Most of the old 0.2.x API has been deprecated and a new, more idiomatic API introduced, along with a minimal DSL to generate basic SQL
-  * Specifics:
-  * Add insert!, query, update!, delete! and execute! high-level API [JDBC-20](https://clojure.atlassian.net/browse/JDBC-20)
-  * Add optional SQL-generating DSL in clojure.java.jdbc.sql (implied by JDBC-20)
-  * Add db- prefixed versions of low-level API
-  * Add db-transaction macro
-  * Add result-set-seq as replacement for resultset-seq (which will be deprecated)
-  * Transaction now correctly rollback on non-Exception Throwables [JDBC-43](https://clojure.atlassian.net/browse/JDBC-43)
-  * Rewrite old API functions in terms of new API, and deprecate old API [JDBC-43](https://clojure.atlassian.net/browse/JDBC-43)
-  * Add :as-arrays to query / result-set-seq [JDBC-41](https://clojure.atlassian.net/browse/JDBC-41)
-  * Better handling of NULL values [JDBC-40](https://clojure.atlassian.net/browse/JDBC-40) and [JDBC-18](https://clojure.atlassian.net/browse/JDBC-18)
-    Note: JDBC-40 is being reverted in 0.3.0-alpha2 because it introduces regressions in PostgreSQL
-  * db-do-commands allows you to execute SQL without a transaction wrapping it [JDBC-38](https://clojure.atlassian.net/browse/JDBC-38)
-  * Remove reflection warning from execute-batch
-  * Add notes to README about 3rd party database driver dependencies
-  * Add optional :identifiers argument to resultset-seq so you can explicitly pass in the naming strategy
-
-* Release 0.2.3 on 2012-06-18
-  * as-str now treats a.b as two identifiers separated by . so quoting produces [a].[b] instead of [a.b]
-  * Add :connection-uri option [JDBC-34](https://clojure.atlassian.net/browse/JDBC-34)
-
-* Release 0.2.2 on 2012-06-10
-  * Handle Oracle unknown row count affected [JDBC-33](https://clojure.atlassian.net/browse/JDBC-33)
-  * Handle jdbc: prefix in string db-specs [JDBC-32](https://clojure.atlassian.net/browse/JDBC-32)
-  * Handle empty columns in make column unique (Juergen Hoetzel) [JDBC-31](https://clojure.atlassian.net/browse/JDBC-31)
-
-* Release 0.2.1 on 2012-05-10
-  * Result set performance enhancement (Juergen Hoetzel) [JDBC-29](https://clojure.atlassian.net/browse/JDBC-29)
-  * Make do-prepared-return-keys (for Korma team) [JDBC-30](https://clojure.atlassian.net/browse/JDBC-30)
-
-* Release 0.2.0 on 2012-04-23
-  * Merge internal namespace into main jdbc namespace [JDBC-19](https://clojure.atlassian.net/browse/JDBC-19)
-
-* Release 0.1.4 on 2012-04-15
-  * Unwrap RTE for nested transaction exceptions (we already
-    unwrapped top-level transaction RTEs).
-  * Remove reflection warning unwrapping RunTimeException (Alan Malloy)
-
-* Release 0.1.3 on 2012-02-29
-  * Fix generated keys inside transactions for SQLite3 [JDBC-26](https://clojure.atlassian.net/browse/JDBC-26)
-
-* Release 0.1.2 on 2012-02-29
-  * Handle prepared statement params correctly [JDBC-23](https://clojure.atlassian.net/browse/JDBC-23)
-  * Add support for SQLite3 [JDBC-26](https://clojure.atlassian.net/browse/JDBC-26)
-  * Replace replicate (deprecated) with repeat [JDBC-27](https://clojure.atlassian.net/browse/JDBC-27)
-  * Ensure MS SQL Server passes tests with both Microsoft and jTDS drivers
-  * Build server now tests derby, hsqldb and sqlite by default
-  * Update README per Stuart Sierra's outline for contrib projects
-
-* Release 0.1.1 on 2011-11-02
-  * Accept string or URI in connection definition [JDBC-21](https://clojure.atlassian.net/browse/JDBC-21)
-  * Allow driver, port and subprotocol to be deduced [JDBC-22](https://clojure.atlassian.net/browse/JDBC-22)
-
-* Release 0.1.0 on 2011-10-16
-  * Remove dependence on deprecated structmap [JDBC-15](https://clojure.atlassian.net/browse/JDBC-15)
-
-* Release 0.0.7 on 2011-10-11
-  * Rename duplicate columns [JDBC-9](https://clojure.atlassian.net/browse/JDBC-9)
-  * Ensure do-preared traps invalid SQL [JDBC-16](https://clojure.atlassian.net/browse/JDBC-16)
-
-* Release 0.0.6 on 2011-08-04
-  * Improve exception handling (unwrap RTE)
-  * Don't use batch for update (causes exceptions on Apache Derby) [JDBC-12](https://clojure.atlassian.net/browse/JDBC-12)
-  * Add test suite
-
-* Release 0.0.5 on 2011-07-18
-  * Expose prepare-statement API
-  * Allow with-query-results to accept a PreparedStatement or options for creating one, instead of SQL query string and parameters
-  * Support databases that cannot return generated keys
-
-* Release 0.0.4 on 2011-07-17
-  * Allow :table-spec {string} in create-table  [JDBC-4](https://clojure.atlassian.net/browse/JDBC-4)
-  * Remove reflection warnings [JDBC-8](https://clojure.atlassian.net/browse/JDBC-8)
-  * Ensure transactions are not committed when Error occurs [JDBC-11](https://clojure.atlassian.net/browse/JDBC-11)
-
-* Release 0.0.3 on 2011-07-01
-  * Key generation compatibility with MS SQL Server, PostgreSQL [JDBC-10](https://clojure.atlassian.net/browse/JDBC-10)
-
-* Release 0.0.2 on 2011-06-07
-  * Clojure 1.2 compatibility [JDBC-7](https://clojure.atlassian.net/browse/JDBC-7)
-
-* Release 0.0.1 on 2011-05-07
-  * Initial release
-
-* Changes from clojure.contrib.sql:
-  * Expose print-... functions; no longer write exceptions to `\*out\*`
-  * Define resultset-seq to replace clojure.core/resultset-seq
-  * Add naming / quoting strategies (see [name mapping documentation](https://clojure.github.io/java.jdbc/doc/clojure/java/jdbc/NameMapping.html)
-  * Return generated keys from insert operations, where possible
-  * Add insert-record function
-  * Clojure 1.3 compatibility
-
-Copyright and License
-========================================
-
-Copyright (c) Sean Corfield, Stephen Gilardi, 2011-2023. All rights reserved.  The use and
-distribution terms for this software are covered by the Eclipse Public
-License 1.0 (https://opensource.org/license/epl-1-0/) which can
-be found in the file epl-v10.html at the root of this distribution.
-By using this software in any fashion, you are agreeing to be bound by
-the terms of this license.  You must not remove this notice, or any
-other, from this software.
diff --git a/api-index.html b/api-index.html
new file mode 100644
index 00000000..5c526b4b
--- /dev/null
+++ b/api-index.html
@@ -0,0 +1,348 @@
+<html>
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <title>Index - java.jdbc 0.7.13-SNAPSHOT API documentation</title>
+    <link rel="icon" href="static/favicon.png" />
+    <link rel="shortcut icon" href="static/favicon.png" />
+    <link rel="stylesheet" href="static/clojure.css" type="text/css" media="all" />
+    <link rel="stylesheet" href="static/wiki.css" type="text/css" media="all" />
+    <link rel="stylesheet" href="static/internal.css" type="text/css" media="all" />
+    <style>.menuWrapper{height: 36px;}</style>
+  </head>
+<!--
+This document was auto-generated from the source by the clojure autodoc system.
+To report errors or ask questions about the overall documentation structure, formatting,
+etc., contact Tom Faulhaber (google mail name: tomfaulhaber).
+For errors in the documentation of a particular namespace, contact the author of that
+namespace.
+-->
+  <body>
+    <div id="AllContentContainer">
+      <div id="Header">
+	<a href="index.html" id="Logo"><img src="static/clojure-icon.gif" width="100" height="100" alt="Clojure" /></a>
+	<h1><a href="index.html" id="page-header" title="page header title">java.jdbc API Reference</a></h1>
+      </div>
+      <div id="leftcolumn"><div style="text-align: center;"></div>
+<div class="menu">
+  <div class="WikiCustomNav WikiElement wiki">
+    <span class="toc-header"><span id="project-name">java.jdbc</span> <span id="version">0.7.13-SNAPSHOT</span> API</span><br />
+    <ul>
+      <li><a href="index.html" class="wiki_link">Overview</a></li>
+      <li><a href="api-index.html" class="wiki_link">API Index</a></li>
+    </ul>
+    
+    
+    <a class="wiki_link" href="https://clojure.org">Clojure Home</a>
+  </div>
+</div>
+</div>
+      <div id="rightcolumn">
+	<div id="Content">
+	  <div class="contentBox"><div class="innerContentBox">
+              <div class="wiki wikiPage" id="content_view">
+                <div id="right-sidebar"></div>
+                <div id="content-tag"><h1 id="overview">Index of Public Functions and Variables - <span id="header-project">java.jdbc</span> <span id="header-version">0.7.13-SNAPSHOT</span><span id="header-status-block"> (<span id="header-status">in development</span>)</span></h1>
+This page has an alphabetical index of all the documented functions and variables
+in <span class="project-name-span">java.jdbc</span>.
+
+<!-- TODO: enable this functionality on github?
+
+In a narrow browser window, you may want to collapse the sidebar (use the \"<<\" link)
+to get more screen space for the index.
+-->
+<p>
+</p><div class="shortcuts">
+Shortcuts:<br />
+<a href="#A">A</a> <a href="#B">B</a> <a href="#C">C</a> <a href="#D">D</a>
+ <a href="#E">E</a> <a href="#F">F</a> <a href="#G">G</a> <a href="#H">H</a>
+ <a href="#I">I</a> <a href="#J">J</a> <a href="#K">K</a> <a href="#L">L</a>
+ <a href="#M">M</a>
+<br />
+<a href="#N">N</a> <a href="#O">O</a> <a href="#P">P</a> <a href="#Q">Q</a>
+ <a href="#R">R</a> <a href="#S">S</a> <a href="#T">T</a> <a href="#U">U</a>
+ <a href="#V">V</a> <a href="#W">W</a> <a href="#X">X</a> <a href="#Y">Y</a>
+ <a href="#Z">Z</a>
+<br />
+<a href="#Other">Other</a>
+<br />
+</div>
+
+<div id="index-body">
+  <h2 id="A"><span id="section-head">A</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/as-arrays?">::as-arrays?</a><span id="line-content">                 spec          clojure.java.jdbc.spec (or :as-is #{:cols-as-is} :truthy (nilable boo...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/as-sql-name">as-sql-name</a><span id="line-content">                  function      clojure.java.jdbc  Given a naming strategy function and a keyword or ...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/auto-commit?">::auto-commit?</a><span id="line-content">               spec          clojure.java.jdbc.spec boolean?.
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="B"><span id="section-head">B</span></h2>
+  <pre>
+
+  </pre>
+</div><div id="index-body">
+  <h2 id="C"><span id="section-head">C</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/classname">::classname</a><span id="line-content">                  spec          clojure.java.jdbc.spec string?.
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/column-direction">::column-direction</a><span id="line-content">           spec          clojure.java.jdbc.spec (or :id :clojure.java.jdbc.spec/identifier :id...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/column-spec">::column-spec</a><span id="line-content">                spec          clojure.java.jdbc.spec (cat :col :clojure.java.jdbc.spec/identifier :...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/concurrency">::concurrency</a><span id="line-content">                spec          clojure.java.jdbc.spec (set (keys (deref (var result-set-concurrency)...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/conditional?">::conditional?</a><span id="line-content">               spec          clojure.java.jdbc.spec (or :b boolean? :s string? :f fn?).
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/connection">::connection</a><span id="line-content">                 spec          clojure.java.jdbc.spec (instance? java.sql.Connection %).
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/connection-binding">::connection-binding</a><span id="line-content">         spec          clojure.java.jdbc.spec (cat :con-db simple-symbol? :db-spec any? :opt...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/connection-options">::connection-options</a><span id="line-content">         spec          clojure.java.jdbc.spec (keys :req-un [] :opt-un [:clojure.java.jdbc.s...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/connection-uri">::connection-uri</a><span id="line-content">             spec          clojure.java.jdbc.spec string?.
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/create-table-ddl">create-table-ddl</a><span id="line-content">             function      clojure.java.jdbc  Given a table name and a vector of column specs, r...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/cursors">::cursors</a><span id="line-content">                    spec          clojure.java.jdbc.spec (set (keys (deref (var result-set-holdability)...
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="D"><span id="section-head">D</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/datasource">::datasource</a><span id="line-content">                 spec          clojure.java.jdbc.spec (instance? javax.sql.DataSource %).
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/db-connection">db-connection</a><span id="line-content">                function      clojure.java.jdbc  Returns the current database connection (or throws...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/db-do-commands">db-do-commands</a><span id="line-content">               function      clojure.java.jdbc  Executes SQL commands on the specified database co...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/db-do-prepared">db-do-prepared</a><span id="line-content">               function      clojure.java.jdbc  Executes an (optionally parameterized) SQL prepare...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/db-do-prepared-return-keys">db-do-prepared-return-keys</a><span id="line-content">   function      clojure.java.jdbc  Executes an (optionally parameterized) SQL prepare...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/db-find-connection">db-find-connection</a><span id="line-content">           function      clojure.java.jdbc  Returns the current database connection (or nil if...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/db-is-rollback-only">db-is-rollback-only</a><span id="line-content">          function      clojure.java.jdbc  Returns true if the outermost transaction will rol...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/db-query-with-resultset">db-query-with-resultset</a><span id="line-content">      function      clojure.java.jdbc  Executes a query, then evaluates func passing in t...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/db-set-rollback-only!">db-set-rollback-only!</a><span id="line-content">        function      clojure.java.jdbc  Marks the outermost transaction such that it will ...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/db-spec">::db-spec</a><span id="line-content">                    spec          clojure.java.jdbc.spec (or :connection :clojure.java.jdbc.spec/db-spe...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/db-spec-connection">::db-spec-connection</a><span id="line-content">         spec          clojure.java.jdbc.spec (keys :req-un [:clojure.java.jdbc.spec/connect...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/db-spec-data-source">::db-spec-data-source</a><span id="line-content">        spec          clojure.java.jdbc.spec (keys :req-un [:clojure.java.jdbc.spec/datasou...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/db-spec-driver-manager">::db-spec-driver-manager</a><span id="line-content">     spec          clojure.java.jdbc.spec (keys :req-un [:clojure.java.jdbc.spec/subprot...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/db-spec-factory">::db-spec-factory</a><span id="line-content">            spec          clojure.java.jdbc.spec (keys :req-un [:clojure.java.jdbc.spec/factory...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/db-spec-friendly">::db-spec-friendly</a><span id="line-content">           spec          clojure.java.jdbc.spec (keys :req-un [:clojure.java.jdbc.spec/dbtype ...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/db-spec-jndi">::db-spec-jndi</a><span id="line-content">               spec          clojure.java.jdbc.spec (keys :req-un [:clojure.java.jdbc.spec/name] :...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/db-spec-raw">::db-spec-raw</a><span id="line-content">                spec          clojure.java.jdbc.spec (keys :req-un [:clojure.java.jdbc.spec/connect...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/db-spec-string">::db-spec-string</a><span id="line-content">             spec          clojure.java.jdbc.spec string?.
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/db-spec-uri">::db-spec-uri</a><span id="line-content">                spec          clojure.java.jdbc.spec (instance? java.net.URI %).
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/db-transaction*">db-transaction*</a><span id="line-content">              function      clojure.java.jdbc  Evaluates func as a transaction on the open databa...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/db-unset-rollback-only!">db-unset-rollback-only!</a><span id="line-content">      function      clojure.java.jdbc  Marks the outermost transaction such that it will ...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/dbname">::dbname</a><span id="line-content">                     spec          clojure.java.jdbc.spec string?.
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/dbtype">::dbtype</a><span id="line-content">                     spec          clojure.java.jdbc.spec (or :alias :clojure.java.jdbc.spec/subprotocol...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/delete!">delete!</a><span id="line-content">                      function      clojure.java.jdbc  Given a database connection, a table name and a wh...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/delimiter">::delimiter</a><span id="line-content">                  spec          clojure.java.jdbc.spec (or :s string? :c char?).
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/direction">::direction</a><span id="line-content">                  spec          clojure.java.jdbc.spec #{:desc "DESC" :asc "ASC" "desc" "asc"}.
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/drop-table-ddl">drop-table-ddl</a><span id="line-content">               function      clojure.java.jdbc  Given a table name, return the DDL string for drop...
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="E"><span id="section-head">E</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/entities">::entities</a><span id="line-content">                   spec          clojure.java.jdbc.spec (fspec :args (cat :s string?) :ret :clojure.ja...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/entity">::entity</a><span id="line-content">                     spec          clojure.java.jdbc.spec string?.
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/environment">::environment</a><span id="line-content">                spec          clojure.java.jdbc.spec (nilable map?).
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/exec-sql-options">::exec-sql-options</a><span id="line-content">           spec          clojure.java.jdbc.spec (keys :req-un [] :opt-un [:clojure.java.jdbc.s...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/execute!">execute!</a><span id="line-content">                     function      clojure.java.jdbc  Given a database connection and a vector containin...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/execute-options">::execute-options</a><span id="line-content">            spec          clojure.java.jdbc.spec (keys :req-un [] :opt-un [:clojure.java.jdbc.s...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/execute-result">::execute-result</a><span id="line-content">             spec          clojure.java.jdbc.spec (* integer?).
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/explain-fn">::explain-fn</a><span id="line-content">                 spec          clojure.java.jdbc.spec fn?.
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/explain?">::explain?</a><span id="line-content">                   spec          clojure.java.jdbc.spec (or :b boolean? :s string?).
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="F"><span id="section-head">F</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/factory">::factory</a><span id="line-content">                    spec          clojure.java.jdbc.spec (fspec :args (cat :db-spec :clojure.java.jdbc....
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/fetch-size">::fetch-size</a><span id="line-content">                 spec          clojure.java.jdbc.spec nat-int?.
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/find-by-keys">find-by-keys</a><span id="line-content">                 function      clojure.java.jdbc  Given a database connection, a table name, a map o...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc.datafy/find-by-keys">find-by-keys</a><span id="line-content">                 function      clojure.java.jdbc.datafy Given a database connection, a table name, a...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/find-by-keys-options">::find-by-keys-options</a><span id="line-content">       spec          clojure.java.jdbc.spec (keys :req-un [] :opt-un [:clojure.java.jdbc.s...
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="G"><span id="section-head">G</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#clojure.java.jdbc/get-by-id">get-by-id</a><span id="line-content">                    function      clojure.java.jdbc  Given a database connection, a table name, a prima...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc.datafy/get-by-id">get-by-id</a><span id="line-content">                    function      clojure.java.jdbc.datafy Given a database connection, a table name, a...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/get-connection">get-connection</a><span id="line-content">               function      clojure.java.jdbc  Creates a connection to a database. db-spec is usu...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/get-isolation-level">get-isolation-level</a><span id="line-content">          function      clojure.java.jdbc  Given a db-spec (with an optional connection), ret...
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="H"><span id="section-head">H</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/host">::host</a><span id="line-content">                       spec          clojure.java.jdbc.spec string?.
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="I"><span id="section-head">I</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/identifier">::identifier</a><span id="line-content">                 spec          clojure.java.jdbc.spec (or :kw keyword? :s string?).
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/identifiers">::identifiers</a><span id="line-content">                spec          clojure.java.jdbc.spec (fspec :args (cat :s :clojure.java.jdbc.spec/e...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/insert!">insert!</a><span id="line-content">                      function      clojure.java.jdbc  Given a database connection, a table name and eith...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/insert-multi!">insert-multi!</a><span id="line-content">                function      clojure.java.jdbc  Given a database connection, a table name and eith...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/IResultSetReadColumn">IResultSetReadColumn</a><span id="line-content">         protocol      clojure.java.jdbc  Protocol for reading objects from the java.sql.Res...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/isolation">::isolation</a><span id="line-content">                  spec          clojure.java.jdbc.spec (set (keys (deref (var isolation-levels)))).
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/ISQLParameter">ISQLParameter</a><span id="line-content">                protocol      clojure.java.jdbc  Protocol for setting SQL parameters in statement o...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/ISQLValue">ISQLValue</a><span id="line-content">                    protocol      clojure.java.jdbc  Protocol for creating SQL values from Clojure valu...
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="J"><span id="section-head">J</span></h2>
+  <pre>
+
+  </pre>
+</div><div id="index-body">
+  <h2 id="K"><span id="section-head">K</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/keywordize?">::keywordize?</a><span id="line-content">                spec          clojure.java.jdbc.spec boolean?.
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="L"><span id="section-head">L</span></h2>
+  <pre>
+
+  </pre>
+</div><div id="index-body">
+  <h2 id="M"><span id="section-head">M</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/max-size">::max-size</a><span id="line-content">                   spec          clojure.java.jdbc.spec nat-int?.
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/metadata-query">metadata-query</a><span id="line-content">               macro         clojure.java.jdbc  Given a Java expression that extracts metadata (in...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/metadata-result">metadata-result</a><span id="line-content">              function      clojure.java.jdbc  If the argument is a java.sql.ResultSet, turn it i...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/multi?">::multi?</a><span id="line-content">                     spec          clojure.java.jdbc.spec boolean?.
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="N"><span id="section-head">N</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/name">::name</a><span id="line-content">                       spec          clojure.java.jdbc.spec string?.
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/naming-strategy">::naming-strategy</a><span id="line-content">            spec          clojure.java.jdbc.spec (fspec :args (cat :x :clojure.java.jdbc.spec/i...
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="O"><span id="section-head">O</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/order-by">::order-by</a><span id="line-content">                   spec          clojure.java.jdbc.spec (coll-of :clojure.java.jdbc.spec/column-direct...
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="P"><span id="section-head">P</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/password">::password</a><span id="line-content">                   spec          clojure.java.jdbc.spec string?.
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/port">::port</a><span id="line-content">                       spec          clojure.java.jdbc.spec (or :port pos-int? :s string?).
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/prepare-options">::prepare-options</a><span id="line-content">            spec          clojure.java.jdbc.spec (merge (keys :req-un [] :opt-un [:clojure.java...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/prepare-statement">prepare-statement</a><span id="line-content">            function      clojure.java.jdbc  Create a prepared statement from a connection, a S...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/prepared-statement">::prepared-statement</a><span id="line-content">         spec          clojure.java.jdbc.spec (instance? java.sql.PreparedStatement %).
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/print-sql-exception">print-sql-exception</a><span id="line-content">          function      clojure.java.jdbc  Prints the contents of an SQLException to *out*.
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/print-sql-exception-chain">print-sql-exception-chain</a><span id="line-content">    function      clojure.java.jdbc  Prints a chain of SQLExceptions to *out*.
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/print-update-counts">print-update-counts</a><span id="line-content">          function      clojure.java.jdbc  Prints the update counts from a BatchUpdateExcepti...
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="Q"><span id="section-head">Q</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/qualifier">::qualifier</a><span id="line-content">                  spec          clojure.java.jdbc.spec (nilable string?).
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/query">query</a><span id="line-content">                        function      clojure.java.jdbc  Given a database connection and a vector containin...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc.datafy/query">query</a><span id="line-content">                        function      clojure.java.jdbc.datafy Given a database connection and a vector con...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/query-options">::query-options</a><span id="line-content">              spec          clojure.java.jdbc.spec (merge (keys :req-un [] :opt-un [:clojure.java...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/quoted">quoted</a><span id="line-content">                       function      clojure.java.jdbc  Given a (vector) pair of delimiters (characters or...
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="R"><span id="section-head">R</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/read-columns">::read-columns</a><span id="line-content">               spec          clojure.java.jdbc.spec fn?.
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/read-only?">::read-only?</a><span id="line-content">                 spec          clojure.java.jdbc.spec boolean?.
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/reducible-query">reducible-query</a><span id="line-content">              function      clojure.java.jdbc  Given a database connection, a vector containing S...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/reducible-query-options">::reducible-query-options</a><span id="line-content">    spec          clojure.java.jdbc.spec (merge (keys :req-un [] :opt-un [:clojure.java...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/reducible-result-set">reducible-result-set</a><span id="line-content">         function      clojure.java.jdbc  Given a java.sql.ResultSet return a reducible coll...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/result-set">::result-set</a><span id="line-content">                 spec          clojure.java.jdbc.spec (instance? java.sql.ResultSet %).
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/result-set-fn">::result-set-fn</a><span id="line-content">              spec          clojure.java.jdbc.spec (fspec :args (cat :rs (coll-of any?)) :ret any...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/result-set-metadata">::result-set-metadata</a><span id="line-content">        spec          clojure.java.jdbc.spec (instance? java.sql.ResultSetMetaData %).
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/result-set-read-column">result-set-read-column</a><span id="line-content">       function      clojure.java.jdbc  Function for transforming values after reading the...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/result-set-seq">result-set-seq</a><span id="line-content">               function      clojure.java.jdbc  Creates and returns a lazy sequence of maps corres...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/result-type">::result-type</a><span id="line-content">                spec          clojure.java.jdbc.spec (set (keys (deref (var result-set-type)))).
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/return-keys">::return-keys</a><span id="line-content">                spec          clojure.java.jdbc.spec (or :columns (coll-of :clojure.java.jdbc.spec/...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/row-fn">::row-fn</a><span id="line-content">                     spec          clojure.java.jdbc.spec (fspec :args (cat :row (map-of keyword? :cloju...
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="S"><span id="section-head">S</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#clojure.java.jdbc/set-parameter">set-parameter</a><span id="line-content">                function      clojure.java.jdbc  Convert a Clojure value into a SQL value and store...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/sql-params">::sql-params</a><span id="line-content">                 spec          clojure.java.jdbc.spec (or :sql :clojure.java.jdbc.spec/sql-stmt :sql...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/sql-stmt">::sql-stmt</a><span id="line-content">                   spec          clojure.java.jdbc.spec (or :sql string? :stmt :clojure.java.jdbc.spec...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/sql-value">sql-value</a><span id="line-content">                    function      clojure.java.jdbc  Convert a Clojure value into a SQL value..
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/sql-value">::sql-value</a><span id="line-content">                  spec          clojure.java.jdbc.spec any?.
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/subname">::subname</a><span id="line-content">                    spec          clojure.java.jdbc.spec string?.
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/subprotocol">::subprotocol</a><span id="line-content">                spec          clojure.java.jdbc.spec string?.
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/subprotocol-alias">::subprotocol-alias</a><span id="line-content">          spec          clojure.java.jdbc.spec #{"mssql" "oracle" "postgres" "jtds" "hsql"}.
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/subprotocol-base">::subprotocol-base</a><span id="line-content">           spec          clojure.java.jdbc.spec #{"h2:mem" "mysql" "oracle:thin" "pgsql" "orac...
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="T"><span id="section-head">T</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/table-spec">::table-spec</a><span id="line-content">                 spec          clojure.java.jdbc.spec string?.
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/timeout">::timeout</a><span id="line-content">                    spec          clojure.java.jdbc.spec nat-int?.
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/transaction-binding">::transaction-binding</a><span id="line-content">        spec          clojure.java.jdbc.spec (cat :t-con simple-symbol? :db-spec any? :opts...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/transaction-options">::transaction-options</a><span id="line-content">        spec          clojure.java.jdbc.spec (keys :req-un [] :opt-un [:clojure.java.jdbc.s...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/transaction?">::transaction?</a><span id="line-content">               spec          clojure.java.jdbc.spec boolean?.
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="U"><span id="section-head">U</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#clojure.java.jdbc/update!">update!</a><span id="line-content">                      function      clojure.java.jdbc  Given a database connection, a table name, a map o...
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/uri">::uri</a><span id="line-content">                        spec          clojure.java.jdbc.spec (instance? java.net.URI %).
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/user">::user</a><span id="line-content">                       spec          clojure.java.jdbc.spec string?.
+</span></span><span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/username">::username</a><span id="line-content">                   spec          clojure.java.jdbc.spec string?.
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="V"><span id="section-head">V</span></h2>
+  <pre>
+
+  </pre>
+</div><div id="index-body">
+  <h2 id="W"><span id="section-head">W</span></h2>
+  <pre>
+<span id="section-content"> <a href="index.html#:clojure.java.jdbc.spec/where-clause">::where-clause</a><span id="line-content">               spec          clojure.java.jdbc.spec (cat :where string? :params (* :clojure.java.j...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/with-db-connection">with-db-connection</a><span id="line-content">           macro         clojure.java.jdbc  Evaluates body in the context of an active connect...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/with-db-metadata">with-db-metadata</a><span id="line-content">             macro         clojure.java.jdbc  Evaluates body in the context of an active connect...
+</span></span><span id="section-content"> <a href="index.html#clojure.java.jdbc/with-db-transaction">with-db-transaction</a><span id="line-content">          macro         clojure.java.jdbc  Evaluates body in the context of a transaction on ...
+</span></span>
+  </pre>
+</div><div id="index-body">
+  <h2 id="X"><span id="section-head">X</span></h2>
+  <pre>
+
+  </pre>
+</div><div id="index-body">
+  <h2 id="Y"><span id="section-head">Y</span></h2>
+  <pre>
+
+  </pre>
+</div><div id="index-body">
+  <h2 id="Z"><span id="section-head">Z</span></h2>
+  <pre>
+
+  </pre>
+</div><div id="index-body">
+  <h2 id="Other"><span id="section-head">Other</span></h2>
+  <pre>
+
+  </pre>
+</div>
+<style type="text/css">
+  #AllContentContainer {min-width: 96em;}
+</style>
+</div>
+              </div>
+            </div>
+          </div>
+	</div>
+	<div id="foot">
+	  <div id="copyright" style="text-align: center;">Copyright 2007-2023 by Rich Hickey and the various contributors</div>
+	</div>
+      </div>
+      <div id="DesignedBy">Logo &amp; site design by <a href="http://www.tomhickey.com" title="Visit Tom Hickey's website.">Tom Hickey</a>.<br />
+      Clojure auto-documentation system by Tom Faulhaber.</div>
+    </div>
+    <!-- /AllContentContainer -->
+  </body>
+
+</html>
\ No newline at end of file
diff --git a/deps.edn b/deps.edn
deleted file mode 100644
index 48b6ef53..00000000
--- a/deps.edn
+++ /dev/null
@@ -1,33 +0,0 @@
-;; You can run clojure.java.jdbc tests with: clj -A:test:runner
-;; You can also specify an alias to select which version of Clojure to test
-;; against: :1.9 :1.10 :1.11 :1.12
-
-{:paths ["src/main/clojure"]
- :aliases {:test
-           {:extra-paths ["src/test/clojure"]
-            :extra-deps {org.clojure/test.check {:mvn/version "1.1.1"}
-                         org.apache.derby/derby {:mvn/version "10.14.2.0"}
-                         org.hsqldb/hsqldb$jdk8 {:mvn/version "2.7.2"}
-                         com.h2database/h2 {:mvn/version "1.4.197"}
-                         net.sourceforge.jtds/jtds {:mvn/version "1.3.1"}
-                         ;; Note: Tests fail with 6.0.2+ driver
-                         mysql/mysql-connector-java {:mvn/version "5.1.41"}
-                         org.postgresql/postgresql {:mvn/version "42.7.3"}
-                         com.impossibl.pgjdbc-ng/pgjdbc-ng {:mvn/version "0.8.9"}
-                         org.xerial/sqlite-jdbc {:mvn/version "3.45.2.0"}
-                         ;; Note: Assumes Java 8; there's a .jre11 version as well
-                         com.microsoft.sqlserver/mssql-jdbc {:mvn/version "12.6.1.jre8"}}}
-           :1.9 {:override-deps {org.clojure/clojure {:mvn/version "1.9.0"}}}
-           :1.10 {:override-deps {org.clojure/clojure {:mvn/version "1.10.3"}}}
-           :1.11 {:override-deps {org.clojure/clojure {:mvn/version "1.11.4"}}}
-           :1.12 {:override-deps {org.clojure/clojure {:mvn/version "1.12.0"}}}
-           :perf {:extra-paths ["src/perf/clojure"]
-                  :extra-deps {criterium/criterium {:mvn/version "0.4.6"}}
-                  :jvm-opts ["-server"
-                             "-Xmx4096m"
-                             "-Dclojure.compiler.direct-linking=true"]}
-           :runner
-           {:extra-deps {io.github.cognitect-labs/test-runner
-                         {:git/tag "v0.5.1" :git/sha "dfb30dd"}}
-            :main-opts ["-m" "cognitect.test-runner"
-                        "-d" "src/test/clojure"]}}}
diff --git a/epl.html b/epl.html
deleted file mode 100644
index fd391227..00000000
--- a/epl.html
+++ /dev/null
@@ -1,261 +0,0 @@
-<?xml version="1.0" encoding="ISO-8859-1" ?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
-
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
-<title>Eclipse Public License - Version 1.0</title>
-<style type="text/css">
-  body {
-    size: 8.5in 11.0in;
-    margin: 0.25in 0.5in 0.25in 0.5in;
-    tab-interval: 0.5in;
-    }
-  p {  	
-    margin-left: auto;
-    margin-top:  0.5em;
-    margin-bottom: 0.5em;
-    }
-  p.list {
-  	margin-left: 0.5in;
-    margin-top:  0.05em;
-    margin-bottom: 0.05em;
-    }
-  </style>
-
-</head>
-
-<body lang="EN-US">
-
-<h2>Eclipse Public License - v 1.0</h2>
-
-<p>THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
-PUBLIC LICENSE (&quot;AGREEMENT&quot;). ANY USE, REPRODUCTION OR
-DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS
-AGREEMENT.</p>
-
-<p><b>1. DEFINITIONS</b></p>
-
-<p>&quot;Contribution&quot; means:</p>
-
-<p class="list">a) in the case of the initial Contributor, the initial
-code and documentation distributed under this Agreement, and</p>
-<p class="list">b) in the case of each subsequent Contributor:</p>
-<p class="list">i) changes to the Program, and</p>
-<p class="list">ii) additions to the Program;</p>
-<p class="list">where such changes and/or additions to the Program
-originate from and are distributed by that particular Contributor. A
-Contribution 'originates' from a Contributor if it was added to the
-Program by such Contributor itself or anyone acting on such
-Contributor's behalf. Contributions do not include additions to the
-Program which: (i) are separate modules of software distributed in
-conjunction with the Program under their own license agreement, and (ii)
-are not derivative works of the Program.</p>
-
-<p>&quot;Contributor&quot; means any person or entity that distributes
-the Program.</p>
-
-<p>&quot;Licensed Patents&quot; mean patent claims licensable by a
-Contributor which are necessarily infringed by the use or sale of its
-Contribution alone or when combined with the Program.</p>
-
-<p>&quot;Program&quot; means the Contributions distributed in accordance
-with this Agreement.</p>
-
-<p>&quot;Recipient&quot; means anyone who receives the Program under
-this Agreement, including all Contributors.</p>
-
-<p><b>2. GRANT OF RIGHTS</b></p>
-
-<p class="list">a) Subject to the terms of this Agreement, each
-Contributor hereby grants Recipient a non-exclusive, worldwide,
-royalty-free copyright license to reproduce, prepare derivative works
-of, publicly display, publicly perform, distribute and sublicense the
-Contribution of such Contributor, if any, and such derivative works, in
-source code and object code form.</p>
-
-<p class="list">b) Subject to the terms of this Agreement, each
-Contributor hereby grants Recipient a non-exclusive, worldwide,
-royalty-free patent license under Licensed Patents to make, use, sell,
-offer to sell, import and otherwise transfer the Contribution of such
-Contributor, if any, in source code and object code form. This patent
-license shall apply to the combination of the Contribution and the
-Program if, at the time the Contribution is added by the Contributor,
-such addition of the Contribution causes such combination to be covered
-by the Licensed Patents. The patent license shall not apply to any other
-combinations which include the Contribution. No hardware per se is
-licensed hereunder.</p>
-
-<p class="list">c) Recipient understands that although each Contributor
-grants the licenses to its Contributions set forth herein, no assurances
-are provided by any Contributor that the Program does not infringe the
-patent or other intellectual property rights of any other entity. Each
-Contributor disclaims any liability to Recipient for claims brought by
-any other entity based on infringement of intellectual property rights
-or otherwise. As a condition to exercising the rights and licenses
-granted hereunder, each Recipient hereby assumes sole responsibility to
-secure any other intellectual property rights needed, if any. For
-example, if a third party patent license is required to allow Recipient
-to distribute the Program, it is Recipient's responsibility to acquire
-that license before distributing the Program.</p>
-
-<p class="list">d) Each Contributor represents that to its knowledge it
-has sufficient copyright rights in its Contribution, if any, to grant
-the copyright license set forth in this Agreement.</p>
-
-<p><b>3. REQUIREMENTS</b></p>
-
-<p>A Contributor may choose to distribute the Program in object code
-form under its own license agreement, provided that:</p>
-
-<p class="list">a) it complies with the terms and conditions of this
-Agreement; and</p>
-
-<p class="list">b) its license agreement:</p>
-
-<p class="list">i) effectively disclaims on behalf of all Contributors
-all warranties and conditions, express and implied, including warranties
-or conditions of title and non-infringement, and implied warranties or
-conditions of merchantability and fitness for a particular purpose;</p>
-
-<p class="list">ii) effectively excludes on behalf of all Contributors
-all liability for damages, including direct, indirect, special,
-incidental and consequential damages, such as lost profits;</p>
-
-<p class="list">iii) states that any provisions which differ from this
-Agreement are offered by that Contributor alone and not by any other
-party; and</p>
-
-<p class="list">iv) states that source code for the Program is available
-from such Contributor, and informs licensees how to obtain it in a
-reasonable manner on or through a medium customarily used for software
-exchange.</p>
-
-<p>When the Program is made available in source code form:</p>
-
-<p class="list">a) it must be made available under this Agreement; and</p>
-
-<p class="list">b) a copy of this Agreement must be included with each
-copy of the Program.</p>
-
-<p>Contributors may not remove or alter any copyright notices contained
-within the Program.</p>
-
-<p>Each Contributor must identify itself as the originator of its
-Contribution, if any, in a manner that reasonably allows subsequent
-Recipients to identify the originator of the Contribution.</p>
-
-<p><b>4. COMMERCIAL DISTRIBUTION</b></p>
-
-<p>Commercial distributors of software may accept certain
-responsibilities with respect to end users, business partners and the
-like. While this license is intended to facilitate the commercial use of
-the Program, the Contributor who includes the Program in a commercial
-product offering should do so in a manner which does not create
-potential liability for other Contributors. Therefore, if a Contributor
-includes the Program in a commercial product offering, such Contributor
-(&quot;Commercial Contributor&quot;) hereby agrees to defend and
-indemnify every other Contributor (&quot;Indemnified Contributor&quot;)
-against any losses, damages and costs (collectively &quot;Losses&quot;)
-arising from claims, lawsuits and other legal actions brought by a third
-party against the Indemnified Contributor to the extent caused by the
-acts or omissions of such Commercial Contributor in connection with its
-distribution of the Program in a commercial product offering. The
-obligations in this section do not apply to any claims or Losses
-relating to any actual or alleged intellectual property infringement. In
-order to qualify, an Indemnified Contributor must: a) promptly notify
-the Commercial Contributor in writing of such claim, and b) allow the
-Commercial Contributor to control, and cooperate with the Commercial
-Contributor in, the defense and any related settlement negotiations. The
-Indemnified Contributor may participate in any such claim at its own
-expense.</p>
-
-<p>For example, a Contributor might include the Program in a commercial
-product offering, Product X. That Contributor is then a Commercial
-Contributor. If that Commercial Contributor then makes performance
-claims, or offers warranties related to Product X, those performance
-claims and warranties are such Commercial Contributor's responsibility
-alone. Under this section, the Commercial Contributor would have to
-defend claims against the other Contributors related to those
-performance claims and warranties, and if a court requires any other
-Contributor to pay any damages as a result, the Commercial Contributor
-must pay those damages.</p>
-
-<p><b>5. NO WARRANTY</b></p>
-
-<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
-PROVIDED ON AN &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS
-OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION,
-ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
-OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
-responsible for determining the appropriateness of using and
-distributing the Program and assumes all risks associated with its
-exercise of rights under this Agreement , including but not limited to
-the risks and costs of program errors, compliance with applicable laws,
-damage to or loss of data, programs or equipment, and unavailability or
-interruption of operations.</p>
-
-<p><b>6. DISCLAIMER OF LIABILITY</b></p>
-
-<p>EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
-NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
-INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
-WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
-DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
-HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.</p>
-
-<p><b>7. GENERAL</b></p>
-
-<p>If any provision of this Agreement is invalid or unenforceable under
-applicable law, it shall not affect the validity or enforceability of
-the remainder of the terms of this Agreement, and without further action
-by the parties hereto, such provision shall be reformed to the minimum
-extent necessary to make such provision valid and enforceable.</p>
-
-<p>If Recipient institutes patent litigation against any entity
-(including a cross-claim or counterclaim in a lawsuit) alleging that the
-Program itself (excluding combinations of the Program with other
-software or hardware) infringes such Recipient's patent(s), then such
-Recipient's rights granted under Section 2(b) shall terminate as of the
-date such litigation is filed.</p>
-
-<p>All Recipient's rights under this Agreement shall terminate if it
-fails to comply with any of the material terms or conditions of this
-Agreement and does not cure such failure in a reasonable period of time
-after becoming aware of such noncompliance. If all Recipient's rights
-under this Agreement terminate, Recipient agrees to cease use and
-distribution of the Program as soon as reasonably practicable. However,
-Recipient's obligations under this Agreement and any licenses granted by
-Recipient relating to the Program shall continue and survive.</p>
-
-<p>Everyone is permitted to copy and distribute copies of this
-Agreement, but in order to avoid inconsistency the Agreement is
-copyrighted and may only be modified in the following manner. The
-Agreement Steward reserves the right to publish new versions (including
-revisions) of this Agreement from time to time. No one other than the
-Agreement Steward has the right to modify this Agreement. The Eclipse
-Foundation is the initial Agreement Steward. The Eclipse Foundation may
-assign the responsibility to serve as the Agreement Steward to a
-suitable separate entity. Each new version of the Agreement will be
-given a distinguishing version number. The Program (including
-Contributions) may always be distributed subject to the version of the
-Agreement under which it was received. In addition, after a new version
-of the Agreement is published, Contributor may elect to distribute the
-Program (including its Contributions) under the new version. Except as
-expressly stated in Sections 2(a) and 2(b) above, Recipient receives no
-rights or licenses to the intellectual property of any Contributor under
-this Agreement, whether expressly, by implication, estoppel or
-otherwise. All rights in the Program not expressly granted under this
-Agreement are reserved.</p>
-
-<p>This Agreement is governed by the laws of the State of New York and
-the intellectual property laws of the United States of America. No party
-to this Agreement will bring a legal action under this Agreement more
-than one year after the cause of action arose. Each party waives its
-rights to a jury trial in any resulting litigation.</p>
-
-</body>
-
-</html>
diff --git a/index.html b/index.html
new file mode 100644
index 00000000..5e8ea13f
--- /dev/null
+++ b/index.html
@@ -0,0 +1,2214 @@
+<html>
+  <head>
+    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+    <title>clojure.java.jdbc - java.jdbc 0.7.13-SNAPSHOT API documentation</title>
+    <link rel="icon" href="static/favicon.png" />
+    <link rel="shortcut icon" href="static/favicon.png" />
+    <link rel="stylesheet" href="static/clojure.css" type="text/css" media="all" />
+    <link rel="stylesheet" href="static/wiki.css" type="text/css" media="all" />
+    <link rel="stylesheet" href="static/internal.css" type="text/css" media="all" />
+    <style>.menuWrapper{height: 36px;}</style>
+  </head>
+<!--
+This document was auto-generated from the source by the clojure autodoc system.
+To report errors or ask questions about the overall documentation structure, formatting,
+etc., contact Tom Faulhaber (google mail name: tomfaulhaber).
+For errors in the documentation of a particular namespace, contact the author of that
+namespace.
+-->
+  <body>
+    <div id="AllContentContainer">
+      <div id="Header">
+	<a href="index.html" id="Logo"><img src="static/clojure-icon.gif" width="100" height="100" alt="Clojure" /></a>
+	<h1><a href="index.html" id="page-header" title="page header title">java.jdbc API Reference</a></h1>
+      </div>
+      <div id="leftcolumn"><div style="text-align: center;"></div>
+<div class="menu">
+  <div class="WikiCustomNav WikiElement wiki">
+    <span class="toc-header"><span id="project-name">java.jdbc</span> <span id="version">0.7.13-SNAPSHOT</span> API</span><br />
+    <ul>
+      <li><a href="index.html" class="wiki_link">Overview</a></li>
+      <li><a href="api-index.html" class="wiki_link">API Index</a></li>
+    </ul>
+    
+    
+    <a class="wiki_link" href="https://clojure.org">Clojure Home</a>
+  </div>
+</div>
+</div>
+      <div id="rightcolumn">
+	<div id="Content">
+	  <div class="contentBox"><div class="innerContentBox">
+              <div class="wiki wikiPage" id="content_view">
+                <div id="right-sidebar"><div id="toc">
+  <h1 class="nopad">Table of Contents</h1>
+  <div class="toc-section" style="margin-left: 1em;">
+    <a style="margin-top: 3px;" href="#toc0">Overview</a>
+    
+  </div><div class="toc-section" style="margin-left: 1em;">
+    <a style="margin-top: 3px;" href="#proto-section">Protocols</a>
+    <div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/IResultSetReadColumn" class="toc-entry-anchor">IResultSetReadColumn</a>
+      <div class="toc-subentry" style="margin-left: 1em;">
+        <a href="#clojure.java.jdbc/result-set-read-column" class="toc-subentry-anchor">result-set-read-column</a>
+      </div>
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/ISQLParameter" class="toc-entry-anchor">ISQLParameter</a>
+      <div class="toc-subentry" style="margin-left: 1em;">
+        <a href="#clojure.java.jdbc/set-parameter" class="toc-subentry-anchor">set-parameter</a>
+      </div>
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/ISQLValue" class="toc-entry-anchor">ISQLValue</a>
+      <div class="toc-subentry" style="margin-left: 1em;">
+        <a href="#clojure.java.jdbc/sql-value" class="toc-subentry-anchor">sql-value</a>
+      </div>
+    </div>
+  </div><div class="toc-section" style="margin-left: 1em;">
+    <a style="margin-top: 3px;" href="#"></a>
+    
+  </div><div class="toc-section" style="margin-left: 1em;">
+    <a style="margin-top: 3px;" href="#var-section">Vars and Functions</a>
+    <div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/as-sql-name" class="toc-entry-anchor">as-sql-name</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/create-table-ddl" class="toc-entry-anchor">create-table-ddl</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/db-connection" class="toc-entry-anchor">db-connection</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/db-do-commands" class="toc-entry-anchor">db-do-commands</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/db-do-prepared" class="toc-entry-anchor">db-do-prepared</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/db-do-prepared-return-keys" class="toc-entry-anchor">db-do-prepared-return-keys</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/db-find-connection" class="toc-entry-anchor">db-find-connection</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/db-is-rollback-only" class="toc-entry-anchor">db-is-rollback-only</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/db-query-with-resultset" class="toc-entry-anchor">db-query-with-resultset</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/db-set-rollback-only!" class="toc-entry-anchor">db-set-rollback-only!</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/db-transaction*" class="toc-entry-anchor">db-transaction*</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/db-unset-rollback-only!" class="toc-entry-anchor">db-unset-rollback-only!</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/delete!" class="toc-entry-anchor">delete!</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/drop-table-ddl" class="toc-entry-anchor">drop-table-ddl</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/execute!" class="toc-entry-anchor">execute!</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/find-by-keys" class="toc-entry-anchor">find-by-keys</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/get-by-id" class="toc-entry-anchor">get-by-id</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/get-connection" class="toc-entry-anchor">get-connection</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/get-isolation-level" class="toc-entry-anchor">get-isolation-level</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/insert!" class="toc-entry-anchor">insert!</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/insert-multi!" class="toc-entry-anchor">insert-multi!</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/metadata-query" class="toc-entry-anchor">metadata-query</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/metadata-result" class="toc-entry-anchor">metadata-result</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/prepare-statement" class="toc-entry-anchor">prepare-statement</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/print-sql-exception" class="toc-entry-anchor">print-sql-exception</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/print-sql-exception-chain" class="toc-entry-anchor">print-sql-exception-chain</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/print-update-counts" class="toc-entry-anchor">print-update-counts</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/query" class="toc-entry-anchor">query</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/quoted" class="toc-entry-anchor">quoted</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/reducible-query" class="toc-entry-anchor">reducible-query</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/reducible-result-set" class="toc-entry-anchor">reducible-result-set</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/result-set-seq" class="toc-entry-anchor">result-set-seq</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/update!" class="toc-entry-anchor">update!</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/with-db-connection" class="toc-entry-anchor">with-db-connection</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/with-db-metadata" class="toc-entry-anchor">with-db-metadata</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc/with-db-transaction" class="toc-entry-anchor">with-db-transaction</a>
+      
+    </div>
+  </div><div class="toc-section" style="margin-left: 1em;">
+    <a style="margin-top: 3px;" href="#"></a>
+    
+  </div><div class="toc-section" style="margin-left: 1em;">
+    <a style="margin-top: 3px;" href="#clojure.java.jdbc.datafy">clojure.java.jdbc.datafy</a>
+    <div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc.datafy/find-by-keys" class="toc-entry-anchor">find-by-keys</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc.datafy/get-by-id" class="toc-entry-anchor">get-by-id</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#clojure.java.jdbc.datafy/query" class="toc-entry-anchor">query</a>
+      
+    </div>
+  </div><div class="toc-section" style="margin-left: 1em;">
+    <a style="margin-top: 3px;" href="#clojure.java.jdbc.spec">clojure.java.jdbc.spec</a>
+    <div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/as-arrays?" class="toc-entry-anchor">::as-arrays?</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/auto-commit?" class="toc-entry-anchor">::auto-commit?</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/classname" class="toc-entry-anchor">::classname</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/column-direction" class="toc-entry-anchor">::column-direction</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/column-spec" class="toc-entry-anchor">::column-spec</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/concurrency" class="toc-entry-anchor">::concurrency</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/conditional?" class="toc-entry-anchor">::conditional?</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/connection" class="toc-entry-anchor">::connection</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/connection-binding" class="toc-entry-anchor">::connection-binding</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/connection-options" class="toc-entry-anchor">::connection-options</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/connection-uri" class="toc-entry-anchor">::connection-uri</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/cursors" class="toc-entry-anchor">::cursors</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/datasource" class="toc-entry-anchor">::datasource</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/db-spec" class="toc-entry-anchor">::db-spec</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/db-spec-connection" class="toc-entry-anchor">::db-spec-connection</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/db-spec-data-source" class="toc-entry-anchor">::db-spec-data-source</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/db-spec-driver-manager" class="toc-entry-anchor">::db-spec-driver-manager</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/db-spec-factory" class="toc-entry-anchor">::db-spec-factory</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/db-spec-friendly" class="toc-entry-anchor">::db-spec-friendly</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/db-spec-jndi" class="toc-entry-anchor">::db-spec-jndi</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/db-spec-raw" class="toc-entry-anchor">::db-spec-raw</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/db-spec-string" class="toc-entry-anchor">::db-spec-string</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/db-spec-uri" class="toc-entry-anchor">::db-spec-uri</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/dbname" class="toc-entry-anchor">::dbname</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/dbtype" class="toc-entry-anchor">::dbtype</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/delimiter" class="toc-entry-anchor">::delimiter</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/direction" class="toc-entry-anchor">::direction</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/entities" class="toc-entry-anchor">::entities</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/entity" class="toc-entry-anchor">::entity</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/environment" class="toc-entry-anchor">::environment</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/exec-sql-options" class="toc-entry-anchor">::exec-sql-options</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/execute-options" class="toc-entry-anchor">::execute-options</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/execute-result" class="toc-entry-anchor">::execute-result</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/explain-fn" class="toc-entry-anchor">::explain-fn</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/explain?" class="toc-entry-anchor">::explain?</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/factory" class="toc-entry-anchor">::factory</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/fetch-size" class="toc-entry-anchor">::fetch-size</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/find-by-keys-options" class="toc-entry-anchor">::find-by-keys-options</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/host" class="toc-entry-anchor">::host</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/identifier" class="toc-entry-anchor">::identifier</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/identifiers" class="toc-entry-anchor">::identifiers</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/isolation" class="toc-entry-anchor">::isolation</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/keywordize?" class="toc-entry-anchor">::keywordize?</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/max-size" class="toc-entry-anchor">::max-size</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/multi?" class="toc-entry-anchor">::multi?</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/name" class="toc-entry-anchor">::name</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/naming-strategy" class="toc-entry-anchor">::naming-strategy</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/order-by" class="toc-entry-anchor">::order-by</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/password" class="toc-entry-anchor">::password</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/port" class="toc-entry-anchor">::port</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/prepare-options" class="toc-entry-anchor">::prepare-options</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/prepared-statement" class="toc-entry-anchor">::prepared-statement</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/qualifier" class="toc-entry-anchor">::qualifier</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/query-options" class="toc-entry-anchor">::query-options</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/read-columns" class="toc-entry-anchor">::read-columns</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/read-only?" class="toc-entry-anchor">::read-only?</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/reducible-query-options" class="toc-entry-anchor">::reducible-query-options</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/result-set" class="toc-entry-anchor">::result-set</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/result-set-fn" class="toc-entry-anchor">::result-set-fn</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/result-set-metadata" class="toc-entry-anchor">::result-set-metadata</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/result-type" class="toc-entry-anchor">::result-type</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/return-keys" class="toc-entry-anchor">::return-keys</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/row-fn" class="toc-entry-anchor">::row-fn</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/sql-params" class="toc-entry-anchor">::sql-params</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/sql-stmt" class="toc-entry-anchor">::sql-stmt</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/sql-value" class="toc-entry-anchor">::sql-value</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/subname" class="toc-entry-anchor">::subname</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/subprotocol" class="toc-entry-anchor">::subprotocol</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/subprotocol-alias" class="toc-entry-anchor">::subprotocol-alias</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/subprotocol-base" class="toc-entry-anchor">::subprotocol-base</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/table-spec" class="toc-entry-anchor">::table-spec</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/timeout" class="toc-entry-anchor">::timeout</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/transaction-binding" class="toc-entry-anchor">::transaction-binding</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/transaction-options" class="toc-entry-anchor">::transaction-options</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/transaction?" class="toc-entry-anchor">::transaction?</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/uri" class="toc-entry-anchor">::uri</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/user" class="toc-entry-anchor">::user</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/username" class="toc-entry-anchor">::username</a>
+      
+    </div><div class="toc-entry" style="margin-left: 1em;">
+      <a href="#:clojure.java.jdbc.spec/where-clause" class="toc-entry-anchor">::where-clause</a>
+      
+    </div>
+  </div>
+</div>
+</div>
+                <div id="content-tag"><h1 id="overview">API for <span id="clojure.java.jdbc">clojure.java.jdbc</span>
+  - <span id="header-project">java.jdbc</span> <span id="header-version">0.7.13-SNAPSHOT</span><span id="header-status-block"> (<span id="header-status">in development</span>)</span>
+  </h1>
+<span id="author-line">by <span id="author-name">Stephen C. Gilardi, Sean Corfield</span><br /></span>
+<br />Full namespace name: <span id="long-name">clojure.java.jdbc</span>
+<p></p>
+<h2>Overview</h2>
+<div id="home-page">Project home page is <a href="https://github.com/clojure/java.jdbc/">https://github.com/clojure/java.jdbc/</a></div>
+<pre id="namespace-docstr">A Clojure interface to SQL databases via JDBC
+
+clojure.java.jdbc provides a simple abstraction for CRUD (create, read,
+update, delete) operations on a SQL database, along with basic transaction
+support. Basic DDL operations are also supported (create table, drop table,
+access to table metadata).
+
+Maps are used to represent records, making it easy to store and retrieve
+data. Results can be processed using any standard sequence operations.
+
+For most operations, Java's PreparedStatement is used so your SQL and
+parameters can be represented as simple vectors where the first element
+is the SQL string, with ? for each parameter, and the remaining elements
+are the parameter values to be substituted.
+
+For more documentation, see:
+
+<a href="http://clojure-doc.org/articles/ecosystem/java_jdbc/home.html">http://clojure-doc.org/articles/ecosystem/java_jdbc/home.html</a></pre>
+
+
+<br />
+
+<div id="proto-section">
+  <p></p>
+  <h2>Protocols</h2>
+  <div id="proto-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/IResultSetReadColumn">IResultSetReadColumn</h2>
+    <span id="proto-type">Protocol</span><br />
+    <pre id="proto-docstr">Protocol for reading objects from the java.sql.ResultSet. Default
+implementations (for Object and nil) return the argument, and the
+Boolean implementation ensures a canonicalized true/false value,
+but it can be extended to provide custom behavior for special types.</pre>
+    Known implementations: <span id="proto-impls">java.lang.Boolean, nil, Object</span>
+    <div id="proto-var-entry">
+      <br />
+      <h3 id="clojure.java.jdbc/result-set-read-column">result-set-read-column</h3>
+      <span id="var-type">function</span><br />
+      <pre id="var-usage">Usage: (result-set-read-column val rsmeta idx)
+</pre>
+      <pre id="var-docstr">Function for transforming values after reading them from the database</pre>
+      <pre id="var-specs"></pre>
+      
+      
+      
+    </div>
+    
+    
+    <a id="proto-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L498">Source</a>
+  </div><div id="proto-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/ISQLParameter">ISQLParameter</h2>
+    <span id="proto-type">Protocol</span><br />
+    <pre id="proto-docstr">Protocol for setting SQL parameters in statement objects, which
+can convert from Clojure values. The default implementation just
+delegates the conversion to ISQLValue's sql-value conversion and
+uses .setObject on the parameter. It can be extended to use other
+methods of PreparedStatement to convert and set parameter values.</pre>
+    Known implementations: <span id="proto-impls">nil, Object</span>
+    <div id="proto-var-entry">
+      <br />
+      <h3 id="clojure.java.jdbc/set-parameter">set-parameter</h3>
+      <span id="var-type">function</span><br />
+      <pre id="var-usage">Usage: (set-parameter val stmt ix)
+</pre>
+      <pre id="var-docstr">Convert a Clojure value into a SQL value and store it as the ix'th
+parameter in the given SQL statement object.</pre>
+      <pre id="var-specs"></pre>
+      
+      
+      
+    </div>
+    
+    
+    <a id="proto-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L471">Source</a>
+  </div><div id="proto-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/ISQLValue">ISQLValue</h2>
+    <span id="proto-type">Protocol</span><br />
+    <pre id="proto-docstr">Protocol for creating SQL values from Clojure values. Default
+implementations (for Object and nil) just return the argument,
+but it can be extended to provide custom behavior to support
+exotic types supported by different databases.</pre>
+    Known implementations: <span id="proto-impls">nil, Object</span>
+    <div id="proto-var-entry">
+      <br />
+      <h3 id="clojure.java.jdbc/sql-value">sql-value</h3>
+      <span id="var-type">function</span><br />
+      <pre id="var-usage">Usage: (sql-value val)
+</pre>
+      <pre id="var-docstr">Convert a Clojure value into a SQL value.</pre>
+      <pre id="var-specs"></pre>
+      
+      
+      
+    </div>
+    
+    
+    <a id="proto-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L457">Source</a>
+  </div>
+</div>
+
+<div id="var-section">
+  <p></p>
+  <h2>Public Variables and Functions</h2>
+  <div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/as-sql-name">as-sql-name</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (as-sql-name f x)
+</pre>
+    <pre id="var-docstr">Given a naming strategy function and a keyword or string, return
+a string per that naming strategy.
+A name of the form x.y is treated as multiple names, x, y, etc,
+and each are turned into strings via the naming strategy and then
+joined back together so x.y might become `x`.`y` if the naming
+strategy quotes identifiers with `.</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :f :clojure.java.jdbc.spec/naming-strategy
+         :x :clojure.java.jdbc.spec/identifier)
+  Ret:  (or :kw keyword? :s string?)</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L53">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/create-table-ddl">create-table-ddl</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (create-table-ddl table specs)
+       (create-table-ddl table specs opts)
+</pre>
+    <pre id="var-docstr">Given a table name and a vector of column specs, return the DDL string for
+creating that table. Each column spec is, in turn, a vector of keywords or
+strings that is converted to strings and concatenated with spaces to form
+a single column description in DDL, e.g.,
+  [:cost :int "not null"]
+  [:name "varchar(32)"]
+The first element of a column spec is treated as a SQL entity (so if you
+provide the :entities option, that will be used to transform it). The
+remaining elements are left as-is when converting them to strings.
+An options map may be provided that can contain:
+:table-spec -- a string that is appended to the DDL -- and/or
+:entities -- a function to specify how column names are transformed.
+:conditional? -- either a boolean, indicating whether to add 'IF NOT EXISTS',
+  or a string, which is inserted literally before the table name, or a
+  function of two arguments (table name and the create statement), that can
+  manipulate the generated statement to better support other databases, e.g.,
+  MS SQL Server which need to wrap create table in an existence query.</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :table :clojure.java.jdbc.spec/identifier
+         :specs (coll-of :clojure.java.jdbc.spec/column-spec)
+         :opts (?
+                 (keys
+                  :req-un []
+                  :opt-un [:clojure.java.jdbc.spec/entities
+                           :clojure.java.jdbc.spec/conditional?
+                           :clojure.java.jdbc.spec/table-spec])))
+  Ret:  string?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L1688">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/db-connection">db-connection</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (db-connection db)
+</pre>
+    <pre id="var-docstr">Returns the current database connection (or throws if there is none)</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat :db-spec :clojure.java.jdbc.spec/db-spec)
+  Ret:  (instance? java.sql.Connection %)</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L731">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/db-do-commands">db-do-commands</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (db-do-commands db sql-commands)
+       (db-do-commands db transaction? sql-commands)
+</pre>
+    <pre id="var-docstr">Executes SQL commands on the specified database connection. Wraps the commands
+in a transaction if transaction? is true. transaction? can be omitted and it
+defaults to true. Accepts a single SQL command (string) or a vector of them.
+Uses executeBatch. This may affect what SQL you can run via db-do-commands.</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :db :clojure.java.jdbc.spec/db-spec
+         :transaction? (? boolean?)
+         :sql-commands (or
+                        :command string?
+                        :commands (coll-of string?)))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L942">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/db-do-prepared">db-do-prepared</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (db-do-prepared db sql-params)
+       (db-do-prepared db transaction? sql-params)
+       (db-do-prepared db transaction? sql-params opts)
+</pre>
+    <pre id="var-docstr">Executes an (optionally parameterized) SQL prepared statement on the
+open database connection. Each param-group is a seq of values for all of
+the parameters. transaction? can be omitted and defaults to true.
+The sql parameter can either be a SQL string or a PreparedStatement.
+Return a seq of update counts (one count for each param-group).</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :db :clojure.java.jdbc.spec/db-spec
+         :transaction? (? boolean?)
+         :sql-params :clojure.java.jdbc.spec/sql-params
+         :opts (?
+                 (merge
+                   :clojure.java.jdbc.spec/execute-options
+                   :clojure.java.jdbc.spec/query-options)))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L1060">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/db-do-prepared-return-keys">db-do-prepared-return-keys</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (db-do-prepared-return-keys db sql-params)
+       (db-do-prepared-return-keys db transaction? sql-params)
+       (db-do-prepared-return-keys db transaction? sql-params opts)
+</pre>
+    <pre id="var-docstr">Executes an (optionally parameterized) SQL prepared statement on the
+open database connection. The param-group is a seq of values for all of
+the parameters. transaction? can be omitted and will default to true.
+Return the generated keys for the (single) update/insert.
+A PreparedStatement may be passed in, instead of a SQL string, in which
+case :return-keys MUST BE SET on that PreparedStatement!</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :db :clojure.java.jdbc.spec/db-spec
+         :transaction? (? boolean?)
+         :sql-params :clojure.java.jdbc.spec/sql-params
+         :opts (?
+                 (merge
+                   :clojure.java.jdbc.spec/execute-options
+                   :clojure.java.jdbc.spec/query-options)))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L1015">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/db-find-connection">db-find-connection</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (db-find-connection db)
+</pre>
+    <pre id="var-docstr">Returns the current database connection (or nil if there is none)</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat :db-spec :clojure.java.jdbc.spec/db-spec)
+  Ret:  (nilable :clojure.java.jdbc.spec/connection)</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L725">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/db-is-rollback-only">db-is-rollback-only</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (db-is-rollback-only db)
+</pre>
+    <pre id="var-docstr">Returns true if the outermost transaction will rollback rather than
+commit when complete</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat :db :clojure.java.jdbc.spec/db-spec)
+  Ret:  boolean?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L748">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/db-query-with-resultset">db-query-with-resultset</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (db-query-with-resultset db sql-params func)
+       (db-query-with-resultset db sql-params func opts)
+</pre>
+    <pre id="var-docstr">Executes a query, then evaluates func passing in the raw ResultSet as an
+ argument. The second argument is a vector containing either:
+  [sql &amp; params] - a SQL query, followed by any parameters it needs
+  [stmt &amp; params] - a PreparedStatement, followed by any parameters it needs
+                    (the PreparedStatement already contains the SQL query)
+The opts map is passed to prepare-statement.
+Uses executeQuery. This may affect what SQL you can run via query.</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :db :clojure.java.jdbc.spec/db-spec
+         :sql-params :clojure.java.jdbc.spec/sql-params
+         :func ifn?
+         :opts (? :clojure.java.jdbc.spec/query-options))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L1119">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/db-set-rollback-only!">db-set-rollback-only!</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (db-set-rollback-only! db)
+</pre>
+    <pre id="var-docstr">Marks the outermost transaction such that it will rollback rather than
+commit when complete</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat :db :clojure.java.jdbc.spec/db-spec)
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L737">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/db-transaction*">db-transaction*</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (db-transaction* db func)
+       (db-transaction* db func opts)
+</pre>
+    <pre id="var-docstr">Evaluates func as a transaction on the open database connection. Any
+nested transactions are absorbed into the outermost transaction. By
+default, all database updates are committed together as a group after
+evaluating the outermost body, or rolled back on any uncaught
+exception. If rollback is set within scope of the outermost transaction,
+the entire transaction will be rolled back rather than committed when
+complete.
+The isolation option may be :none, :read-committed, :read-uncommitted,
+:repeatable-read, or :serializable. Note that not all databases support
+all of those isolation levels, and may either throw an exception or
+substitute another isolation level.
+The read-only? option puts the transaction in readonly mode (if supported).</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :db :clojure.java.jdbc.spec/db-spec
+         :func ifn?
+         :opts (? :clojure.java.jdbc.spec/transaction-options))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L776">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/db-unset-rollback-only!">db-unset-rollback-only!</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (db-unset-rollback-only! db)
+</pre>
+    <pre id="var-docstr">Marks the outermost transaction such that it will not rollback when complete</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat :db :clojure.java.jdbc.spec/db-spec)
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L743">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/delete!">delete!</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (delete! db table where-clause)
+       (delete! db table where-clause opts)
+</pre>
+    <pre id="var-docstr">Given a database connection, a table name and a where clause of columns to match,
+perform a delete. The options may specify how to transform column names in the
+map (default 'as-is') and whether to run the delete in a transaction (default true).
+Example:
+  (delete! db :person ["zip = ?" 94546])
+is equivalent to:
+  (execute! db ["DELETE FROM person WHERE zip = ?" 94546])</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :db :clojure.java.jdbc.spec/db-spec
+         :table :clojure.java.jdbc.spec/identifier
+         :where-clause (spec :clojure.java.jdbc.spec/where-clause)
+         :opts (? :clojure.java.jdbc.spec/exec-sql-options))
+  Ret:  (* integer?)</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L1479">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/drop-table-ddl">drop-table-ddl</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (drop-table-ddl table)
+       (drop-table-ddl table {:keys [entities conditional?], :or {entities identity}})
+</pre>
+    <pre id="var-docstr">Given a table name, return the DDL string for dropping that table.
+An options map may be provided that can contain:
+:entities -- a function to specify how column names are transformed.
+:conditional? -- either a boolean, indicating whether to add 'IF EXISTS',
+  or a string, which is inserted literally before the table name, or a
+  function of two arguments (table name and the create statement), that can
+  manipulate the generated statement to better support other databases, e.g.,
+  MS SQL Server which need to wrap create table in an existence query.</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :table :clojure.java.jdbc.spec/identifier
+         :opts (?
+                 (keys
+                  :req-un []
+                  :opt-un [:clojure.java.jdbc.spec/entities
+                           :clojure.java.jdbc.spec/conditional?])))
+  Ret:  string?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L1734">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/execute!">execute!</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (execute! db sql-params)
+       (execute! db sql-params opts)
+</pre>
+    <pre id="var-docstr">Given a database connection and a vector containing SQL (or PreparedStatement)
+followed by optional parameters, perform a general (non-select) SQL operation.
+
+The :transaction? option specifies whether to run the operation in a
+transaction or not (default true).
+
+If the :multi? option is false (the default), the SQL statement should be
+followed by the parameters for that statement.
+
+If the :multi? option is true, the SQL statement should be followed by one or
+more vectors of parameters, one for each application of the SQL statement.
+
+If :return-keys is provided, db-do-prepared-return-keys will be called
+instead of db-do-prepared, and the result will be a sequence of maps
+containing the generated keys. If present, :row-fn will be applied. If :multi?
+then :result-set-fn will also be applied if present. :as-arrays? may also be
+specified (which will affect what :result-set-fn is passed).
+
+If there are no parameters specified, executeUpdate will be used, otherwise
+executeBatch will be used. This may affect what SQL you can run via execute!</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :db :clojure.java.jdbc.spec/db-spec
+         :sql-params :clojure.java.jdbc.spec/sql-params
+         :opts (? :clojure.java.jdbc.spec/execute-options))
+  Ret:  (or
+         :rows :clojure.java.jdbc.spec/execute-result
+         :keys (coll-of map?))</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L1435">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/find-by-keys">find-by-keys</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (find-by-keys db table columns)
+       (find-by-keys db table columns opts)
+</pre>
+    <pre id="var-docstr">Given a database connection, a table name, a map of column name/value
+pairs, and an optional options map, return any matching rows.
+
+An :order-by option may be supplied to sort the rows, e.g.,
+
+    {:order-by [{:name :asc} {:age :desc} {:income :asc}]}
+    ;; equivalent to:
+    {:order-by [:name {:age :desc} :income]}
+
+The :order-by value is a sequence of column names (to sort in ascending
+order) and/or maps from column names to directions (:asc or :desc). The
+directions may be strings or keywords and are not case-sensitive. They
+are mapped to ASC or DESC in the generated SQL.
+
+Note: if a ordering map has more than one key, the order of the columns
+in the generated SQL ORDER BY clause is unspecified (so such maps should
+only contain one key/value pair).</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :db :clojure.java.jdbc.spec/db-spec
+         :table :clojure.java.jdbc.spec/identifier
+         :columns (map-of
+                    :clojure.java.jdbc.spec/identifier
+                    :clojure.java.jdbc.spec/sql-value)
+         :opts (? :clojure.java.jdbc.spec/find-by-keys-options))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L1386">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/get-by-id">get-by-id</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (get-by-id db table pk-value)
+       (get-by-id db table pk-value pk-name-or-opts)
+       (get-by-id db table pk-value pk-name opts)
+</pre>
+    <pre id="var-docstr">Given a database connection, a table name, a primary key value, an
+optional primary key column name, and an optional options map, return
+a single matching row, or nil.
+The primary key column name defaults to :id.</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :db :clojure.java.jdbc.spec/db-spec
+         :table :clojure.java.jdbc.spec/identifier
+         :pk-value :clojure.java.jdbc.spec/sql-value
+         :opt-args (cat
+                    :pk-name (? :clojure.java.jdbc.spec/identifier)
+                    :opts (?
+                            :clojure.java.jdbc.spec/find-by-keys-options)))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L1419">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/get-connection">get-connection</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (get-connection db-spec)
+       (get-connection {:keys [connection factory connection-uri classname subprotocol subname dbtype dbname host port datasource username password user name environment], :as db-spec} opts)
+</pre>
+    <pre id="var-docstr">Creates a connection to a database. db-spec is usually a map containing connection
+parameters but can also be a URI or a String.
+
+The only time you should call this function is when you need a Connection for
+prepare-statement -- no other public functions in clojure.java.jdbc accept a
+raw Connection object: they all expect a db-spec (either a raw db-spec or one
+obtained via with-db-connection or with-db-transaction).
+
+The correct usage of get-connection for prepare-statement is:
+
+    (with-open [conn (jdbc/get-connection db-spec)]
+      ... (jdbc/prepare-statement conn sql-statement options) ...)
+
+Any connection obtained via calling get-connection directly must be closed
+explicitly (via with-open or a direct call to .close on the Connection object).
+
+The various possibilities are described below:
+
+DriverManager (preferred):
+  :dbtype      (required) a String, the type of the database (the jdbc subprotocol)
+  :dbname      (required) a String, the name of the database
+  :classname   (optional) a String, the jdbc driver class name
+  :host        (optional) a String, the host name/IP of the database
+                          (defaults to 127.0.0.1)
+  :port        (optional) a Long, the port of the database
+                          (defaults to 3306 for mysql, 1433 for mssql/jtds, else nil)
+  (others)     (optional) passed to the driver as properties
+                          (may include :user and :password)
+
+Raw:
+  :connection-uri (required) a String
+               Passed directly to DriverManager/getConnection
+               (both :user and :password may be specified as well, rather
+                than passing them as part of the connection string)
+
+Other formats accepted:
+
+Existing Connection:
+  :connection  (required) an existing open connection that can be used
+               but cannot be closed (only the parent connection can be closed)
+
+DriverManager (alternative / legacy style):
+  :subprotocol (required) a String, the jdbc subprotocol
+  :subname     (required) a String, the jdbc subname
+  :classname   (optional) a String, the jdbc driver class name
+  (others)     (optional) passed to the driver as properties
+                          (may include :user and :password)
+
+Factory:
+  :factory     (required) a function of one argument, a map of params
+  (others)     (optional) passed to the factory function in a map
+
+DataSource:
+  :datasource  (required) a javax.sql.DataSource
+  :username    (optional) a String - deprecated, use :user instead
+  :user        (optional) a String - preferred
+  :password    (optional) a String, required if :user is supplied
+
+JNDI:
+  :name        (required) a String or javax.naming.Name
+  :environment (optional) a java.util.Map
+
+java.net.URI:
+  Parsed JDBC connection string (see java.lang.String format next)
+
+java.lang.String:
+  subprotocol://user:password@host:post/subname
+               An optional prefix of jdbc: is allowed.</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :db-spec :clojure.java.jdbc.spec/db-spec
+         :opts (? :clojure.java.jdbc.spec/connection-options))
+  Ret:  (instance? java.sql.Connection %)</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L274">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/get-isolation-level">get-isolation-level</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (get-isolation-level db)
+</pre>
+    <pre id="var-docstr">Given a db-spec (with an optional connection), return the current
+transaction isolation level, if known. Return nil if there is no
+active connection in the db-spec. Return :unknown if we do not
+recognize the isolation level.</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat :db :clojure.java.jdbc.spec/db-spec)
+  Ret:  (nilable
+          (or
+           :isolation :clojure.java.jdbc.spec/isolation
+           :unknown #{:unknown}))</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L767">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/insert!">insert!</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (insert! db table row)
+       (insert! db table cols-or-row values-or-opts)
+       (insert! db table cols values opts)
+</pre>
+    <pre id="var-docstr">Given a database connection, a table name and either a map representing a rows,
+or a list of column names followed by a list of column values also representing
+a single row, perform an insert.
+When inserting a row as a map, the result is the database-specific form of the
+generated keys, if available (note: PostgreSQL returns the whole row).
+When inserting a row as a list of column values, the result is the count of
+rows affected (1), if available (from getUpdateCount after executeBatch).
+The row map or column value vector may be followed by a map of options:
+The :transaction? option specifies whether to run in a transaction or not.
+The default is true (use a transaction). The :entities option specifies how
+to convert the table name and column names to SQL entities.</pre>
+    <pre id="var-specs">Specs:
+  Args: (or
+         :row (cat
+               :db :clojure.java.jdbc.spec/db-spec
+               :table :clojure.java.jdbc.spec/identifier
+               :row (map-of :clojure.java.jdbc.spec/identifier any?)
+               :opts (?
+                       (merge
+                         :clojure.java.jdbc.spec/execute-options
+                         :clojure.java.jdbc.spec/query-options)))
+         :cvs (cat
+               :db :clojure.java.jdbc.spec/db-spec
+               :table :clojure.java.jdbc.spec/identifier
+               :cols (nilable
+                       (coll-of :clojure.java.jdbc.spec/identifier))
+               :vals (coll-of any?)
+               :opts (?
+                       (merge
+                         :clojure.java.jdbc.spec/execute-options
+                         :clojure.java.jdbc.spec/query-options))))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L1599">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/insert-multi!">insert-multi!</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (insert-multi! db table rows)
+       (insert-multi! db table cols-or-rows values-or-opts)
+       (insert-multi! db table cols values opts)
+</pre>
+    <pre id="var-docstr">Given a database connection, a table name and either a sequence of maps (for
+rows) or a sequence of column names, followed by a sequence of vectors (for
+the values in each row), and possibly a map of options, insert that data into
+the database.
+
+When inserting rows as a sequence of maps, the result is a sequence of the
+generated keys, if available (note: PostgreSQL returns the whole rows). A
+separate database operation is used for each row inserted. This may be slow
+for if a large sequence of maps is provided.
+
+When inserting rows as a sequence of lists of column values, the result is
+a sequence of the counts of rows affected (a sequence of 1's), if available.
+Yes, that is singularly unhelpful. Thank you getUpdateCount and executeBatch!
+A single database operation should be used to insert all the rows at once.
+This may be much faster than inserting a sequence of rows (which performs an
+insert for each map in the sequence).
+
+Note: some database drivers need to be told to rewrite the SQL for this to
+be performed as a single, batched operation. In particular, PostgreSQL
+requires :reWriteBatchedInserts true and My SQL requires
+:rewriteBatchedStatement true (both non-standard JDBC options, of course!).
+These options should be passed into the driver when the connection is
+created (however that is done in your program).
+
+The :transaction? option specifies whether to run in a transaction or not.
+The default is true (use a transaction). The :entities option specifies how
+to convert the table name and column names to SQL entities.</pre>
+    <pre id="var-specs">Specs:
+  Args: (or
+         :rows (cat
+                :db :clojure.java.jdbc.spec/db-spec
+                :table :clojure.java.jdbc.spec/identifier
+                :rows (coll-of
+                        (map-of
+                          :clojure.java.jdbc.spec/identifier
+                          any?))
+                :opts (?
+                        (merge
+                          :clojure.java.jdbc.spec/execute-options
+                          :clojure.java.jdbc.spec/query-options)))
+         :cvs (cat
+               :db :clojure.java.jdbc.spec/db-spec
+               :table :clojure.java.jdbc.spec/identifier
+               :cols (nilable
+                       (coll-of :clojure.java.jdbc.spec/identifier))
+               :vals (coll-of (coll-of any?))
+               :opts (?
+                       (merge
+                         :clojure.java.jdbc.spec/execute-options
+                         :clojure.java.jdbc.spec/query-options))))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L1619">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/metadata-query">metadata-query</h2>
+    <span id="var-type">macro</span><br />
+    <pre id="var-usage">Usage: (metadata-query meta-query &amp; opt-args)
+</pre>
+    <pre id="var-docstr">Given a Java expression that extracts metadata (in the context of with-db-metadata),
+and a map of options like metadata-result, manage the connection for a single
+metadata-based query. Example usage:
+
+(with-db-metadata [meta db-spec]
+  (metadata-query (.getTables meta nil nil nil (into-array String ["TABLE"]))
+    {:row-fn ... :result-set-fn ...}))</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat :meta-query any? :opt-args (? any?))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L930">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/metadata-result">metadata-result</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (metadata-result rs-or-value)
+       (metadata-result rs-or-value opts)
+</pre>
+    <pre id="var-docstr">If the argument is a java.sql.ResultSet, turn it into a result-set-seq,
+else return it as-is. This makes working with metadata easier.
+Also accepts an option map containing :identifiers, :keywordize?, :qualifier,
+:as-arrays?, :row-fn, and :result-set-fn to control how the ResultSet is
+transformed and returned. See query for more details.</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :rs-or-value any?
+         :opts (? :clojure.java.jdbc.spec/query-options))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L918">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/prepare-statement">prepare-statement</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (prepare-statement con sql)
+       (prepare-statement con sql {:keys [return-keys result-type concurrency cursors fetch-size max-rows timeout]})
+</pre>
+    <pre id="var-docstr">Create a prepared statement from a connection, a SQL string and a map
+of options:
+   :return-keys truthy | nil - default nil
+     for some drivers, this may be a vector of column names to identify
+     the generated keys to return, otherwise it should just be true
+   :result-type :forward-only | :scroll-insensitive | :scroll-sensitive
+   :concurrency :read-only | :updatable
+   :cursors     :hold | :close
+   :fetch-size  n
+   :max-rows    n
+   :timeout     n
+Note that :result-type and :concurrency must be specified together as the
+underlying Java API expects both (or neither).</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :con :clojure.java.jdbc.spec/connection
+         :sql string?
+         :opts (? :clojure.java.jdbc.spec/prepare-options))
+  Ret:  (instance? java.sql.PreparedStatement %)</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L626">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/print-sql-exception">print-sql-exception</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (print-sql-exception exception)
+</pre>
+    <pre id="var-docstr">Prints the contents of an SQLException to *out*</pre>
+    <pre id="var-specs"></pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L685">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/print-sql-exception-chain">print-sql-exception-chain</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (print-sql-exception-chain exception)
+</pre>
+    <pre id="var-docstr">Prints a chain of SQLExceptions to *out*</pre>
+    <pre id="var-specs"></pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L699">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/print-update-counts">print-update-counts</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (print-update-counts exception)
+</pre>
+    <pre id="var-docstr">Prints the update counts from a BatchUpdateException to *out*</pre>
+    <pre id="var-specs"></pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L711">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/query">query</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (query db sql-params)
+       (query db sql-params opts)
+</pre>
+    <pre id="var-docstr">Given a database connection and a vector containing SQL and optional parameters,
+perform a simple database query. The options specify how to construct the result
+set (and are also passed to prepare-statement as needed):
+  :as-arrays? - return the results as a set of arrays, default false.
+  :identifiers - applied to each column name in the result set, default lower-case
+  :keywordize? - defaults to true, can be false to opt-out of converting
+      identifiers to keywords
+  :qualifier - optionally provides the namespace qualifier for identifiers
+  :result-set-fn - applied to the entire result set, default doall / vec
+      if :as-arrays? true, :result-set-fn will default to vec
+      if :as-arrays? false, :result-set-fn will default to doall
+  :row-fn - applied to each row as the result set is constructed, default identity
+The second argument is a vector containing a SQL string or PreparedStatement, followed
+by any parameters it needs.
+See also prepare-statement for additional options.</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :db :clojure.java.jdbc.spec/db-spec
+         :sql-params :clojure.java.jdbc.spec/sql-params
+         :opts (?
+                 (merge
+                   :clojure.java.jdbc.spec/query-options
+                   (keys
+                    :req-un []
+                    :opt-un [:clojure.java.jdbc.spec/explain?
+                             :clojure.java.jdbc.spec/explain-fn]))))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L1144">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/quoted">quoted</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (quoted q)
+</pre>
+    <pre id="var-docstr">Given a (vector) pair of delimiters (characters or strings), return a naming
+strategy function that will quote SQL entities with them.
+Given a single delimiter, treat it as a (vector) pair of that delimiter.
+  ((quoted [\[ \]]) "foo") will return "[foo]" -- for MS SQL Server
+  ((quoted \`') "foo") will return "`foo`" -- for MySQL
+Intended to be used with :entities to provide a quoting (naming) strategy that
+is appropriate for your database.</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :q (or
+             :pair (coll-of
+                     :clojure.java.jdbc.spec/delimiter
+                     :kind
+                     vector?
+                     :count
+                     2)
+             :delimiter :clojure.java.jdbc.spec/delimiter
+             :dialect #{:oracle :ansi :mysql :sqlserver}))
+  Ret:  (fspec
+          :args
+          (cat :x :clojure.java.jdbc.spec/identifier)
+          :ret
+          :clojure.java.jdbc.spec/identifier
+          :fn
+          nil)</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L67">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/reducible-query">reducible-query</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (reducible-query db sql-params)
+       (reducible-query db sql-params opts)
+</pre>
+    <pre id="var-docstr">Given a database connection, a vector containing SQL and optional parameters,
+return a reducible collection. When reduced, it will start the database query
+and reduce the result set, and then close the connection:
+  (transduce (map :cost) + (reducible-query db sql-params))
+
+The following options from query etc are not accepted here:
+  :as-arrays? :explain :explain-fn :result-set-fn :row-fn
+See prepare-statement for additional options that may be passed through.
+
+If :raw? true is specified, the rows of the result set are not converted to
+hash maps, and it as if the following options were specified:
+  :identifiers identity :keywordize? false :qualifier nil
+In addition, the rows of the result set may only be read as if they were hash
+maps (get, keyword lookup, select-keys) but the sequence representation is
+not available (so, no keys, no vals, and no seq calls). This is much faster
+than converting each row to a hash map but it is also more restrictive.</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :db :clojure.java.jdbc.spec/db-spec
+         :sql-params :clojure.java.jdbc.spec/sql-params
+         :opts (? :clojure.java.jdbc.spec/reducible-query-options))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L1313">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/reducible-result-set">reducible-result-set</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (reducible-result-set rs {:keys [identifiers keywordize? qualifier read-columns], :or {identifiers lower-case, keywordize? true, read-columns dft-read-columns}})
+</pre>
+    <pre id="var-docstr">Given a java.sql.ResultSet return a reducible collection.
+Compiled with Clojure 1.7 or later -- uses clojure.lang.IReduce
+Note: :as-arrays? is not accepted here.</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :rs :clojure.java.jdbc.spec/result-set
+         :opts (? :clojure.java.jdbc.spec/reducible-query-options))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L1229">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/result-set-seq">result-set-seq</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (result-set-seq rs)
+       (result-set-seq rs {:keys [as-arrays? identifiers keywordize? qualifier read-columns], :or {identifiers lower-case, keywordize? true, read-columns dft-read-columns}})
+</pre>
+    <pre id="var-docstr">Creates and returns a lazy sequence of maps corresponding to the rows in the
+java.sql.ResultSet rs. Loosely based on clojure.core/resultset-seq but it
+respects the specified naming strategy. Duplicate column names are made unique
+by appending _N before applying the naming strategy (where N is a unique integer),
+unless the :as-arrays? option is :cols-as-is, in which case the column names
+are untouched (the result set maintains column name/value order).
+The :identifiers option specifies how SQL column names are converted to Clojure
+keywords. The default is to convert them to lower case.
+The :keywordize? option can be specified as false to opt-out of the conversion
+to keywords.
+The :qualifier option specifies the namespace qualifier for those identifiers
+(and this may not be specified when :keywordize? is false).</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :rs :clojure.java.jdbc.spec/result-set
+         :opts (? :clojure.java.jdbc.spec/query-options))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L545">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/update!">update!</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (update! db table set-map where-clause)
+       (update! db table set-map where-clause opts)
+</pre>
+    <pre id="var-docstr">Given a database connection, a table name, a map of column values to set and a
+where clause of columns to match, perform an update. The options may specify
+how column names (in the set / match maps) should be transformed (default
+'as-is') and whether to run the update in a transaction (default true).
+Example:
+  (update! db :person {:zip 94540} ["zip = ?" 94546])
+is equivalent to:
+  (execute! db ["UPDATE person SET zip = ? WHERE zip = ?" 94540 94546])</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :db :clojure.java.jdbc.spec/db-spec
+         :table :clojure.java.jdbc.spec/identifier
+         :set-map (map-of
+                    :clojure.java.jdbc.spec/identifier
+                    :clojure.java.jdbc.spec/sql-value)
+         :where-clause (spec :clojure.java.jdbc.spec/where-clause)
+         :opts (? :clojure.java.jdbc.spec/exec-sql-options))
+  Ret:  (* integer?)</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L1673">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/with-db-connection">with-db-connection</h2>
+    <span id="var-type">macro</span><br />
+    <pre id="var-usage">Usage: (with-db-connection binding &amp; body)
+</pre>
+    <pre id="var-docstr">Evaluates body in the context of an active connection to the database.
+(with-db-connection [con-db db-spec opts]
+  ... con-db ...)</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :binding :clojure.java.jdbc.spec/connection-binding
+         :body (* any?))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L876">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/with-db-metadata">with-db-metadata</h2>
+    <span id="var-type">macro</span><br />
+    <pre id="var-usage">Usage: (with-db-metadata binding &amp; body)
+</pre>
+    <pre id="var-docstr">Evaluates body in the context of an active connection with metadata bound
+to the specified name. See also metadata-result for dealing with the results
+of operations that retrieve information from the metadata.
+(with-db-metadata [md db-spec opts]
+  ... md ...)</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :binding :clojure.java.jdbc.spec/connection-binding
+         :body (* any?))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L889">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc/with-db-transaction">with-db-transaction</h2>
+    <span id="var-type">macro</span><br />
+    <pre id="var-usage">Usage: (with-db-transaction binding &amp; body)
+</pre>
+    <pre id="var-docstr">Evaluates body in the context of a transaction on the specified database connection.
+The binding provides the database connection for the transaction and the name to which
+that is bound for evaluation of the body. The binding may also specify the isolation
+level for the transaction, via the :isolation option and/or set the transaction to
+readonly via the :read-only? option.
+(with-db-transaction [t-con db-spec {:isolation level :read-only? true}]
+  ... t-con ...)
+See db-transaction* for more details.</pre>
+    <pre id="var-specs">Specs:
+  Args: (cat
+         :binding :clojure.java.jdbc.spec/transaction-binding
+         :body (* any?))
+  Ret:  any?</pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/21512f86a1abd0a42e2174b7239329af6e3c9d9e/src/main/clojure/clojure/java/jdbc.clj#L862">Source</a>
+  </div>
+</div>
+
+<br />
+<h2 id="clojure.java.jdbc.datafy">clojure.java.jdbc.datafy</h2>
+<pre id="namespace-docstr">Variants of 'query' functions from clojure.java.jdbc that support
+the new clojure.datafy functionality in Clojure 1.10.
+
+The whole schema/column lookup piece is very likely to change!
+
+Currently, the :schema option for a 'query' function is a mapping
+from column name to a tuple of table name, key column, and optionally
+the cardinality (:one -- the default -- or :many). The cardinality
+determines whether navigation should produce a single row (hash map)
+or a result set.
+
+One of the problems is that the general case -- query -- doesn't
+have any concept of an associated table name (and may of course
+join across multiple tables), so there's no good way to take the
+table name into account when mapping a column to another table.
+
+For find-by-keys and get-by-id, you do have the starting table
+name so you could map [table1 column1] to [table2 column2] and have
+table-specific mappings.
+
+The obvious, logical thing would be to use SQL metadata to figure
+out actual foreign key constraints but not everyone uses them, for
+a variety of reasons. For folks who do use them, they can build
+their schema structure from the database, and pass the relevant
+part of it to the functions below (via :schema in options).</pre>
+
+
+<br />
+
+
+<div id="var-section">
+  <p></p>
+  <h2>Public Variables and Functions</h2>
+  <div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc.datafy/find-by-keys">find-by-keys</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (find-by-keys db table columns)
+       (find-by-keys db table columns opts)
+</pre>
+    <pre id="var-docstr">Given a database connection, a table name, a map of column name/value
+pairs, and an optional options map, return any matching rows.
+
+An :order-by option may be supplied to sort the rows, e.g.,
+
+    {:order-by [{:name :asc} {:age :desc} {:income :asc}]}
+    ;; equivalent to:
+    {:order-by [:name {:age :desc} :income]}
+
+The :order-by value is a sequence of column names (to sort in ascending
+order) and/or maps from column names to directions (:asc or :desc). The
+directions may be strings or keywords and are not case-sensitive. They
+are mapped to ASC or DESC in the generated SQL.
+
+Note: if a ordering map has more than one key, the order of the columns
+in the generated SQL ORDER BY clause is unspecified (so such maps should
+only contain one key/value pair).</pre>
+    <pre id="var-specs"></pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/79ad004b42e9234d2bbf54df6a254c22b1c68c72/src/main/clojure/clojure/java/jdbc/datafy.clj#L119">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc.datafy/get-by-id">get-by-id</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (get-by-id db table pk-value)
+       (get-by-id db table pk-value pk-name-or-opts)
+       (get-by-id db table pk-value pk-name opts)
+</pre>
+    <pre id="var-docstr">Given a database connection, a table name, a primary key value, an
+optional primary key column name, and an optional options map, return
+a single matching row, or nil.
+The primary key column name defaults to :id.</pre>
+    <pre id="var-specs"></pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/79ad004b42e9234d2bbf54df6a254c22b1c68c72/src/main/clojure/clojure/java/jdbc/datafy.clj#L105">Source</a>
+  </div><div id="var-entry">
+    <br />
+    <hr />
+    <h2 id="clojure.java.jdbc.datafy/query">query</h2>
+    <span id="var-type">function</span><br />
+    <pre id="var-usage">Usage: (query db sql-params)
+       (query db sql-params opts)
+</pre>
+    <pre id="var-docstr">Given a database connection and a vector containing SQL and optional parameters,
+perform a simple database query. The options specify how to construct the result
+set (and are also passed to prepare-statement as needed):
+  :as-arrays? - return the results as a set of arrays, default false.
+  :identifiers - applied to each column name in the result set, default lower-case
+  :keywordize? - defaults to true, can be false to opt-out of converting
+      identifiers to keywords
+  :qualifier - optionally provides the namespace qualifier for identifiers
+  :result-set-fn - applied to the entire result set, default doall / vec
+      if :as-arrays? true, :result-set-fn will default to vec
+      if :as-arrays? false, :result-set-fn will default to doall
+  :row-fn - applied to each row as the result set is constructed, default identity
+The second argument is a vector containing a SQL string or PreparedStatement, followed
+by any parameters it needs.
+See also prepare-statement for additional options.</pre>
+    <pre id="var-specs"></pre>
+    
+    
+    <a id="var-source" href="https://github.com/clojure/java.jdbc/blob/79ad004b42e9234d2bbf54df6a254c22b1c68c72/src/main/clojure/clojure/java/jdbc/datafy.clj#L142">Source</a>
+  </div>
+</div>
+
+<br />
+<h2 id="clojure.java.jdbc.spec">clojure.java.jdbc.spec</h2>
+<pre id="namespace-docstr">Optional specifications for use with Clojure 1.9 or later.</pre>
+
+
+<br />
+
+
+
+<div id="spec-section">
+  <p></p>
+  <h2>Specs</h2>
+  <div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/as-arrays?">::as-arrays?</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(or :as-is #{:cols-as-is} :truthy (nilable boolean?))</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/auto-commit?">::auto-commit?</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">boolean?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/classname">::classname</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">string?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/column-direction">::column-direction</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(or :id ::identifier :id-dir (map-of ::identifier ::direction))</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/column-spec">::column-spec</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(cat
+ :col ::identifier
+ :spec (* (or :kw keyword? :str string? :num number?)))</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/concurrency">::concurrency</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(set (keys (deref #'result-set-concurrency)))</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/conditional?">::conditional?</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(or :b boolean? :s string? :f fn?)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/connection">::connection</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(instance? java.sql.Connection %)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/connection-binding">::connection-binding</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(cat :con-db simple-symbol? :db-spec any? :opts (? any?))</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/connection-options">::connection-options</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(keys :req-un [] :opt-un [::auto-commit? ::read-only?])</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/connection-uri">::connection-uri</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">string?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/cursors">::cursors</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(set (keys (deref #'result-set-holdability)))</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/datasource">::datasource</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(instance? javax.sql.DataSource %)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/db-spec">::db-spec</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(or
+ :connection ::db-spec-connection
+ :friendly ::db-spec-friendly
+ :raw ::db-spec-raw
+ :driver-mgr ::db-spec-driver-manager
+ :factory ::db-spec-factory
+ :datasource ::db-spec-data-source
+ :jndi ::db-spec-jndi
+ :uri-str ::db-spec-string
+ :uri-obj ::db-spec-uri)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/db-spec-connection">::db-spec-connection</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(keys :req-un [::connection])</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/db-spec-data-source">::db-spec-data-source</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(keys :req-un [::datasource] :opt-un [::username ::user ::password])</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/db-spec-driver-manager">::db-spec-driver-manager</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(keys
+ :req-un [::subprotocol ::subname]
+ :opt-un [::classname ::user ::password])</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/db-spec-factory">::db-spec-factory</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(keys :req-un [::factory])</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/db-spec-friendly">::db-spec-friendly</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(keys
+ :req-un [::dbtype ::dbname]
+ :opt-un [::host ::port ::user ::password ::classname])</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/db-spec-jndi">::db-spec-jndi</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(keys :req-un [::name] :opt-un [::environment])</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/db-spec-raw">::db-spec-raw</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(keys :req-un [::connection-uri] :opt-un [::user ::password])</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/db-spec-string">::db-spec-string</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">string?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/db-spec-uri">::db-spec-uri</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(instance? java.net.URI %)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/dbname">::dbname</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">string?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/dbtype">::dbtype</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(or :alias ::subprotocol-alias :name ::subprotocol-base)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/delimiter">::delimiter</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(or :s string? :c char?)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/direction">::direction</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">#{:desc "DESC" :asc "ASC" "desc" "asc"}</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/entities">::entities</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(fspec :args (cat :s string?) :ret ::entity :fn nil)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/entity">::entity</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">string?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/environment">::environment</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(nilable map?)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/exec-sql-options">::exec-sql-options</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(keys :req-un [] :opt-un [::entities ::transaction?])</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/execute-options">::execute-options</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(keys :req-un [] :opt-un [::transaction? ::multi? ::return-keys])</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/execute-result">::execute-result</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(* integer?)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/explain-fn">::explain-fn</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">fn?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/explain?">::explain?</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(or :b boolean? :s string?)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/factory">::factory</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(fspec :args (cat :db-spec ::db-spec) :ret ::connection :fn nil)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/fetch-size">::fetch-size</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">nat-int?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/find-by-keys-options">::find-by-keys-options</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(keys
+ :req-un []
+ :opt-un [::entities
+          ::order-by
+          ::result-set-fn
+          ::row-fn
+          ::identifiers
+          ::qualifier
+          ::keywordize?
+          ::as-arrays?
+          ::read-columns])</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/host">::host</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">string?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/identifier">::identifier</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(or :kw keyword? :s string?)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/identifiers">::identifiers</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(fspec :args (cat :s ::entity) :ret ::identifier :fn nil)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/isolation">::isolation</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(set (keys (deref #'isolation-levels)))</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/keywordize?">::keywordize?</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">boolean?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/max-size">::max-size</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">nat-int?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/multi?">::multi?</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">boolean?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/name">::name</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">string?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/naming-strategy">::naming-strategy</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(fspec :args (cat :x ::identifier) :ret ::identifier :fn nil)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/order-by">::order-by</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(coll-of ::column-direction)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/password">::password</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">string?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/port">::port</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(or :port pos-int? :s string?)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/prepare-options">::prepare-options</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(merge
+  (keys
+   :req-un []
+   :opt-un [::return-keys
+            ::result-type
+            ::concurrency
+            ::cursors
+            ::fetch-size
+            ::max-rows
+            ::timeout])
+  ::connection-options)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/prepared-statement">::prepared-statement</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(instance? java.sql.PreparedStatement %)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/qualifier">::qualifier</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(nilable string?)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/query-options">::query-options</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(merge
+  (keys
+   :req-un []
+   :opt-un [::result-set-fn
+            ::row-fn
+            ::identifiers
+            ::qualifier
+            ::keywordize?
+            ::as-arrays?
+            ::read-columns])
+  ::prepare-options)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/read-columns">::read-columns</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">fn?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/read-only?">::read-only?</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">boolean?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/reducible-query-options">::reducible-query-options</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(merge
+  (keys
+   :req-un []
+   :opt-un [::identifiers ::keywordize? ::qualifier ::read-columns])
+  ::prepare-options)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/result-set">::result-set</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(instance? java.sql.ResultSet %)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/result-set-fn">::result-set-fn</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(fspec :args (cat :rs (coll-of any?)) :ret any? :fn nil)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/result-set-metadata">::result-set-metadata</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(instance? java.sql.ResultSetMetaData %)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/result-type">::result-type</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(set (keys (deref #'result-set-type)))</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/return-keys">::return-keys</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(or :columns (coll-of ::entity :kind vector?) :boolean boolean?)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/row-fn">::row-fn</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(fspec :args (cat :row (map-of keyword? ::sql-value)) :ret any? :fn nil)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/sql-params">::sql-params</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(or
+ :sql ::sql-stmt
+ :sql-params (cat :sql ::sql-stmt :params (* ::sql-value)))</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/sql-stmt">::sql-stmt</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(or :sql string? :stmt ::prepared-statement)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/sql-value">::sql-value</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">any?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/subname">::subname</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">string?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/subprotocol">::subprotocol</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">string?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/subprotocol-alias">::subprotocol-alias</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">#{"mssql" "oracle" "postgres" "jtds" "hsql"}</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/subprotocol-base">::subprotocol-base</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">#{"h2:mem"
+  "mysql"
+  "oracle:thin"
+  "pgsql"
+  "oracle:oci"
+  "postgresql"
+  "sqlite"
+  "h2"
+  "jtds:sqlserver"
+  "hsqldb"
+  "redshift"
+  "derby"
+  "sqlserver"}</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/table-spec">::table-spec</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">string?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/timeout">::timeout</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">nat-int?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/transaction-binding">::transaction-binding</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(cat :t-con simple-symbol? :db-spec any? :opts (? any?))</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/transaction-options">::transaction-options</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(keys :req-un [] :opt-un [::isolation ::read-only?])</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/transaction?">::transaction?</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">boolean?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/uri">::uri</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(instance? java.net.URI %)</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/user">::user</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">string?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/username">::username</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">string?</pre>
+  </div><div id="spec-entry">
+    <br />
+    <hr />
+    <h2 id=":clojure.java.jdbc.spec/where-clause">::where-clause</h2>
+    <span id="spec-type">spec</span><br />
+    <pre id="spec-description">(cat :where string? :params (* ::sql-value))</pre>
+  </div>
+</div>
+
+</div>
+              </div>
+            </div>
+          </div>
+	</div>
+	<div id="foot">
+	  <div id="copyright" style="text-align: center;">Copyright 2007-2023 by Rich Hickey and the various contributors</div>
+	</div>
+      </div>
+      <div id="DesignedBy">Logo &amp; site design by <a href="http://www.tomhickey.com" title="Visit Tom Hickey's website.">Tom Hickey</a>.<br />
+      Clojure auto-documentation system by Tom Faulhaber.</div>
+    </div>
+    <!-- /AllContentContainer -->
+  </body>
+
+</html>
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
deleted file mode 100644
index 2d6da37e..00000000
--- a/pom.xml
+++ /dev/null
@@ -1,125 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-  <modelVersion>4.0.0</modelVersion>
-  <artifactId>java.jdbc</artifactId>
-  <version>0.7.13-SNAPSHOT</version>
-  <name>java.jdbc</name>
-
-  <parent>
-    <groupId>org.clojure</groupId>
-    <artifactId>pom.contrib</artifactId>
-    <version>1.3.0</version>
-  </parent>
-
-  <developers>
-    <developer>
-      <name>Stephen C. Gilardi</name>
-    </developer>
-    <developer>
-      <name>Sean Corfield</name>
-    </developer>
-  </developers>
-
-  <scm>
-    <connection>scm:git:git@github.com:clojure/java.jdbc.git</connection>
-    <developerConnection>scm:git:git@github.com:clojure/java.jdbc.git</developerConnection>
-    <url>git@github.com:clojure/java.jdbc.git</url>
-    <tag>HEAD</tag>
-  </scm>
-
-  <properties>
-    <clojure.version>1.9.0</clojure.version>
-  </properties>
-
-  <build>
-    <plugins>
-      <plugin>
-	    <!-- By default, compile everything as a sanity check, but do
-	         not include any AOT-compiled .class files in the
-	         JAR. Projects may override as needed. -->
-	    <groupId>com.theoryinpractise</groupId>
-	    <artifactId>clojure-maven-plugin</artifactId>
-	    <version>1.7.1</version>
-	    <extensions>true</extensions>
-	    <configuration>
-	      <warnOnReflection>${clojure.warnOnReflection}</warnOnReflection>
-	      <temporaryOutputDirectory>true</temporaryOutputDirectory>
-	    </configuration>
-	    <executions>
-	      <execution>
-	        <id>clojure-compile</id>
-	        <phase>none</phase>
-	      </execution>
-	      <execution>
-	        <id>clojure-test</id>
-	        <phase>test</phase>
-	        <goals>
-	          <goal>test</goal>
-	        </goals>
-	      </execution>
-	    </executions>
-      </plugin>
-    </plugins>
-  </build>
-
-  <dependencies>
-  	<dependency>
-  		<groupId>mysql</groupId>
-  		<artifactId>mysql-connector-java</artifactId>
-  		<version>5.1.41</version>
-  		<scope>test</scope>
-  	</dependency>
-  	<dependency>
-  		<groupId>org.apache.derby</groupId>
-  		<artifactId>derby</artifactId>
-  		<version>10.14.2.0</version>
-  		<scope>test</scope>
-  	</dependency>
-  	<dependency>
-  		<groupId>org.hsqldb</groupId>
-  		<artifactId>hsqldb</artifactId>
-  		<version>2.7.2</version>
-      <classifier>jdk8</classifier>
-  		<scope>test</scope>
-  	</dependency>
-    <dependency>
-      <groupId>com.h2database</groupId>
-      <artifactId>h2</artifactId>
-      <version>1.4.197</version>
-  		<scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.postgresql</groupId>
-      <artifactId>postgresql</artifactId>
-      <version>42.7.3</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.xerial</groupId>
-      <artifactId>sqlite-jdbc</artifactId>
-      <version>3.45.2.0</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>net.sourceforge.jtds</groupId>
-      <artifactId>jtds</artifactId>
-      <version>1.3.1</version>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.clojure</groupId>
-      <artifactId>test.check</artifactId>
-      <version>1.1.1</version>
-      <scope>test</scope>
-    </dependency>
-    <!-- assumes you have the Microsoft JDBC4 Driver 4.0 installed locally -->
-    <!--
-    <dependency>
-      <groupId>sqljdbc4</groupId>
-      <artifactId>sqljdbc4</artifactId>
-      <version>4.0</version>
-      <scope>test</scope>
-    </dependency>
-    -->
-  </dependencies>
-</project>
diff --git a/run-tests.sh b/run-tests.sh
deleted file mode 100755
index 5c4032a2..00000000
--- a/run-tests.sh
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/bin/sh
-#
-# Run this shell script with a list of databases you want to test against:
-#
-# ./run-tests.sh mysql postgres
-#
-# The default list of derby h2 hsqldb sqlite are always tested against.
-#
-# Additionally you can specify: mssql jtds postgres pgsql mysql
-#
-# Alternatives to mysql (a db-spec) are mysql-str and mysql-jdbc-str which use
-# connection strings instead. You may only specify one of these!
-#
-# Note: for mysql, postgres, and pgsql, the tests assume a database schema
-# called clojure_test that is accesible by a user clojure_test with the
-# password # clojure_test (currently hardcoded in the tests, sorry!).
-# This will eventually change...
-#
-# For postgres or pgsql, you can set the following environment variables
-# to override the defaults of 127.0.0.1 and 5432:
-#
-# TEST_POSTGRES_HOST TEST_POSTGRES_PORT
-#
-# Currently you may only specify one of postgres or pgsql!
-#
-# For mssql, you can set the following environment variables to override the
-# defaults of 127.0.0.1\\SQLEXPRESS, 1433, clojure_test, sa, (empty string):
-#
-# TEST_MSSQL_HOST TEST_MSSQL_PORT TEST_MSSQL_NAME TEST_MSSQL_USER TEST_MSSQL_PASS
-#
-# For jtds, you can set the following environment variables (defaults per above):
-#
-# TEST_JTDS_HOST TEST_JTDS_PORT TEST_JTDS_NAME TEST_JTDS_USER TEST_JTDS_PASS
-#
-# For jtds you can just specify the IP address or hostname, you do not need
-# the \\SQLEXPRESS part.
-#
-# Note: if you specify both mssql and jtds, make sure they're pointing at
-# different database names or the tests will fail!
-#
-# Default set of databases to test:
-dbs="derby h2 hsqldb sqlite"
-
-# Start with clean databases each time to avoid slowdown
-rm -rf clojure_test_*
-
-versions="1.9 1.10 1.11 1.12"
-for v in $versions
-do
-  TEST_DBS="$dbs $*" clj -M:test:runner:$v
-  if test $? -ne 0
-  then
-    exit $?
-  fi
-done
diff --git a/src/main/clojure/clojure/java/jdbc.clj b/src/main/clojure/clojure/java/jdbc.clj
deleted file mode 100644
index 5bcf5236..00000000
--- a/src/main/clojure/clojure/java/jdbc.clj
+++ /dev/null
@@ -1,1756 +0,0 @@
-;;  Copyright (c) 2008-2019 Sean Corfield, Stephen C. Gilardi. All rights reserved.
-;;  The use and distribution terms for this software are covered by
-;;  the Eclipse Public License 1.0
-;;  (http://opensource.org/licenses/eclipse-1.0.php) which can be
-;;  found in the file epl-v10.html at the root of this distribution.
-;;  By using this software in any fashion, you are agreeing to be
-;;  bound by the terms of this license.  You must not remove this
-;;  notice, or any other, from this software.
-;;
-;;  jdbc.clj
-;;
-;;  A Clojure interface to sql databases via jdbc
-;;
-;;  scgilardi (gmail)
-;;  Created 2 April 2008
-;;
-;;  seancorfield (gmail)
-;;  Migrated from clojure.contrib.sql 17 April 2011
-
-(ns
-    ^{:author "Stephen C. Gilardi, Sean Corfield",
-      :doc "A Clojure interface to SQL databases via JDBC
-
-clojure.java.jdbc provides a simple abstraction for CRUD (create, read,
-update, delete) operations on a SQL database, along with basic transaction
-support. Basic DDL operations are also supported (create table, drop table,
-access to table metadata).
-
-Maps are used to represent records, making it easy to store and retrieve
-data. Results can be processed using any standard sequence operations.
-
-For most operations, Java's PreparedStatement is used so your SQL and
-parameters can be represented as simple vectors where the first element
-is the SQL string, with ? for each parameter, and the remaining elements
-are the parameter values to be substituted.
-
-For more documentation, see:
-
-http://clojure-doc.org/articles/ecosystem/java_jdbc/home.html"}
-  clojure.java.jdbc
-  (:require [clojure.set :as set]
-            [clojure.string :as str]
-            [clojure.walk :as walk])
-  (:import (java.net URI)
-           (java.sql BatchUpdateException DriverManager
-                     PreparedStatement ResultSet ResultSetMetaData
-                     SQLException Statement Types)
-           (java.util Hashtable Locale Map Properties)
-           (javax.sql DataSource)))
-
-(set! *warn-on-reflection* true)
-
-(defn as-sql-name
-  "Given a naming strategy function and a keyword or string, return
-   a string per that naming strategy.
-   A name of the form x.y is treated as multiple names, x, y, etc,
-   and each are turned into strings via the naming strategy and then
-   joined back together so x.y might become `x`.`y` if the naming
-   strategy quotes identifiers with `."
-  [f x]
-  (let [n (name x)
-        i (.indexOf n (int \.))]
-    (if (= -1 i)
-      (f n)
-      (str/join "." (map f (.split n "\\."))))))
-
-(defn quoted
-  "Given a (vector) pair of delimiters (characters or strings), return a naming
-  strategy function that will quote SQL entities with them.
-  Given a single delimiter, treat it as a (vector) pair of that delimiter.
-    ((quoted [\\[ \\]]) \"foo\") will return \"[foo]\" -- for MS SQL Server
-    ((quoted \\`') \"foo\") will return \"`foo`\" -- for MySQL
-  Intended to be used with :entities to provide a quoting (naming) strategy that
-  is appropriate for your database."
-  [q]
-  (cond (vector? q)
-        (fn [x]
-          (str (first q) x (last q)))
-        (keyword? q)
-        (case q
-          :ansi      (quoted \")
-          :mysql     (quoted \`)
-          :oracle    (quoted \")
-          :sqlserver (quoted [\[ \]]))
-        :else
-        (quoted [q q])))
-
-(defn- table-str
-  "Transform a table spec to an entity name for SQL. The table spec may be a
-  string, a keyword or a map with a single pair - table name and alias."
-  [table entities]
-  (let [entities (or entities identity)]
-    (if (map? table)
-      (let [[k v] (first table)]
-        (str (as-sql-name entities k) " " (as-sql-name entities v)))
-      (as-sql-name entities table))))
-
-(defn- kv-sql
-  "Given a sequence of column name keys and a matching sequence of column
-  values, and an entities mapping function, return a sequence of SQL fragments
-  that can be joined for part of an UPDATE SET or a SELECT WHERE clause.
-  Note that we pass the appropriate operator for NULL since it is different
-  in each case."
-  [ks vs entities null-op]
-  (map (fn [k v]
-         (str (as-sql-name entities k)
-              (if (nil? v) null-op " = ?")))
-       ks vs))
-
-(defn- ^Properties as-properties
-  "Convert any seq of pairs to a java.util.Properties instance.
-   Uses as-sql-name to convert both keys and values into strings."
-  [m]
-  (let [p (Properties.)]
-    (doseq [[k v] m]
-      (.setProperty p (as-sql-name identity k)
-                    (if (instance? clojure.lang.Named v)
-                      (as-sql-name identity v)
-                      (str v))))
-    p))
-
-;; convenience for working with different forms of connections
-(defprotocol Connectable
-  (add-connection [db connection])
-  (get-level [db]))
-
-(defn- inc-level
-  "Increment the nesting level for a transacted database connection.
-   If we are at the top level, also add in a rollback state."
-  [db]
-  (let [nested-db (update-in db [:level] (fnil inc 0))]
-    (if (= 1 (:level nested-db))
-      (assoc nested-db :rollback (atom false))
-      nested-db)))
-
-(extend-protocol Connectable
-  String
-  (add-connection [s connection] {:connection connection :level 0 :connection-uri s})
-  (get-level [_] 0)
-
-  clojure.lang.Associative
-  (add-connection [m connection] (assoc m :connection connection))
-  (get-level [m] (or (:level m) 0))
-
-  nil
-  (add-connection [_ connection] {:connection connection :level 0 :legacy true})
-  (get-level [_] 0))
-
-(def ^:private classnames
-  "Map of subprotocols to classnames. dbtype specifies one of these keys.
-
-  The subprotocols map below provides aliases for dbtype.
-
-  Most databases have just a single class name for their driver but we
-  support a sequence of class names to try in order to allow for drivers
-  that change their names over time (e.g., MySQL)."
-  {"derby"          "org.apache.derby.jdbc.EmbeddedDriver"
-   "h2"             "org.h2.Driver"
-   "h2:mem"         "org.h2.Driver"
-   "hsqldb"         "org.hsqldb.jdbcDriver"
-   "jtds:sqlserver" "net.sourceforge.jtds.jdbc.Driver"
-   "mysql"          ["com.mysql.cj.jdbc.Driver"
-                     "com.mysql.jdbc.Driver"]
-   "oracle:oci"     "oracle.jdbc.OracleDriver"
-   "oracle:thin"    "oracle.jdbc.OracleDriver"
-   "postgresql"     "org.postgresql.Driver"
-   "pgsql"          "com.impossibl.postgres.jdbc.PGDriver"
-   "redshift"       "com.amazon.redshift.jdbc.Driver"
-   "sqlite"         "org.sqlite.JDBC"
-   "sqlserver"      "com.microsoft.sqlserver.jdbc.SQLServerDriver"})
-
-(def ^:private subprotocols
-  "Map of schemes to subprotocols. Used to provide aliases for dbtype."
-  {"hsql"       "hsqldb"
-   "jtds"       "jtds:sqlserver"
-   "mssql"      "sqlserver"
-   "oracle"     "oracle:thin"
-   "oracle:sid" "oracle:thin"
-   "postgres"   "postgresql"})
-
-(def ^:private host-prefixes
-  "Map of subprotocols to non-standard host-prefixes.
-  Anything not listed is assumed to use //."
-  {"oracle:oci"  "@"
-   "oracle:thin" "@"})
-
-(def ^:private ports
-  "Map of subprotocols to ports."
-  {"jtds:sqlserver" 1433
-   "mysql"          3306
-   "oracle:oci"     1521
-   "oracle:sid"     1521
-   "oracle:thin"    1521
-   "postgresql"     5432
-   "sqlserver"      1433})
-
-(def ^:private dbname-separators
-  "Map of schemes to separators. The default is / but a couple are different."
-  {"mssql"      ";DATABASENAME="
-   "sqlserver"  ";DATABASENAME="
-   "oracle:sid" ":"})
-
-(defn- parse-properties-uri [^URI uri]
-  (let [host (.getHost uri)
-        port (if (pos? (.getPort uri)) (.getPort uri))
-        path (.getPath uri)
-        scheme (.getScheme uri)
-        subprotocol (subprotocols scheme scheme)
-        host-prefix (host-prefixes subprotocol "//")
-        ^String query (.getQuery uri)
-        query-parts (and query
-                         (for [^String kvs (.split query "&")]
-                           ((juxt first second) (.split kvs "="))))]
-    (merge
-     {:subname (if host
-                 (if port
-                   (str host-prefix host ":" port path)
-                   (str host-prefix host path))
-                 (.getSchemeSpecificPart uri))
-      :subprotocol subprotocol}
-     (if-let [user-info (.getUserInfo uri)]
-       {:user (first (str/split user-info #":"))
-        :password (second (str/split user-info #":"))})
-     (walk/keywordize-keys (into {} query-parts)))))
-
-(defn- strip-jdbc [^String spec]
-  (if (.startsWith spec "jdbc:")
-    (.substring spec 5)
-    spec))
-
-;; feature testing macro, based on suggestion from Chas Emerick:
-(defmacro when-available
-  [sym & body]
-  (try
-    (when (resolve sym)
-      (list* 'do body))
-    (catch ClassNotFoundException _#)))
-
-(defn- modify-connection
-  "Given a database connection and a map of options, update the connection
-  as specified by the options."
-  ^java.sql.Connection
-  [^java.sql.Connection connection opts]
-  (when (and connection (contains? opts :auto-commit?))
-    (.setAutoCommit connection (boolean (:auto-commit? opts))))
-  (when (and connection (contains? opts :read-only?))
-    (.setReadOnly connection (boolean (:read-only? opts))))
-  connection)
-
-(defn- get-driver-connection
-  "Common logic for loading the DriverManager and the designed JDBC driver
-  class and obtaining the appropriate Connection object."
-  [classname subprotocol db-spec url etc opts error-msg]
-  (if-let [class-name (or classname (classnames subprotocol))]
-    (do
-      ;; force DriverManager to be loaded
-      (DriverManager/getLoginTimeout)
-      (if (string? class-name)
-        (clojure.lang.RT/loadClassForName class-name)
-        (loop [[clazz & more] class-name]
-          (when-let [load-failure
-                     (try
-                       (clojure.lang.RT/loadClassForName clazz)
-                       nil
-                       (catch Exception e
-                         e))]
-            (if (seq more)
-              (recur more)
-              (throw load-failure))))))
-    (throw (ex-info error-msg db-spec)))
-  (-> (DriverManager/getConnection url (as-properties etc))
-      (modify-connection opts)))
-
-(defn get-connection
-  "Creates a connection to a database. db-spec is usually a map containing connection
-  parameters but can also be a URI or a String.
-
-  The only time you should call this function is when you need a Connection for
-  prepare-statement -- no other public functions in clojure.java.jdbc accept a
-  raw Connection object: they all expect a db-spec (either a raw db-spec or one
-  obtained via with-db-connection or with-db-transaction).
-
-  The correct usage of get-connection for prepare-statement is:
-
-      (with-open [conn (jdbc/get-connection db-spec)]
-        ... (jdbc/prepare-statement conn sql-statement options) ...)
-
-  Any connection obtained via calling get-connection directly must be closed
-  explicitly (via with-open or a direct call to .close on the Connection object).
-
-  The various possibilities are described below:
-
-  DriverManager (preferred):
-    :dbtype      (required) a String, the type of the database (the jdbc subprotocol)
-    :dbname      (required) a String, the name of the database
-    :classname   (optional) a String, the jdbc driver class name
-    :host        (optional) a String, the host name/IP of the database
-                            (defaults to 127.0.0.1)
-    :port        (optional) a Long, the port of the database
-                            (defaults to 3306 for mysql, 1433 for mssql/jtds, else nil)
-    (others)     (optional) passed to the driver as properties
-                            (may include :user and :password)
-
-  Raw:
-    :connection-uri (required) a String
-                 Passed directly to DriverManager/getConnection
-                 (both :user and :password may be specified as well, rather
-                  than passing them as part of the connection string)
-
-  Other formats accepted:
-
-  Existing Connection:
-    :connection  (required) an existing open connection that can be used
-                 but cannot be closed (only the parent connection can be closed)
-
-  DriverManager (alternative / legacy style):
-    :subprotocol (required) a String, the jdbc subprotocol
-    :subname     (required) a String, the jdbc subname
-    :classname   (optional) a String, the jdbc driver class name
-    (others)     (optional) passed to the driver as properties
-                            (may include :user and :password)
-
-  Factory:
-    :factory     (required) a function of one argument, a map of params
-    (others)     (optional) passed to the factory function in a map
-
-  DataSource:
-    :datasource  (required) a javax.sql.DataSource
-    :username    (optional) a String - deprecated, use :user instead
-    :user        (optional) a String - preferred
-    :password    (optional) a String, required if :user is supplied
-
-  JNDI:
-    :name        (required) a String or javax.naming.Name
-    :environment (optional) a java.util.Map
-
-  java.net.URI:
-    Parsed JDBC connection string (see java.lang.String format next)
-
-  java.lang.String:
-    subprotocol://user:password@host:post/subname
-                 An optional prefix of jdbc: is allowed."
-  (^java.sql.Connection [db-spec] (get-connection db-spec {}))
-  (^java.sql.Connection
-    [{:keys [connection
-             factory
-             connection-uri
-             classname subprotocol subname
-             dbtype dbname host port
-             datasource username password user
-             name environment]
-      :as db-spec}
-     opts]
-    (cond
-     (string? db-spec)
-     (get-connection (URI. (strip-jdbc db-spec)) opts)
-
-     (instance? URI db-spec)
-     (get-connection (parse-properties-uri db-spec) opts)
-
-     connection
-     connection ;; do not apply opts here
-
-     (or (and datasource username password)  ; legacy
-         (and datasource user     password)) ; preferred
-     (-> (.getConnection ^DataSource datasource
-                         ^String (or username user)
-                         ^String password)
-         (modify-connection opts))
-
-     datasource
-     (-> (.getConnection ^DataSource datasource)
-         (modify-connection opts))
-
-     factory
-     (-> (factory (dissoc db-spec :factory))
-         (modify-connection opts))
-
-     connection-uri
-     (-> (if (and user password)
-           (DriverManager/getConnection connection-uri user password)
-           (DriverManager/getConnection connection-uri))
-         (modify-connection opts))
-
-     (and dbtype dbname)
-     (let [;; allow aliases for dbtype
-           subprotocol (subprotocols dbtype dbtype)
-           host (or host "127.0.0.1")
-           port (or port (ports subprotocol))
-           db-sep (dbname-separators dbtype "/")
-           url (cond (= "h2:mem" dbtype)
-                     (str "jdbc:" subprotocol ":" dbname ";DB_CLOSE_DELAY=-1")
-                     (#{"derby" "h2" "hsqldb" "sqlite"} subprotocol)
-                     (str "jdbc:" subprotocol ":" dbname)
-                     :else
-                     (str "jdbc:" subprotocol ":"
-                          (host-prefixes subprotocol "//")
-                          host
-                          (when port (str ":" port))
-                          db-sep dbname))
-           etc (dissoc db-spec :dbtype :dbname :host :port :classname)]
-       (get-driver-connection classname subprotocol db-spec
-                              url etc opts
-                              (str "Unknown dbtype: " dbtype)))
-
-     (and subprotocol subname)
-     (let [;; allow aliases for subprotocols
-           subprotocol (subprotocols subprotocol subprotocol)
-           url (format "jdbc:%s:%s" subprotocol subname)
-           etc (dissoc db-spec :classname :subprotocol :subname)]
-       (get-driver-connection classname subprotocol db-spec
-                              url etc opts
-                              (str "Unknown subprotocol: " subprotocol)))
-
-     name
-     (or (when-available javax.naming.InitialContext
-           (let [env (and environment (Hashtable. ^Map environment))
-                 context (javax.naming.InitialContext. env)
-                 ^DataSource datasource (.lookup context ^String name)]
-             (-> (.getConnection datasource)
-                 (modify-connection opts))))
-         (throw (ex-info (str "javax.naming.InitialContext is not available for: "
-                              name)
-                         db-spec)))
-
-     ;; passing a raw Connection object to a function expecting a db-spec is
-     ;; usually a confusion over how/when to use get-connection and deserves
-     ;; a custom error message:
-     (instance? java.sql.Connection db-spec)
-     (let [^String msg (str "db-spec is a raw Connection object!\n"
-                            "Did you call get-connection in the wrong context?\n"
-                            "You should only call that to pass a Connection into prepare-statement.\n"
-                            "(and don't forget to close it via with-open or .close)")]
-       (throw (IllegalArgumentException. msg)))
-
-     :else
-     (let [^String msg (format "db-spec %s is missing a required parameter" db-spec)]
-       (throw (IllegalArgumentException. msg))))))
-
-(defn- make-cols-unique
-  "A transducer that, given a collection of strings, returns a collection of
-  strings that have been made unique by appending _n to duplicates."
-  [xf]
-  (let [seen (volatile! {})]
-    (fn
-      ([] (xf))
-      ([result] (xf result))
-      ([result input]
-       (if-let [suffix (get @seen input)]
-         (do
-           (vswap! seen assoc input (inc suffix))
-           (xf result (str input "_" suffix)))
-         (do
-           (vswap! seen assoc input 2)
-           (xf result input)))))))
-
-(defprotocol ISQLValue :extend-via-metadata true
-  "Protocol for creating SQL values from Clojure values. Default
-   implementations (for Object and nil) just return the argument,
-   but it can be extended to provide custom behavior to support
-   exotic types supported by different databases."
-  (sql-value [val] "Convert a Clojure value into a SQL value."))
-
-(extend-protocol ISQLValue
-  Object
-  (sql-value [v] v)
-
-  nil
-  (sql-value [_] nil))
-
-(defprotocol ISQLParameter :extend-via-metadata true
-  "Protocol for setting SQL parameters in statement objects, which
-   can convert from Clojure values. The default implementation just
-   delegates the conversion to ISQLValue's sql-value conversion and
-   uses .setObject on the parameter. It can be extended to use other
-   methods of PreparedStatement to convert and set parameter values."
-  (set-parameter [val stmt ix]
-    "Convert a Clojure value into a SQL value and store it as the ix'th
-     parameter in the given SQL statement object."))
-
-(extend-protocol ISQLParameter
-  Object
-  (set-parameter [v ^PreparedStatement s ^long i]
-    (.setObject s i (sql-value v)))
-
-  nil
-  (set-parameter [_ ^PreparedStatement s ^long i]
-    (.setObject s i (sql-value nil))))
-
-(defn- dft-set-parameters
-  "Default implementation of parameter setting for the given statement."
-  [stmt params]
-  (loop [ix 1 values params]
-    (when (seq values)
-      (set-parameter (first values) stmt ix)
-      (recur (inc ix) (rest values)))))
-
-(defprotocol IResultSetReadColumn :extend-via-metadata true
-  "Protocol for reading objects from the java.sql.ResultSet. Default
-   implementations (for Object and nil) return the argument, and the
-   Boolean implementation ensures a canonicalized true/false value,
-   but it can be extended to provide custom behavior for special types."
-  (result-set-read-column [val rsmeta idx]
-    "Function for transforming values after reading them from the database"))
-
-(extend-protocol IResultSetReadColumn
-  Object
-  (result-set-read-column [x _2 _3] x)
-
-  Boolean
-  (result-set-read-column [x _2 _3] (if (= true x) true false))
-
-  nil
-  (result-set-read-column [_1 _2 _3] nil))
-
-(defn- dft-read-columns
-  "Default implementation of reading row values from result set, given the
-  result set metadata and the indices."
-  [^ResultSet rs rsmeta idxs]
-  (mapv (fn [^Integer i] (result-set-read-column (.getObject rs i) rsmeta i)) idxs))
-
-(defn- make-identifier-fn
-  "Given the user's identifiers function, an optional namespace qualifier, and
-  a flag indicating whether to produce keywords or not, return a compound
-  function that will perform the appropriate entity to identifier conversion."
-  [identifiers qualifier keywordize?]
-  (cond (and qualifier (not keywordize?))
-        (throw (IllegalArgumentException.
-                (str ":qualifier is not allowed unless "
-                     ":keywordize? is true")))
-        (and qualifier keywordize?)
-        (comp (partial keyword qualifier) identifiers)
-        keywordize?
-        (comp keyword identifiers)
-        :else
-        identifiers))
-
-(defn- lower-case
-  "Converts a string to lower case in the US locale to avoid problems in
-  locales where the lower case version of a character is not a valid SQL
-  entity name (e.g., Turkish)."
-  [^String s]
-  (.toLowerCase s Locale/US))
-
-(defn result-set-seq
-  "Creates and returns a lazy sequence of maps corresponding to the rows in the
-  java.sql.ResultSet rs. Loosely based on clojure.core/resultset-seq but it
-  respects the specified naming strategy. Duplicate column names are made unique
-  by appending _N before applying the naming strategy (where N is a unique integer),
-  unless the :as-arrays? option is :cols-as-is, in which case the column names
-  are untouched (the result set maintains column name/value order).
-  The :identifiers option specifies how SQL column names are converted to Clojure
-  keywords. The default is to convert them to lower case.
-  The :keywordize? option can be specified as false to opt-out of the conversion
-  to keywords.
-  The :qualifier option specifies the namespace qualifier for those identifiers
-  (and this may not be specified when :keywordize? is false)."
-  ([rs] (result-set-seq rs {}))
-  ([^ResultSet rs {:keys [as-arrays? identifiers keywordize?
-                          qualifier read-columns]
-                   :or {identifiers lower-case
-                        keywordize? true
-                        read-columns dft-read-columns}}]
-   (let [rsmeta (.getMetaData rs)
-         idxs (range 1 (inc (.getColumnCount rsmeta)))
-         col-name-fn (if (= :cols-as-is as-arrays?) identity make-cols-unique)
-         keys (into [] (comp (map (fn [^Integer i] (.getColumnLabel rsmeta i)))
-                             col-name-fn
-                             (map (make-identifier-fn identifiers
-                                                      qualifier
-                                                      keywordize?)))
-                    idxs)
-         row-values (fn [] (read-columns rs rsmeta idxs))
-         ;; This used to use create-struct (on keys) and then struct to populate each row.
-         ;; That had the side effect of preserving the order of columns in each row. As
-         ;; part of JDBC-15, this was changed because structmaps are deprecated. We don't
-         ;; want to switch to records so we're using regular maps instead. We no longer
-         ;; guarantee column order in rows but using into {} should preserve order for up
-         ;; to 16 columns (because it will use a PersistentArrayMap). If someone is relying
-         ;; on the order-preserving behavior of structmaps, we can reconsider...
-         records (fn thisfn []
-                   (when (.next rs)
-                     (cons (zipmap keys (row-values)) (lazy-seq (thisfn)))))
-         rows (fn thisfn []
-                (when (.next rs)
-                  (cons (vec (row-values)) (lazy-seq (thisfn)))))]
-     (if as-arrays?
-       (cons (vec keys) (rows))
-       (records)))))
-
-(defn- execute-batch
-  "Executes a batch of SQL commands and returns a sequence of update counts.
-   (-2) indicates a single operation operating on an unknown number of rows.
-   Specifically, Oracle returns that and we must call getUpdateCount() to get
-   the actual number of rows affected. In general, operations return an array
-   of update counts, so this may not be a general solution for Oracle..."
-  [^Statement stmt]
-  (let [result (.executeBatch stmt)]
-    (if (and (= 1 (count result)) (= -2 (first result)))
-      (list (.getUpdateCount stmt))
-      (seq result))))
-
-(def ^{:private true
-       :doc "Map friendly :concurrency values to ResultSet constants."}
-  result-set-concurrency
-  {:read-only ResultSet/CONCUR_READ_ONLY
-   :updatable ResultSet/CONCUR_UPDATABLE})
-
-(def ^{:private true
-       :doc "Map friendly :cursors values to ResultSet constants."}
-  result-set-holdability
-  {:hold ResultSet/HOLD_CURSORS_OVER_COMMIT
-   :close ResultSet/CLOSE_CURSORS_AT_COMMIT})
-
-(def ^{:private true
-       :doc "Map friendly :type values to ResultSet constants."}
-  result-set-type
-  {:forward-only ResultSet/TYPE_FORWARD_ONLY
-   :scroll-insensitive ResultSet/TYPE_SCROLL_INSENSITIVE
-   :scroll-sensitive ResultSet/TYPE_SCROLL_SENSITIVE})
-
-(defn ^{:tag (class (into-array String []))} string-array
-  [return-keys]
-  (into-array String return-keys))
-
-(defn prepare-statement
-  "Create a prepared statement from a connection, a SQL string and a map
-  of options:
-     :return-keys truthy | nil - default nil
-       for some drivers, this may be a vector of column names to identify
-       the generated keys to return, otherwise it should just be true
-     :result-type :forward-only | :scroll-insensitive | :scroll-sensitive
-     :concurrency :read-only | :updatable
-     :cursors     :hold | :close
-     :fetch-size  n
-     :max-rows    n
-     :timeout     n
-  Note that :result-type and :concurrency must be specified together as the
-  underlying Java API expects both (or neither)."
-  ([con sql] (prepare-statement con sql {}))
-  ([^java.sql.Connection con ^String sql
-    {:keys [return-keys result-type concurrency cursors
-            fetch-size max-rows timeout]}]
-   (let [^PreparedStatement
-         stmt (cond
-                return-keys
-                (do
-                  (when (or result-type concurrency cursors)
-                    (throw (IllegalArgumentException.
-                            (str ":concurrency, :cursors, and :result-type "
-                                 "may not be specified with :return-keys."))))
-                  (try
-                    (if (vector? return-keys)
-                      (try
-                        (.prepareStatement con sql (string-array return-keys))
-                        (catch Exception _
-                          ;; assume it is unsupported and try regular generated keys:
-                          (.prepareStatement con sql java.sql.Statement/RETURN_GENERATED_KEYS)))
-                      (.prepareStatement con sql java.sql.Statement/RETURN_GENERATED_KEYS))
-                    (catch Exception _
-                      ;; assume it is unsupported and try basic PreparedStatement:
-                      (.prepareStatement con sql))))
-
-                (and result-type concurrency)
-                (if cursors
-                  (.prepareStatement con sql
-                                     (get result-set-type result-type result-type)
-                                     (get result-set-concurrency concurrency concurrency)
-                                     (get result-set-holdability cursors cursors))
-                  (.prepareStatement con sql
-                                     (get result-set-type result-type result-type)
-                                     (get result-set-concurrency concurrency concurrency)))
-
-                (or result-type concurrency cursors)
-                (throw (IllegalArgumentException.
-                        (str ":concurrency, :cursors, and :result-type "
-                             "may not be specified independently.")))
-                :else
-                (.prepareStatement con sql))]
-     (when fetch-size (.setFetchSize stmt fetch-size))
-     (when max-rows (.setMaxRows stmt max-rows))
-     (when timeout (.setQueryTimeout stmt timeout))
-     stmt)))
-
-(defn print-sql-exception
-  "Prints the contents of an SQLException to *out*"
-  [^SQLException exception]
-  (let [^Class exception-class (class exception)]
-    (println
-     (format (str "%s:" \newline
-                  " Message: %s" \newline
-                  " SQLState: %s" \newline
-                  " Error Code: %d")
-             (.getSimpleName exception-class)
-             (.getMessage exception)
-             (.getSQLState exception)
-             (.getErrorCode exception)))))
-
-(defn print-sql-exception-chain
-  "Prints a chain of SQLExceptions to *out*"
-  [^SQLException exception]
-  (loop [e exception]
-    (when e
-      (print-sql-exception e)
-      (recur (.getNextException e)))))
-
-(def ^{:private true} special-counts
-  {Statement/EXECUTE_FAILED "EXECUTE_FAILED"
-   Statement/SUCCESS_NO_INFO "SUCCESS_NO_INFO"})
-
-(defn print-update-counts
-  "Prints the update counts from a BatchUpdateException to *out*"
-  [^BatchUpdateException exception]
-  (println "Update counts:")
-  (dorun
-   (map-indexed
-    (fn [index count]
-      (println (format " Statement %d: %s"
-                       index
-                       (get special-counts count count))))
-    (.getUpdateCounts exception))))
-
-;; java.jdbc pieces rewritten to not use dynamic bindings
-
-(defn db-find-connection
-  "Returns the current database connection (or nil if there is none)"
-  ^java.sql.Connection [db]
-  (and (map? db)
-       (:connection db)))
-
-(defn db-connection
-  "Returns the current database connection (or throws if there is none)"
-  ^java.sql.Connection [db]
-  (or (db-find-connection db)
-      (throw (Exception. "no current database connection"))))
-
-(defn db-set-rollback-only!
-  "Marks the outermost transaction such that it will rollback rather than
-  commit when complete"
-  [db]
-  (reset! (:rollback db) true))
-
-(defn db-unset-rollback-only!
-  "Marks the outermost transaction such that it will not rollback when complete"
-  [db]
-  (reset! (:rollback db) false))
-
-(defn db-is-rollback-only
-  "Returns true if the outermost transaction will rollback rather than
-  commit when complete"
-  [db]
-  (deref (:rollback db)))
-
-(def ^:private
-  isolation-levels
-  "Transaction isolation levels."
-  {:none             java.sql.Connection/TRANSACTION_NONE
-   :read-committed   java.sql.Connection/TRANSACTION_READ_COMMITTED
-   :read-uncommitted java.sql.Connection/TRANSACTION_READ_UNCOMMITTED
-   :repeatable-read  java.sql.Connection/TRANSACTION_REPEATABLE_READ
-   :serializable     java.sql.Connection/TRANSACTION_SERIALIZABLE})
-
-(def ^:private isolation-kws
-  "Map transaction isolation constants to our keywords."
-  (set/map-invert isolation-levels))
-
-(defn get-isolation-level
-  "Given a db-spec (with an optional connection), return the current
-  transaction isolation level, if known. Return nil if there is no
-  active connection in the db-spec. Return :unknown if we do not
-  recognize the isolation level."
-  [db]
-  (when-let [con (db-find-connection db)]
-    (isolation-kws (.getTransactionIsolation con) :unknown)))
-
-(defn db-transaction*
-  "Evaluates func as a transaction on the open database connection. Any
-  nested transactions are absorbed into the outermost transaction. By
-  default, all database updates are committed together as a group after
-  evaluating the outermost body, or rolled back on any uncaught
-  exception. If rollback is set within scope of the outermost transaction,
-  the entire transaction will be rolled back rather than committed when
-  complete.
-  The isolation option may be :none, :read-committed, :read-uncommitted,
-  :repeatable-read, or :serializable. Note that not all databases support
-  all of those isolation levels, and may either throw an exception or
-  substitute another isolation level.
-  The read-only? option puts the transaction in readonly mode (if supported)."
-  ([db func] (db-transaction* db func {}))
-  ([db func opts]
-   (let [{:keys [isolation read-only?] :as opts}
-         (merge (when (map? db) db) opts)]
-     (if (zero? (get-level db))
-       (if-let [con (db-find-connection db)]
-         (let [nested-db (inc-level db)
-               auto-commit   (.getAutoCommit con)
-               old-isolation (.getTransactionIsolation con)
-               old-readonly  (.isReadOnly con)
-               restore-ac?   (volatile! true)]
-           (io!
-            (when isolation
-              (.setTransactionIsolation con (isolation isolation-levels)))
-            (when read-only?
-              (.setReadOnly con true))
-            (.setAutoCommit con false)
-            (try
-              (let [result (func nested-db)]
-                (if (db-is-rollback-only nested-db)
-                  (do
-                    ;; per JDBC-179: if the rollback operation fails, we do not
-                    ;; want to try to restore auto-commit...
-                    (vreset! restore-ac? false)
-                    (.rollback con)
-                    (vreset! restore-ac? true))
-                  (.commit con))
-                result)
-              (catch Throwable t
-                (try
-                  ;; per JDBC-179: if the rollback operation fails, we do not
-                  ;; want to try to restore auto-commit...
-                  (vreset! restore-ac? false)
-                  (.rollback con)
-                  (vreset! restore-ac? true)
-                  (catch Throwable rb
-                    ;; combine both exceptions
-                    (throw (ex-info (str "Rollback failed handling \""
-                                         (.getMessage t)
-                                         "\"")
-                                    {:rollback rb
-                                     :handling t}))))
-                (throw t))
-              (finally
-                (db-unset-rollback-only! nested-db)
-                ;; the following can throw SQLExceptions but we do not
-                ;; want those to replace any exception currently being
-                ;; handled -- and if the connection got closed, we just
-                ;; want to ignore exceptions here anyway
-                (when @restore-ac?
-                  (try ; only restore auto-commit if rollback did not fail
-                    (.setAutoCommit con auto-commit)
-                    (catch Exception _)))
-                (when isolation
-                  (try
-                    (.setTransactionIsolation con old-isolation)
-                    (catch Exception _)))
-                (when read-only?
-                  (try
-                    (.setReadOnly con old-readonly)
-                    (catch Exception _)))))))
-         ;; avoid confusion of read-only? TX and read-only? connection:
-         (with-open [con (get-connection db (dissoc opts :read-only?))]
-           (db-transaction* (add-connection db con) func opts)))
-       (do
-         (when (and isolation
-                    (let [con (db-find-connection db)]
-                      (not= (isolation isolation-levels)
-                            (.getTransactionIsolation con))))
-           (let [msg "Nested transactions may not have different isolation levels"]
-             (throw (IllegalStateException. msg))))
-         (func (inc-level db)))))))
-
-(defmacro with-db-transaction
-  "Evaluates body in the context of a transaction on the specified database connection.
-  The binding provides the database connection for the transaction and the name to which
-  that is bound for evaluation of the body. The binding may also specify the isolation
-  level for the transaction, via the :isolation option and/or set the transaction to
-  readonly via the :read-only? option.
-  (with-db-transaction [t-con db-spec {:isolation level :read-only? true}]
-    ... t-con ...)
-  See db-transaction* for more details."
-  [binding & body]
-  `(db-transaction* ~(second binding)
-                    (^{:once true} fn* [~(first binding)] ~@body)
-                    ~@(rest (rest binding))))
-
-(defmacro with-db-connection
-  "Evaluates body in the context of an active connection to the database.
-  (with-db-connection [con-db db-spec opts]
-    ... con-db ...)"
-  [binding & body]
-  `(let [db-spec# ~(second binding) opts# ~(or (second (rest binding)) {})]
-     (if (db-find-connection db-spec#)
-       (let [~(first binding) db-spec#]
-         ~@body)
-       (with-open [con# (get-connection db-spec# opts#)]
-         (let [~(first binding) (add-connection db-spec# con#)]
-           ~@body)))))
-
-(defmacro with-db-metadata
-  "Evaluates body in the context of an active connection with metadata bound
-   to the specified name. See also metadata-result for dealing with the results
-   of operations that retrieve information from the metadata.
-   (with-db-metadata [md db-spec opts]
-     ... md ...)"
-  [binding & body]
-  `(let [db-spec# ~(second binding) opts# ~(or (second (rest binding)) {})]
-     (if-let [con# (db-find-connection db-spec#)]
-       (let [~(first binding) (.getMetaData con#)]
-         ~@body)
-       (with-open [con# (get-connection db-spec# opts#)]
-         (let [~(first binding) (.getMetaData con#)]
-           ~@body)))))
-
-(defn- process-result-set
-  "Given a Java ResultSet and options, produce a processed result-set-seq,
-  honoring as-arrays?, result-set-fn, and row-fn from opts."
-  [rset opts]
-  (let [{:keys [as-arrays? result-set-fn row-fn]}
-        (merge {:row-fn identity} opts)
-        result-set-fn (or result-set-fn (if as-arrays? vec doall))]
-    (if as-arrays?
-      ((^:once fn* [rs]
-         (result-set-fn (cons (first rs)
-                              (map row-fn (rest rs)))))
-       (result-set-seq rset opts))
-      (result-set-fn (map row-fn (result-set-seq rset opts))))))
-
-(defn metadata-result
-  "If the argument is a java.sql.ResultSet, turn it into a result-set-seq,
-  else return it as-is. This makes working with metadata easier.
-  Also accepts an option map containing :identifiers, :keywordize?, :qualifier,
-  :as-arrays?, :row-fn, and :result-set-fn to control how the ResultSet is
-  transformed and returned. See query for more details."
-  ([rs-or-value] (metadata-result rs-or-value {}))
-  ([rs-or-value opts]
-   (if (instance? java.sql.ResultSet rs-or-value)
-     (process-result-set rs-or-value opts)
-     rs-or-value)))
-
-(defmacro metadata-query
-  "Given a Java expression that extracts metadata (in the context of with-db-metadata),
-  and a map of options like metadata-result, manage the connection for a single
-  metadata-based query. Example usage:
-
-  (with-db-metadata [meta db-spec]
-    (metadata-query (.getTables meta nil nil nil (into-array String [\"TABLE\"]))
-      {:row-fn ... :result-set-fn ...}))"
-  [meta-query & opt-args]
-  `(with-open [rs# ~meta-query]
-     (metadata-result rs# ~@opt-args)))
-
-(defn db-do-commands
-  "Executes SQL commands on the specified database connection. Wraps the commands
-  in a transaction if transaction? is true. transaction? can be omitted and it
-  defaults to true. Accepts a single SQL command (string) or a vector of them.
-  Uses executeBatch. This may affect what SQL you can run via db-do-commands."
-  ([db sql-commands]
-   (db-do-commands db true (if (string? sql-commands) [sql-commands] sql-commands)))
-  ([db transaction? sql-commands]
-   (if (string? sql-commands)
-     (db-do-commands db transaction? [sql-commands])
-     (if-let [con (db-find-connection db)]
-       (with-open [^Statement stmt (.createStatement con)]
-         (doseq [^String cmd sql-commands]
-           (.addBatch stmt cmd))
-         (if transaction?
-           (with-db-transaction [t-db (add-connection db (.getConnection stmt))]
-             (execute-batch stmt))
-           (execute-batch stmt)))
-       (with-open [con (get-connection db)]
-         (db-do-commands (add-connection db con) transaction? sql-commands))))))
-
-(defn- db-do-execute-prepared-return-keys
-  "Executes a PreparedStatement, optionally in a transaction, and (attempts to)
-  return any generated keys.
-
-  Supports :multi? which causes a full result set sequence of keys to be
-  returned, and assumes the param-group is a sequence of parameter lists,
-  rather than a single sequence of parameters.
-
-  Also supports :row-fn and, if :multi? is truthy, :result-set-fn"
-  [db ^PreparedStatement stmt param-group opts]
-  (let [{:keys [as-arrays? multi? row-fn transaction?] :as opts}
-        (merge {:row-fn identity} (when (map? db) db) opts)
-        exec-and-return-keys
-        (^{:once true} fn* []
-         (let [counts (if multi?
-                        (.executeBatch stmt)
-                        (vector (.executeUpdate stmt)))]
-           (try
-             (let [rs (.getGeneratedKeys stmt)
-                   result (cond multi?
-                                (process-result-set rs opts)
-                                as-arrays?
-                                ((^:once fn* [rs]
-                                   (list (first rs)
-                                         (row-fn (second rs))))
-                                 (result-set-seq rs opts))
-                                :else
-                                (row-fn (first (result-set-seq rs opts))))]
-               ;; sqlite (and maybe others?) requires
-               ;; record set to be closed
-               (.close rs)
-               result)
-             (catch Exception _
-               ;; assume generated keys is unsupported and return counts instead:
-               (let [result-set-fn (or (:result-set-fn opts) doall)]
-                 (result-set-fn (map row-fn counts)))))))]
-    (if multi?
-      (doseq [params param-group]
-        ((:set-parameters opts dft-set-parameters) stmt params)
-        (.addBatch stmt))
-      ((:set-parameters opts dft-set-parameters) stmt param-group))
-    (if transaction?
-      (with-db-transaction [t-db (add-connection db (.getConnection stmt))]
-        (exec-and-return-keys))
-      (exec-and-return-keys))))
-
-(defn- sql-stmt?
-  "Given an expression, return true if it is either a string (SQL) or a
-  PreparedStatement."
-  [expr]
-  (or (string? expr) (instance? PreparedStatement expr)))
-
-(defn db-do-prepared-return-keys
-  "Executes an (optionally parameterized) SQL prepared statement on the
-  open database connection. The param-group is a seq of values for all of
-  the parameters. transaction? can be omitted and will default to true.
-  Return the generated keys for the (single) update/insert.
-  A PreparedStatement may be passed in, instead of a SQL string, in which
-  case :return-keys MUST BE SET on that PreparedStatement!"
-  ([db sql-params]
-   (db-do-prepared-return-keys db true sql-params {}))
-  ([db transaction? sql-params]
-   (if (map? sql-params)
-     (db-do-prepared-return-keys db true transaction? sql-params)
-     (db-do-prepared-return-keys db transaction? sql-params {})))
-  ([db transaction? sql-params opts]
-   (let [opts (merge (when (map? db) db) opts)
-         return-keys (or (:return-keys opts) true)]
-     (if-let [con (db-find-connection db)]
-       (let [[sql & params] (if (sql-stmt? sql-params) (vector sql-params) (vec sql-params))]
-         (if (instance? PreparedStatement sql)
-           (db-do-execute-prepared-return-keys db sql params (assoc opts :transaction? transaction?))
-           (with-open [^PreparedStatement stmt (prepare-statement
-                                                 con sql
-                                                 (assoc opts :return-keys return-keys))]
-             (db-do-execute-prepared-return-keys db stmt params (assoc opts :transaction? transaction?)))))
-       (with-open [con (get-connection db opts)]
-         (db-do-prepared-return-keys (add-connection db con) transaction? sql-params opts))))))
-
-(defn- db-do-execute-prepared-statement
-  "Execute a PreparedStatement, optionally in a transaction."
-  [db ^PreparedStatement stmt param-groups opts]
-  (let [{:keys [transaction?] :as opts} (merge (when (map? db) db) opts)]
-    (if (empty? param-groups)
-      (if transaction?
-        (with-db-transaction [t-db (add-connection db (.getConnection stmt))]
-          (vector (.executeUpdate stmt)))
-        (vector (.executeUpdate stmt)))
-      (do
-        (doseq [param-group param-groups]
-          ((:set-parameters opts dft-set-parameters) stmt param-group)
-          (.addBatch stmt))
-        (if transaction?
-          (with-db-transaction [t-db (add-connection db (.getConnection stmt))]
-            (execute-batch stmt))
-          (execute-batch stmt))))))
-
-(defn db-do-prepared
-  "Executes an (optionally parameterized) SQL prepared statement on the
-  open database connection. Each param-group is a seq of values for all of
-  the parameters. transaction? can be omitted and defaults to true.
-  The sql parameter can either be a SQL string or a PreparedStatement.
-  Return a seq of update counts (one count for each param-group)."
-  ([db sql-params]
-   (db-do-prepared db true sql-params {}))
-  ([db transaction? sql-params]
-   (if (map? sql-params)
-     (db-do-prepared db true transaction? sql-params)
-     (db-do-prepared db transaction? sql-params {})))
-  ([db transaction? sql-params opts]
-   (let [opts (merge (when (map? db) db) opts)]
-     (if-let [con (db-find-connection db)]
-       (let [[sql & params] (if (sql-stmt? sql-params) (vector sql-params) (vec sql-params))
-             params         (if (or (:multi? opts) (empty? params)) params [params])]
-         (if (instance? PreparedStatement sql)
-           (db-do-execute-prepared-statement db sql params (assoc opts :transaction? transaction?))
-           (with-open [^PreparedStatement stmt (prepare-statement con sql opts)]
-             (db-do-execute-prepared-statement db stmt params (assoc opts :transaction? transaction?)))))
-       (with-open [con (get-connection db opts)]
-         (db-do-prepared (add-connection db con) transaction? sql-params opts))))))
-
-(defn- execute-query-with-params
-  "Given a prepared statement, a set of parameters, a parameter setting
-  function, and a function to process the result set, execute the query and
-  apply the processing function."
-  [^PreparedStatement stmt params set-parameters func]
-  (set-parameters stmt params)
-  (with-open [rset (.executeQuery stmt)]
-    (func rset)))
-
-(defn- db-query-with-resultset*
-  "Given a db-spec, a SQL statement (or a prepared statement), a set of
-  parameters, a result set processing function and options, execute the query."
-  [db sql params func opts]
-  (if (instance? PreparedStatement sql)
-    (let [^PreparedStatement stmt sql]
-      (execute-query-with-params
-        stmt
-        params
-        (:set-parameters opts dft-set-parameters)
-        func))
-    (if-let [con (db-find-connection db)]
-      (with-open [^PreparedStatement stmt (prepare-statement con sql opts)]
-        (execute-query-with-params
-          stmt
-          params
-          (:set-parameters opts dft-set-parameters)
-          func))
-      (with-open [con (get-connection db opts)]
-        (with-open [^PreparedStatement stmt (prepare-statement con sql opts)]
-          (execute-query-with-params
-            stmt
-            params
-            (:set-parameters opts dft-set-parameters)
-            func))))))
-
-(defn db-query-with-resultset
-  "Executes a query, then evaluates func passing in the raw ResultSet as an
-   argument. The second argument is a vector containing either:
-    [sql & params] - a SQL query, followed by any parameters it needs
-    [stmt & params] - a PreparedStatement, followed by any parameters it needs
-                      (the PreparedStatement already contains the SQL query)
-  The opts map is passed to prepare-statement.
-  Uses executeQuery. This may affect what SQL you can run via query."
-  ([db sql-params func] (db-query-with-resultset db sql-params func {}))
-  ([db sql-params func opts]
-   (let [opts (merge (when (map? db) db) opts)
-         [sql & params] (if (sql-stmt? sql-params) (vector sql-params) (vec sql-params))]
-     (when-not (sql-stmt? sql)
-       (let [^Class sql-class (class sql)
-             ^String msg (format "\"%s\" expected %s %s, found %s %s"
-                                 "sql-params"
-                                 "vector"
-                                 "[sql param*]"
-                                 (.getName sql-class)
-                                 (pr-str sql))]
-         (throw (IllegalArgumentException. msg))))
-     (db-query-with-resultset* db sql params func opts))))
-
-;; top-level API for actual SQL operations
-
-(defn query
-  "Given a database connection and a vector containing SQL and optional parameters,
-  perform a simple database query. The options specify how to construct the result
-  set (and are also passed to prepare-statement as needed):
-    :as-arrays? - return the results as a set of arrays, default false.
-    :identifiers - applied to each column name in the result set, default lower-case
-    :keywordize? - defaults to true, can be false to opt-out of converting
-        identifiers to keywords
-    :qualifier - optionally provides the namespace qualifier for identifiers
-    :result-set-fn - applied to the entire result set, default doall / vec
-        if :as-arrays? true, :result-set-fn will default to vec
-        if :as-arrays? false, :result-set-fn will default to doall
-    :row-fn - applied to each row as the result set is constructed, default identity
-  The second argument is a vector containing a SQL string or PreparedStatement, followed
-  by any parameters it needs.
-  See also prepare-statement for additional options."
-  ([db sql-params] (query db sql-params {}))
-  ([db sql-params opts]
-   (let [{:keys [explain? explain-fn] :as opts}
-         (merge {:explain-fn println} (when (map? db) db) opts)
-         [sql & params] (if (sql-stmt? sql-params) (vector sql-params) (vec sql-params))]
-     (when-not (sql-stmt? sql)
-       (let [^Class sql-class (class sql)
-             ^String msg (format "\"%s\" expected %s %s, found %s %s"
-                                 "sql-params"
-                                 "vector"
-                                 "[sql param*]"
-                                 (.getName sql-class)
-                                 (pr-str sql))]
-         (throw (IllegalArgumentException. msg))))
-     (when (and explain? (string? sql))
-       (query db (into [(str (if (string? explain?) explain? "EXPLAIN")
-                             " "
-                             sql)]
-                       params)
-              (-> opts
-                  (dissoc :explain? :result-set-fn :row-fn)
-                  (assoc :result-set-fn explain-fn))))
-     (db-query-with-resultset* db sql params
-                               (^:once fn* [rset]
-                                 (process-result-set rset opts))
-                              opts))))
-
-(defn- get-rs-columns
-  "Given a set of indices, a result set's metadata, and a function to convert
-  SQL entity names to Clojure column names,
-  return the unique vector of column names."
-  [idxs ^ResultSetMetaData rsmeta identifier-fn]
-  (into [] (comp (map (fn [^Integer i] (.getColumnLabel rsmeta i)))
-                 make-cols-unique
-                 (map identifier-fn))
-        idxs))
-
-(defn- init-reduce-rs
-  "Given a sequence of columns, a result set, its metadata, a sequence of
-  indices, a mapping function to apply, an initial value, and a function that
-  can read column data from the result set, reduce the result set and
-  return the result of that reduction."
-  [cols ^ResultSet rs rsmeta idxs f init read-columns]
-  (loop [init' init]
-    (if (.next rs)
-      (let [result (f init' (zipmap cols (read-columns rs rsmeta idxs)))]
-        (if (reduced? result)
-          @result
-          (recur result)))
-      init')))
-
-(defn- reducible-result-set*
-  "Given a java.sql.ResultSet, indices, metadata, column names and a reader,
-  return a reducible collection.
-  Compiled with Clojure 1.7 or later -- uses clojure.lang.IReduce."
-  [^ResultSet rs idxs ^ResultSetMetaData rsmeta cols read-columns]
-  (reify clojure.lang.IReduce
-    (reduce [this f]
-            (if (.next rs)
-              ;; reduce init is first row of ResultSet
-              (init-reduce-rs cols rs rsmeta idxs f
-                              (zipmap cols (read-columns rs rsmeta idxs))
-                              read-columns)
-              ;; no rows so call 0-arity f to get result value
-              ;; per reduce docstring contract
-              (f)))
-    (reduce [this f init]
-            (init-reduce-rs cols rs rsmeta idxs f init read-columns))))
-
-(defn reducible-result-set
-  "Given a java.sql.ResultSet return a reducible collection.
-  Compiled with Clojure 1.7 or later -- uses clojure.lang.IReduce
-  Note: :as-arrays? is not accepted here."
-  [^ResultSet rs {:keys [identifiers keywordize? qualifier read-columns]
-                  :or {identifiers lower-case
-                       keywordize? true
-                       read-columns dft-read-columns}}]
-  (let [rsmeta (.getMetaData rs)
-        idxs (range 1 (inc (.getColumnCount rsmeta)))
-        cols (get-rs-columns idxs rsmeta
-                             (make-identifier-fn identifiers
-                                                 qualifier
-                                                 keywordize?))]
-    (reducible-result-set* rs idxs rsmeta cols read-columns)))
-
-(defn- query-reducer
-  "Given options, return a function of f (or f and init) that accepts a
-  result set and reduces it using f."
-  [identifiers keywordize? qualifier read-columns]
-  (let [identifier-fn (make-identifier-fn identifiers qualifier keywordize?)]
-    (fn
-      ([f]
-       (^{:once true} fn* [^ResultSet rs]
-         (let [rsmeta (.getMetaData rs)
-               idxs (range 1 (inc (.getColumnCount rsmeta)))
-               cols (get-rs-columns idxs rsmeta identifier-fn)]
-           (reduce f (reducible-result-set* rs idxs rsmeta cols read-columns)))))
-      ([f init]
-       (^{:once true} fn* [^ResultSet rs]
-         (let [rsmeta (.getMetaData rs)
-               idxs (range 1 (inc (.getColumnCount rsmeta)))
-               cols (get-rs-columns idxs rsmeta identifier-fn)]
-           (reduce f init (reducible-result-set* rs idxs rsmeta cols read-columns))))))))
-
-(defn- mapify-result-set
-  "Given a result set, return an object that wraps the current row as a hash
-  map. Note that a result set is mutable and the current row will change behind
-  this wrapper so operations need to be eager (and fairly limited).
-  Supports ILookup (keywords are treated as strings).
-  Supports Associative for lookup only (again, keywords are treated as strings).
-  Later we may realize a new hash map when assoc (and other, future, operations
-  are performed on the result set row)."
-  [^ResultSet rs]
-  (reify
-    clojure.lang.ILookup
-    (valAt [this k]
-           (try
-             (.getObject rs (name k))
-             (catch SQLException _)))
-    (valAt [this k not-found]
-           (try
-             (.getObject rs (name k))
-             (catch SQLException _
-               not-found)))
-    clojure.lang.Associative
-    (containsKey [this k]
-                 (try
-                   (.getObject rs (name k))
-                   true
-                   (catch SQLException _
-                     false)))
-    (entryAt [this k]
-             (try
-               (clojure.lang.MapEntry. k (.getObject rs (name k)))
-               (catch SQLException _)))
-    (assoc [this _ _]
-           (throw (ex-info "assoc not supported on raw result set" {})))))
-
-(defn- raw-query-reducer
-  "Given a function f and an initial value, return a function that accepts a
-  result set and reduces it using no translation. The result set is extended
-  to support ILookup and the readonly parts of Associative only."
-  [f init]
-  (^{:once true} fn* [^ResultSet rs]
-    (let [rs-map (mapify-result-set rs)]
-      (loop [init' init]
-        (if (.next rs)
-          (let [result (f init' rs-map)]
-            (if (reduced? result)
-              @result
-              (recur result)))
-          init')))))
-
-(defn reducible-query
-  "Given a database connection, a vector containing SQL and optional parameters,
-  return a reducible collection. When reduced, it will start the database query
-  and reduce the result set, and then close the connection:
-    (transduce (map :cost) + (reducible-query db sql-params))
-
-  The following options from query etc are not accepted here:
-    :as-arrays? :explain :explain-fn :result-set-fn :row-fn
-  See prepare-statement for additional options that may be passed through.
-
-  If :raw? true is specified, the rows of the result set are not converted to
-  hash maps, and it as if the following options were specified:
-    :identifiers identity :keywordize? false :qualifier nil
-  In addition, the rows of the result set may only be read as if they were hash
-  maps (get, keyword lookup, select-keys) but the sequence representation is
-  not available (so, no keys, no vals, and no seq calls). This is much faster
-  than converting each row to a hash map but it is also more restrictive."
-  ([db sql-params] (reducible-query db sql-params {}))
-  ([db sql-params opts]
-   (let [{:keys [identifiers keywordize? qualifier read-columns] :as opts}
-         (merge {:identifiers lower-case :keywordize? true
-                 :read-columns dft-read-columns}
-                (when (map? db) db)
-                opts)
-         [sql & params] (if (sql-stmt? sql-params) (vector sql-params) (vec sql-params))
-         reducing-fn (if (:raw? opts)
-                       raw-query-reducer
-                       (query-reducer identifiers keywordize? qualifier read-columns))]
-     (when-not (sql-stmt? sql)
-       (let [^Class sql-class (class sql)
-             ^String msg (format "\"%s\" expected %s %s, found %s %s"
-                                 "sql-params"
-                                 "vector"
-                                 "[sql param*]"
-                                 (.getName sql-class)
-                                 (pr-str sql))]
-         (throw (IllegalArgumentException. msg))))
-     (reify clojure.lang.IReduce
-       (reduce [this f]
-               (db-query-with-resultset*
-                 db sql params
-                 (reducing-fn f)
-                 opts))
-       (reduce [this f init]
-               (db-query-with-resultset*
-                 db sql params
-                 (reducing-fn f init)
-                 opts))))))
-
-(defn- direction
-  "Given an entities function, a column name, and a direction,
-  return the matching SQL column / order.
-  Throw an exception for an invalid direction."
-  [entities c d]
-  (str (as-sql-name entities c) " "
-       (if-let [dir (#{"ASC" "DESC"} (str/upper-case (name d)))]
-         dir
-         (throw (IllegalArgumentException. (str "expected :asc or :desc, found: " d))))))
-
-(defn- order-by-sql
-  "Given a sequence of column specs and an entities function, return
-  a SQL fragment for the ORDER BY clause. A column spec may be a name
-  (either a string or keyword) or a map from column name to direction
-  (:asc or :desc)."
-  [order-by entities]
-  (str/join ", " (mapcat (fn [col]
-                           (if (map? col)
-                             (reduce-kv (fn [v c d]
-                                          (conj v (direction entities c d)))
-                                        []
-                                        col)
-                             [(direction entities col :asc)])) order-by)))
-
-(defn find-by-keys
-  "Given a database connection, a table name, a map of column name/value
-  pairs, and an optional options map, return any matching rows.
-
-  An :order-by option may be supplied to sort the rows, e.g.,
-
-      {:order-by [{:name :asc} {:age :desc} {:income :asc}]}
-      ;; equivalent to:
-      {:order-by [:name {:age :desc} :income]}
-
-  The :order-by value is a sequence of column names (to sort in ascending
-  order) and/or maps from column names to directions (:asc or :desc). The
-  directions may be strings or keywords and are not case-sensitive. They
-  are mapped to ASC or DESC in the generated SQL.
-
-  Note: if a ordering map has more than one key, the order of the columns
-  in the generated SQL ORDER BY clause is unspecified (so such maps should
-  only contain one key/value pair)."
-  ([db table columns] (find-by-keys db table columns {}))
-  ([db table columns opts]
-   (let [{:keys [entities order-by] :as opts}
-         (merge {:entities identity} (when (map? db) db) opts)
-         ks (keys columns)
-         vs (vals columns)]
-     (query db (into [(str "SELECT * FROM " (table-str table entities)
-                           " WHERE " (str/join " AND "
-                                               (kv-sql ks vs entities " IS NULL"))
-                           (when (seq order-by)
-                             (str " ORDER BY "
-                                  (order-by-sql order-by entities))))]
-                     (remove nil? vs))
-            opts))))
-
-(defn get-by-id
-  "Given a database connection, a table name, a primary key value, an
-  optional primary key column name, and an optional options map, return
-  a single matching row, or nil.
-  The primary key column name defaults to :id."
-  ([db table pk-value] (get-by-id db table pk-value :id {}))
-  ([db table pk-value pk-name-or-opts]
-   (if (map? pk-name-or-opts)
-     (get-by-id db table pk-value :id pk-name-or-opts)
-     (get-by-id db table pk-value pk-name-or-opts {})))
-  ([db table pk-value pk-name opts]
-   (let [opts (merge (when (map? db) db) opts)
-         r-s-fn (or (:result-set-fn opts) identity)]
-     (find-by-keys db table {pk-name pk-value}
-                   (assoc opts :result-set-fn (comp first r-s-fn))))))
-
-(defn execute!
-  "Given a database connection and a vector containing SQL (or PreparedStatement)
-  followed by optional parameters, perform a general (non-select) SQL operation.
-
-  The :transaction? option specifies whether to run the operation in a
-  transaction or not (default true).
-
-  If the :multi? option is false (the default), the SQL statement should be
-  followed by the parameters for that statement.
-
-  If the :multi? option is true, the SQL statement should be followed by one or
-  more vectors of parameters, one for each application of the SQL statement.
-
-  If :return-keys is provided, db-do-prepared-return-keys will be called
-  instead of db-do-prepared, and the result will be a sequence of maps
-  containing the generated keys. If present, :row-fn will be applied. If :multi?
-  then :result-set-fn will also be applied if present. :as-arrays? may also be
-  specified (which will affect what :result-set-fn is passed).
-
-  If there are no parameters specified, executeUpdate will be used, otherwise
-  executeBatch will be used. This may affect what SQL you can run via execute!"
-  ([db sql-params] (execute! db sql-params {}))
-  ([db sql-params opts]
-   (let [{:keys [transaction? return-keys] :as opts}
-         (merge {:transaction? true :multi? false} (when (map? db) db) opts)
-         db-do-helper (if return-keys
-                        db-do-prepared-return-keys
-                        db-do-prepared)
-         execute-helper (^{:once true} fn* [db]
-                         (db-do-helper db transaction? sql-params opts))]
-     (if (db-find-connection db)
-       (execute-helper db)
-       (with-open [con (get-connection db opts)]
-         (execute-helper (add-connection db con)))))))
-
-(defn- delete-sql
-  "Given a table name, a where class and its parameters and an optional entities spec,
-  return a vector of the SQL for that delete operation followed by its parameters. The
-  entities spec (default 'as-is') specifies how to transform column names."
-  [table [where & params] entities]
-  (into [(str "DELETE FROM " (table-str table entities)
-              (when where " WHERE ") where)]
-        params))
-
-(defn delete!
-  "Given a database connection, a table name and a where clause of columns to match,
-  perform a delete. The options may specify how to transform column names in the
-  map (default 'as-is') and whether to run the delete in a transaction (default true).
-  Example:
-    (delete! db :person [\"zip = ?\" 94546])
-  is equivalent to:
-    (execute! db [\"DELETE FROM person WHERE zip = ?\" 94546])"
-  ([db table where-clause] (delete! db table where-clause {}))
-  ([db table where-clause opts]
-   (let [{:keys [entities] :as opts}
-         (merge {:entities identity :transaction? true} (when (map? db) db) opts)]
-     (execute! db (delete-sql table where-clause entities) opts))))
-
-(defn- multi-insert-helper
-  "Given a (connected) database connection and some SQL statements (for multiple
-   inserts), run a prepared statement on each and return any generated keys.
-   Note: we are eager so an unrealized lazy-seq cannot escape from the connection."
-  [db stmts opts]
-  (let [{:keys [as-arrays? result-set-fn]} (merge (when (map? db) db) opts)
-        per-statement (fn [stmt]
-                        (db-do-prepared-return-keys db false stmt opts))]
-    (if as-arrays?
-      (let [rs (map per-statement stmts)]
-        (cond (apply = (map first rs))
-              ;; all the columns are the same, rearrange to cols + rows format
-              ((or result-set-fn vec)
-               (cons (ffirst rs)
-                     (map second rs)))
-              result-set-fn
-              (throw (ex-info (str "Cannot apply result-set-fn to"
-                                   " non-homogeneous generated keys array")
-                              {:generated-keys rs}))
-              :else
-              ;; non-non-homogeneous generated keys array - return as-is
-              rs))
-      (if result-set-fn
-        (result-set-fn (map per-statement stmts))
-        (seq (mapv per-statement stmts))))))
-
-(defn- insert-helper
-  "Given a (connected) database connection, a transaction flag and some SQL statements
-   (for one or more inserts), run a prepared statement or a sequence of them."
-  [db transaction? stmts opts]
-  (if transaction?
-    (with-db-transaction [t-db db] (multi-insert-helper t-db stmts opts))
-    (multi-insert-helper db stmts opts)))
-
-(defn- col-str
-  "Transform a column spec to an entity name for SQL. The column spec may be a
-  string, a keyword or a map with a single pair - column name and alias."
-  [col entities]
-  (if (map? col)
-    (let [[k v] (first col)]
-      (str (as-sql-name entities k) " AS " (as-sql-name entities v)))
-    (as-sql-name entities col)))
-
-(defn- insert-multi-row-sql
-  "Given a table and a list of columns, followed by a list of column value sequences,
-  return a vector of the SQL needed for the insert followed by the list of column
-  value sequences. The entities function specifies how column names are transformed."
-  [table columns values entities]
-  (let [nc (count columns)
-        vcs (map count values)]
-    (if (not (and (or (zero? nc) (= nc (first vcs))) (apply = vcs)))
-      (throw (IllegalArgumentException. "insert! called with inconsistent number of columns / values"))
-      (into [(str "INSERT INTO " (table-str table entities)
-                  (when (seq columns)
-                    (str " ( "
-                         (str/join ", " (map (fn [col] (col-str col entities)) columns))
-                         " )"))
-                  " VALUES ( "
-                  (str/join ", " (repeat (first vcs) "?"))
-                  " )")]
-            values))))
-
-(defn- insert-single-row-sql
-  "Given a table and a map representing a row, return a vector of the SQL needed for
-  the insert followed by the list of column values. The entities function specifies
-  how column names are transformed."
-  [table row entities]
-  (let [ks (keys row)]
-    (into [(str "INSERT INTO " (table-str table entities) " ( "
-                (str/join ", " (map (fn [col] (col-str col entities)) ks))
-                " ) VALUES ( "
-                (str/join ", " (repeat (count ks) "?"))
-                " )")]
-          (vals row))))
-
-(defn- insert-rows!
-  "Given a database connection, a table name, a sequence of rows, and an options
-  map, insert the rows into the database."
-  [db table rows opts]
-  (let [{:keys [entities transaction?] :as opts}
-        (merge {:entities identity :identifiers lower-case
-                :keywordize? true :transaction? true}
-               (when (map? db) db)
-               opts)
-        sql-params (map (fn [row]
-                          (when-not (map? row)
-                            (throw (IllegalArgumentException. "insert! / insert-multi! called with a non-map row")))
-                          (insert-single-row-sql table row entities)) rows)]
-    (if (db-find-connection db)
-      (insert-helper db transaction? sql-params opts)
-      (with-open [con (get-connection db opts)]
-        (insert-helper (add-connection db con) transaction? sql-params opts)))))
-
-(defn- insert-cols!
-  "Given a database connection, a table name, a sequence of columns names, a
-  sequence of vectors of column values, one per row, and an options map,
-  insert the rows into the database."
-  [db table cols values opts]
-  (let [{:keys [entities transaction?] :as opts}
-        (merge {:entities identity :transaction? true} (when (map? db) db) opts)
-        sql-params (insert-multi-row-sql table cols values entities)]
-    (if (db-find-connection db)
-      (db-do-prepared db transaction? sql-params (assoc opts :multi? true))
-      (with-open [con (get-connection db opts)]
-        (db-do-prepared (add-connection db con) transaction? sql-params
-                        (assoc opts :multi? true))))))
-
-(defn insert!
-  "Given a database connection, a table name and either a map representing a rows,
-  or a list of column names followed by a list of column values also representing
-  a single row, perform an insert.
-  When inserting a row as a map, the result is the database-specific form of the
-  generated keys, if available (note: PostgreSQL returns the whole row).
-  When inserting a row as a list of column values, the result is the count of
-  rows affected (1), if available (from getUpdateCount after executeBatch).
-  The row map or column value vector may be followed by a map of options:
-  The :transaction? option specifies whether to run in a transaction or not.
-  The default is true (use a transaction). The :entities option specifies how
-  to convert the table name and column names to SQL entities."
-  ([db table row] (insert! db table row {}))
-  ([db table cols-or-row values-or-opts]
-   (if (map? values-or-opts)
-     (insert-rows! db table [cols-or-row] values-or-opts)
-     (insert-cols! db table cols-or-row [values-or-opts] {})))
-  ([db table cols values opts]
-   (insert-cols! db table cols [values] opts)))
-
-(defn insert-multi!
-  "Given a database connection, a table name and either a sequence of maps (for
-  rows) or a sequence of column names, followed by a sequence of vectors (for
-  the values in each row), and possibly a map of options, insert that data into
-  the database.
-
-  When inserting rows as a sequence of maps, the result is a sequence of the
-  generated keys, if available (note: PostgreSQL returns the whole rows). A
-  separate database operation is used for each row inserted. This may be slow
-  for if a large sequence of maps is provided.
-
-  When inserting rows as a sequence of lists of column values, the result is
-  a sequence of the counts of rows affected (a sequence of 1's), if available.
-  Yes, that is singularly unhelpful. Thank you getUpdateCount and executeBatch!
-  A single database operation should be used to insert all the rows at once.
-  This may be much faster than inserting a sequence of rows (which performs an
-  insert for each map in the sequence).
-
-  Note: some database drivers need to be told to rewrite the SQL for this to
-  be performed as a single, batched operation. In particular, PostgreSQL
-  requires :reWriteBatchedInserts true and My SQL requires
-  :rewriteBatchedStatement true (both non-standard JDBC options, of course!).
-  These options should be passed into the driver when the connection is
-  created (however that is done in your program).
-
-  The :transaction? option specifies whether to run in a transaction or not.
-  The default is true (use a transaction). The :entities option specifies how
-  to convert the table name and column names to SQL entities."
-  ([db table rows] (insert-rows! db table rows {}))
-  ([db table cols-or-rows values-or-opts]
-   (if (map? values-or-opts)
-     (insert-rows! db table cols-or-rows values-or-opts)
-     (insert-cols! db table cols-or-rows values-or-opts {})))
-  ([db table cols values opts]
-   (insert-cols! db table cols values opts)))
-
-(defn- update-sql
-  "Given a table name, a map of columns to set, a optional map of columns to
-  match, and an entities, return a vector of the SQL for that update followed
-  by its parameters. Example:
-    (update :person {:zip 94540} [\"zip = ?\" 94546] identity)
-  returns:
-    [\"UPDATE person SET zip = ? WHERE zip = ?\" 94540 94546]"
-  [table set-map [where & params] entities]
-  (let [ks (keys set-map)
-        vs (vals set-map)]
-    (cons (str "UPDATE " (table-str table entities)
-               " SET " (str/join
-                        ","
-                        (kv-sql ks vs entities " = NULL"))
-               (when where " WHERE ")
-               where)
-          (concat (remove nil? vs) params))))
-
-(defn update!
-  "Given a database connection, a table name, a map of column values to set and a
-  where clause of columns to match, perform an update. The options may specify
-  how column names (in the set / match maps) should be transformed (default
-  'as-is') and whether to run the update in a transaction (default true).
-  Example:
-    (update! db :person {:zip 94540} [\"zip = ?\" 94546])
-  is equivalent to:
-    (execute! db [\"UPDATE person SET zip = ? WHERE zip = ?\" 94540 94546])"
-  ([db table set-map where-clause] (update! db table set-map where-clause {}))
-  ([db table set-map where-clause opts]
-   (let [{:keys [entities] :as opts}
-         (merge {:entities identity :transaction? true} (when (map? db) db) opts)]
-     (execute! db (update-sql table set-map where-clause entities) opts))))
-
-(defn create-table-ddl
-  "Given a table name and a vector of column specs, return the DDL string for
-  creating that table. Each column spec is, in turn, a vector of keywords or
-  strings that is converted to strings and concatenated with spaces to form
-  a single column description in DDL, e.g.,
-    [:cost :int \"not null\"]
-    [:name \"varchar(32)\"]
-  The first element of a column spec is treated as a SQL entity (so if you
-  provide the :entities option, that will be used to transform it). The
-  remaining elements are left as-is when converting them to strings.
-  An options map may be provided that can contain:
-  :table-spec -- a string that is appended to the DDL -- and/or
-  :entities -- a function to specify how column names are transformed.
-  :conditional? -- either a boolean, indicating whether to add 'IF NOT EXISTS',
-    or a string, which is inserted literally before the table name, or a
-    function of two arguments (table name and the create statement), that can
-    manipulate the generated statement to better support other databases, e.g.,
-    MS SQL Server which need to wrap create table in an existence query."
-  ([table specs] (create-table-ddl table specs {}))
-  ([table specs opts]
-   (let [table-spec     (:table-spec opts)
-         conditional?   (:conditional? opts)
-         entities       (:entities   opts identity)
-         table-name     (as-sql-name entities table)
-         table-spec-str (or (and table-spec (str " " table-spec)) "")
-         stringify      (fn [x] (if (keyword? x) (name x) (str x)))
-         spec-to-string (fn [spec]
-                          (try
-                            (str/join " " (cons (as-sql-name entities (first spec))
-                                                (map stringify (rest spec))))
-                            (catch Exception _
-                              (throw (IllegalArgumentException.
-                                      "column spec is not a sequence of keywords / strings")))))]
-     (cond->> (format "CREATE TABLE%s %s (%s)%s"
-                      (cond (or (nil? conditional?)
-                                (instance? Boolean conditional?))
-                            (if conditional? " IF NOT EXISTS" "")
-                            (fn? conditional?)
-                            ""
-                            :else
-                            (str " " conditional?))
-                      table-name
-                      (str/join ", " (map spec-to-string specs))
-                      table-spec-str)
-       (fn? conditional?) (conditional? table-name)))))
-
-(defn drop-table-ddl
-  "Given a table name, return the DDL string for dropping that table.
-  An options map may be provided that can contain:
-  :entities -- a function to specify how column names are transformed.
-  :conditional? -- either a boolean, indicating whether to add 'IF EXISTS',
-    or a string, which is inserted literally before the table name, or a
-    function of two arguments (table name and the create statement), that can
-    manipulate the generated statement to better support other databases, e.g.,
-    MS SQL Server which need to wrap create table in an existence query."
-  ([table] (drop-table-ddl table {}))
-  ([table {:keys [entities conditional?] :or {entities identity}}]
-   (let [table-name (as-sql-name entities table)]
-     (cond->> (format "DROP TABLE%s %s"
-                      (cond (or (nil? conditional?)
-                                (instance? Boolean conditional?))
-                            (if conditional? " IF EXISTS" "")
-                            (fn? conditional?)
-                            ""
-                            :else
-                            (str " " conditional?))
-                      table-name)
-       (fn? conditional?) (conditional? table-name)))))
diff --git a/src/main/clojure/clojure/java/jdbc/datafy.clj b/src/main/clojure/clojure/java/jdbc/datafy.clj
deleted file mode 100644
index 10d61adc..00000000
--- a/src/main/clojure/clojure/java/jdbc/datafy.clj
+++ /dev/null
@@ -1,161 +0,0 @@
-;;  Copyright (c) 2018 Sean Corfield. All rights reserved.
-;;  The use and distribution terms for this software are covered by
-;;  the Eclipse Public License 1.0
-;;  (http://opensource.org/licenses/eclipse-1.0.php) which can be
-;;  found in the file epl-v10.html at the root of this distribution.
-;;  By using this software in any fashion, you are agreeing to be
-;;  bound by the terms of this license.  You must not remove this
-;;  notice, or any other, from this software.
-;;
-;;  datafy.clj
-;;
-;;  Exploring datafy and nav for JDBC databases
-
-(ns
-    ^{:author "Sean Corfield",
-      :doc "Variants of 'query' functions from clojure.java.jdbc that support
-           the new clojure.datafy functionality in Clojure 1.10.
-
-           The whole schema/column lookup piece is very likely to change!
-
-           Currently, the :schema option for a 'query' function is a mapping
-           from column name to a tuple of table name, key column, and optionally
-           the cardinality (:one -- the default -- or :many). The cardinality
-           determines whether navigation should produce a single row (hash map)
-           or a result set.
-
-           One of the problems is that the general case -- query -- doesn't
-           have any concept of an associated table name (and may of course
-           join across multiple tables), so there's no good way to take the
-           table name into account when mapping a column to another table.
-
-           For find-by-keys and get-by-id, you do have the starting table
-           name so you could map [table1 column1] to [table2 column2] and have
-           table-specific mappings.
-
-           The obvious, logical thing would be to use SQL metadata to figure
-           out actual foreign key constraints but not everyone uses them, for
-           a variety of reasons. For folks who do use them, they can build
-           their schema structure from the database, and pass the relevant
-           part of it to the functions below (via :schema in options)."}
-  clojure.java.jdbc.datafy
-  (:require [clojure.core.protocols :as p]
-            [clojure.java.jdbc :as jdbc]))
-
-(declare datafy-result-set)
-(declare datafy-row)
-
-(defn- default-schema
-  "The default schema lookup rule for column names.
-
-  If a column name ends with _id or id, it is assumed to be a foreign key
-  into the table identified by the first part of the column name."
-  [col]
-  (let [[_ table] (re-find #"^(.*?)_?id$" (name col))]
-    (when table
-      [(keyword table) :id])))
-
-(defn- schema-opt
-  "Returns the schema 'option'.
-
-  As with other clojure.java.jdbc options, it can be provided in the db-spec
-  hash map or in the options for a particular function call.
-
-  A schema can a simple map from column names to pairs of table name and
-  the key column to be used in that table. A schema can also be a function
-  that is called with column names and should return nil if the column is
-  not to be treated as a foreign key, or a pair of table name and the key
-  column within that table."
-  [db-spec opts]
-  (:schema (merge {:schema default-schema}
-                  (when (map? db-spec) db-spec)
-                  opts)))
-
-(defn- navize-row [db-spec opts row]
-  "Given a db-spec, a map of options, and a row -- a hash map -- return the
-  row with metadata that provides navigation via foreign keys."
-  (let [schema (schema-opt db-spec opts)]
-    (with-meta row
-         {`p/nav (fn [coll k v]
-                   (let [[table fk cardinality] (schema k)]
-                     (if fk
-                       (try
-                         (if (= :many cardinality)
-                           (datafy-result-set db-spec opts
-                                              (jdbc/find-by-keys db-spec table {fk v}))
-                           (datafy-row db-spec opts
-                                       (jdbc/get-by-id db-spec table v fk)))
-                         (catch Exception _
-                           ;; assume an exception means we just cannot
-                           ;; navigate anywhere, so return just the value
-                           v))
-                       v)))})))
-
-(defn- datafy-row [db-spec opts row]
-  "Given a db-spec, a map of options, and a row -- a hash map -- return the
-  row with metadata that provides datafication (which in turn provides).
-  navigation)."
-  (with-meta row {`p/datafy (partial navize-row db-spec opts)}))
-
-(defn- datafy-result-set [db-spec opts rs]
-  "Given a db-spec, a map of options, and a result set -- a sequence of hash
-  maps that represent rows -- return a sequence of datafiable rows."
-  (mapv (partial datafy-row db-spec opts) rs))
-
-(defn get-by-id
-  "Given a database connection, a table name, a primary key value, an
-  optional primary key column name, and an optional options map, return
-  a single matching row, or nil.
-  The primary key column name defaults to :id."
-  ([db table pk-value] (get-by-id db table pk-value :id {}))
-  ([db table pk-value pk-name-or-opts]
-   (if (map? pk-name-or-opts)
-     (get-by-id db table pk-value :id pk-name-or-opts)
-     (get-by-id db table pk-value pk-name-or-opts {})))
-  ([db table pk-value pk-name opts]
-   (datafy-row db opts
-               (jdbc/get-by-id db table pk-value pk-name opts))))
-
-(defn find-by-keys
-  "Given a database connection, a table name, a map of column name/value
-  pairs, and an optional options map, return any matching rows.
-
-  An :order-by option may be supplied to sort the rows, e.g.,
-
-      {:order-by [{:name :asc} {:age :desc} {:income :asc}]}
-      ;; equivalent to:
-      {:order-by [:name {:age :desc} :income]}
-
-  The :order-by value is a sequence of column names (to sort in ascending
-  order) and/or maps from column names to directions (:asc or :desc). The
-  directions may be strings or keywords and are not case-sensitive. They
-  are mapped to ASC or DESC in the generated SQL.
-
-  Note: if a ordering map has more than one key, the order of the columns
-  in the generated SQL ORDER BY clause is unspecified (so such maps should
-  only contain one key/value pair)."
-  ([db table columns] (find-by-keys db table columns {}))
-  ([db table columns opts]
-   (datafy-result-set db opts
-                      (jdbc/find-by-keys db table columns opts))))
-
-(defn query
-  "Given a database connection and a vector containing SQL and optional parameters,
-  perform a simple database query. The options specify how to construct the result
-  set (and are also passed to prepare-statement as needed):
-    :as-arrays? - return the results as a set of arrays, default false.
-    :identifiers - applied to each column name in the result set, default lower-case
-    :keywordize? - defaults to true, can be false to opt-out of converting
-        identifiers to keywords
-    :qualifier - optionally provides the namespace qualifier for identifiers
-    :result-set-fn - applied to the entire result set, default doall / vec
-        if :as-arrays? true, :result-set-fn will default to vec
-        if :as-arrays? false, :result-set-fn will default to doall
-    :row-fn - applied to each row as the result set is constructed, default identity
-  The second argument is a vector containing a SQL string or PreparedStatement, followed
-  by any parameters it needs.
-  See also prepare-statement for additional options."
-  ([db sql-params] (query db sql-params {}))
-  ([db sql-params opts]
-   (datafy-result-set db opts
-                      (jdbc/query db sql-params opts))))
diff --git a/src/main/clojure/clojure/java/jdbc/spec.clj b/src/main/clojure/clojure/java/jdbc/spec.clj
deleted file mode 100644
index eca21eaa..00000000
--- a/src/main/clojure/clojure/java/jdbc/spec.clj
+++ /dev/null
@@ -1,429 +0,0 @@
-;;  Copyright (c) 2016-2019 Sean Corfield. All rights reserved.
-;;  The use and distribution terms for this software are covered by
-;;  the Eclipse Public License 1.0
-;;  (http://opensource.org/licenses/eclipse-1.0.php) which can be
-;;  found in the file epl-v10.html at the root of this distribution.
-;;  By using this software in any fashion, you are agreeing to be
-;;  bound by the terms of this license.  You must not remove this
-;;  notice, or any other, from this software.
-;;
-;;  jdbc/spec.clj
-;;
-;;  Optional specifications for clojure.java.jdbc
-
-(ns ^{:author "Sean Corfield"
-      :doc "Optional specifications for use with Clojure 1.9 or later."}
-  clojure.java.jdbc.spec
-  (:require [clojure.spec.alpha :as s]
-            [clojure.java.jdbc :as sql]))
-
-(set! *warn-on-reflection* true)
-
-;; basic java.sql types -- cannot be generated!
-
-(s/def ::connection #(instance? java.sql.Connection %))
-(s/def ::datasource #(instance? javax.sql.DataSource %))
-(s/def ::prepared-statement #(instance? java.sql.PreparedStatement %))
-(s/def ::result-set #(instance? java.sql.ResultSet %))
-(s/def ::result-set-metadata #(instance? java.sql.ResultSetMetaData %))
-(s/def ::uri #(instance? java.net.URI %))
-
-;; database specification (connection description)
-
-(s/def ::subprotocol-base  #{"derby" "h2" "h2:mem" "hsqldb" "jtds:sqlserver" "mysql"
-                             "oracle:oci" "oracle:thin" "pgsql" "postgresql"
-                             "redshift" "sqlite" "sqlserver"})
-(s/def ::subprotocol-alias #{"hsql" "jtds" "mssql" "oracle" "postgres"})
-;; technically :subprotocol can be any string...
-(s/def ::subprotocol string?)
-;; ...but :dbtype must be a recognizable database type
-(s/def ::dbtype   (s/or :alias ::subprotocol-alias
-                        :name  ::subprotocol-base))
-(s/def ::dbname   string?)
-;; usually IP address or domain name but could be more general string
-;; (e.g., it could be username:password@domain.name)
-(s/def ::host     string?)
-;; usually a numeric port number, but could be an arbitrary string if
-;; the specified database accepts URIs constructed that way
-(s/def ::port     (s/or :port pos-int?
-                        :s    string?))
-(s/def ::subname  string?)
-;; will be a valid Java classname (including package)
-(s/def ::classname string?)
-(s/def ::factory  (s/fspec :args (s/cat :db-spec ::db-spec)
-                           :ret  ::connection))
-(s/def ::user     string?)
-(s/def ::username ::user) ; an alias
-(s/def ::password string?)
-(s/def ::name     string?)
-(s/def ::environment (s/nilable map?))
-;; raw connection-uri
-(s/def ::connection-uri string?)
-
-(s/def ::db-spec-connection (s/keys :req-un [::connection]))
-(s/def ::db-spec-friendly (s/keys :req-un [::dbtype ::dbname]
-                                  :opt-un [::host ::port ::user ::password
-                                           ::classname]))
-(s/def ::db-spec-raw (s/keys :req-un [::connection-uri]
-                             :opt-un [::user ::password]))
-(s/def ::db-spec-driver-manager (s/keys :req-un [::subprotocol ::subname]
-                                        :opt-un [::classname ::user ::password]))
-(s/def ::db-spec-factory (s/keys :req-un [::factory]))
-(s/def ::db-spec-data-source (s/keys :req-un [::datasource]
-                                     :opt-un [::username ::user ::password]))
-(s/def ::db-spec-jndi (s/keys :req-un [::name]
-                              :opt-un [::environment]))
-(s/def ::db-spec-string string?)
-(s/def ::db-spec-uri ::uri)
-(s/def ::db-spec (s/or :connection ::db-spec-connection
-                       :friendly   ::db-spec-friendly
-                       :raw        ::db-spec-raw
-                       :driver-mgr ::db-spec-driver-manager
-                       :factory    ::db-spec-factory
-                       :datasource ::db-spec-data-source
-                       :jndi       ::db-spec-jndi
-                       :uri-str    ::db-spec-string
-                       :uri-obj    ::db-spec-uri))
-
-;; naming
-
-(s/def ::entity string?)
-
-(s/def ::identifier (s/or :kw keyword? :s string?))
-
-;; SQL and parameters
-
-(s/def ::sql-stmt (s/or :sql string? :stmt ::prepared-statement))
-
-(s/def ::sql-value any?) ;; for now
-
-(s/def ::sql-params (s/or :sql        ::sql-stmt
-                          :sql-params (s/cat :sql ::sql-stmt :params (s/* ::sql-value))))
-
-(s/def ::where-clause (s/cat :where string? :params (s/* ::sql-value)))
-
-;; results
-
-(s/def ::execute-result (s/* integer?))
-
-;; specific options that can be passed
-;; a few of them are nilable, where the functions either pass a possibly nil
-;; version of the option to a called function, but most are not nilable because
-;; the corresponding options must either be omitted or given valid values
-
-(s/def ::as-arrays? (s/or :as-is #{:cols-as-is} :truthy (s/nilable boolean?)))
-(s/def ::auto-commit? boolean?)
-(s/def ::concurrency (set (keys @#'sql/result-set-concurrency)))
-(s/def ::cursors (set (keys @#'sql/result-set-holdability)))
-(s/def ::fetch-size nat-int?)
-;; note the asymmetry here: the identifiers function converts a SQL entity to
-;; an identifier (a symbol or a string), whereas the entities function converts
-;; a string (not an identifier) to a SQL entity; SQL entities are always strings
-;; but whilst java.jdbc lets you produce a keyword from identifiers, it does not
-;; assume that entities can accept keywords!
-(s/def ::identifiers (s/fspec :args (s/cat :s ::entity)
-                              :ret  ::identifier))
-(s/def ::isolation (set (keys @#'sql/isolation-levels)))
-(s/def ::entities (s/fspec :args (s/cat :s string?)
-                           :ret  ::entity))
-(s/def ::keywordize? boolean?)
-(s/def ::max-size nat-int?)
-(s/def ::multi? boolean?)
-;; strictly speaking we accept any keyword or string whose upper case name
-;; is either ASC or DESC so this spec is overly restrictive; the :id-dir
-;; can actually be an empty map although that is not very useful
-(s/def ::direction #{:asc :desc "asc" "desc" "ASC" "DESC"})
-(s/def ::column-direction (s/or :id ::identifier
-                                :id-dir (s/map-of ::identifier ::direction)))
-(s/def ::order-by (s/coll-of ::column-direction))
-(s/def ::qualifier (s/nilable string?))
-;; cannot generate a result set so we can't specify this yet
-#_(s/def ::read-columns (s/fspec :args (s/cat :rs     ::result-set
-                                              :rsmeta ::result-set-metadata
-                                              :idxs   (s/coll-of pos-int?))
-                                 :ret  (s/coll-of any?)))
-(s/def ::read-columns fn?)
-(s/def ::read-only? boolean?)
-;; there's not much we can say about result-set-fn -- it accepts a collection of
-;; transformed rows (from row-fn), and it produces whatever it wants
-(s/def ::result-set-fn (s/fspec :args (s/cat :rs (s/coll-of any?))
-                                :ret  any?))
-(s/def ::result-type (set (keys @#'sql/result-set-type)))
-;; there's not much we can say about row-fn -- it accepts a row from a ResultSet
-;; which is a map of keywords to SQL values, and it produces whatever it wants
-(s/def ::row-fn (s/fspec :args (s/cat :row (s/map-of keyword? ::sql-value))
-                         :ret  any?))
-(s/def ::return-keys (s/or :columns (s/coll-of ::entity :kind vector?)
-                           :boolean boolean?))
-(s/def ::table-spec string?)
-(s/def ::timeout nat-int?)
-(s/def ::transaction? boolean?)
-(s/def ::explain? (s/or :b boolean? :s string?))
-(s/def ::explain-fn fn?)
-(s/def ::conditional? (s/or :b boolean? :s string? :f fn?))
-
-;; various types of options
-
-(s/def ::exec-sql-options (s/keys :req-un [] :opt-un [::entities ::transaction?]))
-
-(s/def ::execute-options (s/keys :req-un [] :opt-un [::transaction? ::multi?
-                                                     ::return-keys]))
-
-(s/def ::find-by-keys-options (s/keys :req-un []
-                                      :opt-un [::entities ::order-by
-                                               ::result-set-fn ::row-fn
-                                               ::identifiers ::qualifier
-                                               ::keywordize?
-                                               ::as-arrays? ::read-columns]))
-
-(s/def ::connection-options (s/keys :req-un []
-                                    :opt-un [::auto-commit? ::read-only?]))
-
-(s/def ::prepare-options (s/merge (s/keys :req-un []
-                                          :opt-un [::return-keys ::result-type
-                                                   ::concurrency ::cursors ::fetch-size
-                                                   ::max-rows ::timeout])
-                                  ::connection-options))
-
-(s/def ::transaction-options (s/keys :req-un []
-                                     :opt-un [::isolation ::read-only?]))
-
-(s/def ::query-options (s/merge (s/keys :req-un []
-                                        :opt-un [::result-set-fn ::row-fn
-                                                 ::identifiers ::qualifier
-                                                 ::keywordize?
-                                                 ::as-arrays? ::read-columns])
-                                ::prepare-options))
-
-(s/def ::reducible-query-options (s/merge (s/keys :req-un []
-                                                  :opt-un [::identifiers
-                                                           ::keywordize?
-                                                           ::qualifier
-                                                           ::read-columns])
-                                          ::prepare-options))
-
-;; the function API
-
-(s/def ::naming-strategy (s/fspec :args (s/cat :x ::identifier)
-                                  :ret  ::identifier))
-
-(s/fdef sql/as-sql-name
-        :args (s/cat :f ::naming-strategy :x ::identifier)
-        :ret  ::identifier)
-
-(s/def ::delimiter (s/or :s string? :c char?))
-(s/fdef sql/quoted
-        :args (s/cat :q (s/or :pair      (s/coll-of ::delimiter
-                                                    :kind vector? :count 2)
-                              :delimiter ::delimiter
-                              :dialect   #{:ansi :mysql :sqlserver :oracle}))
-        :ret  ::naming-strategy)
-
-(s/fdef sql/get-connection
-        :args (s/cat :db-spec ::db-spec
-                     :opts    (s/? ::connection-options))
-        :ret  ::connection)
-
-(s/fdef sql/result-set-seq
-        :args (s/cat :rs   ::result-set
-                     :opts (s/? ::query-options))
-        :ret  any?)
-
-(s/fdef sql/prepare-statement
-        :args (s/cat :con  ::connection
-                     :sql  string?
-                     :opts (s/? ::prepare-options))
-        :ret  ::prepared-statement)
-
-;; print-sql-exception, print-sql-exception-chain, print-update-counts
-
-(s/fdef sql/db-find-connection
-        :args (s/cat :db-spec ::db-spec)
-        :ret  (s/nilable ::connection))
-
-(s/fdef sql/db-connection
-        :args (s/cat :db-spec ::db-spec)
-        :ret  ::connection)
-
-;; transaction functions
-
-(s/fdef sql/db-set-rollback-only!
-        :args (s/cat :db ::db-spec))
-
-(s/fdef sql/db-unset-rollback-only!
-        :args (s/cat :db ::db-spec))
-
-(s/fdef sql/db-is-rollback-only
-        :args (s/cat :db ::db-spec)
-        :ret  boolean?)
-
-(s/fdef sql/get-isolation-level
-        :args (s/cat :db ::db-spec)
-        :ret  (s/nilable (s/or :isolation ::isolation
-                               :unknown   #{:unknown})))
-
-(s/fdef sql/db-transaction*
-        :args (s/cat :db   ::db-spec
-                     :func ifn?
-                     :opts (s/? ::transaction-options))
-        :ret  any?)
-
-(s/def ::transaction-binding (s/spec (s/cat :t-con   simple-symbol?
-                                            :db-spec any?
-                                            :opts    (s/? any?))))
-
-(s/fdef sql/with-db-transaction
-        :args (s/cat :binding ::transaction-binding
-                     :body    (s/* any?)))
-
-(s/def ::connection-binding (s/spec (s/cat :con-db  simple-symbol?
-                                           :db-spec any?
-                                           :opts    (s/? any?))))
-
-(s/fdef sql/with-db-connection
-        :args (s/cat :binding ::connection-binding
-                     :body    (s/* any?)))
-
-(s/fdef sql/with-db-metadata
-        :args (s/cat :binding ::connection-binding
-                     :body    (s/* any?)))
-
-(s/fdef sql/metadata-result
-        :args (s/cat :rs-or-value any?
-                     :opts        (s/? ::query-options))
-        :ret  any?)
-
-(s/fdef sql/metadata-query
-        :args (s/cat :meta-query any?
-                     :opt-args   (s/? any?)))
-
-(s/fdef sql/db-do-commands
-        :args (s/cat :db           ::db-spec
-                     :transaction? (s/? boolean?)
-                     :sql-commands (s/or :command  string?
-                                         :commands (s/coll-of string?)))
-        :ret  any?)
-
-(s/fdef sql/db-do-prepared-return-keys
-        :args (s/cat :db           ::db-spec
-                     :transaction? (s/? boolean?)
-                     :sql-params   ::sql-params
-                     :opts         (s/? (s/merge ::execute-options ::query-options)))
-        :ret  any?)
-
-(s/fdef sql/db-do-prepared
-        :args (s/cat :db           ::db-spec
-                     :transaction? (s/? boolean?)
-                     :sql-params   ::sql-params
-                     ;; TODO: this set of options needs reviewing:
-                     :opts         (s/? (s/merge ::execute-options ::query-options)))
-        :ret  any?)
-
-(s/fdef sql/db-query-with-resultset
-        :args (s/cat :db           ::db-spec
-                     :sql-params   ::sql-params
-                     :func         ifn?
-                     :opts         (s/? ::query-options))
-        :ret  any?)
-
-(s/fdef sql/query
-        :args (s/cat :db         ::db-spec
-                     :sql-params ::sql-params
-                     :opts       (s/? (s/merge ::query-options
-                                               (s/keys :req-un []
-                                                       :opt-un [::explain?
-                                                                ::explain-fn]))))
-        :ret  any?)
-
-(s/fdef sql/reducible-result-set
-        :args (s/cat :rs   ::result-set
-                     :opts (s/? ::reducible-query-options))
-        :ret  any?)
-
-(s/fdef sql/reducible-query
-        :args (s/cat :db         ::db-spec
-                     :sql-params ::sql-params
-                     :opts       (s/? ::reducible-query-options))
-        :ret  any?)
-
-(s/fdef sql/find-by-keys
-        :args (s/cat :db      ::db-spec
-                     :table   ::identifier
-                     :columns (s/map-of ::identifier ::sql-value)
-                     :opts    (s/? ::find-by-keys-options))
-        :ret  any?)
-
-(s/fdef sql/get-by-id
-        :args (s/cat :db       ::db-spec
-                     :table    ::identifier
-                     :pk-value ::sql-value
-                     :opt-args (s/cat :pk-name (s/? ::identifier)
-                                      :opts    (s/? ::find-by-keys-options)))
-        :ret  any?)
-
-(s/fdef sql/execute!
-        :args (s/cat :db         ::db-spec
-                     :sql-params ::sql-params
-                     :opts       (s/? ::execute-options))
-        :ret  (s/or :rows ::execute-result
-                    :keys (s/coll-of map?)))
-
-(s/fdef sql/delete!
-        :args (s/cat :db           ::db-spec
-                     :table        ::identifier
-                     :where-clause (s/spec ::where-clause)
-                     :opts         (s/? ::exec-sql-options))
-        :ret  ::execute-result)
-
-(s/fdef sql/insert!
-        :args (s/or :row (s/cat :db    ::db-spec
-                                :table ::identifier
-                                :row   (s/map-of ::identifier any?)
-                                :opts  (s/? (s/merge ::execute-options ::query-options)))
-                    :cvs (s/cat :db    ::db-spec
-                                :table ::identifier
-                                :cols  (s/nilable (s/coll-of ::identifier))
-                                :vals  (s/coll-of any?)
-                                :opts  (s/? (s/merge ::execute-options ::query-options))))
-        :ret  any?)
-
-(s/fdef sql/insert-multi!
-        :args (s/or :rows (s/cat :db    ::db-spec
-                                 :table ::identifier
-                                 :rows  (s/coll-of (s/map-of ::identifier any?))
-                                 :opts  (s/? (s/merge ::execute-options ::query-options)))
-                    :cvs  (s/cat :db    ::db-spec
-                                 :table ::identifier
-                                 :cols  (s/nilable (s/coll-of ::identifier))
-                                 :vals  (s/coll-of (s/coll-of any?))
-                                 :opts  (s/? (s/merge ::execute-options ::query-options))))
-        :ret  any?)
-
-(s/fdef sql/update!
-        :args (s/cat :db           ::db-spec
-                     :table        ::identifier
-                     :set-map      (s/map-of ::identifier ::sql-value)
-                     :where-clause (s/spec ::where-clause)
-                     :opts         (s/? ::exec-sql-options))
-        :ret  ::execute-result)
-
-(s/def ::column-spec (s/cat :col ::identifier :spec (s/* (s/or :kw keyword?
-                                                               :str string?
-                                                               :num number?))))
-
-(s/fdef sql/create-table-ddl
-        :args (s/cat :table ::identifier
-                     :specs (s/coll-of ::column-spec)
-                     :opts  (s/? (s/keys :req-un []
-                                         :opt-un [::entities
-                                                  ::conditional?
-                                                  ::table-spec])))
-
-        :ret  string?)
-
-(s/fdef sql/drop-table-ddl
-        :args (s/cat :table ::identifier
-                     :opts  (s/? (s/keys :req-un []
-                                         :opt-un [::entities
-                                                  ::conditional?])))
-        :ret  string?)
diff --git a/src/perf/clojure/clojure/java/perf_jdbc.clj b/src/perf/clojure/clojure/java/perf_jdbc.clj
deleted file mode 100644
index 7e2cdffd..00000000
--- a/src/perf/clojure/clojure/java/perf_jdbc.clj
+++ /dev/null
@@ -1,244 +0,0 @@
-;;  Copyright (c) 2017 Tommmi Reiman, Sean Corfield. All rights reserved.
-;;  The use and distribution terms for this software are covered by
-;;  the Eclipse Public License 1.0
-;;  (http://opensource.org/licenses/eclipse-1.0.php) which can be
-;;  found in the file epl-v10.html at the root of this distribution.
-;;  By using this software in any fashion, you are agreeing to be
-;;  bound by the terms of this license.  You must not remove this
-;;  notice, or any other, from this software.
-
-(ns clojure.java.perf-jdbc
-  "Performance tests for parts of clojure.java.jdbc.
-
-  Here's how to run these tests:
-
-  $ clj -A:test:perf
-  Clojure 1.9.0
-  user=> (require '[clojure.java.perf-jdbc :as p])
-  nil
-  user=> (p/calibrate)
-  ...
-  nil
-  user=> (p/test-dummy)
-  ...
-  nil
-  user=> (p/test-h2)
-  ...
-  nil
-  user=>
-
-  These test compare the raw performance (against an in-memory H2 database)
-  for hand-crafted Java JDBC calls and various `query` and `reducible-query`
-  calls."
-  (:require [criterium.core :as cc]
-            [clojure.java.jdbc :as sql])
-  (:import (java.sql Connection PreparedStatement ResultSet Statement ResultSetMetaData)))
-
-(defn calibrate []
-  ;; 840ms
-  (cc/quick-bench (reduce + (take 10e6 (range)))))
-
-(def db
-  "Note: loading this namespace creates a connection to the H2 database!"
-  {:connection (sql/get-connection "jdbc:h2:mem:test_mem")})
-
-(defn create-table! [db]
-  (sql/db-do-commands
-    db (sql/create-table-ddl
-         :fruit
-         [[:id :int "DEFAULT 0"]
-          [:name "VARCHAR(32)" "PRIMARY KEY"]
-          [:appearance "VARCHAR(32)"]
-          [:cost :int]
-          [:grade :real]]
-         {:table-spec ""})))
-
-(defn- drop-table! [db]
-  (doseq [table [:fruit :fruit2 :veggies :veggies2]]
-    (try
-      (sql/db-do-commands db (sql/drop-table-ddl table))
-      (catch java.sql.SQLException _))))
-
-(defn add-stuff! [db]
-  (sql/insert-multi! db
-                     :fruit
-                     nil
-                     [[1 "Apple" "red" 59 87]
-                      [2 "Banana" "yellow" 29 92.2]
-                      [3 "Peach" "fuzzy" 139 90.0]
-                      [4 "Orange" "juicy" 89 88.6]]))
-
-(def dummy-con
-  (reify
-    Connection
-    (createStatement [_]
-      (reify
-        Statement
-        (addBatch [_ _])))
-    (prepareStatement [_ _]
-      (reify
-        PreparedStatement
-        (setObject [_ _ _])
-        (setString [_ _ _])
-        (close [_])
-        (executeQuery [_]
-          (reify
-            ResultSet
-            (getMetaData [_]
-              (reify
-                ResultSetMetaData
-                (getColumnCount [_] 1)
-                (getColumnLabel [_ _] "name")))
-            (next [_] true)
-            (close [_])
-            (^Object getObject [_ ^int s]
-              "Apple")
-            (^Object getObject [_ ^String s]
-              "Apple")
-            (^String getString [_ ^String s]
-              "Apple")))))))
-
-(defn select [db]
-  (sql/query db ["SELECT * FROM fruit WHERE appearance = ?" "red"]
-             {:row-fn :name :result-set-fn first}))
-
-(defn select-p [db ps]
-  (sql/query db [ps "red"]
-             {:row-fn :name :result-set-fn first}))
-
-(defn select* [^Connection con]
-  (let [ps (doto (.prepareStatement con "SELECT * FROM fruit WHERE appearance = ?")
-             (.setObject 1 "red"))
-        rs (.executeQuery ps)
-        _ (.next rs)
-        value (.getObject rs "name")]
-    (.close ps)
-    value))
-
-(defn test-dummy []
-  (do
-    (let [db {:connection dummy-con}]
-      (assert (= "Apple" (select db)))
-      ;(time (dotimes [_ 100000] (select db)))
-
-      ; 3.029268 ms (3030 ns)
-      (cc/quick-bench (dotimes [_ 1000] (select db))))
-
-    (let [con dummy-con]
-      (assert (= "Apple" (select* con)))
-      ;(time (dotimes [_ 100000] (select* con)))
-
-      ;  716.661522 ns (0.7ns) -> 4300x faster
-      (cc/quick-bench (dotimes [_ 1000] (select* con))))))
-
-(defn test-h2 []
-  (do
-    (drop-table! db)
-    (create-table! db)
-    (add-stuff! db)
-
-    (println "Basic select...")
-    (let [db db]
-      (assert (= "Apple" (select db)))
-      (cc/quick-bench (select db)))
-
-    (println "Basic select first rs...")
-    (let [db db]
-      (cc/quick-bench (sql/query db ["SELECT * FROM fruit WHERE appearance = ?" "red"]
-                                 {:result-set-fn first :qualifier "fruit"})))
-
-    (println "Select with prepared statement...")
-    (let [con (:connection db)]
-      (with-open [ps (sql/prepare-statement con "SELECT * FROM fruit WHERE appearance = ?")]
-        (assert (= "Apple" (select-p db ps)))
-        (cc/quick-bench (select-p db ps))))
-
-    (println "Reducible query...")
-    (let [db db
-          rq (sql/reducible-query db ["SELECT * FROM fruit WHERE appearance = ?" "red"])]
-      (assert (= "Apple" (reduce (fn [_ row] (reduced (:name row)))
-                                 nil rq)))
-      (cc/quick-bench (reduce (fn [_ row] (reduced (:name row)))
-                              nil rq)))
-
-    (println "Reducible query with prepared statement...")
-    (let [con (:connection db)]
-      (with-open [ps (sql/prepare-statement con "SELECT * FROM fruit WHERE appearance = ?")]
-        (let [rq (sql/reducible-query db [ps "red"])]
-          (assert (= "Apple" (reduce (fn [_ row] (reduced (:name row)))
-                                     nil rq)))
-          (cc/quick-bench (reduce (fn [_ row] (reduced (:name row)))
-                                  nil rq)))))
-
-    (println "Reducible query with prepared statement and simple identifiers...")
-    (let [con (:connection db)]
-      (with-open [ps (sql/prepare-statement con "SELECT * FROM fruit WHERE appearance = ?")]
-        (let [rq (sql/reducible-query db [ps "red"]
-                                      {:keywordize? false :identifiers identity})]
-          (assert (= "Apple" (reduce (fn [_ row] (reduced (get row "NAME")))
-                                     nil rq)))
-          (cc/quick-bench (reduce (fn [_ row] (reduced (get row "NAME")))
-                                  nil rq)))))
-
-    (println "Reducible query with prepared statement and raw result set...")
-    (let [con (:connection db)]
-      (with-open [ps (sql/prepare-statement con "SELECT * FROM fruit WHERE appearance = ?")]
-        (let [rq (sql/reducible-query db [ps "red"] {:raw? true})]
-          (assert (= "Apple" (reduce (fn [_ row] (reduced (:name row)))
-                                     nil rq)))
-          (cc/quick-bench (reduce (fn [_ row] (reduced (:name row)))
-                                  nil rq)))))
-
-    (println "Reducible query with raw result set...")
-    (let [db db
-          rq (sql/reducible-query
-              db
-              ["SELECT * FROM fruit WHERE appearance = ?" "red"]
-              {:raw? true})]
-      (assert (= "Apple" (reduce (fn [_ row] (reduced (:name row)))
-                                 nil rq)))
-      (cc/quick-bench (reduce (fn [_ row] (reduced (:name row)))
-                              nil rq)))
-
-    (println "Repeated reducible query with raw result set...")
-    (let [db db]
-      (assert (= "Apple" (reduce (fn [_ row] (reduced (:name row)))
-                                 nil (sql/reducible-query
-                                      db
-                                      ["SELECT * FROM fruit WHERE appearance = ?" "red"]
-                                      {:raw? true}))))
-      (cc/quick-bench (reduce (fn [_ row] (reduced (:name row)))
-                              nil (sql/reducible-query
-                                   db
-                                   ["SELECT * FROM fruit WHERE appearance = ?" "red"]
-                                   {:raw? true}))))
-
-    (println "Raw Java...")
-    (let [con (:connection db)]
-      (assert (= "Apple" (select* con)))
-      (cc/quick-bench (select* con)))))
-
-(comment
-  (calibrate)
-  (test-dummy)
-  (test-h2)
-  ;; The following are just some things I was double-checking while adding
-  ;; to Tommi's original tests -- Sean.
-  ;; Shows the row is a reify instance, but you can select by key:
-  (reduce (fn [_ row] (println row) (reduced (:name row)))
-          nil (sql/reducible-query
-               db
-               ["SELECT * FROM fruit WHERE appearance = ?" "red"]
-               {:raw? true}))
-  ;; Shows you can construct a map result using select-keys:
-  (reduce (fn [_ row] (reduced (select-keys row [:cost])))
-          nil (sql/reducible-query
-               db
-               ["SELECT * FROM fruit WHERE appearance = ?" "red"]
-               {:raw? true}))
-  ;; Shows you can reconstruct an entire result set (with very little overhead):
-  (transduce (map #(select-keys % [:id :name :cost :appearance :grade]))
-             conj [] (sql/reducible-query
-                      db
-                      "SELECT * FROM fruit"
-                      {:raw? true})))
diff --git a/src/test/clojure/clojure/java/jdbc/utilities_test.clj b/src/test/clojure/clojure/java/jdbc/utilities_test.clj
deleted file mode 100644
index 886b7cfa..00000000
--- a/src/test/clojure/clojure/java/jdbc/utilities_test.clj
+++ /dev/null
@@ -1,96 +0,0 @@
-;;  Copyright (c) 2008-2017 Sean Corfield, Stephen C. Gilardi.
-;;                                       All rights reserved.  The use and
-;;  distribution terms for this software are covered by the Eclipse Public
-;;  License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which can
-;;  be found in the file epl-v10.html at the root of this distribution.  By
-;;  using this software in any fashion, you are agreeing to be bound by the
-;;  terms of this license.  You must not remove this notice, or any other,
-;;  from this software.
-;;
-;;  test_utilities.clj
-;;
-;;  This namespace contains tests of all the utility functions within java.jdbc
-;;  and does not rely on any databases.
-;;
-;;  scgilardi (gmail)
-;;  Created 13 September 2008
-;;
-;;  seancorfield (gmail)
-;;  Migrated from clojure.contrib.test-sql 17 April 2011
-
-(ns clojure.java.jdbc.utilities-test
-  (:use clojure.test)
-  (:require [clojure.java.jdbc :as sql]))
-
-(deftest test-print-update-counts
-  (let [bu-ex (java.sql.BatchUpdateException. (int-array [1 2 3]))]
-    (let [e (is (thrown? java.sql.BatchUpdateException (throw bu-ex)))
-          counts-str (with-out-str (sql/print-update-counts e))]
-      (is (re-find #"^Update counts" counts-str))
-      (is (re-find #"Statement 0: 1" counts-str))
-      (is (re-find #"Statement 2: 3" counts-str)))))
-
-(deftest test-print-exception-chain
-  (let [base-ex (java.sql.SQLException. "Base Message" "Base State")
-        test-ex (java.sql.BatchUpdateException. "Test Message" "Test State" (int-array [1 2 3]))]
-    (.setNextException test-ex base-ex)
-    (let [e (is (thrown? java.sql.BatchUpdateException (throw test-ex)))
-          except-str (with-out-str (sql/print-sql-exception-chain e))
-          pattern (fn [s] (java.util.regex.Pattern/compile s java.util.regex.Pattern/DOTALL))]
-      (is (re-find (pattern "^BatchUpdateException:.*SQLException:") except-str))
-      (is (re-find (pattern "Message: Test Message.*Message: Base Message") except-str))
-      (is (re-find (pattern "SQLState: Test State.*SQLState: Base State") except-str)))))
-
-(deftest test-make-cols-unique
-  (let [make-cols-unique @#'sql/make-cols-unique]
-    (is (= []
-           (into [] make-cols-unique [])))
-    (is (= ["a"]
-           (into [] make-cols-unique ["a"])))
-    (is (= ["a" "a_2"]
-           (into [] make-cols-unique ["a" "a"])))
-    (is (= ["a" "b" "a_2" "a_3"]
-           (into [] make-cols-unique ["a" "b" "a" "a"])))
-    (is (= ["a" "b" "a_2" "b_2" "a_3" "b_3"]
-           (into [] make-cols-unique ["a" "b" "a" "b" "a" "b"])))))
-
-;; DDL tests
-
-(deftest test-create-table-ddl
-  (is (= "CREATE TABLE THING (COL1 INT, COL2 int)"
-         (sql/create-table-ddl :thing [["col1 int"] [:col2 :int]]
-                               {:entities clojure.string/upper-case})))
-  (is (= "CREATE TABLE THING (COL1 int, COL2 int) ENGINE=MyISAM"
-         (sql/create-table-ddl :thing [[:col1 "int"] ["col2" :int]]
-                               {:table-spec "ENGINE=MyISAM"
-                                :entities clojure.string/upper-case}))))
-
-;; since we have clojure.spec instrumentation enabled for Clojure 1.9.0
-;; we need to account for the fact that we'll get different exceptions
-;; for Clojure < 1.9.0 since the spec will trigger first and obscure
-;; our own argument checking on 1.9.0+
-
-(defn argument-exception?
-  "Given a thunk, try to execute it and return true if it throws
-  either an IllegalArgumentException or a Clojure exception from
-  clojure.spec."
-  [thunk]
-  (try
-    (thunk)
-    false
-    (catch IllegalArgumentException _ true)
-    (catch clojure.lang.ExceptionInfo e
-      (re-find #"did not conform to spec" (.getMessage e)))))
-
-(deftest test-invalid-create-table-ddl
-  (is (argument-exception? (fn [] (sql/create-table-ddl :thing [[]]))))
-  (is (argument-exception? (fn [] (sql/create-table-ddl :thing [[:col1 "int"] []]))))
-  (is (argument-exception? (fn [] (sql/create-table-ddl :thing [:col1 "int"])))))
-
-(deftest test-quoted
-  (is (= "`x`" ((sql/quoted \`) "x")))
-  (is (= "[x]" ((sql/quoted [\[ \]]) "x")))
-  (is (= "`x`" ((sql/quoted :mysql) "x")))
-  (is (= "\"x\"" ((sql/quoted :ansi) "x")))
-  (is (= "\"x\"" ((sql/quoted :oracle) "x")))
-  (is (= "[x]" ((sql/quoted :sqlserver) "x"))))
diff --git a/src/test/clojure/clojure/java/jdbc_test.clj b/src/test/clojure/clojure/java/jdbc_test.clj
deleted file mode 100644
index f8b11819..00000000
--- a/src/test/clojure/clojure/java/jdbc_test.clj
+++ /dev/null
@@ -1,1358 +0,0 @@
-;;  Copyright (c) Stephen C. Gilardi, Sean Corfield. All rights reserved.
-;;  The use and distribution terms for this software are covered by the Eclipse
-;;  Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) which
-;;  can be found in the file epl-v10.html at the root of this distribution. By
-;;  using this software in any fashion, you are agreeing to be bound by the
-;;  terms of this license. You must not remove this notice, or any other,
-;;  from this software.
-;;
-;;  test_jdbc.clj
-;;
-;;  This namespace contains tests that exercise the JDBC portion of java.jdbc
-;;  so these tests expect databases to be available. Embedded databases can
-;;  be tested without external infrastructure (Apache Derby, HSQLDB). Other
-;;  databases will be available for testing in different environments. The
-;;  available databases for testing can be configured below.
-;;
-;;  scgilardi (gmail)
-;;  Created 13 September 2008
-;;
-;;  seancorfield (gmail)
-;;  Migrated from clojure.contrib.test-sql 17 April 2011
-
-(ns clojure.java.jdbc-test
-  (:require [clojure.test :refer [deftest is use-fixtures]]
-            [clojure.java.jdbc :as sql]
-            [clojure.string :as str]))
-
-(println "\nTesting with Clojure" (clojure-version))
-(def with-spec? (try
-                  (require 'clojure.java.jdbc.spec)
-                  (require 'clojure.spec.test.alpha)
-                  ;; require this to workaround rebinding of report multi-fn
-                  (require 'clojure.test.check.clojure-test)
-                  (let [syms ((resolve 'clojure.spec.test.alpha/enumerate-namespace) 'clojure.java.jdbc)]
-                    ((resolve 'clojure.spec.test.alpha/instrument) syms))
-                  (println "Instrumenting clojure.java.jdbc with clojure.spec")
-                  true
-                  (catch Exception _
-                    false)))
-
-;; Set test-databases according to whether you have the local database available:
-;; Possible values so far: [:mysql :postgres :derby :hsqldb :mysql-str :postgres-str]
-;; Apache Derby and HSQLDB can run without an external setup.
-(def test-databases
-  (if-let [dbs (System/getenv "TEST_DBS")]
-    (map keyword (.split dbs " "))
-    ;; enable more by default once the build server is equipped?
-    [:derby :hsqldb :h2 :sqlite]))
-
-;; MS SQL Server requires more specialized configuration:
-(def mssql-host   (or (System/getenv "TEST_MSSQL_HOST") "127.0.0.1\\SQLEXPRESS"))
-(def mssql-port   (or (System/getenv "TEST_MSSQL_PORT") "1433"))
-(def mssql-user   (or (System/getenv "TEST_MSSQL_USER") "sa"))
-(def mssql-pass   (or (System/getenv "TEST_MSSQL_PASS") ""))
-(def mssql-dbname (or (System/getenv "TEST_MSSQL_NAME") "clojure_test"))
-(def jtds-host    (or (System/getenv "TEST_JTDS_HOST") mssql-host))
-(def jtds-port    (or (System/getenv "TEST_JTDS_PORT") mssql-port))
-(def jtds-user    (or (System/getenv "TEST_JTDS_USER") mssql-user))
-(def jtds-pass    (or (System/getenv "TEST_JTDS_PASS") mssql-pass))
-(def jtds-dbname  (or (System/getenv "TEST_JTDS_NAME") mssql-dbname))
-
-;; PostgreSQL host/port
-(def postgres-host (or (System/getenv "TEST_POSTGRES_HOST") "127.0.0.1"))
-(def postgres-port (or (System/getenv "TEST_POSTGRES_PORT") "5432"))
-
-;; database connections used for testing:
-
-(def mysql-db {:dbtype   "mysql"
-               :dbname   "clojure_test"
-               :user     "clojure_test"
-               :password "clojure_test"
-               :useSSL   false})
-
-(def derby-db {:dbtype "derby"
-               :dbname "clojure_test_derby"
-               :create true})
-
-(def hsqldb-db {:dbtype "hsql"
-                :dbname "clojure_test_hsqldb"})
-
-;; test with new (0.7.6) in-memory H2 database
-(def h2-db {:dbtype "h2:mem"
-            :dbname "clojure_test_h2"})
-
-(def sqlite-db {:dbtype "sqlite"
-                :dbname "clojure_test_sqlite"})
-
-(def postgres-db {:dbtype   "postgres"
-                  :dbname   "clojure_test"
-                  :host     postgres-host
-                  :port     postgres-port
-                  :user     "clojure_test"
-                  :password "clojure_test"})
-
-(def pgsql-db {:dbtype   "pgsql"
-               :dbname   "clojure_test"
-               :host     postgres-host
-               :port     postgres-port
-               :user     "clojure_test"
-               :password "clojure_test"})
-
-(def mssql-db {:dbtype   "mssql"
-               :dbname   mssql-dbname
-               :host     mssql-host
-               :port     mssql-port
-               :user     mssql-user
-               :password mssql-pass})
-
-(def jtds-db {:dbtype   "jtds"
-              :dbname   jtds-dbname
-              :host     jtds-host
-              :port     jtds-port
-              :user     jtds-user
-              :password jtds-pass})
-
-;; To test against the stringified DB connection settings:
-(def mysql-str-db
-  "mysql://clojure_test:clojure_test@localhost:3306/clojure_test")
-
-(def mysql-jdbc-str-db
-  "jdbc:mysql://clojure_test:clojure_test@localhost:3306/clojure_test")
-
-(def postgres-str-db
-  "postgres://clojure_test:clojure_test@localhost/clojure_test")
-
-(defn- test-specs
-  "Return a sequence of db-spec maps that should be used for tests"
-  []
-  (for [db test-databases]
-    @(ns-resolve 'clojure.java.jdbc-test (symbol (str (name db) "-db")))))
-
-(defn- clean-up
-  "Attempt to drop any test tables before we start a test."
-  [t]
-  (doseq [db (test-specs)]
-    (doseq [table [:fruit :fruit2 :veggies :veggies2]]
-      (try
-        (sql/db-do-commands db (sql/drop-table-ddl table))
-        (catch java.sql.SQLException _))))
-          ;; ignore
-
-  (t))
-
-(use-fixtures
-  :each clean-up)
-
-;; We start with all tables dropped and each test has to create the tables
-;; necessary for it to do its job, and populate it as needed...
-
-(defn- string->type [db]
-  (last (re-find #"^(jdbc:)?([^:]+):" db)))
-
-(defn- db-type [db]
-  (or (:subprotocol db) (:dbtype db)
-      (and (string? db) (string->type db))
-      (and (:connection-uri db) (string->type (:connection-uri db)))))
-
-(defn- derby? [db]
-  (= "derby" (db-type db)))
-
-(defn- hsqldb? [db]
-  (#{"hsql" "hsqldb"} (db-type db)))
-
-(defn- mssql? [db]
-  (#{"jtds" "jtds:sqlserver" "mssql" "sqlserver"} (db-type db)))
-
-(defn- mysql? [db]
-  (= "mysql" (db-type db)))
-
-(defn- postgres? [db]
-  (#{"postgres" "pgsql"} (db-type db)))
-
-(defn- pgsql? [db]
-  (= "pgsql" (db-type db)))
-
-(defn- sqlite? [db]
-  (= "sqlite" (db-type db)))
-
-(defmulti create-test-table
-  "Create a standard test table. Uses db-do-commands.
-   For MySQL, ensure table uses an engine that supports transactions!"
-  (fn [table db]
-    (cond
-      (mysql? db) :mysql
-      (postgres? db) :postgres
-      :else :default)))
-
-(defmethod create-test-table :mysql
-  [table db]
-  (sql/db-do-commands
-   db (sql/create-table-ddl
-       table
-       [[:id :int "PRIMARY KEY AUTO_INCREMENT"]
-        [:name "VARCHAR(32)"]
-        [:appearance "VARCHAR(32)"]
-        [:cost :int]
-        [:grade :real]]
-       {:table-spec "ENGINE=InnoDB"})))
-
-(defmethod create-test-table :postgres
-  [table db]
-  (sql/db-do-commands
-   db (sql/create-table-ddl
-       table
-       [[:id :serial "PRIMARY KEY"]
-        [:name "VARCHAR(32)"]
-        [:appearance "VARCHAR(32)"]
-        [:cost :int]
-        [:grade :real]]
-       {:table-spec ""})))
-
-(defmethod create-test-table :default
-  [table db]
-  (sql/db-do-commands
-   db (sql/create-table-ddl
-       table
-       [[:id :int "DEFAULT 0"]
-        [:name "VARCHAR(32)" "PRIMARY KEY"]
-        [:appearance "VARCHAR(32)"]
-        [:cost :int]
-        [:grade :real]]
-       {:table-spec ""})))
-
-(deftest test-drop-table-ddl
-  (is (= "DROP TABLE something" (sql/drop-table-ddl :something))))
-
-(deftest test-uri-spec-parsing
-  (is (= {:advanced "false" :ssl "required" :password "clojure_test"
-          :user "clojure_test" :subname "//localhost/clojure_test"
-          :subprotocol "postgresql"}
-         (@#'sql/parse-properties-uri
-          (java.net.URI.
-           (str "postgres://clojure_test:clojure_test@localhost/clojure_test?"
-                "ssl=required&advanced=false")))))
-  (is (= {:password "clojure_test" :user "clojure_test"
-          :subname "//localhost:3306/clojure_test", :subprotocol "mysql"}
-         (@#'sql/parse-properties-uri
-          (java.net.URI.
-           "mysql://clojure_test:clojure_test@localhost:3306/clojure_test")))))
-
-(defn- returned-key [db k]
-  (case (db-type db)
-    "derby"  {(keyword "1") nil}
-    ("hsql" "hsqldb") nil
-    ("h2" "h2:mem") {:id 0}
-    "mysql"  {:generated_key k}
-    nil      (if (mysql? db) ; string-based tests
-               {:generated_key k}
-               k)
-    ("jtds" "jtds:sqlserver") {:id nil}
-    ("mssql" "sqlserver") {:generated_keys nil}
-    "sqlite" {(keyword "last_insert_rowid()") k}
-    k))
-
-(defn- select-key [db]
-  (case (db-type db)
-    ("postgres" "postgresql" "pgsql") :id
-    identity))
-
-(defn- generated-key [db k]
-  (case (db-type db)
-    "derby" 0
-    ("hsql" "hsqldb") 0
-    ("h2" "h2:mem") 0
-    ("jtds" "jtds:sqlserver") 0
-    ("mssql" "sqlserver") 0
-    "sqlite" 0
-    k))
-
-(defn- float-or-double [db v]
-  (case (db-type db)
-    "derby" (Float. v)
-    ("h2" "h2:mem") (Float. v)
-    ("jtds" "jtds:sqlserver") (Float. v)
-    ("mssql" "sqlserver") (Float. v)
-    ("postgres" "postgresql" "pgsql") (Float. v)
-    v))
-
-(deftest test-create-table
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (is (= 0 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))))
-
-(deftest test-drop-table
-  (doseq [db (test-specs)]
-    (create-test-table :fruit2 db)
-    (sql/db-do-commands db (sql/drop-table-ddl :fruit2))
-    (is (thrown? java.sql.SQLException
-                 (sql/query db ["SELECT * FROM fruit2"] {:result-set-fn count})))))
-
-(deftest test-do-commands
-  (doseq [db (test-specs)]
-    (create-test-table :fruit2 db)
-    (sql/db-do-commands db "DROP TABLE fruit2")
-    (is (thrown? java.sql.SQLException
-                 (sql/query db ["SELECT * FROM fruit2"] {:result-set-fn count})))))
-
-(deftest test-do-commands-transaction
-  (doseq [db (test-specs)]
-    (create-test-table :fruit2 db)
-    (sql/db-do-commands db true "DROP TABLE fruit2")
-    (is (thrown? java.sql.SQLException
-                 (sql/query db ["SELECT * FROM fruit2"] {:result-set-fn count})))))
-
-(deftest test-do-commands-multi
-  (doseq [db (test-specs)]
-    (sql/db-do-commands db
-                        [(sql/create-table-ddl :fruit3
-                                               [[:name       "VARCHAR(32)"]
-                                                [:appearance "VARCHAR(32)"]
-                                                [:cost       :int]])
-                         "DROP TABLE fruit3"])
-    (is (thrown? java.sql.SQLException
-                 (sql/query db ["SELECT * FROM fruit2"] {:result-set-fn count})))))
-
-(deftest test-do-commands-multi-transaction
-  (doseq [db (test-specs)]
-    (sql/db-do-commands db true
-                        [(sql/create-table-ddl :fruit3
-                                               [[:name       "VARCHAR(32)"]
-                                                [:appearance "VARCHAR(32)"]
-                                                [:cost       :int]])
-                         "DROP TABLE fruit3"])
-    (is (thrown? java.sql.SQLException
-                 (sql/query db ["SELECT * FROM fruit2"] {:result-set-fn count})))))
-
-(deftest test-do-prepared1a
-  (doseq [db (test-specs)]
-    (create-test-table :fruit2 db)
-    ;; single string is acceptable
-    (sql/db-do-prepared db "INSERT INTO fruit2 ( name, appearance, cost, grade ) VALUES ( 'test', 'test', 1, 1.0 )")
-    (is (= 1 (sql/query db ["SELECT * FROM fruit2"] {:result-set-fn count})))))
-
-(deftest test-do-prepared1b
-  (doseq [db (test-specs)]
-    (create-test-table :fruit2 db)
-    (with-open [con (sql/get-connection db)]
-      (let [stmt (sql/prepare-statement con "INSERT INTO fruit2 ( name, appearance, cost, grade ) VALUES ( 'test', 'test', 1, 1.0 )")]
-        ;; single PreparedStatement is acceptable
-        (is (= [1] (sql/db-do-prepared db stmt)))))
-    (is (= 1 (sql/query db ["SELECT * FROM fruit2"] {:result-set-fn count})))))
-
-(deftest test-do-prepared1ci
-  (doseq [db (test-specs)]
-    (create-test-table :fruit2 db)
-    (is (= (returned-key db 1)
-           ((select-key db) (sql/db-do-prepared-return-keys db "INSERT INTO fruit2 ( name, appearance, cost, grade ) VALUES ( 'test', 'test', 1, 1.0 )"))))
-    (is (= 1 (sql/query db ["SELECT * FROM fruit2"] {:result-set-fn count})))))
-
-(deftest test-do-prepared1cii
-  (doseq [db (test-specs)]
-    (create-test-table :fruit2 db)
-    (is (= (returned-key db 1)
-           ((select-key db) (sql/db-do-prepared-return-keys db ["INSERT INTO fruit2 ( name, appearance, cost, grade ) VALUES ( 'test', 'test', 1, 1.0 )"]))))
-    (is (= 1 (sql/query db ["SELECT * FROM fruit2"] {:result-set-fn count})))))
-
-(deftest test-do-prepared1di
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (with-open [con (sql/get-connection db)]
-      (let [stmt (sql/prepare-statement con "INSERT INTO fruit ( name, appearance, cost, grade ) VALUES ( 'test', 'test', 1, 1.0 )"
-                                        {:return-keys true})]
-        (is (= (returned-key db 1)
-               ((select-key db) (sql/db-do-prepared-return-keys db [stmt]))))))
-    (is (= 1 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))))
-
-(deftest test-do-prepared1dii
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (with-open [con (sql/get-connection db)]
-      (let [stmt (sql/prepare-statement con "INSERT INTO fruit ( name, appearance, cost, grade ) VALUES ( 'test', 'test', 1, 1.0 )"
-                                        {:return-keys true})]
-        (is (= (returned-key db 1)
-               ((select-key db) (sql/db-do-prepared-return-keys db stmt))))))
-    (is (= 1 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))))
-
-(deftest test-do-prepared1e
-  (doseq [db (test-specs)]
-    ;; Derby/SQL Server does not have auto-generated id column which we're testing here
-    (when-not (#{"derby" "jtds" "jtds:sqlserver"} (db-type db))
-      (create-test-table :fruit db)
-      (with-open [con (sql/get-connection db)]
-        (let [stmt (sql/prepare-statement con "INSERT INTO fruit ( name, appearance, cost, grade ) VALUES ( 'test', 'test', 1, 1.0 )"
-                                          {:return-keys ["id"]})]
-          ;; HSQLDB returns the named key if you ask
-          (is (= (if (hsqldb? db) {:id 0} (returned-key db 1))
-                 ((select-key db) (sql/db-do-prepared-return-keys db stmt))))))
-      (is (= 1 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count}))))))
-
-(deftest test-do-prepared2
-  (doseq [db (test-specs)]
-    (create-test-table :fruit2 db)
-    (sql/db-do-prepared db "DROP TABLE fruit2")
-    (is (thrown? java.sql.SQLException
-                 (sql/query db ["SELECT * FROM fruit2"] {:result-set-fn count})))))
-
-(deftest test-do-prepared3a
-  (doseq [db (test-specs)]
-    (create-test-table :fruit2 db)
-    (sql/db-do-prepared db ["INSERT INTO fruit2 ( name, appearance, cost, grade ) VALUES ( ?, ?, ?, ? )" ["test" "test" 1 1.0]] {:multi? true})
-    (is (= 1 (sql/query db ["SELECT * FROM fruit2"] {:result-set-fn count})))))
-
-(deftest test-do-prepared3b
-  (doseq [db (test-specs)]
-    (create-test-table :fruit2 db)
-    (sql/db-do-prepared db ["INSERT INTO fruit2 ( name, appearance, cost, grade ) VALUES ( ?, ?, ?, ? )" "test" "test" 1 1.0])
-    (is (= 1 (sql/query db ["SELECT * FROM fruit2"] {:result-set-fn count})))))
-
-(deftest test-do-prepared4
-  (doseq [db (test-specs)]
-    (create-test-table :fruit2 db)
-    (sql/db-do-prepared db ["INSERT INTO fruit2 ( name, appearance, cost, grade ) VALUES ( ?, ?, ?, ? )" ["test" "test" 1 1.0] ["two" "two" 2 2.0]] {:multi? true})
-    (is (= 2 (sql/query db ["SELECT * FROM fruit2"] {:result-set-fn count})))))
-
-(deftest test-insert-rows
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (let [r (sql/insert-multi! db
-                               :fruit
-                               nil
-                               [[1 "Apple" "red" 59 87]
-                                [2 "Banana" "yellow" 29 92.2]
-                                [3 "Peach" "fuzzy" 139 90.0]
-                                [4 "Orange" "juicy" 139 88.6]])]
-      (is (= '(1 1 1 1) r)))
-    (is (= 4 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))
-    (is (= 4 (sql/with-db-connection [con db {}]
-               (sql/query con (sql/prepare-statement (sql/db-connection con) "SELECT * FROM fruit") {:result-set-fn count}))))
-    (when-not (pgsql? db)
-      ;; maxRows does not appear to be supported on Impossibl pgsql?
-      (is (= 2 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count :max-rows 2})))
-      (is (= 2 (sql/with-db-connection [con db]
-                 (sql/query con [(sql/prepare-statement (sql/db-connection con) "SELECT * FROM fruit" {:max-rows 2})] {:result-set-fn count})))))
-    (is (= "Apple" (sql/query db ["SELECT * FROM fruit WHERE appearance = ?" "red"] {:row-fn :name :result-set-fn first})))
-    (is (= "juicy" (sql/query db ["SELECT * FROM fruit WHERE name = ?" "Orange"] {:row-fn :appearance :result-set-fn first})))
-    (is (= "Apple" (:name (sql/get-by-id db :fruit 1))))
-    (is (= ["Apple"] (map :name (sql/find-by-keys db :fruit {:appearance "red"}))))
-    (is (= "Peach" (:name (sql/get-by-id db :fruit 3 :id))))
-    (is (= ["Peach"] (map :name (sql/find-by-keys db :fruit {:id 3 :cost 139}))))
-    (is (= ["Peach" "Orange"] (map :name (sql/find-by-keys db :fruit {:cost 139} {:order-by [:id]}))))
-    (is (= ["Orange" "Peach"] (map :name (sql/find-by-keys db :fruit {:cost 139} {:order-by [{:appearance :desc}]}))))
-    ;; reduce with init (and ensure we can pass :fetch-size & connection opts through)
-    (is (= 466 (reduce (fn [n r] (+ n (:cost r))) 100
-                       (sql/reducible-query db "SELECT * FROM fruit"
-                                            (cond-> {:fetch-size 100 :raw? true}
-                                              (not (sqlite? db))
-                                              (assoc :read-only? true)
-                                              (not (derby? db))
-                                              (assoc :auto-commit? false))))))
-    ;; reduce without init -- uses first row as init!
-    (is (= 366
-           (:cost (reduce (fn
-                            ([] (throw (ex-info "I should not be called!" {})))
-                            ([m r] (update-in m [:cost] + (:cost r))))
-                          (sql/reducible-query db "SELECT * FROM fruit")))))
-    ;; verify reduce without init on empty rs calls 0-arity only
-    (is (= "Zero-arity!"
-           (reduce (fn
-                     ([] "Zero-arity!")
-                     ([m r] (throw (ex-info "I should not be called!"
-                                            {:m m :r r}))))
-                   (sql/reducible-query db "SELECT * FROM fruit WHERE ID = -99"))))
-    ;; verify reduce with init does not call f for empty rs
-    (is (= "Unchanged!"
-           (reduce (fn
-                     ([] (throw (ex-info "I should not be called!" {})))
-                     ([m r] (throw (ex-info "I should not be called!"
-                                            {:m m :r r}))))
-                   "Unchanged!"
-                   (sql/reducible-query db "SELECT * FROM fruit WHERE ID = -99"))))
-    ;; verify reduce without init does not call f if only one row is in the rs
-    (is (= "Orange"
-           (:name (reduce (fn
-                            ([] (throw (ex-info "I should not be called!" {})))
-                            ([m r] (throw (ex-info "I should not be called!"
-                                                   {:m m :r r}))))
-                          (sql/reducible-query db "SELECT * FROM fruit WHERE ID = 4")))))
-    ;; verify reduce with init does not call 0-arity f and
-    ;; only calls 2-arity f once if only one row is in the rs
-    (is (= 239
-           (reduce (fn
-                     ([] (throw (ex-info "I should not be called!" {})))
-                     ;; cannot be called on its own result:
-                     ([m r] (+ (:a m) (:cost r))))
-                   {:a 100}
-                   (sql/reducible-query db "SELECT * FROM fruit WHERE ID = 4"))))
-    ;; plain old into (uses (reduce conj coll) behind the scenes)
-    (is (= 4 (count (into [] (sql/reducible-query db "SELECT * FROM fruit")))))
-    ;; transducing into
-    (is (= [29 59 139 139]
-           (into []
-                 (map :cost)
-                 (sql/reducible-query db (str "SELECT * FROM fruit"
-                                              " ORDER BY cost")
-                                      {:raw? true}))))
-    ;; transduce without init (calls (+) to get init value)
-    (is (= 366 (transduce (map :cost) +
-                          (sql/reducible-query db "SELECT * FROM fruit"))))
-    ;; transduce with init
-    (is (= 466 (transduce (map :cost) + 100
-                          (sql/reducible-query db "SELECT * FROM fruit"))))))
-
-(deftest test-insert-values
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (let [r (sql/insert-multi! db
-                               :fruit
-                               [:name :cost]
-                               [["Mango" 722]
-                                ["Feijoa" 441]])]
-      (is (= '(1 1) r)))
-    (is (= 2 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))
-    (is (= "Mango" (sql/query db ["SELECT * FROM fruit WHERE cost = ?" 722] {:row-fn :name :result-set-fn first})))))
-
-(deftest test-insert-records
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (let [r (map (select-key db) (sql/insert-multi! db
-                                                    :fruit
-                                                    [{:name "Pomegranate" :appearance "fresh" :cost 585}
-                                                     {:name "Kiwifruit" :grade 93}]))]
-      (is (= (list (returned-key db 1) (returned-key db 2)) r)))
-    (is (= 2 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))
-    (is (= "Pomegranate" (sql/query db ["SELECT * FROM fruit WHERE cost = ?" 585] {:row-fn :name :result-set-fn first})))))
-
-(deftest test-insert-via-execute
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (sql/execute! db [(str "INSERT INTO fruit ( name, appearance, cost ) "
-                           "VALUES ( ?, ?, ? )")
-                      "Apple" "Green" 75])
-    (sql/execute! db [(str "INSERT INTO fruit ( name, appearance, cost ) "
-                           "VALUES ( 'Pear', 'Yellow', 99 )")])
-    (is (= 2 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))
-    (is (= "Pear" (sql/query db ["SELECT * FROM fruit WHERE cost = ?" 99]
-                             {:row-fn :name :result-set-fn first})))))
-
-(deftest execute-with-prepared-statement
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (sql/with-db-connection [conn db]
-      (let [connection (:connection conn)
-            prepared-statement (sql/prepare-statement connection (str "INSERT INTO fruit ( name, appearance, cost ) "
-                                                                      "VALUES ( ?, ?, ? )"))]
-
-        (sql/execute! db [prepared-statement "Apple" "Green" 75])
-        (sql/execute! db [prepared-statement "Pear" "Yellow" 99])))
-    (is (= 2 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))
-    (is (= "Pear" (sql/query db ["SELECT * FROM fruit WHERE cost = ?" 99]
-                             {:row-fn :name :result-set-fn first})))))
-
-(deftest execute-with-prepared-statement-with-return-keys
-  (doseq [db (test-specs)]
-    ;; Derby/SQL Server does not have auto-generated id column which we're testing here
-    (when-not (#{"derby" "jtds" "jtds:sqlserver"} (db-type db))
-      (create-test-table :fruit db)
-      (sql/with-db-connection [conn db]
-        (let [connection (:connection conn)
-              ;; although we ask for keys to come back, execute! cannot see into
-              ;; the PreparedStatement so it doesn't know to call things in a
-              ;; different way, so we get affected row counts instead!
-              prepared-statement (sql/prepare-statement connection (str "INSERT INTO fruit ( name, appearance, cost ) "
-                                                                        "VALUES ( ?, ?, ? )")
-                                                        {:return-keys ["id"]})]
-          ;; what is returned is affected row counts due to how execute! works
-          (is (= [1] (sql/execute! db [prepared-statement "Apple" "Green" 75])))
-          (is (= [1] (sql/execute! db [prepared-statement "Pear" "Yellow" 99])))))
-      (is (= 2 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))
-      (is (= "Pear" (sql/query db ["SELECT * FROM fruit WHERE cost = ?" 99]
-                               {:row-fn :name :result-set-fn first}))))))
-
-(deftest execute-with-return-keys-option
-  (doseq [db (test-specs)]
-    ;; Derby/SQL Server does not have auto-generated id column which we're testing here
-    (when-not (#{"derby" "jtds" "jtds:sqlserver"} (db-type db))
-      (create-test-table :fruit db)
-      (sql/with-db-connection [conn db]
-        (let [sql-stmt (str "INSERT INTO fruit ( name, appearance, cost ) "
-                            "VALUES ( ?, ?, ? )")
-              selector (select-key db)]
-          ;; HSQLDB returns the named key if you ask
-          (is (= (if (hsqldb? db) {:id 0} (returned-key db 1))
-                 (selector (sql/execute! db [sql-stmt "Apple" "Green" 75]
-                                         {:return-keys ["id"]}))))
-          ;; HSQLDB returns the named key if you ask
-          (is (= (if (hsqldb? db) {:id 0} (returned-key db 2))
-                 (sql/execute! db [sql-stmt "Pear" "Yellow" 99]
-                               {:return-keys ["id"]
-                                :row-fn selector})))))
-      (is (= 2 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))
-      (is (= "Pear" (sql/query db ["SELECT * FROM fruit WHERE cost = ?" 99]
-                               {:row-fn :name :result-set-fn first}))))))
-
-(deftest test-nested-with-connection
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (sql/with-db-connection [conn1 db]
-      (sql/query conn1 "select * from fruit")
-      (sql/with-db-connection [conn2 conn1]
-        (sql/query conn2 "select * from fruit"))
-      ;; JDBC-171 bug: this blows up because with-db-connection won't nest
-      (is (= [] (sql/query conn1 "select * from fruit"))))))
-
-(deftest test-update-values
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (let [r (sql/insert-multi! db
-                               :fruit
-                               nil
-                               [[1 "Apple" "red" 59 87]
-                                [2 "Banana" "yellow" 29 92.2]
-                                [3 "Peach" "fuzzy" 139 90.0]
-                                [4 "Orange" "juicy" 89 88.6]])]
-      (is (= '(1 1 1 1) r)))
-    (sql/update! db
-                 :fruit
-                 {:appearance "bruised" :cost 14}
-                 ["name=?" "Banana"])
-    (is (= 4 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))
-    (is (= "Apple" (sql/query db ["SELECT * FROM fruit WHERE appearance = ?" "red"]
-                              {:row-fn :name :result-set-fn first})))
-    (is (= "Banana" (sql/query db ["SELECT * FROM fruit WHERE appearance = ?" "bruised"]
-                               {:row-fn :name :result-set-fn first})))
-    (is (= 14 (sql/query db ["SELECT * FROM fruit WHERE name = ?" "Banana"]
-                         {:row-fn :cost :result-set-fn first})))))
-
-(defn update-or-insert-values
-  [db table row where]
-  (sql/with-db-transaction [t-conn db]
-    (let [result (sql/update! t-conn table row where)]
-      (if (zero? (first result))
-        (sql/insert! t-conn table row)
-        result))))
-
-(defn update-or-insert-values-with-isolation
-  [db table row where]
-  (sql/with-db-transaction [t-conn db {:isolation :read-uncommitted}]
-    (let [result (sql/update! t-conn table row where)]
-      (if (zero? (first result))
-        (sql/insert! t-conn table row)
-        result))))
-
-(deftest test-update-or-insert-values
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (update-or-insert-values db
-                             :fruit
-                             {:name "Pomegranate" :appearance "fresh" :cost 585}
-                             ["name=?" "Pomegranate"])
-    (is (= 1 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))
-    (is (= 585 (sql/query db ["SELECT * FROM fruit WHERE appearance = ?" "fresh"]
-                          {:row-fn :cost :result-set-fn first})))
-    (update-or-insert-values db
-                             :fruit
-                             {:name "Pomegranate" :appearance "ripe" :cost 565}
-                             ["name=?" "Pomegranate"])
-    (is (= 1 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))
-    (is (= 565 (sql/query db ["SELECT * FROM fruit WHERE appearance = ?" "ripe"]
-                          {:row-fn :cost :result-set-fn first})))
-    (update-or-insert-values db
-                             :fruit
-                             {:name "Apple" :appearance "green" :cost 74}
-                             ["name=?" "Apple"])
-    (is (= 2 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))))
-
-(deftest test-update-or-insert-values-with-isolation
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (update-or-insert-values-with-isolation db
-                                            :fruit
-                                            {:name "Pomegranate" :appearance "fresh" :cost 585}
-                                            ["name=?" "Pomegranate"])
-    (is (= 1 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))
-    (is (= 585 (sql/query db ["SELECT * FROM fruit WHERE appearance = ?" "fresh"]
-                          {:row-fn :cost :result-set-fn first})))
-    (update-or-insert-values db
-                             :fruit
-                             {:name "Pomegranate" :appearance "ripe" :cost 565}
-                             ["name=?" "Pomegranate"])
-    (is (= 1 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))
-    (is (= 565 (sql/query db ["SELECT * FROM fruit WHERE appearance = ?" "ripe"]
-                          {:row-fn :cost :result-set-fn first})))
-    (update-or-insert-values db
-                             :fruit
-                             {:name "Apple" :appearance "green" :cost 74}
-                             ["name=?" "Apple"])
-    (is (= 2 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))))
-
-(defn- file-not-found-exception-via-reflection
-  "In Clojure 1.3.0 this caused a wrapped exception and we introduced throw-non-rte
-  to workaround that. This was fixed in 1.4.0 but we never removed the workaround.
-  Added this hack from the mailing list specifically to test the exception handling
-  so that we can verify only Clojure 1.3.0 fails the tests and drop support for it."
-  [f]
-  (java.io.FileReader. f))
-
-(deftest test-partial-exception
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (try
-      (sql/with-db-transaction [t-conn db]
-        (sql/insert-multi! t-conn
-                           :fruit
-                           [:name :appearance]
-                           [["Grape" "yummy"]
-                            ["Pear" "bruised"]])
-        (is (= 2 (sql/query t-conn ["SELECT * FROM fruit"] {:result-set-fn count})))
-        (file-not-found-exception-via-reflection "/etc/password_no_such_file"))
-      (catch java.io.FileNotFoundException _
-        (is (= 0 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count}))))
-      (catch Exception _
-        (is false "Unexpected exception encountered (not wrapped?).")))))
-
-(deftest test-partial-exception-with-isolation
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (try
-      (sql/with-db-transaction [t-conn db {:isolation :serializable}]
-        (sql/insert-multi! t-conn
-                           :fruit
-                           [:name :appearance]
-                           [["Grape" "yummy"]
-                            ["Pear" "bruised"]])
-        (is (= 2 (sql/query t-conn ["SELECT * FROM fruit"] {:result-set-fn count})))
-        (throw (Exception. "deliberate exception")))
-      (catch Exception _
-        (is (= 0 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))))))
-
-(defmacro illegal-arg-or-spec
-  "Execute a form in the context of a try/catch that verifies either
-  IllegalArgumentException was thrown or a spec violation occurred
-  so that we can test transparently across Clojure 1.7 to 1.9+."
-  [fn-name & body]
-  `(try
-     ~@body
-     (is false (str "Illegal arguments to " ~fn-name " were not detected!"))
-     (catch IllegalArgumentException _#)
-     (catch clojure.lang.ExceptionInfo e#
-       (is (re-find #"did not conform to spec" (.getMessage e#))))))
-
-(deftest test-sql-exception
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (illegal-arg-or-spec "insert!"
-      (sql/with-db-transaction [t-conn db]
-        (sql/insert! t-conn
-                     :fruit
-                     [:name :appearance]
-                     ["Apple" "strange" "whoops"])))
-    (is (= 0 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))))
-
-(deftest test-sql-exception-with-isolation
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (illegal-arg-or-spec "insert!"
-      (sql/with-db-transaction [t-conn db {:isolation :read-uncommitted}]
-        (sql/insert! t-conn
-                     :fruit
-                     [:name :appearance]
-                     ["Apple" "strange" "whoops"])))
-    (is (= 0 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))))
-
-(deftest test-insert-values-exception
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (illegal-arg-or-spec "insert-multi!"
-      (sql/with-db-transaction [t-conn db]
-        (sql/insert-multi! t-conn
-                           :fruit
-                           [:name :appearance]
-                           [["Grape" "yummy"]
-                            ["Pear" "bruised"]
-                            ["Apple" "strange" "whoops"]])))
-    (is (= 0 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))))
-
-(deftest test-insert-values-exception-with-isolation
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (illegal-arg-or-spec
-      (sql/with-db-transaction [t-conn db {:isolation :read-uncommitted}]
-        (sql/insert-multi! t-conn
-                           :fruit
-                           [:name :appearance]
-                           [["Grape" "yummy"]
-                            ["Pear" "bruised"]
-                            ["Apple" "strange" "whoops"]])))
-    (is (= 0 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))))
-
-(deftest test-rollback
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (try
-      (sql/with-db-transaction [t-conn db]
-        (is (not (sql/db-is-rollback-only t-conn)))
-        (sql/db-set-rollback-only! t-conn)
-        (is (sql/db-is-rollback-only t-conn))
-        (sql/insert-multi! t-conn
-                           :fruit
-                           [:name :appearance]
-                           [["Grape" "yummy"]
-                            ["Pear" "bruised"]
-                            ["Apple" "strange"]])
-        (is (= 3 (sql/query t-conn ["SELECT * FROM fruit"] {:result-set-fn count}))))
-      (catch java.sql.SQLException _
-        (is (= 0 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))))
-    (is (= 0 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))))
-
-(deftest test-rollback-with-isolation
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (try
-      (sql/with-db-transaction [t-conn db {:isolation :read-uncommitted}]
-        (is (not (sql/db-is-rollback-only t-conn)))
-        (sql/db-set-rollback-only! t-conn)
-        (is (sql/db-is-rollback-only t-conn))
-        (sql/insert-multi! t-conn
-                           :fruit
-                           [:name :appearance]
-                           [["Grape" "yummy"]
-                            ["Pear" "bruised"]
-                            ["Apple" "strange"]])
-        (is (= 3 (sql/query t-conn ["SELECT * FROM fruit"] {:result-set-fn count}))))
-      (catch java.sql.SQLException _
-        (is (= 0 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))))
-    (is (= 0 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))))
-
-(deftest test-transactions-with-possible-generated-keys-result-set
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (sql/with-db-transaction [t-conn db]
-      (sql/db-set-rollback-only! t-conn)
-      (sql/insert! t-conn
-                   :fruit
-                   [:name :appearance]
-                   ["Grape" "yummy"])
-      (is (= 1 (sql/query t-conn ["SELECT * FROM fruit"] {:result-set-fn count}))))
-    (is (= 0 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))))
-
-(deftest test-transactions-with-possible-generated-keys-result-set-and-isolation
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (sql/with-db-transaction [t-conn db {:isolation :read-uncommitted}]
-      (sql/db-set-rollback-only! t-conn)
-      (sql/insert! t-conn
-                   :fruit
-                   [:name :appearance]
-                   ["Grape" "yummy"])
-      (is (= 1 (sql/query t-conn ["SELECT * FROM fruit"] {:result-set-fn count}))))
-    (is (= 0 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))))
-
-(deftest test-nested-transactions-check-transaction-isolation-level
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (sql/with-db-transaction [t-conn db {:isolation :read-uncommitted}]
-      (is (thrown? IllegalStateException
-                   (sql/with-db-transaction [t-conn' t-conn {:isolation :serializable}]
-                     (sql/insert! t-conn'
-                                  :fruit
-                                  [:name :appearance]
-                                  ["Grape" "yummy"])))))
-    (is (= 0 (sql/query db ["SELECT * FROM fruit"] {:result-set-fn count})))))
-
-(deftest test-raw-metadata
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (let [table-info (with-open [conn (sql/get-connection db)]
-                       (into []
-                             (sql/result-set-seq
-                              (-> conn
-                                  (.getMetaData)
-                                  (.getTables nil nil nil
-                                              (into-array ["TABLE" "VIEW"]))))))]
-      (is (not= [] table-info))
-      (is (= "fruit" (-> table-info
-                         first
-                         :table_name
-                         clojure.string/lower-case))))))
-
-(deftest test-metadata-managed
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (sql/with-db-metadata [metadata db {}]
-      (let [table-info (sql/metadata-query (.getTables metadata
-                                                       nil nil nil
-                                                       (into-array ["TABLE" "VIEW"])))]
-        (is (not= [] table-info))
-        (is (= "fruit" (-> table-info
-                           first
-                           :table_name
-                           clojure.string/lower-case))))
-     (sql/with-db-connection [conn db]
-       (sql/with-db-metadata [metadata conn {}]
-         (let [table-info (sql/metadata-query (.getTables metadata
-                                                          nil nil nil
-                                                          (into-array ["TABLE" "VIEW"])))]
-           (is (not= [] table-info))
-           (is (= "fruit" (-> table-info
-                              first
-                              :table_name
-                              clojure.string/lower-case)))))
-       ;; JDBC-171 this used to blow up because the connnection is closed
-       (sql/with-db-metadata [metadata conn {}]
-         (let [table-info (sql/metadata-query (.getTables metadata
-                                                          nil nil nil
-                                                          (into-array ["TABLE" "VIEW"])))]
-           (is (not= [] table-info))
-           (is (= "fruit" (-> table-info
-                              first
-                              :table_name
-                              clojure.string/lower-case)))))))))
-
-(deftest test-metadata-managed-computed
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (is (= "fruit"
-           (sql/with-db-metadata [metadata db]
-             (sql/metadata-query (.getTables metadata
-                                             nil nil nil
-                                             (into-array ["TABLE" "VIEW"]))
-                                 {:row-fn (comp clojure.string/lower-case str :table_name)
-                                  :result-set-fn first}))))))
-
-(deftest test-metadata
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (sql/with-db-metadata [metadata db]
-      ;; make sure to close the ResultSet
-      (with-open [table-info-result (.getTables metadata
-                                                nil nil nil
-                                                (into-array ["TABLE" "VIEW"]))]
-        (let [table-info (sql/metadata-result table-info-result)]
-          (is (not= [] table-info))
-          (is (= "fruit" (-> table-info
-                             first
-                             :table_name
-                             clojure.string/lower-case))))))))
-
-(deftest empty-query
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (is (= [] (sql/query db ["SELECT * FROM fruit"])))))
-
-(deftest query-with-string
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (is (= [] (sql/query db "SELECT * FROM fruit")))))
-
-(deftest insert-one-via-execute
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (let [new-key ((select-key db)
-                   (sql/execute! db [(str "INSERT INTO fruit ( name )"
-                                          " VALUES ( ? )")
-                                     "Apple"]
-                                 {:return-keys true}))]
-      (is (= (returned-key db 1) new-key)))))
-
-(deftest insert-two-via-execute
-   (doseq [db (test-specs)]
-     (create-test-table :fruit db)
-     (let [execute-multi-insert
-           (fn [db]
-             (sql/execute! db [(str "INSERT INTO fruit ( name )"
-                                    " VALUES ( ? )")
-                               ["Apple"]
-                               ["Orange"]]
-                           {:return-keys true
-                            :multi? true}))
-           new-keys (map (select-key db)
-                         (if (#{"jtds" "jtds:sqlserver"} (db-type db))
-                           (do
-                             (is (thrown? java.sql.BatchUpdateException
-                                          (execute-multi-insert db)))
-                             [])
-                           (execute-multi-insert db)))]
-       (case (db-type db)
-         ;; SQLite returns nothing useful now
-         "sqlite" (is (= [] new-keys))
-         ;; Derby returns a single row count
-         "derby"  (is (= [(returned-key db 1)] new-keys))
-         ;; H2 returns dummy keys
-         ("h2" "h2:mem")
-         (is (= [(returned-key db 1) (returned-key db 2)] new-keys))
-         ;; HSQL returns nothing useful
-         "hsql"   (is (= [] new-keys))
-         ;; MS SQL returns row counts
-         "mssql"  (is (= [1 1] new-keys))
-         ;; jTDS disallows batch updates returning keys (handled above)
-         ("jtds" "jtds:sqlserver")
-         (is (= [] new-keys))
-         ;; otherwise expect two rows with the correct keys
-         (do
-           (when-not (= [(returned-key db 1) (returned-key db 2)] new-keys)
-             (println "FAIL FOR" db))
-           (is (= [(returned-key db 1)
-                   (returned-key db 2)]
-                  new-keys)))))))
-
-(deftest insert-two-via-execute-result-set-fn
-   (doseq [db (test-specs)]
-     (create-test-table :fruit db)
-     (let [execute-multi-insert
-           (fn [db]
-             (sql/execute! db [(str "INSERT INTO fruit ( name )"
-                                    " VALUES ( ? )")
-                               ["Apple"]
-                               ["Orange"]]
-                           {:return-keys true
-                            :multi? true
-                            :result-set-fn count}))
-           n (if (#{"jtds" "jtds:sqlserver"} (db-type db))
-               (do
-                 (is (thrown? java.sql.BatchUpdateException
-                              (execute-multi-insert db)))
-                 0)
-               (execute-multi-insert db))]
-       (case (db-type db)
-         ;; SQLite returns nothing useful now
-         "sqlite" (is (= 0 n))
-         ;; Derby returns a single row count
-         "derby"  (is (= 1 n))
-         ;; H2 returns (zero) keys now
-         ("h2" "h2:mem") (is (= 2 n))
-         ;; HSQL returns nothing useful
-         "hsql"   (is (= 0 n))
-         ;; MS SQL returns row counts (we still apply result-set-fn)
-         "mssql"  (is (= 2 n))
-         ;; jTDS disallows batch updates returning keys (handled above)
-         ("jtds" "jtds:sqlserver")
-         (is (= 0 n))
-         ;; otherwise expect two rows with the correct keys
-         (do
-           (when-not (= 2 n)
-             (println "FAIL FOR" db))
-           (is (= 2 n)))))))
-
-(deftest insert-one-row
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (let [new-keys (map (select-key db) (sql/insert! db :fruit {:name "Apple"}))]
-      (is (= [(returned-key db 1)] new-keys)))))
-
-(deftest insert-one-row-opts
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (let [new-keys (map (select-key db) (sql/insert! db :fruit {:name "Apple"} {}))]
-      (is (= [(returned-key db 1)] new-keys)))))
-
-(deftest insert-one-row-opts-row-fn
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (let [new-keys (sql/insert! db :fruit {:name "Apple"} {:row-fn (select-key db)})]
-      (is (= [(returned-key db 1)] new-keys)))))
-
-(deftest insert-one-col-val
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (let [new-keys (sql/insert! db :fruit [:name] ["Apple"])]
-      (is (= [1] new-keys)))))
-
-(deftest insert-one-col-val-opts
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (let [new-keys (sql/insert! db :fruit [:name] ["Apple"] {})]
-      (is (= [1] new-keys)))))
-
-(deftest insert-query
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (let [new-keys (map (select-key db) (sql/insert! db :fruit {:name "Apple"}))]
-      (is (= [(returned-key db 1)] new-keys))
-      (is (= [{:id (generated-key db 1) :name "Apple" :appearance nil :grade nil :cost nil}]
-             (sql/query db "SELECT * FROM fruit")))
-      (is (= [{:id (generated-key db 1) :name "Apple" :appearance nil :grade nil :cost nil}]
-             (sql/query db ["SELECT * FROM fruit"])))
-      (is (= [{:ID (generated-key db 1) :NAME "Apple" :APPEARANCE nil :GRADE nil :COST nil}]
-             (sql/query db ["SELECT * FROM fruit"] {:identifiers str/upper-case})))
-      (when (map? db)
-        (is (= [{:ID (generated-key db 1) :NAME "Apple" :APPEARANCE nil :GRADE nil :COST nil}]
-               (sql/query (assoc db :identifiers str/upper-case) ["SELECT * FROM fruit"]))))
-      (is (= [{:fruit/id (generated-key db 1) :fruit/name "Apple" :fruit/appearance nil
-               :fruit/grade nil :fruit/cost nil}]
-             (sql/query db ["SELECT * FROM fruit"] {:qualifier "fruit"})))
-      (is (= [{:fruit/name "Apple"}]
-             (sql/query db ["SELECT name FROM fruit"]
-                        {:identifiers (comp (partial str "fruit/") str/lower-case)})))
-      (is (= [{:name "Apple"}]
-             (sql/query db ["SELECT name FROM fruit"]
-                        {:identifiers (comp keyword str/lower-case)})))
-      (when (map? db)
-        (is (= [{:fruit/id (generated-key db 1) :fruit/name "Apple" :fruit/appearance nil
-                 :fruit/grade nil :fruit/cost nil}]
-               (sql/query (assoc db :qualifier "fruit") ["SELECT * FROM fruit"]))))
-      (is (= [{:id (generated-key db 1) :name "Apple" :appearance nil :grade nil :cost nil}]
-             (with-open [con (sql/get-connection db)]
-               (sql/query db [(sql/prepare-statement con "SELECT * FROM fruit")]))))
-      (is (= [{:id (generated-key db 1) :name "Apple" :appearance nil :grade nil :cost nil}]
-             (sql/query db ["SELECT * FROM fruit"] {:max-rows 1})))
-      (cond (derby? db) nil
-            (hsqldb? db) (is (seq (with-out-str
-                                    (sql/query db ["SELECT * FROM fruit"]
-                                               {:explain? "EXPLAIN PLAN FOR"}))))
-            (mssql? db) nil
-            :else (is (seq (with-out-str
-                             (sql/query db ["SELECT * FROM fruit"]
-                                        {:explain? true}))))))))
-
-(deftest insert-two-by-map-and-query
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (let [new-keys (map (select-key db) (sql/insert-multi! db :fruit [{:name "Apple"} {:name "Pear"}]))
-          rows (sql/query db ["SELECT * FROM fruit ORDER BY name"])]
-      (is (= [(returned-key db 1) (returned-key db 2)] new-keys))
-      (is (= [{:id (generated-key db 1) :name "Apple" :appearance nil :grade nil :cost nil}
-              {:id (generated-key db 2) :name "Pear" :appearance nil :grade nil :cost nil}] rows)))))
-
-(deftest insert-two-by-map-row-fn
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (let [new-keys (sql/insert-multi! db :fruit [{:name "Apple"} {:name "Pear"}]
-                                      {:row-fn (select-key db)})]
-      (is (= [(returned-key db 1) (returned-key db 2)] new-keys)))))
-
-(deftest insert-two-by-map-result-set-fn
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (is (= 2 (sql/insert-multi! db :fruit [{:name "Apple"} {:name "Pear"}]
-                                {:result-set-fn count})))))
-
-(deftest insert-identifiers-respected-1
-  (doseq [db (filter postgres? (test-specs))]
-    (create-test-table :fruit db)
-    (let [inserted (sql/insert! db
-                                :fruit
-                                {:name "Apple"}
-                                {:identifiers clojure.string/upper-case
-                                 :qualifier "foo"})
-          rows     (sql/query db ["SELECT * FROM fruit ORDER BY name"]
-                              {:identifiers clojure.string/upper-case
-                               :qualifier "foo"})]
-      (is (= rows inserted)))))
-
-(deftest insert-identifiers-respected-2
-  (doseq [db (filter postgres? (test-specs))]
-    (create-test-table :fruit db)
-    (let [inserted (sql/insert-multi! db
-                                      :fruit
-                                      [{:name "Apple"} {:name "Pear"}]
-                                      {:identifiers clojure.string/upper-case})
-          rows     (sql/query db ["SELECT * FROM fruit ORDER BY name"]
-                              {:identifiers clojure.string/upper-case})]
-      (is (= rows inserted)))))
-
-(deftest insert-two-by-map-and-query-as-arrays
-  ;; this test also serves to illustrate qualified keyword usage
-  (doseq [db (test-specs)]
-    ;; qualifier on table name ignored by default
-    (create-test-table :table/fruit db)
-    (let [new-keys (map (select-key db)
-                        ;; insert ignores namespace qualifier by default
-                        (sql/insert-multi! db :table/fruit
-                                           [{:fruit/name "Apple"}
-                                            {:fruit/name "Pear"}]))
-          rows (sql/query db ["SELECT * FROM fruit ORDER BY name"]
-                          {:as-arrays? :cols-as-is
-                           :qualifier "fruit"})]
-      (is (= [(returned-key db 1) (returned-key db 2)] new-keys))
-      (is (= [[:fruit/id :fruit/name :fruit/appearance :fruit/cost :fruit/grade]
-              [(generated-key db 1) "Apple" nil nil nil]
-              [(generated-key db 2) "Pear" nil nil nil]] rows)))))
-
-(deftest insert-two-by-cols-and-query
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (let [update-counts (sql/insert-multi! db :fruit [:name] [["Apple"] ["Pear"]])
-          rows (sql/query db ["SELECT * FROM fruit ORDER BY name"])]
-      (is (= [1 1] update-counts))
-      (is (= [{:id (generated-key db 1) :name "Apple" :appearance nil :grade nil :cost nil}
-              {:id (generated-key db 2) :name "Pear" :appearance nil :grade nil :cost nil}] rows)))))
-
-(deftest insert-update-and-query
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (let [new-keys (map (select-key db) (sql/insert! db :fruit {:name "Apple"}))
-          update-result (sql/update! db :fruit {:cost 12 :grade 1.2 :appearance "Green"}
-                                     ["id = ?" (generated-key db 1)])
-          rows (sql/query db ["SELECT * FROM fruit"])]
-      (is (= [(returned-key db 1)] new-keys))
-      (is (= [1] update-result))
-      (is (= [{:id (generated-key db 1)
-               :name "Apple" :appearance "Green"
-               :grade (float-or-double db 1.2)
-               :cost 12}] rows)))))
-
-(deftest insert-delete-and-query
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (let [new-keys (map (select-key db) (sql/insert! db :fruit {:name "Apple"}))
-          delete-result (sql/delete! db :fruit
-                                     ["id = ?" (generated-key db 1)])
-          rows (sql/query db ["SELECT * FROM fruit"])]
-      (is (= [(returned-key db 1)] new-keys))
-      (is (= [1] delete-result))
-      (is (= [] rows)))))
-
-(deftest insert-delete-and-query-in-connection
-  (doseq [db (test-specs)]
-    (sql/with-db-connection [con-db db]
-      (create-test-table :fruit con-db)
-      (let [new-keys (map (select-key db) (sql/insert! con-db :fruit {:name "Apple"}))
-            delete-result (sql/delete! con-db :fruit
-                                       ["id = ?" (generated-key con-db 1)])
-            rows (sql/query con-db ["SELECT * FROM fruit"])]
-        (is (= [(returned-key con-db 1)] new-keys))
-        (is (= [1] delete-result))
-        (is (= [] rows))))))
-
-#_{:clj-kondo/ignore [:invalid-arity]}
-(deftest illegal-insert-arguments
-  (doseq [db (test-specs)]
-    (illegal-arg-or-spec "insert!" (sql/insert! db))
-    (illegal-arg-or-spec "insert!" (sql/insert! db {:name "Apple"} [:name]))
-    (illegal-arg-or-spec "insert!" (sql/insert! db {:name "Apple"} [:name] {:entities identity}))
-    (illegal-arg-or-spec "insert!" (sql/insert! db [:name]))
-    (if with-spec? ; clojure.spec catches this differently
-      (is (thrown? clojure.lang.ExceptionInfo (sql/insert! db [:name] {:entities identity})))
-      (is (thrown? ClassCastException (sql/insert! db [:name] {:entities identity}))))))
-
-(deftest test-execute!-fails-with-multi-param-groups
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    ;; RuntimeException -> SQLException -> ArrayIndexOutOfBoundsException
-    (is (thrown? Exception
-                 (sql/execute!
-                  db
-                  ["INSERT INTO fruit (name,appearance) VALUES (?,?)"
-                   ["Apple" "rosy"]
-                   ["Pear" "yellow"]
-                   ["Orange" "round"]])))))
-
-(deftest test-execute!-with-multi?-true-param-groups
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    ;; RuntimeException -> SQLException -> ArrayIndexOutOfBoundsException
-    (let [counts (sql/execute!
-                  db
-                  ["INSERT INTO fruit (name,appearance) VALUES (?,?)"
-                   ["Apple" "rosy"]
-                   ["Pear" "yellow"]
-                   ["Orange" "round"]]
-                  {:multi? true})
-          rows (sql/query db ["SELECT * FROM fruit ORDER BY name"])]
-      (is (= [1 1 1] counts))
-      (is (= [{:id (generated-key db 1) :name "Apple" :appearance "rosy" :cost nil :grade nil}
-              {:id (generated-key db 3) :name "Orange" :appearance "round" :cost nil :grade nil}
-              {:id (generated-key db 2) :name "Pear" :appearance "yellow" :cost nil :grade nil}] rows)))))
-
-(deftest check-prepared-performance
-  (let [ones     (repeat 100 1)
-        select-1 [(str "select " (str/join ", " ones))]
-        select-? (into [(str "select "
-                             (str/join ", " (map (fn [_] "?") ones)))]
-                       ones)]
-    (println "\nSanity check on prepared statement parameter performance.")
-    (doseq [db (test-specs)
-            :when (not (or (derby? db) (hsqldb? db)))]
-      (println " " db)
-      (time (dotimes [n 100] (sql/query db select-1)))
-      (time (dotimes [n 100] (sql/query db select-?)))
-      (sql/with-db-connection [con db]
-        (time (dotimes [n 100] (sql/query con select-1)))
-        (time (dotimes [n 100] (sql/query con select-?)))))))
-
-(deftest test-create-table-ddl
-  (is (re-find #"`foo` int default 0"
-               (sql/create-table-ddl :table
-                                     [[:foo :int :default 0]]
-                                     {:entities (sql/quoted :mysql)}))))
-
-#_{:clj-kondo/ignore [:unresolved-symbol]}
-(comment
-   db (sql/create-table-ddl
-       table
-       [[:id :int "PRIMARY KEY AUTO_INCREMENT"]
-        [:name "VARCHAR(32)"]
-        [:appearance "VARCHAR(32)"]
-        [:cost :int]
-        [:grade :real]]
-       {:table-spec "ENGINE=InnoDB"}))
-
-(deftest test-resultset-read-column
-  (extend-protocol sql/IResultSetReadColumn
-    String
-    (result-set-read-column [s _ _] ::FOO))
-
-  (try
-    (doseq [db (test-specs)]
-      (create-test-table :fruit db)
-      (sql/insert-multi! db
-                         :fruit
-                         [:name :cost :grade]
-                         [["Crepes" 12 87.7]
-                          ["Vegetables" -88 nil]
-                          ["Teenage Mutant Ninja Turtles" 0 100.0]])
-      (is (= {:name ::FOO, :cost -88, :grade nil}
-             (sql/query db ["SELECT name, cost, grade FROM fruit WHERE name = ?"
-                            "Vegetables"]
-                        {:result-set-fn first}))))
-
-    ;; somewhat "undo" the first extension
-    (finally
-      (extend-protocol sql/IResultSetReadColumn
-        String
-        (result-set-read-column [s _ _] s)))))
-
-(deftest test-sql-value
-  (extend-protocol sql/ISQLValue
-    clojure.lang.Keyword
-    (sql-value [_] "KW"))
-
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (sql/insert! db
-                 :fruit
-                 [:name :cost :grade]
-                 [:test 12 nil])
-    (is (= {:name "KW", :cost 12, :grade nil}
-           (sql/query db ["SELECT name, cost, grade FROM fruit"]
-                      {:result-set-fn first}))))
-
-  ;; somewhat "undo" the first extension
-  (extend-protocol sql/ISQLValue
-    clojure.lang.Keyword
-    (sql-value [k] k)))
-
-(deftest test-sql-parameter
-  (extend-protocol sql/ISQLParameter
-    clojure.lang.Keyword
-    (set-parameter [v ^java.sql.PreparedStatement s ^long i]
-      (if (= :twelve v)
-        (.setLong   s i 12)
-        (.setString s i (str (name v) i)))))
-
-  (doseq [db (test-specs)]
-    (create-test-table :fruit db)
-    (sql/insert! db
-                 :fruit
-                 [:name :cost :grade]
-                 [:test :twelve nil])
-    (is (= {:name "test1", :cost 12, :grade nil}
-           (sql/query db ["SELECT name, cost, grade FROM fruit"]
-                      {:result-set-fn first}))))
-
-  ;; somewhat "undo" the first extension
-  (extend-protocol sql/ISQLParameter
-    clojure.lang.Keyword
-    (set-parameter [v ^java.sql.PreparedStatement s ^long i]
-      (.setObject s i (sql/sql-value v)))))
diff --git a/static/clojure-icon.gif b/static/clojure-icon.gif
new file mode 100644
index 00000000..84eee16d
Binary files /dev/null and b/static/clojure-icon.gif differ
diff --git a/static/clojure.css b/static/clojure.css
new file mode 100644
index 00000000..d40ea359
--- /dev/null
+++ b/static/clojure.css
@@ -0,0 +1,53 @@
+
+body {margin: 0;padding: 0;background-color: #e3e3e3;border-top: 4px solid #b3ccfe;color: #272727}
+body, .wiki, #Content, .wikipage {font-family: "Lucida Grande","Trebuchet MS","Bitstream Vera Sans",Verdana,Helvetica,sans-serif;font-size: 12px;line-height: 18px;}
+#leftcolumn .wiki_link, #toc, #toc a, .toc-header {font-size: 11px;line-height: 18px;text-decoration: none}
+img {border: 0;}
+#AllContentContainer {max-width: 96em;min-width: 663px;background: #fff url(space/content-background.gif) right repeat-y;padding: 0 40px 18px 0;}
+
+#Header {position: relative;clear: both;overflow: auto;height: 110px}
+#Logo {position: absolute;top: 0;left: 0;padding: 10px 0 0 62px;width: 138px;height: 100px}
+#Header h1 {float: left;border: 0;margin: 0;padding: 0;position: absolute;top: 50;left: 200px; height: 60px}
+#Header h1 a:link, #Header h1 a:visited, #Header h1 a:hover {color:#000000; text-decoration: none;}
+#Resources {min-height: 110px;width: 234px;padding: 5px 0;float: right;border-bottom: 1px solid #abc4e2;background: #e4eaf7 url(space/resources-background.gif) repeat-y;overflow: auto;}
+#Resources ul {margin: 0;padding: 0 25px;list-style: none;}
+#ResourcesB {float: right;}
+#Resources a {text-decoration: none;}
+#Resources a:link, #Resources a:visited, #Resources a:hover, #Resources a:active {color: #4c5770;}
+#Resources a:hover {text-decoration: underline;}
+
+#leftcolumn {margin: 0 0 0 22px;float: left;width: 168px;padding-bottom: 18px;background: #c5d2eb url(space/left-nav-bottom.gif) bottom no-repeat;}
+
+#leftcolumn ul {list-style: none;margin: 0;padding: 0;}
+
+#leftcolumn a, #leftcolumn .toc-header {font-weight: bold;display: block;background: transparent url(space/left-nav-divider.gif) repeat-x;padding: 6px 0 0 17px;margin: 12px 0 0 0;}
+#leftcolumn li a {font-weight: normal;background:none;margin: 0;padding: 0 0 0 17px;}
+#leftcolumn br {display: none;}
+#leftcolumn .menu {margin-top: 14px;background: #fff url(space/left-nav-background.gif) repeat-y;}
+
+#leftcolumn a:link , #leftcolumn a:visited , #leftcolumn a:active {color: #666;}
+#leftcolumn a:hover {text-decoration: underline;color: #222;}
+
+#rightcolumn {margin-left: 220px;}
+
+.wiki #toc {border: none;margin: 0 0 30px 18px;width: 222px;padding: 0 0 17px 12px;background: transparent url(space/toc-background.gif) repeat-y;border-bottom: 1px solid #d6d6d6;}
+.wiki #toc h1, .wiki #toc div {margin: 0;padding: 0;}
+.wiki #toc h1 {font-size: 14px;line-height: 18px;font-family: Georgia, "Times New Roman", Times, serif;font-style: italic;font-weight: normal;color: #969696;padding: 10px 0 8px 11px;}
+.wiki #toc a:link, .wiki #toc a:visited, .wiki #toc a:active {color: #646464;}
+.wiki #toc a:hover {background: none;color: #333333;}
+
+.wiki pre {font-family: Inconsolata, Monaco, Consolas, "Lucida Console", "Courier New", Courier, monospace;background-color: transparent;border: 0px;color: #000000}
+#DesignedBy { clear: both; text-align: right; margin-top: 18px;}
+#DesignedBy, #DesignedBy a, #DesignedBy a:link, #DesignedBy a:visited, #DesignedBy a:hover, #DesignedBy a:active { color: #999; }
+
+#WikiHeaderNavContainer { height: 36px; position: relative; }
+#leftcolumn .WikiActions a {display: inline;}
+
+.comment { color: gray; }
+.string {	color: teal; }
+.function { color: #00c; }
+.macro, .specialops { color: #60c; }
+.parens { color: #000; }
+.keyword { color: #c09; }
+.brackets { color: #006; }
+.curlybrackets { color: #906; }
diff --git a/static/favicon.png b/static/favicon.png
new file mode 100644
index 00000000..b1653e82
Binary files /dev/null and b/static/favicon.png differ
diff --git a/static/internal.css b/static/internal.css
new file mode 100644
index 00000000..08ce7fb2
--- /dev/null
+++ b/static/internal.css
@@ -0,0 +1,18 @@
+/* *** MISC STUFF USED ALL OVER *** */
+.nowrap { white-space: nowrap; }
+.hidden { display: none; }
+tr td .sm { font-size: 90%; }
+.grey { color: #666; }
+.smgrey { color: #666; font-size: 80%; }
+.grey a { color: #666; }
+.textentry { font-family: arial, helvetica, sans-serif; border: 1px solid #999; }
+.nopad { padding: 0; margin: 0; }
+.bblack { color: #000; font-size: 1.1em; font-weight: bold; }
+.bblacklight { color: #000; font-size: 1.1em; }
+
+/* IE6 min-height: http://www.dustindiaz.com/min-height-fast-hack */
+#content_view { display: block; padding-bottom: 2em; width: 100%; min-height: 600px; height: auto !important; height: 600px; }
+
+/* Used with .innerContentBox and #WikiAds to position the ad column */
+.contentBox { position: relative; min-height: 600px; height: auto !important; height: 600px; }
+
diff --git a/static/space/content-background.gif b/static/space/content-background.gif
new file mode 100644
index 00000000..0786c72c
Binary files /dev/null and b/static/space/content-background.gif differ
diff --git a/static/space/left-nav-background.gif b/static/space/left-nav-background.gif
new file mode 100644
index 00000000..e6e59044
Binary files /dev/null and b/static/space/left-nav-background.gif differ
diff --git a/static/space/left-nav-bottom.gif b/static/space/left-nav-bottom.gif
new file mode 100644
index 00000000..061c0895
Binary files /dev/null and b/static/space/left-nav-bottom.gif differ
diff --git a/static/space/left-nav-divider.gif b/static/space/left-nav-divider.gif
new file mode 100644
index 00000000..1854e565
Binary files /dev/null and b/static/space/left-nav-divider.gif differ
diff --git a/static/space/resources-background.gif b/static/space/resources-background.gif
new file mode 100644
index 00000000..9657769c
Binary files /dev/null and b/static/space/resources-background.gif differ
diff --git a/static/space/toc-background.gif b/static/space/toc-background.gif
new file mode 100644
index 00000000..0b7c95b9
Binary files /dev/null and b/static/space/toc-background.gif differ
diff --git a/static/wiki.css b/static/wiki.css
new file mode 100644
index 00000000..1cb1bdd4
--- /dev/null
+++ b/static/wiki.css
@@ -0,0 +1,22 @@
+/* Wiki Rendered Styles */
+.wiki { line-height: 150%; font-family: arial, helvetica, sans-serif; font-size: small; }
+.wiki h1 { font-weight: bold; padding: 5px 0 0 0; margin: 0; font-size: 1.4em; }
+.wiki h2 { font-weight: bold; padding: 5px 0 0 0; margin: 0; font-size: 1.3em; }
+.wiki h3 { font-weight: bold; padding: 5px 0 0 0; margin: 0; font-size: 1.1em; }
+.wiki h4 { font-weight: normal; padding: 5px 0 0 0; margin: 0; font-size: 1.066em; }
+.wiki h5 { font-weight: normal; padding: 5px 0 0 0; margin: 0; font-size: 1.033em; }
+.wiki h6 { font-weight: normal; padding: 5px 0 0 0; margin: 0; font-size: 1.0em; }
+.wiki table { border-collapse: collapse; margin: 10px 0; font-size: small; }
+.wiki p { margin: 0; padding: 0; padding: 5px 0; }
+.wiki td { border: 1px solid #DDD; }
+.wiki #toc { border: 1px solid #AAA; background: #fff; padding: 5px; margin: 0 0 10px 10px; width: 25%; float: right; clear: right;}
+.wiki #toc h1 { font-weight: normal; font-size: 1.2em; padding: 0; }
+.wiki #toc a:hover { color: #00D; background: #FFD; }
+
+.wiki hr { height: 1px; color: #AAA; background-color: #AAA; border: 0; margin: 0 10px; }
+.wiki ul { padding: .5em 0 0 3em; margin: 0; }
+.wiki ol { padding: .5em 0 0 3em; margin: 0; }
+.wiki ul.quotelist { list-style: none; }
+.wiki tt { font-size: small; }
+.wiki img { border: 0; padding: 4px; }
+
