-
Notifications
You must be signed in to change notification settings - Fork 0
/
data.json
1 lines (1 loc) · 267 KB
/
data.json
1
{"version":{"jar":{},"scm":{"files":{"CONTRIBUTING.md":"ade0a310b99d6ae5039625a7050dc1953f2a63a5243108c6f4984d650d237243","CODE_OF_CONDUCT.md":"8908b1b5570cbe66c84082dd67d919bdd5d4db55d37101afe72306d6cf13bdbb","test/next/jdbc_test.clj":"6c15107bb83157f0c2357983f49b06f562fb0597182062a93717c84d7bab16a5","test/next/jdbc/quoted_test.clj":"7af95f93e0991749ddd7e05dccead16d06f4721a9c4817ea0d899c34600ce140","pom.xml":"cafb327693f36ce543c1370410d79668dceb00202b50eb67714e9b13f2311093","test/next/jdbc/optional_test.clj":"7e2adb49936b649ee0b4ca031f3fefdd6fb515047e05bfb98a8f1ddd24c7d581","README.md":"44e2dc418f6eab877d7bb5fd056b289f7d805560b22821276b0d9804b116c6da","src/next/jdbc/datafy.clj":"76fce63b84bb3b78fe7db1f68bef2e5b0ce255c90bed341871a95d1687e5fdb2","test/next/jdbc/prepare_test.clj":"74c46e56a2273f1ffc9b24f11c8a4f3424c132487f88c24f6820e3f0d0794d69","src/next/jdbc/result_set.clj":"1e50f2c5515e36b0396ba2a68a0a26919d615e2f8d52f22b94dfd1edb4d92c48","run-tests.sh":"1db47e9feb08c198c263ec605badd338bf203b9204cd10b68f090d6db49111b6","test/next/jdbc/test_fixtures.clj":"a4c9e86ca67d546f2c68059911a62500c17c1d79b6e9e189740a052167f5100d","doc/all-the-options.md":"84628ad795ba683f1582adb68776404171cbdd7079cd4de48ddfb4a3cf7527ac","LICENSE":"a5cb01efb6648a83f1f466ea82c32bb52dc4c70ab27d0b70f0c7407d8fc3a815",".circleci/config.yml":"ae9a33ce12a03caadf009909d97c2dc3ce3fd18d59330b22281ca0448b29628b","test/next/jdbc/datafy_test.clj":"bb387532dbe5b7ed6204254ce2bb1248cf80f0982493883c8d3c5a39555d7534","doc/datafy-nav-and-schema.md":"fb77f60e164e243112598f9a2a58b1ec5f0009c0a687e83b86b8a794a3d19fc9","doc/friendly-sql-functions.md":"f6297bf52d6a0e87a68301c88b8bfb5368036d6f5aef4ed4c931c3720a8bf45e","src/next/jdbc/connection.clj":"45b20addab5c85b20fc50e0461aaaba088217213a22e66197fe54f3f6669dfcd","test/next/jdbc/specs_test.clj":"70ccf593aca2ec08398c337215c1b83117e2828969012ecb2c789aeaa9238222","test/next/jdbc/protocols_test.clj":"10796a0e462df1747f64d36ecdbe22595a11464e4ca9855c724e24fdf95f4cf6","doc/prepared-statements.md":"1a10503aec9339c845a7ec1dc61ce1de4eef2d056191d692a8f49e1a7e83c316","src/next/jdbc/types.clj":"270a9da90178789669ff5c5cfa541e8badcb7b157d92cb51725950ad9aa40062","test/next/jdbc/sql/builder_test.clj":"36ba3e741d270ba470d94c8b416802f1a537279ccd9256b0b7739ce5614cbe69","doc/result-set-builders.md":"16878a26f93b7c7663b91225eff8dcadfec078d2c2ccbd0567b0cc0c2ae62baf","src/next/jdbc/prepare.clj":"8587a7f65c0bf199739affc8818d734924f02891a9009138f60b0fd6f2d47c59","src/next/jdbc/sql.clj":"cc80d7bc92917aaf512c8d5274c0eed6a1810ff73dcc36cd235bbc45af845ea2","src/next/jdbc/sql/builder.clj":"c23e5ee3604cbd20c57ed417135a4cc732cf6cad89758a515727209b99ff919a","test/next/jdbc/plan_test.clj":"de7e53dfd09871c6d6c8e170bf100a5a791600642512115a4cd952e3f31f5798","src/next/jdbc/specs.clj":"997619ea6eaa6f65b7a7d3c18a3482d734c7544257d1caa34db3837a173d0538","src/next/jdbc/quoted.clj":"062e6027a031f7dcac1f8ee196c7cf985a64e073f9cef9341215952a147c7ff9",".joker":"c7ff9f973d0e13c7bea1e5bae4e6b96cfdcbc12eea9f7166da2ca495c90d4086","doc/migration-from-clojure-java-jdbc.md":"8ec1510330de771c65db2beeaf0ef22d8a32cb7e86f28cfd9e7efff7f15626e8","src/next/jdbc/date_time.clj":"dc4bc13ea6b92b8db6b61b3945d003f458dc7075796a3fea29a979872bc883a1",".github/workflows/test.yml":"d1b32c72ae68d8703ab2a582a5b435ed7b3fa952b3d135627cdc5fe2667777d7",".github/ISSUE_TEMPLATE/bug_report.md":"9f59dee3903ad83d642625460e8f1fae0d128fb41bd883abb565d647c78de194",".github/FUNDING.yml":"d4d13f9b3f4a8b397bf11351ab8798f33137761633a414b2f6cd5d3042ce9d42","test/next/jdbc/types_test.clj":"83a81383f9bbac31a06ba8659e097f752eb570a80dea2a84a4499456db9955ff","test/next/jdbc/sql_test.clj":"cdd5e7231355fb3eb85642a3d21fc1df85aa89f0b2def0b36117f729018f95c8","test/next/jdbc/date_time_test.clj":"a827d74d1ea6e8460826566ff014ab6ff5410122486922bafec5e55c9fc06c81",".gitignore":"0f52e455a95c79884637036847d13a439e3a1f0406c91f6af66c8e2e6e401332","src/next/jdbc/plan.clj":"82635769c8c7c03353fc14fd63bc85b8806eed341f27b776f9754d139240fcd8","src/next/jdbc/optional.clj":"63e39cbe0f013d56a8adfbd0278bda8427075228e5d39a344c970b1700548dc5","test/log4j2-info.properties":"7227b5ddf13f3988497d08dba3d923db1d955376862a7ce1934bc35a5ea2877a","src/next/jdbc/default_options.clj":"2c34c609bae49da932d0e45b417846769ae62d36f3d9d644dd4b5e22e7ca5e9e","src/next/jdbc/transaction.clj":"c3cdd21c97ec642b5e09c99d0e5dbf58ada35beaaa7b6f9a0c8eb0ccb22b6579",".github/ISSUE_TEMPLATE/feature_request.md":"1f48c52f209a971b8e7eae4120144d28fcf8ee38a7778a7b4d8cf1ab356617d2","doc/getting-started.md":"e91b35cfc89243b9a649459c6d207283614ba069f51bd03dedecd308d2ba4a9b","test/next/jdbc/connection_test.clj":"6b5761f64ec5fa0b76351b5a53f849a87b03259a35205e3a49a8df32d197f432","doc/cljdoc.edn":"edf8be43d04a0539cb0a793cd46d89d178d47efcccaffe786290febbecd6c742","CHANGELOG.md":"361622cb24f64f9689222a59f807b9d812284c9640ae51d8702803e8287b3f07","test/next/jdbc/default_options_test.clj":"e856226d7e547c20e77ff98aed2820485ccf6b4b0e1706cf45585022eff8959f","src/next/jdbc.clj":"175fa691033fe8f7e4b0282b78690324f0f1b84fc9c49443e030aea4ed8223a0","doc/transactions.md":"cda97e182ebcf39b20896cba6ababcdba67e090cb3c56985863395a9527787d8","deps.edn":"db688ede523a9ebfec3604925ad976186a21edb940943f6fcead30be60fe37e9","src/next/jdbc/protocols.clj":"288629465f5c3811633264632ff193ef3cfa93e885677e8c02dda9a480878c78","test/next/jdbc/result_set_test.clj":"472d47f6e0a1d656ba8209156d2fb0e724dc5dc5cbfa06fec831de7daa559199","test/next/jdbc/transaction_test.clj":"04247b47f80d4cefaf20c86fa3213d6b8f1a65dff0c43bfc059437044411ee6b","doc/tips-and-tricks.md":"ba06d3d61b08fbf3d2000c54cee91036a6779f62662cc6bd7bda9bdd5db38565"},"rev":"v1.2.659","branch":"develop","tag":{"name":"v1.2.659","sha":"1177b4ad440931b4537cbea8324230b46a0b73f1","commit":"1177b4ad440931b4537cbea8324230b46a0b73f1"},"url":"https://github.com/seancorfield/next-jdbc","commit":"v1.2.659"},"doc":[{"title":"Readme","attrs":{"cljdoc.doc/source-file":"README.md","cljdoc/markdown":"# next.jdbc [![CircleCI](https://circleci.com/gh/seancorfield/next-jdbc/tree/develop.svg?style=svg)](https://circleci.com/gh/seancorfield/next-jdbc/tree/develop)\n\nThe next generation of `clojure.java.jdbc`: a new low-level Clojure wrapper for JDBC-based access to databases.\n\n**Featured in [Jacek Schae's Learn Reitit Pro online course](https://www.jacekschae.com/learn-reitit-pro/pfec2)!**\n\n## TL;DR\n\nThe latest versions on Clojars and on cljdoc:\n\n[![Clojars Project](https://clojars.org/com.github.seancorfield/next.jdbc/latest-version.svg)](https://clojars.org/com.github.seancorfield/next.jdbc) [![cljdoc badge](https://cljdoc.org/badge/com.github.seancorfield/next.jdbc?1.2.659)](https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT)\n\nThe documentation on [cljdoc.org](https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT) is for the current version of `next.jdbc`:\n\n* [Getting Started](https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/doc/getting-started)\n* [API Reference](https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/api/next)\n* [Migrating from `clojure.java.jdbc`](https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/doc/migration-from-clojure-java-jdbc)\n* Feedback via [issues](https://github.com/seancorfield/next-jdbc/issues) or in the [`#sql` channel on the Clojurians Slack](https://clojurians.slack.com/messages/C1Q164V29/details/) or the [`#sql` stream on the Clojurians Zulip](https://clojurians.zulipchat.com/#narrow/stream/152063-sql).\n\nThe documentation on GitHub is for **develop** since the 1.2.659 release -- [see the CHANGELOG](https://github.com/seancorfield/next-jdbc/blob/develop/CHANGELOG.md) and then read the [corresponding updated documentation](https://github.com/seancorfield/next-jdbc/tree/develop/doc) on GitHub if you want. Older versions of `next.jdbc` were published under the `seancorfield` group ID and you can find [older seancorfield/next.jdbc documentation on cljdoc.org](https://cljdoc.org/versions/seancorfield/next.jdbc).\n\nThis project follows the version scheme MAJOR.MINOR.COMMITS where MAJOR and MINOR provide some relative indication of the size of the change, but do not follow semantic versioning. In general, all changes endeavor to be non-breaking (by moving to new names rather than by breaking existing names). COMMITS is an ever-increasing counter of commits since the beginning of this repository.\n\n## Motivation\n\nWhy another JDBC library? Why a different API from `clojure.java.jdbc`?\n\n* Performance: there's a surprising amount of overhead in how `ResultSet` objects are converted to sequences of hash maps in `clojure.java.jdbc` – which can be really noticeable for large result sets – so I wanted a better way to handle that. There's also quite a bit of overhead and complexity in all the conditional logic and parsing that is associated with `db-spec`-as-hash-map.\n* A more modern API, based on using qualified keywords and transducers etc: `:qualifier` and `reducible-query` in recent `clojure.java.jdbc` versions were steps toward that but there's a lot of \"legacy\" API in the library and I want to present a more focused, more streamlined API so folks naturally use the `IReduceInit` / transducer approach from day one and benefit from qualified keywords.\n* Simplicity: `clojure.java.jdbc` uses a variety of ways to execute SQL which can lead to inconsistencies and surprises – `query`, `execute!`, and `db-do-commands` are all different ways to execute different types of SQL statement so you have to remember which is which and you often have to watch out for restrictions in the underlying JDBC API.\n\nThose were my three primary drivers. In addition, the `db-spec`-as-hash-map approach in `clojure.java.jdbc` has caused a lot of frustration and confusion in the past, especially with the wide range of conflicting options that are supported. `next.jdbc` is heavily protocol-based so it's easier to mix'n'match how you use it with direct Java JDBC code (and the protocol-based approach contributes to the improved performance overall). There's a much clearer path of `db-spec` -> `DataSource` -> `Connection` now, which should steer people toward more connection reuse and better performing apps.\n\nI also wanted `datafy`/`nav` support baked right in (it was added to `clojure.java.jdbc` back in December 2018 as an undocumented, experimental API in a separate namespace). It is the default behavior for `execute!` and `execute-one!`. The protocol-based function `next.jdbc.result-set/datafiable-row` can be used with `plan` if you need to add `datafy`/`nav` support to rows you are creating in your reduction.\n\nAs `next.jdbc` moved from alpha to beta, the last breaking change was made (renaming `reducible!` to `plan`) and the API should be considered stable. Only accretive and fixative changes will be made from now on.\n\nAfter a month of alpha builds being available for testing, the first beta build was released on May 24th, 2019. A release candidate followed on June 4th and the \"gold\" (1.0.0) release was on June 12th. In addition to the small, core API in `next.jdbc`, there are \"syntactic sugar\" SQL functions (`insert!`, `query`, `update!`, and `delete!`) available in `next.jdbc.sql` that are similar to the main API in `clojure.java.jdbc`. See [Migrating from `clojure.java.jdbc`](https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/doc/migration-from-clojure-java-jdbc) for more detail about the differences.\n\n## Usage\n\nThe primary concepts behind `next.jdbc` are that you start by producing a `javax.sql.DataSource`. You can create a pooled datasource object using your preferred library (c3p0, hikari-cp, etc). You can use `next.jdbc`'s `get-datasource` function to create a `DataSource` from a `db-spec` hash map or from a JDBC URL (string). The underlying protocol, `Sourceable`, can be extended to allow more things to be turned into a `DataSource` (and can be extended via metadata on an object as well as via types).\n\nFrom a `DataSource`, either you or `next.jdbc` can create a `java.sql.Connection` via the `get-connection` function. You can specify an options hash map to `get-connection` to modify the connection that is created: `:read-only`, `:auto-commit`.\n\nThe primary SQL execution API in `next.jdbc` is:\n* `plan` -- yields an `IReduceInit` that, when reduced, executes the SQL statement and then reduces over the `ResultSet` with as little overhead as possible.\n* `execute!` -- executes the SQL statement and produces a vector of realized hash maps, that use qualified keywords for the column names, of the form `:<table>/<column>`. If you join across multiple tables, the qualified keywords will reflect the originating tables for each of the columns. If the SQL produces named values that do not come from an associated table, a simple, unqualified keyword will be used. The realized hash maps returned by `execute!` are `Datafiable` and thus `Navigable` (see Clojure 1.10's `datafy` and `nav` functions, and tools like Cognitect's REBL). Alternatively, you can specify `{:builder-fn rs/as-arrays}` and produce a vector with column names followed by vectors of row values. `rs/as-maps` is the default for `:builder-fn` but there are also `rs/as-unqualified-maps` and `rs/as-unqualified-arrays` if you want unqualified `:<column>` column names (and there are also lower-case variants of all of these).\n* `execute-one!` -- executes the SQL or DDL statement and produces a single realized hash map. The realized hash map returned by `execute-one!` is `Datafiable` and thus `Navigable`.\n\nIn addition, there are API functions to create `PreparedStatement`s (`prepare`) from `Connection`s, which can be passed to `plan`, `execute!`, or `execute-one!`, and to run code inside a transaction (the `transact` function and the `with-transaction` macro).\n\nSince `next.jdbc` uses raw Java JDBC types, you can use `with-open` directly to reuse connections and ensure they are cleaned up correctly:\n\n```clojure\n (let [my-datasource (jdbc/get-datasource {:dbtype \"...\" :dbname \"...\" ...})]\n (with-open [connection (jdbc/get-connection my-datasource)]\n (jdbc/execute! connection [...])\n (reduce my-fn init-value (jdbc/plan connection [...]))\n (jdbc/execute! connection [...])))\n```\n\n### Usage scenarios\n\nThere are three intended usage scenarios that have driven the design of the API:\n* Execute a SQL statement and process it in a single eager operation, which may allow for the results to be streamed from the database (how to persuade JDBC to do that is database-specific!), and which cleans up resources before returning the result -- even if the reduction is short-circuited via `reduced`. This usage is supported by `plan`. This is likely to be the fastest approach and should be the first option you consider for SQL queries.\n* Execute a SQL or DDL statement to obtain a single, fully-realized, `Datafiable` hash map that represents either the first row from a `ResultSet`, the first generated keys result (again, from a `ResultSet`), or the first result where neither of those are available (`next.jdbc` yields `{:next.jdbc/update-count N}` when it can only return an update count). This usage is supported by `execute-one!`. This is probably your best choice for most non-query operations.\n* Execute a SQL statement to obtain a fully-realized, `Datafiable` result set -- a vector of hash maps. This usage is supported by `execute!`. You can also produce a vector of column names/row values (`next.jdbc.result-set/as-arrays`).\n\nIn addition, convenience functions -- \"syntactic sugar\" -- are provided to insert rows, run queries, update rows, and delete rows, using the same names as in `clojure.java.jdbc`. These are in `next.jdbc.sql` since they involve SQL creation -- they are not considered part of the core API.\n\n## More Detailed Documentation\n\n* [Getting Started](/doc/getting-started.md)\n* [Friendly SQL Functions](/doc/friendly-sql-functions.md)\n* [Tips & Tricks](/doc/tips-and-tricks.md)\n* [Result Set Builders](/doc/result-set-builders.md)\n* [Prepared Statements](/doc/prepared-statements.md)\n* [Transactions](/doc/transactions.md)\n* [All The Options](/doc/all-the-options.md)\n* [`datafy`, `nav`, and `:schema`](/doc/datafy-nav-and-schema.md)\n* [Migration from `clojure.java.jdbc`](/doc/migration-from-clojure-java-jdbc.md)\n\n## License\n\nCopyright © 2018-2021 Sean Corfield\n\nDistributed under the Eclipse Public License version 1.0.\n","cljdoc.doc/type":"cljdoc/markdown","slug":"readme","cljdoc.doc/contributors":["Sean Corfield","Nate Smith","jreighley"]}},{"title":"Changes","attrs":{"cljdoc.doc/source-file":"CHANGELOG.md","cljdoc/markdown":"# Change Log\n\nOnly accretive/fixative changes will be made from now on.\n\n* 1.2.659 -- 2021-05-05\n * Address #164 by making `clj-commons/camel-snake-kebab` an unconditional dependency. _[Being a conditional dependency that could be brought in at runtime caused problems with GraalVM-based native compilation as well as with multi-project monorepos]_\n * Add **Tips & Tricks** section about working with PostgreSQL \"interval\" types (via PR #163 from @snorremd).\n * Address #162 by adding GraalVM to the test matrix (thank you @DeLaGuardo).\n * Update several dependency versions.\n\n* 1.1.646 -- 2021-03-15\n * Fix #161 by allowing `execute-batch!` to work with datasources and connections, and providing the SQL statement directly.\n\n* 1.1.643 -- 2021-03-06\n * Change coordinates to `com.github.seancorfield/next.jdbc` (although new versions will continue to be deployed to `seancorfield/next.jdbc` for a while -- see the [Clojars Verified Group Names policy](https://github.com/clojars/clojars-web/wiki/Verified-Group-Names)).\n * Documented `next.jdbc.transaction/*nested-tx*` more thoroughly since that difference from `clojure.java.jdbc` has come up in conversation a few times recently.\n * Fix #158 by documenting (and testing) `:allowMultiQueries true` as an option for MySQL/MariaDB to allow multiple statements to be executed and multiple result sets to be returned.\n * Fix #157 by copying `next.jdbc.prepare/execute-batch!` to `next.jdbc/execute-batch!` (to avoid a circular dependency that previously relied on requiring `next.jdbc.result-set` at runtime -- which was problematic for GraalVM-based native compilation); **`next.jdbc.prepare/execute-batch!` is deprecated:** it will continue to exist and work, but is no longer documented. In addition, `next.jdbc.prepare/execute-batch!` now relies on a private `volatile!` in order to reference `next.jdbc.result-set/datafiable-result-set` so that it is GraalVM-friendly. Note: code that requires `next.jdbc.prepare` and uses `execute-batch!` without also requiring something that causes `next.jdbc.result-set` to be loaded will no longer return generated keys from `execute-batch!` but that's an almost impossible path since nearly all code that uses `execute-batch!` will have called `next.jdbc/prepare` to get the `PreparedStatement` in the first place.\n\n* 1.1.613 -- 2020-11-05\n * Fix #144 by ensuring `camel-snake-case` is properly required before use in an uberjar context.\n\n* 1.1.610 -- 2020-10-19\n * Fix #140 by adding `\"duckdb\"` to `next.jdbc.connection/dbtypes`.\n * Change `next.jdbc.types/as-*` functions to use a thunk instead of a vector to convey metadata, so that wrapped values do not get unpacked by HoneySQL.\n * Refactor reducing and folding code around `ResultSet`, so that `reducible-result-set` and `foldable-result-set` can be exposed for folks who want more control over processing result sets obtained from database metadata.\n * `datafiable-result-set` can now be called without the `connectable` and/or `opts` arguments; a `nil` connectable now disables foreign key navigation in datafied results (rather than throwing an obscure exception).\n\n* 1.1.588 -- 2020-09-09\n * Fix #139 by adding `next.jdbc.plan/select-one!` and `next.jdbc.plan/select!`.\n * If `ResultSet.getMetaData()` returns `null`, we assume the column count is zero, i.e., an empty result set. This should \"never happen\" but some JDBC drivers are badly behaved and their idea of an \"empty result set\" does not match the JDBC API spec.\n\n* 1.1.582 -- 2020-08-05\n * Fix #138 by exposing `next.jdbc.connection/jdbc-url` to build `:jdbcUrl` values that can be passed to `->pool` or `component`.\n\n* 1.1.581 -- 2020-08-03\n * Fix #137 by adding support for specifying username and password per-connection (if your datasource supports this).\n * Document SQLite handling of `bool` and `bit` columns in a new **Tips & Tricks** section, inspired by #134.\n * Address #133 by adding `:return-generated-keys` as an option on `execute-batch!`.\n\n* 1.1.569 -- 2020-07-10\n * Fix #132 by adding specs for `next.jdbc/with-options` and `next.jdbc.prepare/statement`; correct spec for `next.jdbc.connection/component`. PR #131 from @Briaoeuidhtns.\n * Fix #130 by implementing `clojure.lang.ILookup` on the three builder adapters.\n * Fix #129 by adding `with-column-value` to `RowBuilder` and a more generic `builder-adapter`.\n * Fix #128 by adding a test for the \"not found\" arity of lookup on mapified result sets.\n * Fix #121 by conditionally adding `next.jdbc/snake-kebab-opts`, `next.jdbc/unqualified-snake-kebab-opts`, `next.jdbc.result-set/as-kebab-maps`, and `next.jdbc.result-set/as-unqualified-kebab-maps` (which are present only if `camel-snake-kebab` is on your classpath).\n * Correct MySQL batch statement rewrite tip: it's `:rewriteBatchedStatements true` (plural). Also surface the batch statement tips in the **Tips & Tricks** page.\n * Clarify how combining is interleaving with reducing in **Reducing and Folding with `plan`**.\n * Use \"JDBC URL\" consistently everywhere (instead of \"JDBC URI\" in several places).\n\n* 1.1.547 -- 2020-06-29\n * Address #125 by making the result of `plan` foldable (in the `clojure.core.reducers` sense).\n * Address #124 by extending `next.jdbc.sql.builder/for-query` to support `:top` (SQL Server), `:limit` / `:offset` (MySQL/PostgreSQL), `:offset` / `:fetch` (SQL Standard) for `find-by-keys`.\n * Address #117 by adding `next.jdbc.transaction/*nested-tx*` to provide control over how attempts to create nested transactions should be handled.\n * Address #116 by adding a `:multi-rs` option to `execute!` to retrieve multiple result sets, for example from stored procedure calls or T-SQL scripts.\n * Allow `:all` to be passed into `find-by-keys` instead of an example hash map or a where clause vector so all rows will be returned (expected to be used with `:offset` etc to support simple pagination of an entire table).\n * Add `:columns` option to `find-by-keys` (and `get-by-id`) to specify a subset of columns to be returned in each row. This can also specify an alias for the column and allows for computed expressions to be selected with an alias.\n\n* 1.0.478 -- 2020-06-24\n * Address #123 by adding `next.jdbc.types` namespace, full of auto-generated `as-xxx` functions, one for each of the `java.sql.Types` values.\n\n* 1.0.476 -- 2020-06-22\n * Extend default options behavior to `next.jdbc.sql` functions.\n\n* 1.0.475 -- 2020-06-22\n * Add tests for `\"jtds\"` database driver (against MS SQL Server), making it officially supported.\n * Switch from OpenTable Embedded PostgreSQL to Zonky's version, so that testing can move forward from PostgreSQL 10.11 to 12.2.0.\n * Fix potential reflection warnings caused by `next.jdbc.prepare/statement` being incorrectly type-hinted.\n * Address #122 by adding `next.jdbc/with-options` that lets you wrap up a connectable along with default options that should be applied to all operations on that connectable.\n * Address #119 by clarifying realization actions in the docstrings for `row-number`, `column-names`, and `metadata`.\n * Address #115 by adding equivalent of `db-do-commands` in the `clojure.java.jdbc` migration guide.\n * Add log4j2 as a test dependency so that I have better control over logging (which makes debugging easier!).\n\n* 1.0.462 -- 2020-05-31\n * Addition of `next.jdbc.datafy` to provide more `datafy`/`nav` introspection (see the additional section in **datafy, nav, and :schema** for details).\n * Addition of `next.jdbc.result-set/metadata` to provide (datafied) result set metadata within `plan`.\n\n* 1.0.445 -- 2020-05-23\n * Enhanced support in `plan` for \"metadata\" access: `row-number` and `column-names` can be called on the abstract row (even after calling `datafiable-row`). In addition, `Associative` access via numeric \"keys\" will read columns by index, and row abstractions now support `Indexed` access via `nth` (which will also read columns by index). Fixes #110.\n * Support for Stuart Sierra's Component library, via `next.jdbc.connection/component`. See updated **Getting Started** guide for usage.\n * Add example of getting generated keys from `execute-batch!`.\n * Add MySQL-specific result set streaming tip.\n * Add array handling example to PostgreSQL **Tips & Tricks**. PR #108 from @maxp.\n * Investigate possible solutions for #106 (mutable transaction thread safety) -- experimental `locking` on `Connection` object.\n\n* 1.0.424 -- 2020-04-10\n * In **Tips & Tricks**, noted that MySQL returns `BLOB` columns as `byte[]` instead of `java.sql.Blob`.\n * Address #103, #104 by adding a section on timeouts to **Tips & Tricks**.\n * Fix #102 by allowing keywords or strings in `:return-keys`.\n * Fix #101 by tightening the spec on a JDBC URL to correctly reflect that it must start with `jdbc:`.\n * Add support for calling `.getLoginTimeout`/`.setLoginTimeout` on the reified `DataSource` returned by `get-datasource` when called on a hash map \"db-spec\" or JDBC URL string.\n * Documentation improvements based on feedback (mostly from Slack), including a section on database metadata near the end of **Getting Started**.\n\n* 1.0.409 -- 2020-03-16\n * Address #100 by adding support for MariaDB (@green-coder). Set `NEXT_JDBC_TEST_MARIADB=true` as well as `NEXT_JDBC_TEST_MYSQL=true` in order to run tests against MariaDB.\n\n* 1.0.405 -- 2020-03-14 (no code changes -- just documentation)\n * Improve documentation around `plan` so `reduce` etc is more obvious.\n * Attempt to drive readers to cljdoc.org instead of the GitHub version (which is harder to navigate).\n\n* 1.0.395 -- 2020-03-02\n * Add `read-as-instant` and `read-as-local` functions to `next.jdbc.date-time` to extend `ReadableColumn` so that SQL `DATE` and `TIMESTAMP` columns can be read as Java Time types.\n * Specifically call out PostgreSQL as needing `next.jdbc.date-time` to enable automatic conversion of `java.util.Date` objects to SQL timestamps for prepared statements (#95).\n * Split **Tips & Tricks** into its own page, with a whole new section on using JSON data types with PostgreSQL (#94 -- thank you @vharmain).\n * Bump dependencies to latest.\n\n* 1.0.384 -- 2020-02-28\n * Add PostgreSQL streaming option information to **Tips & Tricks** (#87).\n * Minor documentation fixes (including #85, #92, #93).\n * Improve `Unknown dbtype` exception message (to clarify that `:classname` is also missing, #90).\n * Fix #88 by using 1-arity `keyword` call when table name unavailable (or `:qualifier-fn` returns `nil` or an empty string); also allows `:qualifier-fn` function to be called on empty table name (so `:qualifier-fn (constantly \"qual\")` will now work much like `clojure.java.jdbc`'s `:qualifier \"qual\"` worked).\n * Address #89, #91 by making minor performance tweaks to `next.jdbc.result-set` functions.\n * Planning to move to MAJOR.MINOR.COMMITS versioning scheme (1.0.384).\n\n* 1.0.13 -- 2019-12-20\n * Fix #82 by adding `clojure.java.data`-based support for setting arbitrary properties on `Connection` and `PreparedStatement` objects, post-creation. Note: this uses the Java reflection API under the hood.\n * Adds `next.jdbc.prepare/statement` to create `Statement` objects with all the options available to `prepare` except `:return-keys`.\n * Update `org.clojure/java.data` to 0.1.5 (for property setting).\n * Additional clarifications in the documentation based on feedback on Slack.\n\n* 1.0.12 -- 2019-12-11\n * Address #81 by splitting the SQL-building functions out of `next.jdbc.sql` into `next.jdbc.sql.builder`.\n * Fix #80 by avoiding the auto-commit restore after a failed rollback in a failed transaction.\n * Address #78 by documenting the `:connectionInitSql` workaround for HikariCP/PostgreSQL and non-default schemas.\n\n* 1.0.11 -- 2019-12-07\n * Fix #76 by avoiding conversions on `java.sql.Date` and `java.sql.Timestamp`.\n * Add testing against Microsoft SQL Server (run tests with environment variables `NEXT_JDBC_TEST_MSSQL=yes` and `MSSQL_SA_PASSWORD` set to your local -- `127.0.0.1:1433` -- SQL Server `sa` user password; assumes that it can create and drop `fruit` and `fruit_time` tables in the `model` database).\n * Add testing against MySQL (run tests with environment variables `NEXT_JDBC_TEST_MYSQL=yes` and `MYSQL_ROOT_PASSWORD` set to your local -- `127.0.0.1:3306` -- MySQL `root` user password; assumes you have already created an empty database called `clojure_test`).\n * Bump several JDBC driver versions for up-to-date testing.\n * Minor documentation fixes.\n\n* 1.0.10 -- 2019-11-14\n * Fix #75 by adding support for `java.sql.Statement` to `plan`, `execute!`, and `execute-one!`.\n * Address #74 by making several small changes to satisfy Eastwood.\n * Fix #73 by providing a new, optional namespace `next.jdbc.date-time` that can be required if your database driver needs assistance converting `java.util.Date` (PostgreSQL!) or the Java Time types to SQL `timestamp` (or SQL `date`/`time`).\n * Fix link to **All The Options** in **Migration from `clojure.java.jdbc`**. PR #71 (@laurio).\n * Address #70 by adding **CLOB & BLOB SQL Types** to the **Tips & Tricks** section of **Friendly SQL Functions** and by adding `next.jdbc.result-set/clob-column-reader` and `next.jdbc.result-set/clob->string` helper to make it easier to deal with `CLOB` column data.\n * Clarify what `execute!` and `execute-one!` produce when the result set is empty (`[]` and `nil` respectively, and there are now tests for this). Similarly for `find-by-keys` and `get-by-id`.\n * Add **MS SQL Server** section to **Tips & Tricks** to note that it returns an empty string for table names by default (so table-qualified column names are not available). Using the `:result-type` (scroll) and `:concurrency` options will cause table names to be returned.\n * Clarify that **Friendly SQL Functions** are deliberately simple (hint: they will not be enhanced or expanded -- use `plan`, `execute!`, and `execute-one!` instead, with a DSL library if you want!).\n * Improve migration docs: explicitly recommend the use of a datasource for code that needs to work with both `clojure.java.jdbc` and `next.jdbc`; add caveats about column name conflicts (in several places).\n * Improve `datafy`/`nav` documentation around `:schema`.\n * Update `org.clojure/java.data` to `\"0.1.4\"` (0.1.2 fixes a number of reflection warnings).\n\n* 1.0.9 -- 2019-10-11\n * Address #69 by trying to clarify when to use `execute-one!` vs `execute!` vs `plan`.\n * Address #68 by clarifying that builder functions do not affect the \"fake result set\" containing `:next.jdbc/update-count`.\n * Fix #67 by adding `:jdbcUrl` version spec.\n * Add `next.jdbc.optional/as-maps-adapter` to provide a way to override the default result set reading behavior of using `.getObject` when omitting SQL `NULL` values from result set maps.\n\n* 1.0.8 -- 2019-09-27\n * Fix #66 by adding support for a db-spec hash map format containing a `:jdbcUrl` key (consistent with `->pool`) so that you can create a datasource from a JDBC URL string and additional options.\n * Address #65 by adding a HugSQL \"quick start\" to the **Friendly SQL Functions** section of the docs.\n * Add `next.jdbc.specs/unstrument`. PR #64 (@gerred).\n * Address #63 by improving documentation around qualified column names and `:qualifier` (`clojure.java.jdbc`) migration, with a specific caveat about Oracle not fully supporting `.getTableName()`.\n\n* 1.0.7 -- 2019-09-09\n * Address #60 by supporting simpler schema entry formats: `:table/column` is equivalent to the old `[:table :column :one]` and `[:table/column]` is equivalent to the old `[:table :column :many]`. The older formats will continue to be supported but should be considered deprecated. PR #62 (@seancorfield).\n * Added test for using `ANY(?)` and arrays in PostgreSQL for `IN (?,,,?)` style queries. Added a **Tips & Tricks** section to **Friendly SQL Functions** with database-specific suggestions, that starts with this one.\n * Improved documentation in several areas.\n\n* 1.0.6 -- 2019-08-24\n * Improved documentation around `insert-multi!` and `execute-batch!` (addresses #57).\n * Fix #54 by improving documentation around data type conversions (and the `ReadableColumn` and `SettableParameter` protocols).\n * Fix #52 by using a US-locale function in the \"lower\" result set builders to avoid unexpected character changes in column names in locales such as Turkish. If you want the locale-sensitive behavior, pass `clojure.string/lower-case` into one of the \"modified\" result set builders.\n * Add `next.jdbc.result-set/as-maps-adapter` and `next.jdbc.result-set/as-arrays-adapter` to provide a way to override the default result set reading behavior of using `.getObject`.\n * Update `org.clojure/test.check` to `\"0.10.0\"`.\n\n* 1.0.5 -- 2019-08-05\n * Fix #51 by implementing `IPersistentMap` fully for the \"mapified\" result set inside `plan`. This adds support for `dissoc` and `cons` (which will both realize a row), `count` (which returns the column count but does not realize a row), `empty` (returns an empty hash map without realizing a row), etc.\n * Improved documentation around connection pooling (HikariCP caveats).\n\n* 1.0.4 -- 2019-07-24\n * Fix #50 by adding machinery to test against (embedded) PostgreSQL!\n * Improved documentation for connection pooled datasources (including adding a Component example); clarified the recommendations for globally overriding default options (write a wrapper namespace that suits your usage).\n * Note: this release is primarily to fix the cljdoc.org documentation via repackaging the JAR file.\n\n* 1.0.3 -- 2019-07-23\n * Fix #48 by adding `next.jdbc.connection/->pool` and documenting how to use HikariCP and c3p0 in the Getting Started docs (as well as adding tests for both libraries).\n * Documentation improvements, including examples of extending `ReadableColumn` and `SettableParameter`.\n * Updated test dependencies (testing against more recent versions of several drivers).\n\n* 1.0.2 -- 2019-07-15\n * Fix #47 by refactoring database specs to be a single hash map instead of pouring multiple maps into one.\n * Fix #46 by allowing `:host` to be `:none` which tells `next.jdbc` to omit the host/port section of the JDBC URL, so that local databases can be used with `:dbtype`/`:classname` for database types that `next.jdbc` does not know. Also added `:dbname-separator` and `:host-prefix` to the \"db-spec\" to allow fine-grained control over how the JDBC URL is assembled.\n * Fix #45 by adding [TimesTen](https://www.oracle.com/database/technologies/related/timesten.html) driver support.\n * Fix #44 so that `insert-multi!` with an empty `rows` vector returns `[]`.\n * Fix #43 by adjusting the spec for `insert-multi!` to \"require less\" of the `cols` and `rows` arguments.\n * Fix #42 by adding specs for `execute-batch!` and `set-parameters` in `next.jdbc.prepare`.\n * Fix #41 by improving docstrings and documentation, especially around prepared statement handling.\n * Fix #40 by adding `next.jdbc/execute-batch!` (previously `next.jdbc.prepare/execute-batch!`).\n * Added `assert`s in `next.jdbc.sql` as more informative errors for cases that would generate SQL exceptions (from malformed SQL).\n * Added spec for `:order-by` to reflect what is actually permitted.\n * Expose `next.jdbc.connect/dbtypes` as a table of known database types and aliases, along with their class name(s), port, and other JDBC string components.\n\n* 1.0.1 -- 2019-07-03\n * Fix #37 by adjusting the spec for `with-transaction` to \"require less\" of the `:binding` vector.\n * Fix #36 by adding type hint in `with-transaction` macro.\n * Fix #35 by explaining the database-specific options needed to ensure `insert-multi!` performs a single, batched operation.\n * Fix #34 by explaining save points (in the Transactions documentation).\n * Fix #33 by updating the spec for the example `key-map` in `find-by-keys`, `update!`, and `delete!` to reflect that you cannot pass an empty map to these functions (and added tests to ensure the calls fail with spec errors).\n\n* 1.0.0 \"gold\" -- 2019-06-12\n * Address #31 by making `reify`'d objects produce a more informative string representation if they are printed (e.g., misusing `plan` by not reducing it or not mapping an operation over the rows).\n * Fix #26 by exposing `next.jdbc.result-set/datafiable-result-set` so that various `java.sql.DatabaseMetaData` methods that return result metadata information in `ResultSet`s can be easily turned into a fully realized result set.\n\n* 1.0.0-rc1 -- 2019-06-04\n * Fix #24 by adding return type hints to `next.jdbc` functions.\n * Fix #22 by adding `next.jdbc.optional` with six map builders that omit `NULL` columns from the row hash maps.\n * Documentation improvements (#27, #28, and #29), including changing \"connectable\" to \"transactable\" for the `transact` function and the `with-transaction` macro (for consistency with the name of the underlying protocol).\n * Fix #30 by adding `modified` variants of column name functions and builders. The `lower` variants have been rewritten in terms of these new `modified` variants. This adds `:label-fn` and `:qualifier-fn` options that mirror `:column-fn` and `:table-fn` for row builders.\n\n* 1.0.0-beta1 -- 2019-05-24\n * Set up CircleCI testing (just local DBs for now).\n * Address #21 by adding `next.jdbc.specs` and documenting basic usage.\n * Fix #19 by caching loaded database driver classes.\n * Address #16 by renaming `reducible!` to `plan` (**BREAKING CHANGE!**).\n * Address #3 by deciding to maintain this library outside Clojure Contrib.\n\n## Alpha Builds\n\n* 1.0.0-alpha13 -- 2019-05-04 -- Fix #18 by removing more keys from properties when creating connections.\n* 1.0.0-alpha12 -- 2019-04-26 -- Fix #17 by renaming `:next.jdbc/sql-string` to `:next.jdbc/sql-params` (**BREAKING CHANGE!**) and pass whole vector.\n* 1.0.0-alpha11 -- 2019-04-24 -- Rename `:gen-fn` to `:builder-fn` (**BREAKING CHANGE!**); Fix #13 by adding documentation for `datafy`/`nav`/`:schema`; Fix #15 by automatically adding `:next.jdbc/sql-string` (as of 1.0.0-alpha12: `:next.jdbc/sql-params`) into the options hash map, so custom builders can depend on the SQL string.\n* 1.0.0-alpha9 -- 2019-04-22 -- Fix #14 by respecting `:gen-fn` (as of 1.0.0-alpha11: `:builder-fn`) in `execute-one!` for `PreparedStatement`.\n* 1.0.0-alpha8 -- 2019-04-21 -- Initial publicly announced release.\n","cljdoc.doc/type":"cljdoc/markdown","slug":"changes","cljdoc.doc/contributors":["Sean Corfield"]}},{"title":"Getting Started","attrs":{"cljdoc.doc/source-file":"doc/getting-started.md","cljdoc/markdown":"# Getting Started with next.jdbc\n\nThe `next.jdbc` library provides a simpler, faster alternative to the [`clojure.java.jdbc`](https://github.com/clojure/java.jdbc) Contrib library and is the next step in the evolution of that library.\n\nIt is designed to work with Clojure 1.10 or later, supports `datafy`/`nav`, and by default produces hash maps with automatically qualified keywords, indicating source tables and column names (labels), if your database supports that.\n\n## Installation\n\n**You must be using Clojure 1.10 or later.** 1.10.1 is the most recent stable version of Clojure (as of November 3rd, 2020).\n\nYou can add `next.jdbc` to your project with either:\n\n```clojure\ncom.github.seancorfield/next.jdbc {:mvn/version \"1.2.659\"}\n```\nfor `deps.edn` or:\n\n```clojure\n[com.github.seancorfield/next.jdbc \"1.2.659\"]\n```\nfor `project.clj` or `build.boot`.\n\n**In addition, you will need to add dependencies for the JDBC drivers you wish to use for whatever databases you are using. For example:**\n\n* MySQL: `mysql/mysql-connector-java {:mvn/version \"8.0.19\"}` ([search for latest version](https://search.maven.org/artifact/mysql/mysql-connector-java))\n* PostgreSQL: `org.postgresql/postgresql {:mvn/version \"42.2.10\"}` ([search for latest version](https://search.maven.org/artifact/org.postgresql/postgresql))\n* Microsoft SQL Server: `com.microsoft.sqlserver/mssql-jdbc {:mvn/version \"8.2.1.jre8\"}` ([search for latest version](https://search.maven.org/artifact/com.microsoft.sqlserver/mssql-jdbc))\n\n> Note: these are the versions that `next.jdbc` is tested against but there may be more recent versions and those should generally work too -- click the \"search for latest version\" link to see all available versions of those drivers on Maven Central. You can see the full list of drivers and versions that `next.jdbc` is tested against in [the project's `deps.edn` file](https://github.com/seancorfield/next-jdbc/blob/develop/deps.edn#L10-L27), but many other JDBC drivers for other databases should also work (e.g., Oracle, Red Shift).\n\n## An Example REPL Session\n\nTo start using `next.jdbc`, you need to create a datasource (an instance of `javax.sql.DataSource`). You can use `next.jdbc/get-datasource` with either a \"db-spec\" -- a hash map describing the database you wish to connect to -- or a JDBC URL string. Or you can construct a datasource from one of the connection pooling libraries out there, such as [HikariCP](https://brettwooldridge.github.io/HikariCP/) or [c3p0](https://www.mchange.com/projects/c3p0/) -- see [Connection Pooling](#connection-pooling) below.\n\nFor the examples in this documentation, we will use a local H2 database on disk, and we'll use the [Clojure CLI tools](https://clojure.org/guides/deps_and_cli) and `deps.edn`:\n\n```clojure\n;; deps.edn\n{:deps {org.clojure/clojure {:mvn/version \"1.10.3\"}\n com.github.seancorfield/next.jdbc {:mvn/version \"1.2.659\"}\n com.h2database/h2 {:mvn/version \"1.4.199\"}}}\n```\n\n### Create & Populate a Database\n\nIn this REPL session, we'll define an H2 datasource, create a database with a simple table, and then add some data and query it:\n\n```clojure\n> clj\nClojure 1.10.1\nuser=> (require '[next.jdbc :as jdbc])\nnil\nuser=> (def db {:dbtype \"h2\" :dbname \"example\"})\n#'user/db\nuser=> (def ds (jdbc/get-datasource db))\n#'user/ds\nuser=> (jdbc/execute! ds [\"\ncreate table address (\n id int auto_increment primary key,\n name varchar(32),\n email varchar(255)\n)\"])\n[#:next.jdbc{:update-count 0}]\nuser=> (jdbc/execute! ds [\"\ninsert into address(name,email)\n values('Sean Corfield','sean@corfield.org')\"])\n[#:next.jdbc{:update-count 1}]\nuser=> (jdbc/execute! ds [\"select * from address\"])\n[#:ADDRESS{:ID 1, :NAME \"Sean Corfield\", :EMAIL \"sean@corfield.org\"}]\nuser=>\n```\n\n### The \"db-spec\" hash map\n\nWe described the database with just `:dbtype` and `:dbname` because it is created as a local file and needs no authentication. For most databases, you would need `:user` and `:password` for authentication, and if the database is running on a remote machine you would need `:host` and possibly `:port` (`next.jdbc` tries to guess the correct port based on the `:dbtype`).\n\n> Note: You can see the full list of `:dbtype` values supported in [next.jdbc/get-datasource](https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/api/next.jdbc#get-datasource)'s docstring. If you need this programmatically, you can get it from the [next.jdbc.connection/dbtypes](https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/api/next.jdbc.connection#dbtypes) hash map. If those lists differ, the hash map is the definitive list (and I'll need to fix the docstring!). The docstring of that Var explains how to tell `next.jdbc` about additional databases.\n\nIf you already have a JDBC URL (string), you can use that as-is instead of the db-spec hash map. If you have a JDBC URL and still need additional options passed into the JDBC driver, you can use a hash map with the `:jdbcUrl` key specifying the string and whatever additional options you need.\n\n### `execute!` & `execute-one!`\n\nWe used `execute!` to create the `address` table, to insert a new row into it, and to query it. In all three cases, `execute!` returns a vector of hash maps with namespace-qualified keys, representing the result set from the operation, if available.\nIf the result set contains no rows, `execute!` returns an empty vector `[]`.\nWhen no result set is available, `next.jdbc` returns a \"result set\" containing the \"update count\" from the operation (which is usually the number of rows affected; note that `:builder-fn` does not affect this fake \"result set\"). By default, H2 uses uppercase names and `next.jdbc` returns these as-is.\n\nIf you only want a single row back -- the first row of any result set, generated keys, or update counts -- you can use `execute-one!` instead. Continuing the REPL session, we'll insert another address and ask for the generated keys to be returned, and then we'll query for a single row:\n\n```clojure\nuser=> (jdbc/execute-one! ds [\"\ninsert into address(name,email)\n values('Someone Else','some@elsewhere.com')\n\"] {:return-keys true})\n#:ADDRESS{:ID 2}\nuser=> (jdbc/execute-one! ds [\"select * from address where id = ?\" 2])\n#:ADDRESS{:ID 2, :NAME \"Someone Else\", :EMAIL \"some@elsewhere.com\"}\nuser=>\n```\n\nSince we used `execute-one!`, we get just one row back (a hash map). This also shows how you provide parameters to SQL statements -- with `?` in the SQL and then the corresponding parameter values in the vector after the SQL string.\nIf the result set contains no rows, `execute-one!` returns `nil`.\nWhen no result is available, and `next.jdbc` returns a fake \"result set\" containing the \"update count\", `execute-one!` returns just a single hash map with the key `next.jdbc/update-count` and the number of rows updated.\n\nIn the same way that you would use `execute-one!` if you only want one row or one update count, compared to `execute!` for multiple rows or a vector containing an update count, you can also ask `execute!` to return multiple result sets -- such as might be returned from a stored procedure call, or a T-SQL script (for SQL Server), or multiple statements (for MySQL) -- instead of just one. If you pass the `:multi-rs true` option to `execute!`, you will get back a vector of results sets, instead of just one result set: a vector of zero or more vectors. The result may well be a mix of vectors containing realized rows and vectors containing update counts, reflecting the results from specific SQL operations in the stored procedure or script.\n\n> Note: In general, you should use `execute-one!` for DDL operations since you will only get back an update count. If you have a SQL statement that you know will only return an update count, `execute-one!` is the right choice. If you have a SQL statement that you know will only return a single row in the result set, you probably want to use `execute-one!`. If you use `execute-one!` for a SQL statement that would return multiple rows in a result set, even though you will only get the first row back (as a hash map), the full result set will still be retrieved from the database -- it does not limit the SQL in any way.\n\n### Options & Result Set Builders\n\nAll functions in `next.jdbc` (except `get-datasource`) can accept, as the optional last argument, a hash map containing a [variety of options](/doc/all-the-options.md) that control the behavior of the `next.jdbc` functions.\n\nWe saw `:return-keys` provided as an option to the `execute-one!` function above and mentioned the `:builder-fn` option just above that. As noted, the default behavior is to return rows as hash maps with namespace-qualified keywords identifying the column names with the table name as the qualifier. There's a whole chapter on [result set builders](/doc/result-set-builders.md) but here's a quick example showing how to get unqualified, lower case keywords instead:\n\n```clojure\nuser=> (require '[next.jdbc.result-set :as rs])\nnil\nuser=> (jdbc/execute-one! ds [\"\ninsert into address(name,email)\n values('Someone Else','some@elsewhere.com')\n\"] {:return-keys true :builder-fn rs/as-unqualified-lower-maps})\n{:id 3}\nuser=> (jdbc/execute-one! ds [\"select * from address where id = ?\" 3]\n {:builder-fn rs/as-unqualified-lower-maps})\n{:id 3, :name \"Someone Else\", :email \"some@elsewhere.com\"}\nuser=>\n```\n\nRelying on the default result set builder -- and table-qualified column names -- is the recommended approach to take, if possible, with a few caveats:\n* MS SQL Server produces unqualified column names by default (see [**Tips & Tricks**](/doc/tips-and-tricks.md) for how to get table names back from MS SQL Server),\n* Oracle's JDBC driver doesn't support `.getTableName()` so it will only produce unqualified column names (also mentioned in **Tips & Tricks**),\n* If your SQL query joins tables in a way that produces duplicate column names, and you use unqualified column names, then those duplicated column names will conflict and you will get only one of them in your result -- use aliases in SQL (`as`) to make the column names distinct,\n* If your SQL query joins a table to itself under different aliases, the _qualified_ column names will conflict because they are based on the underlying table name provided by the JDBC driver rather the alias you used in your query -- again, use aliases in SQL to make those column names distinct.\n\nIf you want to pass the same set of options into several operations, you can use `next.jdbc/with-options` to wrap your datasource (or connection) in a way that will pass \"default options\". Here's the example above rewritten with that:\n\n```clojure\nuser=> (require '[next.jdbc.result-set :as rs])\nnil\nuser=> (def ds-opts (jdbc/with-options ds {:builder-fn rs/as-unqualified-lower-maps}))\n#'user/ds-opts\nuser=> (jdbc/execute-one! ds-opts [\"\ninsert into address(name,email)\n values('Someone Else','some@elsewhere.com')\n\"] {:return-keys true})\n{:id 4}\nuser=> (jdbc/execute-one! ds-opts [\"select * from address where id = ?\" 4])\n{:id 4, :name \"Someone Else\", :email \"some@elsewhere.com\"}\nuser=>\n```\n\n> Note: See the `next.jdbc/with-option` examples in the [**Datasources, Connections & Transactions**](#datasources-connections--transactions) below for some caveats around using this function.\n\nIn addition, two pre-built option hash maps are available in `next.jdbc`, that leverage the [camel-snake-kebab library](https://github.com/clj-commons/camel-snake-kebab/):\n* `snake-kebab-opts` -- provides `:column-fn`, `:table-fn`, `:label-fn`, `:qualifier-fn`, and `:builder-fn` that will convert Clojure identifiers in `:kebab-case` to SQL entities in `snake_case` and will produce result sets with qualified `:kebab-case` names from SQL entities that use `snake_case`,\n* `unqualified-snake-kebab-opts` -- provides `:column-fn`, `:table-fn`, `:label-fn`, `:qualifier-fn`, and `:builder-fn` that will convert Clojure identifiers in `:kebab-case` to SQL entities in `snake_case` and will produce result sets with _unqualified_ `:kebab-case` names from SQL entities that use `snake_case`.\n\n> Note: Using `camel-snake-kebab` might also be helpful if your database has `camelCase` table and column names, although you'll have to provide `:column-fn` and `:table-fn` yourself as `->camelCase` from that library. Either way, consider relying on the _default_ result set builder first and avoid converting column and table names (see [Advantages of 'snake case': portability and ubiquity](https://vvvvalvalval.github.io/posts/clojure-key-namespacing-convention-considered-harmful.html#advantages_of_'snake_case':_portability_and_ubiquity) for an interesting discussion on kebab-case vs snake_case -- I do not agree with all of the author's points in that article, particularly his position against qualified keywords, but his argument for retaining snake_case around system boundaries is compelling).\n\n\n### `plan` & Reducing Result Sets\n\nWhile the `execute!` and `execute-one!` functions are fine for retrieving result sets as data, most of the time you want to process that data efficiently without necessarily converting the entire result set into a Clojure data structure, so `next.jdbc` provides a SQL execution function that works with `reduce` and with transducers to consume the result set without the intermediate overhead of creating Clojure data structures for every row.\n\nWe're going to create a new table that contains invoice items so we can see how to use `plan` without producing data structures:\n\n```clojure\nuser=> (jdbc/execute-one! ds [\"\ncreate table invoice (\n id int auto_increment primary key,\n product varchar(32),\n unit_price decimal(10,2),\n unit_count int unsigned,\n customer_id int unsigned\n)\"])\n#:next.jdbc{:update-count 0}\nuser=> (jdbc/execute-one! ds [\"\ninsert into invoice (product, unit_price, unit_count, customer_id)\nvalues ('apple', 0.99, 6, 100),\n ('banana', 1.25, 3, 100),\n ('cucumber', 2.49, 2, 100)\n\"])\n#:next.jdbc{:update-count 3}\nuser=> (reduce\n (fn [cost row]\n (+ cost (* (:unit_price row)\n (:unit_count row))))\n 0\n (jdbc/plan ds [\"select * from invoice where customer_id = ?\" 100]))\n14.67M\n```\n\nThe call to `jdbc/plan` returns an `IReduceInit` object but does not actually run the SQL. Only when the returned object is reduced is the connection obtained from the data source, the SQL executed, and the computation performed. The connection is closed automatically when the reduction is complete. The `row` in the reduction is an abstraction over the underlying (mutable) `ResultSet` object -- it is not a Clojure data structure. Because of that, you can simply access the columns via their SQL labels as shown -- you do not need to use the column-qualified name, and you do not need to worry about the database returning uppercase column names (SQL labels are not case sensitive).\n\nHere's the same computation rewritten using `transduce`:\n\n```clojure\nuser=> (transduce\n (map #(* (:unit_price %) (:unit_count %)))\n +\n 0\n (jdbc/plan ds [\"select * from invoice where customer_id = ?\" 100]))\n14.67M\n```\n\nor composing the transforms:\n\n```clojure\nuser=> (transduce\n (comp (map (juxt :unit_price :unit_count))\n (map #(apply * %)))\n +\n 0\n (jdbc/plan ds [\"select * from invoice where customer_id = ?\" 100]))\n14.67M\n```\n\nIf you just wanted the total item count:\n\n```clojure\nuser=> (transduce\n (map :unit_count)\n +\n 0\n (jdbc/plan ds [\"select * from invoice where customer_id = ?\" 100]))\n11\n```\n\nYou can use other functions that perform reductions to process the result of `plan`, such as obtaining a set of unique products from an invoice:\n\n```clojure\nuser=> (into #{}\n (map :product)\n (jdbc/plan ds [\"select * from invoice where customer_id = ?\" 100]))\n#{\"apple\" \"banana\" \"cucumber\"}\n```\n\nAny operation that can perform key-based lookup can be used here without creating hash maps from the rows: `get`, `contains?`, `find` (returns a `MapEntry` of whatever key you requested and the corresponding column value), or direct keyword access as shown above. Any operation that would require a Clojure hash map, such as `assoc` or anything that invokes `seq` (`keys`, `vals`), will cause the full row to be expanded into a hash map, such as produced by `execute!` or `execute-one!`, which implements `Datafiable` and `Navigable` and supports lazy navigation via foreign keys, explained in [`datafy`, `nav`, and the `:schema` option](/doc/datafy-nav-and-schema.md).\n\nThis means that `select-keys` can be used to create regular Clojure hash map from (a subset of) columns in the row, without realizing the row, and it will not implement `Datafiable` or `Navigable`.\n\nIf you wish to create a Clojure hash map that supports that lazy navigation, you can call `next.jdbc.result-set/datafiable-row`, passing in the current row, a `connectable`, and an options hash map, just as you passed into `plan`. Compare the difference in output between these four expressions (see below for a simpler way to do this):\n\n```clojure\n;; selects specific keys (as simple keywords):\nuser=> (into []\n (map #(select-keys % [:id :product :unit_price :unit_cost :customer_id]))\n (jdbc/plan ds [\"select * from invoice where customer_id = ?\" 100]))\n;; selects specific keys (as qualified keywords):\nuser=> (into []\n (map #(select-keys % [:invoice/id :invoice/product\n :invoice/unit_price :invoice/unit_cost\n :invoice/customer_id]))\n (jdbc/plan ds [\"select * from invoice where customer_id = ?\" 100]))\n;; selects specific keys (as qualified keywords -- ignoring the table name):\nuser=> (into []\n (map #(select-keys % [:foo/id :bar/product\n :quux/unit_price :wibble/unit_cost\n :blah/customer_id]))\n (jdbc/plan ds [\"select * from invoice where customer_id = ?\" 100]))\n;; do not do this:\nuser=> (into []\n (map #(into {} %))\n (jdbc/plan ds [\"select * from invoice where customer_id = ?\" 100]))\n;; do this if you just want realized rows with default qualified names:\nuser=> (into []\n (map #(rs/datafiable-row % ds {}))\n (jdbc/plan ds [\"select * from invoice where customer_id = ?\" 100]))\n```\n\nThe latter produces a vector of hash maps, just like the result of `execute!`, where each \"row\" follows the case conventions of the database, the keys are qualified by the table name, and the hash map is datafiable and navigable. The third expression produces a result that looks identical but has stripped all the metadata away: it has still called `rs/datafiable-row` to fully-realize a datafiable and navigable hash map but it has then \"poured\" that into a new, empty hash map, losing the metadata.\n\nIn addition to the hash map operations described above, the abstraction over the `ResultSet` can also respond to a couple of functions in `next.jdbc.result-set`:\n\n* `next.jdbc.result-set/row-number` - returns the 1-based row number, by calling `.getRow()` on the `ResultSet`,\n* `next.jdbc.result-set/column-names` - returns a vector of column names from the `ResultSet`, as created by the result set builder specified,\n* `next.jdbc.result-set/metadata` - returns the `ResultSetMetaData` object, datafied (so the result will depend on whether you have required `next.jdbc.datafy`).\n\n> Note: Apache Derby requires the following options to be provided in order to call `.getRow()` (and therefore `row-number`): `{:concurrency :read-only, :cursors :close, :result-type :scroll-insensitive}`\n\nIf you realize a row, by calling `datafiable-row` on the abstract row passed into the reducing function, you can still call `row-number` and `column-names` on that realized row. These functions are _not_ available on the realized rows returned from `execute!` or `execute-one!`, only within reductions over `plan`.\n\nThe order of the column names returned by `column-names` matches SQL's natural order, based on the operation performed, and will also match the order of column values provided in the reduction when using an array-based result set builder (`plan` provides just the column values, one row at a time, when using an array-based builder, without the leading vector of column names that you would get from `execute!`: if you call `datafiable-row` on such a row, you will get a realized vector of column values).\n\n> Note: since `plan` expects you to process the result set via reduction, you should not use it for DDL or for SQL statements that only produce update counts.\n\nAs of 1.1.588, two helper functions are available to make some `plan` operations easier:\n\n* `next.jdbc.plan/select-one!` -- reduces over `plan` and returns part of just the first row,\n* `next.jdbc.plan/select!` -- reduces over `plan` and returns a sequence of parts of each row.\n\n`select!` accepts a vector of column names to extract or a function to apply to each row. It is equivalent to the following:\n\n```clojure\n;; select! with vector of column names:\nuser=> (into [] (map #(select-keys % cols)) (jdbc/plan ...))\n;; select! with a function:\nuser=> (into [] (map f) (jdbc/plan ...))\n```\n\nThe `:into` option lets you override the default of `[]` as the first argument to `into`.\n\n`select-one!` performs the same transformation on just the first row returned from a reduction over `plan`, equivalent to the following:\n\n```clojure\n;; select-one! with vector of column names:\nuser=> (reduce (fn [_ row] (reduced (select-keys row cols))) nil (jdbc/plan ...))\n;; select-one! with a function:\nuser=> (reduce (fn [_ row] (reduced (f row))) nil (jdbc/plan ...))\n```\n\nFor example:\n\n```clojure\n;; select columns:\nuser=> (plan/select-one!\n ds [:n] [\"select count(*) as n from invoice where customer_id = ?\" 100])\n{:n 3}\n;; apply a function:\nuser=> (plan/select-one!\n ds :n [\"select count(*) as n from invoice where customer_id = ?\" 100])\n3\n```\n\nHere are some of the above sequence-producing operations, showing their `select!` equivalent:\n\n```clojure\nuser=> (require '[next.jdbc.plan :as plan])\nnil\nuser=> (into #{}\n (map :product)\n (jdbc/plan ds [\"select * from invoice where customer_id = ?\" 100]))\n#{\"apple\" \"banana\" \"cucumber\"}\n;; or:\nuser=> (plan/select! ds\n :product\n [\"select * from invoice where customer_id = ?\" 100]\n {:into #{}}) ; product a set, rather than a vector\n#{\"apple\" \"banana\" \"cucumber\"}\n;; selects specific keys (as simple keywords):\nuser=> (into []\n (map #(select-keys % [:id :product :unit_price :unit_cost :customer_id]))\n (jdbc/plan ds [\"select * from invoice where customer_id = ?\" 100]))\n;; or:\nuser=> (plan/select! ds\n [:id :product :unit_price :unit_cost :customer_id]\n [\"select * from invoice where customer_id = ?\" 100])\n;; selects specific keys (as qualified keywords):\nuser=> (into []\n (map #(select-keys % [:invoice/id :invoice/product\n :invoice/unit_price :invoice/unit_cost\n :invoice/customer_id]))\n (jdbc/plan ds [\"select * from invoice where customer_id = ?\" 100]))\n;; or:\nuser=> (plan/select! ds\n [:invoice/id :invoice/product\n :invoice/unit_price :invoice/unit_cost\n :invoice/customer_id]\n [\"select * from invoice where customer_id = ?\" 100])\n;; selects specific keys (as qualified keywords -- ignoring the table name):\nuser=> (into []\n (map #(select-keys % [:foo/id :bar/product\n :quux/unit_price :wibble/unit_cost\n :blah/customer_id]))\n (jdbc/plan ds [\"select * from invoice where customer_id = ?\" 100]))\n;; or:\nuser=> (plan/select! ds\n [:foo/id :bar/product\n :quux/unit_price :wibble/unit_cost\n :blah/customer_id]\n [\"select * from invoice where customer_id = ?\" 100])\n```\n\n> Note: you need to be careful when using stateful transducers, such as `partition-by`, when reducing over the result of `plan`. Since `plan` returns an `IReduceInit`, the resource management (around the `ResultSet`) only applies to the `reduce` operation: many stateful transducers have a completing function that will access elements of the result sequence -- and this will usually fail after the reduction has cleaned up the resources. This is an inherent problem with stateful transducers over resource-managing reductions with no good solution.\n\n## Datasources, Connections & Transactions\n\nIn the examples above, we created a datasource and then passed it into each function call. When `next.jdbc` is given a datasource, it creates a `java.sql.Connection` from it, uses it for the SQL operation (by creating and populating a `java.sql.PreparedStatement` from the connection and the SQL string and parameters passed in), and then closes it. If you're not using a connection pooling datasource (see below), that can be quite an overhead: setting up database connections to remote servers is not cheap!\n\nIf you want to run multiple SQL operations without that overhead each time, you can create the connection yourself and reuse it across several operations using `with-open` and `next.jdbc/get-connection`:\n\n```clojure\n(with-open [con (jdbc/get-connection ds)]\n (jdbc/execute! con ...)\n (jdbc/execute! con ...)\n (into [] (map :column) (jdbc/plan con ...)))\n```\n\nIf any of these operations throws an exception, the connection will still be closed but operations prior to the exception will have already been committed to the database. If you want to reuse a connection across multiple operations but have them all rollback if an exception occurs, you can use `next.jdbc/with-transaction`:\n\n```clojure\n(jdbc/with-transaction [tx ds]\n (jdbc/execute! tx ...)\n (jdbc/execute! tx ...)\n (into [] (map :column) (jdbc/plan tx ...)))\n```\n\nIf `with-transaction` is given a datasource, it will create and close the connection for you. If you pass in an existing connection, `with-transaction` will set up a transaction on that connection and, after either committing or rolling back the transaction, will restore the state of the connection and leave it open:\n\n```clojure\n(with-open [con (jdbc/get-connection ds)]\n (jdbc/execute! con ...) ; committed\n (jdbc/with-transaction [tx con] ; will commit or rollback this group:\n (jdbc/execute! tx ...)\n (jdbc/execute! tx ...)\n (into [] (map :column) (jdbc/plan tx ...)))\n (jdbc/execute! con ...)) ; committed\n```\n\nYou can read more about [working with transactions](/doc/transactions.md) further on in the documentation.\n\n> Note: Because `get-datasource` and `get-connection` return plain JDBC objects (`javax.sql.DataSource` and `java.sql.Connection` respectively), `next.jdbc/with-options` cannot flow options across those calls, so if you are explicitly managing connections or transactions as above, you would need to have local bindings for the wrapped versions:\n\n```clojure\n(with-open [con (jdbc/get-connection ds)]\n (let [con-opts (jdbc/with-options con some-options)]\n (jdbc/execute! con-opts ...) ; committed\n (jdbc/with-transaction [tx con-opts] ; will commit or rollback this group:\n (let [tx-opts (jdbc/with-options tx (:options con-opts)]\n (jdbc/execute! tx-opts ...)\n (jdbc/execute! tx-opts ...)\n (into [] (map :column) (jdbc/plan tx-opts ...))))\n (jdbc/execute! con-opts ...))) ; committed\n```\n\n### Prepared Statement Caveat\n\nNot all databases support using a `PreparedStatement` for every type of SQL operation. You might have to create a `java.sql.Statement` instead, directly from a `java.sql.Connection` and use that, without parameters, in `plan`, `execute!`, or `execute-one!`. See the following example:\n\n```clojure\n(require '[next.jdbc.prepare :as prep])\n\n(with-open [con (jdbc/get-connection ds)]\n (jdbc/execute! (prep/statement con) [\"...just a SQL string...\"])\n (jdbc/execute! con [\"...some SQL...\" \"and\" \"parameters\"]) ; uses PreparedStatement\n (into [] (map :column) (jdbc/plan (prep/statement con) [\"...\"])))\n```\n\n## Connection Pooling\n\n`next.jdbc` makes it easy to use either HikariCP or c3p0 for connection pooling.\n\nFirst, you need to add the connection pooling library as a dependency, e.g.,\n\n```clojure\ncom.zaxxer/HikariCP {:mvn/version \"3.3.1\"}\n;; or:\ncom.mchange/c3p0 {:mvn/version \"0.9.5.4\"}\n```\n\n_Check those libraries' documentation for the latest version to use!_\n\nThen import the appropriate classes into your code:\n\n```clojure\n(ns my.main\n (:require [next.jdbc :as jdbc]\n [next.jdbc.connection :as connection])\n (:import (com.zaxxer.hikari HikariDataSource)\n ;; or:\n (com.mchange.v2.c3p0 ComboPooledDataSource PooledDataSource)))\n```\n\nFinally, create the connection pooled datasource. `db-spec` here contains the regular `next.jdbc` options (`:dbtype`, `:dbname`, and maybe `:host`, `:port`, `:classname` etc -- or the `:jdbcUrl` format mentioned above). Those are used to construct the JDBC URL that is passed into the datasource object (by calling `.setJdbcUrl` on it). You can also specify any of the connection pooling library's options, as mixed case keywords corresponding to any simple setter methods on the class being passed in, e.g., `:connectionTestQuery`, `:maximumPoolSize` (HikariCP), `:maxPoolSize`, `:preferredTestQuery` (c3p0).\n\nSome important notes regarding HikariCP:\n\n* Authentication credentials must use `:username` (if you are using c3p0 or regular, non-pooled, connections, then the db-spec hash map must contain `:user`).\n* When using `:dbtype \"jtds\"`, you must specify `:connectionTestQuery \"SELECT 1\"` (or some other query to verify the health of a connection) because the jTDS JDBC driver does not implement `.isValid()` so HikariCP requires a specific test query instead (c3p0 does not rely on this method so it works with jTDS without needing `:preferredTestQuery`).\n* When using PostgreSQL, and trying to set a default `:schema` via HikariCP, you will need to specify `:connectionInitSql \"COMMIT;\"` until [this HikariCP issue](https://github.com/brettwooldridge/HikariCP/issues/1369) is addressed.\n\nYou will generally want to create the connection pooled datasource at the start of your program (and close it before you exit, although that's not really important since it'll be cleaned up when the JVM shuts down):\n\n```clojure\n(defn -main [& args]\n (with-open [^HikariDataSource ds (connection/->pool HikariDataSource db-spec)]\n (jdbc/execute! ds ...)\n (jdbc/execute! ds ...)\n (do-other-stuff ds args)\n (into [] (map :column) (jdbc/plan ds ...))))\n;; or:\n(defn -main [& args]\n (with-open [^PooledDataSource ds (connection/->pool ComboPooledDataSource db-spec)]\n (jdbc/execute! ds ...)\n (jdbc/execute! ds ...)\n (do-other-stuff ds args)\n (into [] (map :column) (jdbc/plan ds ...))))\n```\n\nYou only need the type hints on `ds` if you plan to call methods on it via Java interop, such as `.close` (or using `with-open` to auto-close it) and you want to avoid reflection.\n\nIf you are using [Component](https://github.com/stuartsierra/component), a connection pooled datasource is a good candidate since it has a `start`/`stop` lifecycle. `next.jdbc` has support for Component built-in, via the `next.jdbc.connection/component` function which creates a Component-compatible entity which you can `start` and then invoke as a function with no arguments to obtain the `DataSource` within.\n\n```clojure\n(ns my.data.program\n (:require [com.stuartsierra.component :as component]\n [next.jdbc :as jdbc]\n [next.jdbc.connection :as connection])\n (:import (com.zaxxer.hikari HikariDataSource)))\n\n;; HikariCP requires :username instead of :user in the db-spec:\n(def ^:private db-spec {:dbtype \"...\" :dbname \"...\" :username \"...\" :password \"...\"})\n\n(defn -main [& args]\n ;; connection/component takes the same arguments as connection/->pool:\n (let [ds (component/start (connection/component HikariDataSource db-spec))]\n (try\n ;; \"invoke\" the data source component to get the javax.sql.DataSource:\n (jdbc/execute! (ds) ...)\n (jdbc/execute! (ds) ...)\n ;; can pass the data source component around other code:\n (do-other-stuff ds args)\n (into [] (map :column) (jdbc/plan (ds) ...))\n (finally\n ;; stopping the component will close the connection pool:\n (component/stop ds)))))\n```\n\n## Working with Additional Data Types\n\nBy default, `next.jdbc` relies on the JDBC driver to handle all data type conversions when reading from a result set (to produce Clojure values from SQL values) or setting parameters (to produce SQL values from Clojure values). Sometimes that means that you will get back a database-specific Java object that would need to be manually converted to a Clojure data structure, or that certain database column types require you to manually construct the appropriate database-specific Java object to pass into a SQL operation. You can usually automate those conversions using either the [`ReadableColumn` protocol](/doc/result-set-builders.md#readablecolumn) (for converting database-specific types to Clojure values) or the [`SettableParameter` protocol](/doc/prepared-statements.md#prepared-statement-parameters) (for converting Clojure values to database-specific types).\n\nIn particular, PostgreSQL does not seem to perform a conversion from `java.util.Date` to a SQL data type automatically. You can `require` the [`next.jdbc.date-time` namespace](https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/api/next.jdbc.date-time) to enable that conversion.\n\nIf you are working with Java Time, some JDBC drivers will automatically convert `java.time.Instant` (and `java.time.LocalDate` and `java.time.LocalDateTime`) to a SQL data type automatically, but others will not. Requiring `next.jdbc.date-time` will enable those automatic conversions for all databases.\n\n> Note: `next.jdbc.date-time` also provides functions you can call to enable automatic conversion of SQL date/timestamp types to Clojure data types when reading result sets. If you need specific conversions beyond that to happen automatically, consider extending the `ReadableColumn` protocol, mentioned above.\n\nThe `next.jdbc.types` namespace provides over three dozen convenience functions for \"type hinting\" values so that the JDBC driver might automatically handle some conversions that the default parameter setting function does not. Each function is named for the corresponding SQL type, prefixed by `as-`: `as-bigint`, `as-other`, `as-real`, etc. An example of where this helps is when dealing with PostgreSQL enumerated types: the default behavior, when passed a string that should correspond to an enumerated type, is to throw an exception that `column \"...\" is of type ... but expression is of type character varying`. You can wrap such strings with `(as-other \"...\")` which tells PostgreSQL to treat this as `java.sql.Types/OTHER` when setting the parameter.\n\n## Processing Database Metadata\n\nJDBC provides several features that let you introspect the database to obtain lists of tables, views, and so on. `next.jdbc` does not provide any specific functions for this but you can easily get this metadata from a `java.sql.Connection` and turn it into Clojure data as follows:\n\n```clojure\n(with-open [con (p/get-connection ds opts)]\n (-> (.getMetaData con) ; produces java.sql.DatabaseMetaData\n ;; return a java.sql.ResultSet describing all tables and views:\n (.getTables nil nil nil (into-array [\"TABLE\" \"VIEW\"]))\n (rs/datafiable-result-set ds opts)))\n```\n\nSeveral methods on `DatabaseMetaData` return a `ResultSet` object, e.g., `.getCatalogs()`, `.getClientInfoProperties()`, `.getSchemas()`.\nAll of those can be handled in a similar manner to the above. See the [Oracle documentation for `java.sql.DatabaseMetaData`](https://docs.oracle.com/en/java/javase/11/docs/api/java.sql/java/sql/DatabaseMetaData.html) (Java 11) for more details.\n\n## Support from Specs\n\nAs you are developing with `next.jdbc`, it can be useful to have assistance from `clojure.spec` in checking calls to `next.jdbc`'s functions, to provide explicit argument checking and/or better error messages for some common mistakes, e.g., trying to pass a plain SQL string where a vector (containing a SQL string, and no parameters) is expected.\n\nYou can enable argument checking for functions in `next.jdbc`, `next.jdbc.connection`, `next.jdbc.prepare`, and `next.jdbc.sql` by requiring the `next.jdbc.specs` namespace and instrumenting the functions. A convenience function is provided:\n\n```clojure\n(require '[next.jdbc.specs :as specs])\n(specs/instrument) ; instruments all next.jdbc API functions\n\n(jdbc/execute! ds \"SELECT * FROM fruit\")\nCall to #'next.jdbc/execute! did not conform to spec.\n```\n\nIn the `:problems` output, you'll see the `:path [:sql :sql-params]` and `:pred vector?` for the `:val \"SELECT * FROM fruit\"`. Without the specs' assistance, this mistake would produce a more cryptic error, a `ClassCastException`, that a `Character` cannot be cast to a `String`, from inside `next.jdbc.prepare`.\n\nA convenience function also exists to revert that instrumentation:\n\n```clojure\n(specs/unstrument) ; undoes the instrumentation of all next.jdbc API functions\n```\n\n[Friendly SQL Functions :>](/doc/friendly-sql-functions.md)\n","cljdoc.doc/type":"cljdoc/markdown","slug":"getting-started","cljdoc.doc/contributors":["Sean Corfield"]},"children":[{"title":"Friendly SQL Functions","attrs":{"cljdoc.doc/source-file":"doc/friendly-sql-functions.md","cljdoc/markdown":"# Friendly SQL Functions\n\nIn [Getting Started](/doc/getting-started.md), we used `execute!` and `execute-one!` for all our SQL operations, except when we were reducing a result set. These functions (and `plan`) all expect a \"connectable\" and a vector containing a SQL string followed by any parameter values required.\n\nA \"connectable\" can be a `javax.sql.DataSource`, a `java.sql.Connection`, or something that can produce a datasource (when `get-datasource` is called on it). It can also be a `java.sql.PreparedStatement` but we'll cover that a bit later...\n\nBecause string-building isn't always much fun, `next.jdbc.sql` also provides some \"friendly\" functions for basic CRUD operations:\n\n* `insert!` and `insert-multi!` -- for inserting one or more rows into a table -- \"Create\",\n* `query` -- an alias for `execute!` when using a vector of SQL and parameters -- \"Read\",\n* `update!` -- for updating one or more rows in a table -- \"Update\",\n* `delete!` -- for deleting one or more rows in a table -- \"Delete\".\n\nas well as these more specific \"read\" operations:\n\n* `find-by-keys` -- a query on one or more column values, specified as a hash map or `WHERE` clause,\n* `get-by-id` -- a query to return a single row, based on a single column value, usually the primary key.\n\nThese functions are described in more detail below. They are deliberately simple and intended to cover only the most common, basic SQL operations. The primary API (`plan`, `execute!`, `execute-one!`) is the recommended approach for everything beyond that. If you need more expressiveness, consider one of the following libraries to build SQL/parameter vectors, or run queries:\n\n* [HoneySQL](https://github.com/jkk/honeysql) -- a composable DSL for creating SQL/parameter vectors from Clojure data structures\n* [seql](https://github.com/exoscale/seql) -- a simplified EQL-inspired query language, built on `next.jdbc` (as of release 0.1.6)\n* [SQLingvo](https://github.com/r0man/sqlingvo) -- a composable DSL for creating SQL/parameter vectors\n* [Walkable](https://github.com/walkable-server/walkable) -- full EQL query language support for creating SQL/parameter vectors\n\nIf you prefer to write your SQL separately from your code, take a look at [HugSQL](https://github.com/layerware/hugsql) -- [HugSQL documentation](https://www.hugsql.org/) -- which has a `next.jdbc` adapter, as of version 0.5.1. See below for a \"[quick start](#hugsql-quick-start)\" for using HugSQL with `next.jdbc`.\n\n## `insert!`\n\nGiven a table name (as a keyword) and a hash map of column names and values, this performs a single row insertion into the database:\n\n```clojure\n(sql/insert! ds :address {:name \"A. Person\" :email \"albert@person.org\"})\n;; equivalent to\n(jdbc/execute-one! ds [\"INSERT INTO address (name,email) VALUES (?,?)\"\n \"A.Person\" \"albert@person.org\"] {:return-keys true})\n```\n\n## `insert-multi!`\n\nGiven a table name (as a keyword), a vector of column names, and a vector of row value vectors, this performs a multi-row insertion into the database:\n\n```clojure\n(sql/insert-multi! ds :address\n [:name :email]\n [[\"Stella\" \"stella@artois.beer\"]\n [\"Waldo\" \"waldo@lagunitas.beer\"]\n [\"Aunt Sally\" \"sour@lagunitas.beer\"]])\n;; equivalent to\n(jdbc/execute! ds [\"INSERT INTO address (name,email) VALUES (?,?), (?,?), (?,?)\"\n \"Stella\" \"stella@artois.beer\"\n \"Waldo\" \"waldo@lagunitas.beer\"\n \"Aunt Sally\" \"sour@lagunitas.beer\"] {:return-keys true})\n```\n\n> Note: this expands to a single SQL statement with placeholders for every\nvalue being inserted -- for large sets of rows, this may exceed the limits\non SQL string size and/or number of parameters for your JDBC driver or your\ndatabase. Several databases have a limit of 1,000 parameter placeholders.\nOracle does not support this form of multi-row insert, requiring a different\nsyntax altogether.\n\nYou should look at [`next.jdbc/execute-batch!`](https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/api/next.jdbc#execute-batch!) for an alternative approach.\n\n## `query`\n\nGiven a vector of SQL and parameters, execute it:\n\n```clojure\n(sql/query ds [\"select * from address where name = ?\" \"Stella\"])\n;; equivalent to\n(jdbc/execute! ds [\"SELECT * FROM address WHERE name = ?\" \"Stella\"])\n```\n\nNote that the single argument form of `execute!`, taking just a `PreparedStatement`, is not supported by `query`.\n\n## `update!`\n\nGiven a table name (as a keyword), a hash map of columns names and values to set, and either a hash map of column names and values to match on or a vector containing a partial `WHERE` clause and parameters, perform an update operation on the database:\n\n```clojure\n(sql/update! ds :address {:name \"Somebody New\"} {:id 2})\n;; equivalent to\n(sql/update! ds :address {:name \"Somebody New\"} [\"id = ?\" 2])\n;; equivalent to\n(jdbc/execute-one! ds [\"UPDATE address SET name = ? WHERE id = ?\"\n \"Somebody New\" 2])\n```\n\n## `delete!`\n\nGiven a table name (as a keyword) and either a hash map of column names and values to match on or a vector containing a partial `WHERE` clause and parameters, perform a delete operation on the database:\n\n```clojure\n(sql/delete! ds :address {:id 8})\n;; equivalent to\n(sql/delete! ds :address [\"id = ?\" 8])\n;; equivalent to\n(jdbc/execute-one! ds [\"DELETE FROM address WHERE id = ?\" 8])\n```\n\n## `find-by-keys`\n\nGiven a table name (as a keyword) and either a hash map of column names and values to match on or a vector containing a partial `WHERE` clause and parameters, execute a query on the database:\n\n```clojure\n(sql/find-by-keys ds :address {:name \"Stella\" :email \"stella@artois.beer\"})\n;; equivalent to\n(sql/find-by-keys ds :address [\"name = ? AND email = ?\"\n \"Stella\" \"stella@artois.beer\"])\n;; equivalent to\n(jdbc/execute! ds [\"SELECT * FROM address WHERE name = ? AND email = ?\"\n \"Stella\" \"stella@artois.beer\"])\n```\n\nThe default behavior is to return all the columns in each row. You can specify a subset of columns to return using the `:columns` option. It takes a vector and each element of the vector can be:\n\n* a simple keyword representing the column name (`:column-fn` will be applied, if provided),\n* a pair of keywords representing the column name and an alias (`:column-fn` will be applied to both, if provided),\n* a pair consisting of a string and a keyword, representing a SQL expression and an alias (`:column-fn` will be applied to the alias, if provided).\n\n```clojure\n(sql/find-by-keys ds :address {:name \"Stella\"} {:columns [[:email :address]]})\n;; equivalent to\n(jdbc/execute! ds [\"SELECT email AS address FROM address WHERE name = ?\"\n \"Stella\"])\n\n(sql/find-by-keys ds :address {:name \"Stella\"} {:columns [[\"count(*)\" :n]]})\n;; equivalent to\n(jdbc/execute! ds [\"SELECT count(*) AS n FROM address WHERE name = ?\"\n \"Stella\"])\n```\n\n> Note: the SQL string provided for a column is copied exactly as-is into the generated SQL -- you are responsible for ensuring it is legal SQL!\n\n`find-by-keys` supports an `:order-by` option which can specify a vector of column names to sort the results by. Elements may be column names or pairs of a column name and the direction to sort: `:asc` or `:desc`:\n\n```clojure\n(sql/find-by-keys ds :address\n {:name \"Stella\" :email \"stella@artois.beer\"}\n {:order-by [[:id :desc]]})\n;; equivalent to\n(jdbc/execute! ds [\"SELECT * FROM address WHERE name = ? AND email = ? ORDER BY id DESC\"\n \"Stella\" \"stella@artois.beer\"])\n```\n\n`find-by-keys` also supports basic pagination with `:offset` and `:fetch` options which both accept numeric values and adds `OFFSET ? ROWS FETCH NEXT ? ROWS ONLY` to the generated query. To support MySQL and SQLite, you can specify `:limit` instead `:fetch` which adds `LIMIT ? OFFSET ?` to the generated query instead.\n\nIf you want to match all rows in a table -- perhaps with the pagination options in effect -- you can pass the keyword `:all` instead of either a hash map of column names and values or a vector containing a partial `WHERE` clause and parameters.\n\n```clojure\n(sql/find-by-keys ds :address :all {:order-by [:id] :offset 5 :fetch 10})\n;; equivalent to\n(jdbc/execute! ds [\"SELECT * FROM address ORDER BY id OFFSET ? ROWS FETCH NEXT ? ROWS ONLY\" 5 10])\n```\n\nIf no rows match, `find-by-keys` returns `[]`, just like `execute!`.\n\n## `get-by-id`\n\nGiven a table name (as a keyword) and a primary key value, with an optional primary key column name, execute a query on the database:\n\n```clojure\n(sql/get-by-id ds :address 2)\n;; equivalent to\n(sql/get-by-id ds :address 2 {}) ; empty options map\n;; equivalent to\n(sql/get-by-id ds :address 2 :id {}) ; empty options map\n;; equivalent to\n(jdbc/execute-one! ds [\"SELECT * FROM address WHERE id = ?\" 2])\n```\n\nNote that in order to override the default primary key column name (of `:id`), you need to specify both the column name and an options hash map.\n\nIf no rows match, `get-by-id` returns `nil`, just like `execute-one!`.\n\n## Table & Column Entity Names\n\nBy default, `next.jdbc.sql` functions construct SQL strings with the entity names exactly matching the (unqualified) keywords provided. If you are trying to use a table name or column name that is a reserved name in SQL for your database, you will need to tell those functions to quote those names.\n\nThe namespace `next.jdbc.quoted` provides five functions that cover the most common types of entity quoting, and a modifier function for quoting dot-separated names (e.g., that include schemas):\n\n* `ansi` -- wraps entity names in double quotes,\n* `mysql` -- wraps entity names in back ticks,\n* `sql-server` -- wraps entity names in square brackets,\n* `oracle` -- an alias for `ansi`,\n* `postgres` -- an alias for `ansi`.\n\n* `schema` -- wraps a quoting function to support `dbo.table` style entity names.\n\nThese quoting functions can be provided to any of the friendly SQL functions above using the `:table-fn` and `:column-fn` options, in a hash map provided as the (optional) last argument in any call. If you want to provide your own entity naming function, you can do that:\n\n```clojure\n(defn snake-case [s] (str/replace s #\"-\" \"_\"))\n\n(sql/insert! ds :my-table {:some \"data\"} {:table-fn snake-case})\n```\n\n`next.jdbc` provides `snake-kebab-opts` and `unqualified-snake-kebab-opts` which are hash maps containing `:column-fn` and `:table-fn` that use the `->snake_case` function from the [camel-snake-kebab library](https://github.com/clj-commons/camel-snake-kebab/) which performs a more sophisticated transformation.\n\n> Note: The entity naming function is passed a string, the result of calling `name` on the keyword passed in. Also note that the default quoting functions do not handle schema-qualified names, such as `dbo.table_name` -- `sql-server` would produce `[dbo.table_name]` from that. Use the `schema` function to wrap the quoting function if you need that behavior, e.g,. `{:table-fn (schema sql-server)}` which would produce `[dbo].[table_name]`.\n\n## HugSQL Quick Start\n\nHere's how to get up and running quickly with `next.jdbc` and HugSQL. For more detail, consult the [HugSQL documentation](https://www.hugsql.org/). Add the following dependencies to your project (in addition to `com.github.seancorfield/next.jdbc` and whichever JDBC drivers you need):\n\n```clojure\n com.layerware/hugsql-core {:mvn/version \"0.5.1\"}\n com.layerware/hugsql-adapter-next-jdbc {:mvn/version \"0.5.1\"}\n```\n\n_Check the HugSQL documentation for the latest versions to use!_\n\nWrite your SQL in `.sql` files that are on the classpath (somewhere under `src` or `resources`). For our purposes, assume a SQL file `db/example.sql` containing your first set of definitions. In your namespace, add these `require`s:\n\n```clojure\n [hugsql.core :as hugsql]\n [hugsql.adapter.next-jdbc :as adapter]\n [next.jdbc :as jdbc]\n```\n\nAt program startup you'll need to call these functions (either at the top-level of your namespace on inside your initialization function):\n\n```clojure\n;; regular SQL functions\n(hugsql/def-db-fns \"db/example.sql\"\n {:adapter (adapter/hugsql-adapter-next-jdbc)})\n\n;; development/advanced usage functions that produce a vector containing\n;; SQL and parameters that could be passed to jdbc/execute! etc\n(hugsql/def-sqlvec-fns \"db/example.sql\"\n {:adapter (adapter/hugsql-adapter-next-jdbc)})\n```\n\nThose calls will add function definitions to that namespace based on what is in the `.sql` files. Now set up your db-spec and datasource as usual with `next.jdbc`:\n\n```clojure\n(def db-spec {:dbtype \"h2:mem\" :dbname \"example\"}) ; assumes H2 driver in deps.edn\n\n(def ds (jdbc/get-datasource db-spec))\n```\n\nBorrowing from Princess Bride examples from the HugSQL documentation, you can now do things like this:\n\n```clojure\n(create-characters-table ds)\n;;=> [#:next.jdbc{:update-count 0}]\n(insert-character ds {:name \"Westley\", :specialty \"love\"})\n;;=> 1\n```\n\nBy default, for compatibility with their default adapter (`clojure.java.jdbc`), the `next.jdbc` adapter uses the `next.jdbc.result-set/as-unqualified-lower-maps` builder function. You can specify a different builder function when you pass in the adapter:\n\n```clojure\n;; add require next.jdbc.result-set :as rs to your ns\n\n(hugsql/def-db-fns \"db/example.sql\"\n {:adapter (adapter/hugsql-adapter-next-jdbc\n {:builder-fn rs/as-maps})})\n\n;; now you'll get qualified as-is hash maps back:\n(character-by-id ds {:id 1})\n;;=> #:CHARACTERS{:ID 1, :NAME \"Westley\", :SPECIALTY \"love\", :CREATED_AT #inst \"2019-09-27T18:52:54.413000000-00:00\"}\n```\n\n[<: Getting Started](/doc/getting-started.md) | [Tips & Tricks :>](/doc/tips-and-tricks.md)\n","cljdoc.doc/type":"cljdoc/markdown","slug":"friendly-sql-functions","cljdoc.doc/contributors":["Sean Corfield","alexandrkozyrev","Valtteri Harmainen"]}},{"title":"Tips & Tricks","attrs":{"cljdoc.doc/source-file":"doc/tips-and-tricks.md","cljdoc/markdown":"# Tips & Tricks\n\nThis page contains various tips and tricks that make it easier to use `next.jdbc` with a variety of databases. It is mostly organized by database, but there are a few that are cross-database and those are listed first.\n\n## CLOB & BLOB SQL Types\n\nColumns declared with the `CLOB` or `BLOB` SQL types are typically rendered into Clojure result sets as database-specific custom types but they should implement `java.sql.Clob` or `java.sql.Blob` (as appropriate). In general, you can only read the data out of those Java objects during the current transaction, which effectively means that you need to do it either inside the reduction (for `plan`) or inside the result set builder (for `execute!` or `execute-one!`). If you always treat these types the same way for all columns across the whole of your application, you could simply extend `next.jdbc.result-set/ReadableColumn` to `java.sql.Clob` (and/or `java.sql.Blob`). Here's an example for reading `CLOB` into a `String`:\n\n```clojure\n(extend-protocol rs/ReadableColumn\n java.sql.Clob\n (read-column-by-label [^java.sql.Clob v _]\n (with-open [rdr (.getCharacterStream v)] (slurp rdr)))\n (read-column-by-index [^java.sql.Clob v _2 _3]\n (with-open [rdr (.getCharacterStream v)] (slurp rdr))))\n```\n\nThere is a helper in `next.jdbc.result-set` to make this easier -- `clob->string`:\n\n```clojure\n(extend-protocol rs/ReadableColumn\n java.sql.Clob\n (read-column-by-label [^java.sql.Clob v _]\n (rs/clob->string v))\n (read-column-by-index [^java.sql.Clob v _2 _3]\n (rs/clob->string v)))\n```\n\nAs noted in [Result Set Builders](/doc/result-set-builders.md), there is also `clob-column-reader` that can be used with the `as-*-adapter` result set builder functions.\n\nNo helper or column reader is provided for `BLOB` data since it is expected that the semantics of any given binary data will be application specific. For a raw `byte[]` you could probably use:\n\n```clojure\n (.getBytes v 1 (.length v)) ; BLOB has 1-based byte index!\n```\n\nConsult the [java.sql.Blob documentation](https://docs.oracle.com/javase/8/docs/api/java/sql/Blob.html) for more ways to process it.\n\n> Note: the standard MySQL JDBC driver seems to return `BLOB` data as `byte[]` instead of `java.sql.Blob`.\n\n## Handling Timeouts\n\nJDBC provides a number of ways in which you can decide how long an operation should run before it times out. Some of these timeouts are specified in seconds and some are in milliseconds. Some are handled via connection properties (or JDBC URL parameters), some are handled via methods on various JDBC objects.\n\nHere's how to specify various timeouts using `next.jdbc`:\n\n* `connectTimeout` -- can be specified via the \"db-spec\" hash map or in a JDBC URL, it is the number of **milliseconds** that JDBC should wait for the initial (socket) connection to complete. Database-specific (may be MySQL only?).\n* `loginTimeout` -- can be set via `.setLoginTimeout()` on a `DriverManager` or `DataSource`, it is the number of **seconds** that JDBC should wait for a connection to the database to be made. `next.jdbc` exposes this on the `javax.sql.DataSource` object it reifies from calling `get-datasource` on a \"db-spec\" hash map or JDBC URL string.\n* `queryTimeout` -- can be set via `.setQueryTimeout()` on a `Statement` (or `PreparedStatement`), it is the number of **seconds** that JDBC should wait for a SQL statement to complete. Since this is the most commonly used type of timeout, `next.jdbc` exposes this via the `:timeout` option which can be passed to any function that may construct a `Statement` or `PreparedStatement`.\n* `socketTimeout` -- can be specified via the \"db-spec\" hash map or in a JDBC URL, it is the number of milliseconds that JDBC should wait for socket operations to complete. Database-specific (MS SQL Server and MySQL support this, other databases may too).\n\nExamples:\n\n```clojure\n;; connectTimeout / socketTimeout via db-spec:\n(def db-spec {:dbtype \"mysql\" :dbname \"example\" :user \"root\" :password \"secret\"\n ;; milliseconds:\n :connectTimeout 60000 :socketTimeout 30000}))\n\n;; socketTimeout via JDBC URL:\n(def db-url (str \"jdbc:sqlserver://localhost;user=sa;password=secret\"\n ;; milliseconds:\n \";database=model;socketTimeout=10000\"))\n\n;; loginTimeout via DataSource:\n(def ds (jdbc/get-datasource db-spec))\n(.setLoginTimeout ds 20) ; seconds\n\n;; queryTimeout via options:\n(jdbc/execute! ds [\"select * from some_table\"] {:timeout 5}) ; seconds\n\n;; queryTimeout via method call:\n(let [ps (jdbc/prepare ds [\"select * from some_table\"])]\n (.setQueryTimeout ps 10) ; seconds\n (jdbc/execute! ps))\n```\n\n## Reducing and Folding with `plan`\n\nMost of this documentation describes using `plan` specifically for reducing and notes that you can avoid the overhead of realizing rows from the `ResultSet` into Clojure data structures if your reducing function uses only functions that get column values by name. If you perform any function on the row that would require an actual hash map or a sequence, the row will be realized into a full Clojure hash map via the builder function passed in the options (or via `next.jdbc.result-set/as-maps` by default).\n\nOne of the benefits of reducing over `plan` is that you can stream very large result sets, very efficiently, without having the entire result set in memory (assuming your reducing function doesn't build a data structure that is too large!). See the tips below on **Streaming Result Sets**.\n\nThe result of `plan` is also foldable in the [clojure.core.reducers](https://clojure.org/reference/reducers) sense. While you could use `execute!` to produce a vector of fully-realized rows as hash maps and then fold that vector (Clojure's vectors support fork-join parallel reduce-combine), that wouldn't be possible for very large result sets. If you fold the result of `plan`, the result set will be partitioned and processed using fork-join parallel reduce-combine. Unlike reducing over `plan`, each row **is** realized into a Clojure data structure and each batch is forked for reduction as soon as that many rows have been realized. By default, `fold`'s batch size is 512 but you can specify a different value in the 4-arity call. Once the entire result set has been read, the last (partial) batch is forked for reduction. The combining operations are forked and interleaved with the reducing operations, so the order (of forked tasks) is batch-1, batch-2, combine-1-2, batch-3, combine-1&2-3, batch-4, combine-1&2&3-4, etc. The amount of parallelization you get will depend on many factors including the number of processors, the speed of your reducing function, the speed of your combining function, and the speed with which result sets can actually be streamed from your database.\n\nThere is no back pressure here so if your reducing function is slow, you may end up with more of the realized result set in memory than your system can cope with.\n\n## MS SQL Server\n\nIn MS SQL Server, the generated key from an insert comes back as `:GENERATED_KEYS`.\n\nBy default, you won't get table names as qualifiers with Microsoft's JDBC driver (you might with the jTDS drive -- I haven't tried that recently). See this [MSDN forum post about `.getTableName()`](https://social.msdn.microsoft.com/Forums/sqlserver/en-US/55e8cbb2-b11c-446e-93ab-dc30658caf99/resultsetmetadatagettablename-returns-instead-of-table-name) for details. According to one of the answers posted there, if you specify `:result-type` and `:concurrency` in the options for `execute!`, `execute-one!`, `plan`, or `prepare`, that will cause SQL Server to return table names for columns. `:result-type` needs to be `:scoll-sensitive` or `:scroll-insensitive` for this to work. `:concurrency` can be `:read-only` or `:updatable`.\n\nMS SQL Server supports execution of multiple statements when surrounded by `begin`/`end` and can return multiple result sets, when requested via `:multi-rs true` on `execute!`.\n\n```clojure\n(jdbc/execute! db-spec [\"begin select * from table1; select * from table2; end\"] {:multi-rs true})\n;; vector of result sets:\n=> [[{.. table1 row ..} {.. table1 row ..}]\n [{.. table2 row ..} {.. table2 row ..} {..}]]\n```\n\n## MySQL & MariaDB\n\nIn MySQL, the generated key from an insert comes back as `:GENERATED_KEY`. In MariaDB, the generated key from an insert comes back as `:insert_id`.\n\nMySQL generally stores tables as files so they are case-sensitive if your O/S is (Linux) or case-insensitive if your O/S is not (Mac, Windows) but the column names are generally case-insensitive. This can matter when if you use `next.jdbc.result-set/as-lower-maps` because that will lower-case the table names (as well as the column names) so if you are round-tripping based on the keys you get back, you may produce an incorrect table name in terms of case. You'll also need to be careful about `:table-fn`/`:column-fn` because of this.\n\nIt's also worth noting that column comparisons are case-insensitive so `WHERE foo = 'BAR'` will match `\"bar\"` or `\"BAR\"` etc.\n\nMySQL has a connection option, `:allowMultiQueries true`, that allows you to pass multiple SQL statements in a single operation and can return multiple result sets, when requested via `:multi-rs true`.\n\n```clojure\n(def db-spec {:dbtype \"mysql\" .. :allowMultiQueries true})\n;; equivalent to allowMultiQueries=true in the JDBC URL\n(jdbc/execute! db-spec [\"select * from table1; select * from table2\"] {:multi-rs true})\n;; vector of result sets:\n=> [[{.. table1 row ..} {.. table1 row ..}]\n [{.. table2 row ..} {.. table2 row ..} {..}]]\n```\n\nCompare this with MS SQL Server above: MySQL does not support `begin`/`end` here. This is not the default behavior because allowing multiple statements in a single operation is generally considered a bit of a risk as it can make it easier for SQL injection attacks to be performed.\n\n### Batch Statements\n\nEven when using `next.jdbc/execute-batch!`, MySQL will still send multiple statements to the database unless you specify `:rewriteBatchedStatements true` as part of the db-spec hash map or JDBC URL when the datasource is created.\n\n### Streaming Result Sets\n\nYou should be able to get MySQL to stream very large result sets (when you are reducing over `plan`) by setting the following options:\n\n* `:fetch-size Integer/MIN_VALUE` -- when running `plan` (or when creating a `PreparedStatement`).\n\n> Note: it's possible that other options may be required as well -- I have not verified this yet -- see, for example, the additional options PostgreSQL requires, below.\n\n## Oracle\n\nAh, dear old Oracle! Over the years of maintaining `clojure.java.jdbc` and now `next.jdbc`, I've had all sorts of bizarre and non-standard behavior reported from Oracle users. The main issue I'm aware of with `next.jdbc` is that Oracle's JDBC drivers all return an empty string from `ResultSetMetaData.getTableName()` so you won't get qualified keywords in the result set hash maps. Sorry!\n\n## PostgreSQL\n\nWhen you use `:return-keys true` with `execute!` or `execute-one!` (or you use `insert!`), PostgreSQL returns the entire inserted row (unlike nearly every other database that just returns any generated keys!).\n\nIf you have a query where you want to select where a column is `IN` a sequence of values, you can use `col = ANY(?)` with a native array of the values instead of `IN (?,?,?,,,?)` and a sequence of values.\n\nWhat does this mean for your use of `next.jdbc`? In `plan`, `execute!`, and `execute-one!`, you can use `col = ANY(?)` in the SQL string and a single primitive array parameter, such as `(int-array [1 2 3 4])`. That means that in `next.jdbc.sql`'s functions that take a where clause (`find-by-keys`, `update!`, and `delete!`) you can specify `[\"col = ANY(?)\" (int-array data)]` for what would be a `col IN (?,?,?,,,?)` where clause for other databases and require multiple values.\n\n### Batch Statements\n\nEven when using `next.jdbc/execute-batch!`, PostgreSQL will still send multiple statements to the database unless you specify `:reWriteBatchedInserts true` as part of the db-spec hash map or JDBC URL when the datasource is created.\n\n### Streaming Result Sets\n\nYou can get PostgreSQL to stream very large result sets (when you are reducing over `plan`) by setting the following options:\n\n* `:auto-commit false` -- when opening the connection\n* `:fetch-size 4000, :concurrency :read-only, :cursors :close, :result-type :forward-only` -- when running `plan` (or when creating a `PreparedStatement`).\n\n### Working with Arrays\n\nResultSet protocol extension to read SQL arrays as Clojure vectors.\n\n```clojure\n(import '[java.sql Array])\n(require '[next.jdbc.result-set :as rs])\n\n(extend-protocol rs/ReadableColumn\n Array\n (read-column-by-label [^Array v _] (vec (.getArray v)))\n (read-column-by-index [^Array v _ _] (vec (.getArray v))))\n\n```\n\nInsert and read vector example:\n\n```sql\ncreate table example(\n tags varchar[]\n);\n```\n```clojure\n\n(execute-one! db-spec\n [\"insert into example(tags) values (?)\"\n (into-array String [\"tag1\" \"tag2\"])])\n\n(execute-one! db-spec\n [\"select * from example limit 1\"])\n\n;; => #:example{:tags [\"tag1\" \"tag2\"]}\n```\n\n> Note: PostgreSQL JDBC driver supports only 7 primitive array types, but not array types like `UUID[]` -\n[PostgreSQL™ Extensions to the JDBC API](https://jdbc.postgresql.org/documentation/head/arrays.html).\n\n### Working with Date and Time\n\nBy default, PostgreSQL's JDBC driver does not always perform conversions from `java.util.Date` to a SQL data type.\nYou can enable this by extending `SettableParameter` to the appropriate (Java) types, or by simply requiring [`next.jdbc.date-time`](https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/api/next.jdbc.date-time).\n\nIn addition, if you want `java.time.Instant`, `java.time.LocalDate`, and `java.time.LocalDateTime` to be automatically converted to SQL data types, requiring `next.jdbc.date-time` will enable those as well (by extending `SettableParameter` for you).\n\n`next.jdbc.date-time` also includes functions that you can call at application startup to extend `ReadableColumn` to either return `java.time.Instant` or `java.time.LocalDate`/`java.time.LocalDateTime` (as well as a function to restore the default behavior of returning `java.sql.Date` and `java.sql.Timestamp`).\n\n### Working with Interval\n\nPostgres has a nonstandard SQL type Interval that is implemented in the Postgres driver as the `org.postgresql.util.PGInterval` type.\nIn many cases you would want to work with intervals as `java.time.Duration` type by default.\n\nYou can support `Duration` instances by extending `SettableParameter` to the `java.time.Duration` type.\nConversely you can support converting PGIntervals back to Durations by extending `ReadableColumn` to the `org.postgresql.util.PGInterval` type.\n\n```clojure\n(import '[org.postgresql.util PGInterval])\n(import '[java.sql PreparedStatement])\n(import '[java.time Duration])\n(require '[next.jdbc.result-set :as rs])\n(require '[next.jdbc.prepare :as p])\n\n(defn ->pg-interval\n \"Takes a Dudration instance and converts it into a PGInterval\n instance where the interval is created as a number of seconds.\"\n [^java.time.Duration duration]\n (doto (PGInterval.)\n (.setSeconds (.getSeconds duration))))\n\n(extend-protocol p/SettableParameter\n ;; Convert durations to PGIntervals before inserting into db\n java.time.Duration\n (set-parameter [^java.time.Duration v ^PreparedStatement s ^long i]\n (.setObject s i (->pg-interval v))))\n\n\n(defn <-pg-interval\n \"Takes a PGInterval instance and converts it into a Duration\n instance. Ignore sub-second units.\"\n [^org.postgresql.util.PGInterval interval]\n (-> Duration/ZERO\n (.plusSeconds (.getSeconds interval))\n (.plusMinutes (.getMinutes interval))\n (.plusHours (.getHours interval))\n (.plusDays (.getDays interval))))\n\n(extend-protocol rs/ReadableColumn\n ;; Convert PGIntervals back to durations\n org.postgresql.util.PGInterval\n (read-column-by-label [^org.postgresql.util.PGInterval v _]\n (<-pg-interval v))\n (read-column-by-index [^org.postgresql.util.PGInterval v _2 _3]\n (<-pg-interval v)))\n```\n\n### Working with Enumerated Types\n\nPostgreSQL has a SQL extension for defining enumerated types and the default `set-parameter` implementation will not work for those. You can use `next.jdbc.types/as-other` to wrap string values in a way that the JDBC driver will convert them to enumerated type values:\n\n```sql\nCREATE TYPE language AS ENUM('en','fr','de');\n\nCREATE TABLE person (\n ...\n speaks language NOT NULL,\n ...\n);\n```\n\n```clojure\n(require '[next.jdbc.sql :as sql]\n '[next.jdbc.types :refer [as-other]])\n\n(sql/insert! ds :person {:speaks (as-other \"fr\")})\n```\n\nThat call produces a vector `[\"fr\"]` with metadata that implements `set-parameter` such that `.setObject()` is called with `java.sql.Types/OTHER` which allows PostgreSQL to \"convert\" the string `\"fr\"` to the corresponding `language` enumerated type value.\n\n### Working with JSON and JSONB\n\nPostgreSQL has good support for [storing, querying and manipulating JSON data](https://www.postgresql.org/docs/current/datatype-json.html). Basic Clojure data structures (lists, vectors, and maps) transform pretty well to JSON data. With a little help `next.jdbc` can automatically convert Clojure data to JSON and back for us.\n\nFirst we define functions for JSON encoding and decoding. We're using [metosin/jsonista](https://github.com/metosin/jsonista) in these examples but you could use any JSON library, such as [Cheshire](https://github.com/dakrone/cheshire) or [clojure.data.json](https://github.com/clojure/data.json).\n\n```clojure\n(require '[jsonista.core :as json])\n\n;; :decode-key-fn here specifies that JSON-keys will become keywords:\n(def mapper (json/object-mapper {:decode-key-fn keyword}))\n(def ->json json/write-value-as-string)\n(def <-json #(json/read-value % mapper))\n```\n\nNext we create helper functions to transform Clojure data to and from PostgreSQL Objects\ncontaining JSON:\n\n```clojure\n(import '(org.postgresql.util PGobject))\n\n(defn ->pgobject\n \"Transforms Clojure data to a PGobject that contains the data as\n JSON. PGObject type defaults to `jsonb` but can be changed via\n metadata key `:pgtype`\"\n [x]\n (let [pgtype (or (:pgtype (meta x)) \"jsonb\")]\n (doto (PGobject.)\n (.setType pgtype)\n (.setValue (->json x)))))\n\n(defn <-pgobject\n \"Transform PGobject containing `json` or `jsonb` value to Clojure\n data.\"\n [^org.postgresql.util.PGobject v]\n (let [type (.getType v)\n value (.getValue v)]\n (if (#{\"jsonb\" \"json\"} type)\n (when value\n (with-meta (<-json value) {:pgtype type}))\n value)))\n```\n\nFinally we extend `next.jdbc.prepare/SettableParameter` and `next.jdbc.result-set/ReadableColumn` protocols to make the conversion between clojure data and PGobject JSON automatic:\n\n```clojure\n(require '[next.jdbc.prepare :as prepare])\n(require '[next.jdbc.result-set :as rs])\n\n(import '[java.sql PreparedStatement])\n\n(set! *warn-on-reflection* true)\n\n;; if a SQL parameter is a Clojure hash map or vector, it'll be transformed\n;; to a PGobject for JSON/JSONB:\n(extend-protocol prepare/SettableParameter\n clojure.lang.IPersistentMap\n (set-parameter [m ^PreparedStatement s i]\n (.setObject s i (->pgobject m)))\n\n clojure.lang.IPersistentVector\n (set-parameter [v ^PreparedStatement s i]\n (.setObject s i (->pgobject v))))\n\n;; if a row contains a PGobject then we'll convert them to Clojure data\n;; while reading (if column is either \"json\" or \"jsonb\" type):\n(extend-protocol rs/ReadableColumn\n org.postgresql.util.PGobject\n (read-column-by-label [^org.postgresql.util.PGobject v _]\n (<-pgobject v))\n (read-column-by-index [^org.postgresql.util.PGobject v _2 _3]\n (<-pgobject v)))\n```\n\n#### Inserting and Querying JSON\n\nLet's assume we have following table:\n\n``` sql\ncreate table demo (\n id serial primary key,\n doc_jsonb jsonb,\n doc_json json\n)\n```\n\nWe can now insert Clojure data into json and jsonb fields:\n\n```clojure\n(require '[next.jdbc :as jdbc])\n(require '[next.jdbc.sql :as sql])\n\n(def db { ...db-spec here... })\n(def ds (jdbc/get-datasource db))\n\n(def test-map\n {:some-key \"some val\" :nested {:a 1} :null-val nil :vector [1 2 3]})\n\n(def data1\n {:doc_jsonb test-map\n :doc_json (with-meta test-map {:pgtype \"json\"})})\n\n(sql/insert! ds :demo data1)\n\n(def test-vector\n [{:a 1} nil 2 \"lalala\" []])\n\n(def data2\n {:doc_jsonb test-vector\n :doc_json (with-meta test-vector {:pgtype \"json\"})})\n\n(sql/insert! ds :demo data2)\n```\n\nAnd those columns are nicely transformed into Clojure data when querying:\n\n```clojure\n(sql/get-by-id ds :demo 1)\n=> #:demo{:id 1,\n :doc_json\n {:some-key \"some val\",\n :nested {:a 1},\n :vector [1 2 3],\n :null-val nil},\n :doc_jsonb\n {:some-key \"some val\",\n :nested {:a 1},\n :vector [1 2 3],\n :null-val nil}}\n\n(sql/get-by-id ds :demo 2)\n=> #:demo{:id 2,\n :doc_json [{:a 1} nil 2 \"lalala\" []],\n :doc_jsonb [{:a 1} nil 2 \"lalala\" []]}\n\n;; Query by value of JSON field 'some-key'\n(sql/query ds [(str \"select id, doc_jsonb::json->'nested' as foo\"\n \" from demo where doc_jsonb::json->>'some-key' = ?\")\n \"some val\"])\n=> [{:demo/id 1, :foo {:a 1}}]\n```\n\n#### JSON or JSONB?\n\n* A `json` column stores JSON data as strings (reading and writing is fast but manipulation is slow, field order is preserved)\n* A `jsonb` column stores JSON data in binary format (manipulation is significantly faster but reading and writing is a little slower)\n\nIf you're unsure whether you want to use json or jsonb, use jsonb.\n\n## SQLite\n\nSQLite supports both `bool` and `bit` column types but, unlike pretty much every other database out there, it yields `0` or `1` as the column value instead of `false` or `true`. This means that with SQLite alone, you can't just rely on `bool` or `bit` columns being treated as truthy/falsey values in Clojure.\n\nYou can work around this using a builder that handles reading the column directly as a `Boolean`:\n\n```clojure\n(jdbc/execute! ds [\"select * from some_table\"]\n {:builder-fn (rs/builder-adapter\n rs/as-maps\n (fn [builder ^ResultSet rs ^Integer i]\n (let [rsm ^ResultSetMetaData (:rsmeta builder)]\n (rs/read-column-by-index\n (if (#{\"BIT\" \"BOOL\" \"BOOLEAN\"} (.getColumnTypeName rsm i))\n (.getBoolean rs i)\n (.getObject rs i))\n rsm\n i))))})\n```\n\nIf you are using `plan`, you'll most likely be accessing columns by just the label (as a keyword) and avoiding the result set building machinery completely. In such cases, you'll still get `bool` and `bit` columns back as `0` or `1` and you'll need to explicitly convert them on a per-column basis since you should know which columns need converting:\n\n```clojure\n(reduce (fn [acc row]\n (conj acc (-> (select-keys row [:name :is_active])\n (update :is_active pos?))))\n []\n (jdbc/plan ds [\"select * from some_table\"]))\n```\n\n[<: Friendly SQL Functions](/doc/friendly-sql-functions.md) | [Result Set Builders :>](/doc/result-set-builders.md)\n","cljdoc.doc/type":"cljdoc/markdown","slug":"tips-tricks","cljdoc.doc/contributors":["Sean Corfield","Maxim Penzin","Snorre Magnus Davøen","Kimmo Koskinen"]}},{"title":"Result Set Builders","attrs":{"cljdoc.doc/source-file":"doc/result-set-builders.md","cljdoc/markdown":"# RowBuilder and ResultSetBuilder\n\nIn [Getting Started](/doc/getting-started.md), it was noted that, by default, `execute!` and `execute-one!` return result sets as (vectors of) hash maps with namespace-qualified keys as-is. If your database naturally produces uppercase column names from the JDBC driver, that's what you'll get. If it produces mixed-case names, that's what you'll get.\n\n> Note: Some databases do not return the table name in the metadata by default. If you run into this, you might try adding `:ResultSetMetaDataOptions \"1\"` to your db-spec (so it is passed as a property to the JDBC driver when you create connections). If your database supports that, it will perform additional work to try to add table names to the result set metadata. It has been reported that Oracle just plain old does not support table names at all in its JDBC drivers.\n\nThe default builder for rows and result sets creates qualified keywords that match whatever case the JDBC driver produces. That builder is `next.jdbc.result-set/as-maps` but there are several options available:\n\n* `as-maps` -- table-qualified keywords as-is, the default, e.g., `:ADDRESS/ID`, `:myTable/firstName`,\n* `as-unqualified-maps` -- simple keywords as-is, e.g., `:ID`, `:firstName`,\n* `as-lower-maps` -- table-qualified lower-case keywords, e.g., `:address/id`, `:mytable/firstname`,\n* `as-unqualified-lower-maps` -- simple lower-case keywords, e.g., `:id`, `:firstname`,\n* `as-arrays` -- table-qualified keywords as-is (vector of column names, followed by vectors of row values),\n* `as-unqualified-arrays` -- simple keywords as-is,\n* `as-lower-arrays` -- table-qualified lower-case keywords,\n* `as-unqualified-lower-arrays` -- simple lower-case keywords.\n\nThe reason behind the default is to a) be a simple transform, b) produce qualified keys in keeping with Clojure's direction (with `clojure.spec` etc), and c) not mess with the data. `as-arrays` is (slightly) faster than `as-maps` since it produces less data (vectors of values instead of vectors of hash maps), but the `lower` options will be slightly slower since they include (conditional) logic to convert strings to lower-case. The `unqualified` options may be slightly faster than their qualified equivalents but **make no attempt to keep column names unique if your SQL joins across multiple tables**.\n\n> Note: This is a deliberate difference from `clojure.java.jdbc` which would make column names unique by appending numeric suffixes. It was always poor practice to rely on `clojure.java.jdbc`'s renaming behavior and it added quite an overhead to result set building, which is why `next.jdbc` does not support it -- use explicit column aliasing in your SQL instead if you want _unqualified_ column names!\n\nIn addition, the following generic builders can take `:label-fn` and `:qualifier-fn` options to control how the label and qualified are processed. The `lower` variants above are implemented in terms of these, passing a `lower-case` function for both of those options.\n\n* `as-modified-maps` -- table-qualified keywords,\n* `as-unqualified-modified-maps` -- simple keywords,\n* `as-modified-arrays` -- table-qualified keywords,\n* `as-unqualified-modified-arrays` -- simple keywords.\n\nAn example builder that converts `snake_case` database table/column names to `kebab-case` keywords:\n\n```clojure\n(defn as-kebab-maps [rs opts]\n (let [kebab #(str/replace % #\"_\" \"-\")]\n (result-set/as-modified-maps rs (assoc opts :qualifier-fn kebab :label-fn kebab))))\n```\n\nHowever, a version of `as-kebab-maps` is built-in, as is `as-unqualified-kebab-maps`, which both use the `->kebab-case` function from the [camel-snake-kebab library](https://github.com/clj-commons/camel-snake-kebab/) with `as-modified-maps` and `as-unqualified-modified-maps` respectively.\n\nAnd finally there are two styles of adapters for the existing builders that let you override the default way that columns are read from result sets.\nThe first style takes a `column-reader` function, which is called with the `ResultSet`, the `ResultSetMetaData`, and the column index, and is expected to read the raw column value from the result set and return it. The result is then passed through `read-column-by-index` (from `ReadableColumn`, which may be implemented directly via protocol extension or via metadata on the result of the `column-reader` function):\n\n* `as-maps-adapter` -- adapts an existing map builder function with a new column reader,\n* `as-arrays-adapter` -- adapts an existing array builder function with a new column reader.\n\nThe default `column-reader` function behavior would be:\n\n```clojure\n(defn default-column-reader\n [^ResultSet rs ^ResultSetMetaData rsmeta ^Integer i]\n (.getObject rs i))\n```\n\nAn example column reader is provided -- `clob-column-reader` -- that still uses `.getObject` but will expand `java.sql.Clob` values into string (using the `clob->string` helper function):\n\n```clojure\n {:builder-fn (result-set/as-maps-adapter\n result-set/as-maps\n result-set/clob-column-reader)}\n```\n\nAs of 1.1.569, the second style of adapter relies on `with-column-value` from `RowBuilder` (see below) and allows you to take complete control of the column reading process. This style takes a `column-by-index-fn` function, which is called with the builder itself, the `ResultSet`, and the column index, and is expected to read the raw column value from the result set and perform any and all processing on it, before returning it. The result is added directly to the current row with no further processing.\n\n* `builder-adapter` -- adapts any existing builder function with a new column reading function.\n\nThe default `column-by-index-fn` function behavior would be:\n\n```clojure\n(defn default-column-by-index-fn\n [builder ^ResultSet rs ^Integer i]\n (result-set/read-column-by-index (.getObject rs i) (:rsmeta builder) i))\n```\n\nBecause the builder itself is passed in, the vector of processed column names is available as `(:cols builder)` (in addition to the `ResultSetMetaData` as `(:rsmeta builder)`). This allows you to take different actions based on the metadata or the column name, as well as bypassing the `read-column-by-index` call if you wish.\n\nThe older `as-*-adapter` functions are now implemented in terms of this `builder-adapter` because `with-column-value` abstracts away _how_ the new column's value is added to the row being built.\n\n## RowBuilder Protocol\n\nThis protocol defines five functions and is used whenever `next.jdbc` needs to materialize a row from a `ResultSet` as a Clojure data structure:\n\n* `(->row builder)` -- produces a new row (a `(transient {})` by default),\n* `(column-count builder)` -- returns the number of columns in each row,\n* `(with-column builder row i)` -- given the row so far, fetches column `i` from the current row of the `ResultSet`, converts it to a Clojure value, and adds it to the row (for `as-maps` this is a call to `.getObject`, a call to `read-column-by-index` -- see the `ReadableColumn` protocol below, and a call to `assoc!`),\n* `(with-column-value builder row col v)` -- given the row so far, the column name, and the column value, add the column name/value to the row in the appropriate way: this is a low-level utility, intended to be used in builders (or adapters) that want to control more of the value handling process -- in general, `with-column` will be implemented by calling `with-column-value`,\n* `(row! builder row)` -- completes the row (a `(persistent! row)` call by default).\n\n`execute!` and `execute-one!` call these functions for each row they need to build. `plan` _may_ call these functions if the reducing function causes a row to be materialized.\n\n## ResultSet Protocol\n\nThis protocol defines three functions and is used whenever `next.jdbc` needs to materialize a result set (multiple rows) from a `ResultSet` as a Clojure data structure:\n\n* `(->rs builder)` -- produces a new result set (a `(transient [])` by default),\n* `(with-row builder rs row)` -- given the result set so far and a new row, returns the updated result set (a `(conj! rs row)` call by default),\n* `(rs! builder rs)` -- completes the result set (a `(persistent! rs)` call by default).\n\nOnly `execute!` expects this protocol to be implemented. `execute-one!` and `plan` do not call these functions.\n\n## Result Set Builder Functions\n\nThe `as-*` functions described above are all implemented in terms of these protocols. They are passed the `ResultSet` object and the options hash map (as passed into various `next.jdbc` functions). They return an implementation of the protocols that is then used to build rows and the result set. Note that the `ResultSet` passed in is _mutable_ and is advanced from row to row by the SQL execution function, so each time `->row` is called, the underlying `ResultSet` object points at each new row in turn. By contrast, `->rs` (which is only called by `execute!`) is invoked _before_ the `ResultSet` is advanced to the first row.\n\nThe result set builder implementation is also assumed to implement `clojure.lang.ILookup` such that the keys `:cols` and `:rsmeta` are supported and should map to the vector of column names that the builder will produce and the `ResultSetMetaData` object (which can be obtained from the `ResultSet`, if necessary). This is intended to allow `plan` and various builder adapters to access certain information that may be needed for processing results. The default builder implementations (for maps and arrays) are both records with fields `rsmeta` and `cols` (in addition to `rs` -- the `ResultSet` itself). The adapters provided in `next.jdbc.result-set` returned reified implementations that delegate field lookup to the underlying builder implementation.\n\nThe options hash map for any `next.jdbc` function can contain a `:builder-fn` key and the value is used as the row/result set builder function. The tests for `next.jdbc.result-set` include a [record-based builder function](https://github.com/seancorfield/next-jdbc/blob/develop/test/next/jdbc/result_set_test.clj#L335-L353) as an example of how you can extend this to satisfy your needs.\n\n> Note: When `next.jdbc` cannot obtain a `ResultSet` object and returns `{:next.jdbc/count N}` instead, the builder function is not applied -- the `:builder-fn` option does not affect the shape of the result.\n\nThe options hash map passed to the builder function will contain a `:next.jdbc/sql-params` key, whose value is the SQL + parameters vector passed into the top-level `next.jdbc` functions (`plan`, `execute!`, and `execute-one!`).\n\nThere is also a convenience function, `datafiable-result-set`, that accepts a `ResultSet` object (and a connectable and an options hash map) and returns a fully realized result set, per the `:builder-fn` option (or `as-maps` if that option is omitted).\n\nThe array-based builders warrant special mention:\n\n* When used with `execute!`, the array-based builders will produce a data structure that is a vector of vectors, with the first element being a vector of column names and subsequent elements being vectors of column values in the same corresponding order. The order of column names and values follows the \"natural\" order from the SQL operation, as determined by the underlying `ResultSet`.\n* When used with `execute-one!`, the array-based builders will produce a single vector containing the column values in the \"natural\" SQL order but you will not get the corresponding column names back.\n* When used with `plan`, the array-based builders will cause each abstract row to represent a vector of column values rather than a hash map which limits the operations you can perform on the abstraction to just `Associative` (`get` with a numeric key), `Counted` (`count`), and `Indexed` (`nth`). All other operations will either realize a vector, as if by calling `datafiable-row`, or will fail if the operation does not make sense on a vector (as opposed to a hash map).\n\n## `next.jdbc.optional`\n\nThis namespace contains variants of the six `as-maps`-style builders above that omit keys from the row hash maps if the corresponding column is `NULL`. This is in keeping with Clojure's views of \"optionality\" -- that optional elements should simply be omitted -- and is provided as an \"opt-in\" style of rows and result sets.\n\n# ReadableColumn\n\nAs mentioned above, when `with-column` is called, the expectation is that the row builder will call `.getObject` on the current state of the `ResultSet` object with the column index and will then call `read-column-by-index`, passing the column value, the `ResultSetMetaData`, and the column index. That function is part of the `ReadableColumn` protocol that you can extend to handle conversion of arbitrary database-specific types to Clojure values. It is extensible via metadata so the value you return can have metadata specifying the implementation of `read-column-by-index`.\n\nIf you need more control over how values are read from the `ResultSet` object, you can use `next.jdbc.result-set/as-maps-adapter` (or `next.jdbc.result-set/as-arrays-adapter`, or the more low-level but more generic `next.jdbc.result-set/builder-adapter`) which takes an existing builder function and a column reading function and returns a new builder function that calls your column reading function (with the `ResultSet` object, the `ResultSetMetaData` object, and the column index -- or the builder itself, the `ResultSet` object, and the column index in the case of `builder-adapter`) instead of calling `.getObject` directly.\nNote that the `as-*` adapters still call `read-column-by-index` on the value your column reading function returns.\n\nIn addition, inside `plan`, as each value is looked up by name in the current state of the `ResultSet` object, the `read-column-by-label` function is called, again passing the column value and the column label (the name used in the SQL to identify that column). This function is also part of the `ReadableColumn` protocol.\n\nThe default implementation of this protocol is for these two functions to return `nil` as `nil`, a `Boolean` value as a canonical `true` or `false` value (unfortunately, JDBC drivers cannot be relied on to return unique values here!), and for all other objects to be returned as-is.\n\n`next.jdbc` makes no assumptions beyond `nil` and `Boolean`, but common extensions here could include converting `java.sql.Date` to `java.time.LocalDate` and `java.sql.Timestamp` to `java.time.Instant` for example:\n\n```clojure\n(extend-protocol rs/ReadableColumn\n java.sql.Date\n (read-column-by-label [^java.sql.Date v _]\n (.toLocalDate v))\n (read-column-by-index [^java.sql.Date v _2 _3]\n (.toLocalDate v))\n java.sql.Timestamp\n (read-column-by-label [^java.sql.Timestamp v _]\n (.toInstant v))\n (read-column-by-index [^java.sql.Timestamp v _2 _3]\n (.toInstant v)))\n```\n\nRemember that a protocol extension will apply to all code running in your application so with the above code **all** timestamp values coming from the database will be converted to `java.time.Instant` for all queries. If you want to control behavior across different calls, consider the adapters described above (`as-maps-adapter`, `as-arrays-adapter`, and `builder-adapter`, and think about using metadata to implement the `rs/ReadableColumn` protocol instead of extending it).\n\nNote that the converse, converting Clojure values to database-specific types is handled by the `SettableParameter` protocol, discussed in the next section ([Prepared Statements](/doc/prepared-statements.md#prepared-statement-parameters)).\n\n[<: Tips & Tricks](/doc/tips-and-tricks.md) | [Prepared Statements :>](/doc/prepared-statements.md)\n","cljdoc.doc/type":"cljdoc/markdown","slug":"result-set-builders","cljdoc.doc/contributors":["Sean Corfield","bpringe"]}},{"title":"Prepared Statements","attrs":{"cljdoc.doc/source-file":"doc/prepared-statements.md","cljdoc/markdown":"# Prepared Statements\n\nUnder the hood, whenever you ask `next.jdbc` to execute some SQL (via `plan`, `execute!`, `execute-one!` or the \"friendly\" SQL functions) it calls `prepare` to create a `java.sql.PreparedStatement`, adds in the parameters you provide, and then calls `.execute` on it. Then it attempts to get a `ResultSet` from that and either return it or process it. If you asked for generated keys to be returned, that `ResultSet` will contain those generated keys if your database supports it, otherwise it will be whatever the `.execute` function produces. If no `ResultSet` is available at all, `next.jdbc` will ask for the count of updated rows and return that as if it were a result set.\n\n> Note: Some databases do not support all SQL operations via `PreparedStatement`, in which case you may need to create a `java.sql.Statement` instead, via `next.jdbc.prepare/statement`, and pass that into `plan`, `execute!`, or `execute-one!`, along with the SQL you wish to execute. Note that such statement execution may not have parameters. See the [Prepared Statement Caveat in Getting Started](/doc/getting-started.md#prepared-statement-caveat) for an example.\n\nIf you have a SQL operation that you intend to run multiple times on the same `java.sql.Connection`, it may be worth creating the prepared statement yourself and reusing it. `next.jdbc/prepare` accepts a connection and a vector of SQL and optional parameters and returns a `java.sql.PreparedStatement` which can be passed to `plan`, `execute!`, or `execute-one!` as the first argument. It is your responsibility to close the prepared statement after it has been used.\n\nIf you need to pass an option map to `plan`, `execute!`, or `execute-one!` when passing a statement or prepared statement, you must pass `nil` or `[]` as the second argument:\n\n```clojure\n(with-open [con (jdbc/get-connection ds)]\n (with-open [ps (jdbc/prepare con [\"...\" ...])]\n (jdbc/execute-one! ps nil {...})))\n (with-open [stmt (jdbc/statement con)]\n (jdbc/execute-one! stmt nil {...})))\n```\n\nYou can provide the parameters in the `prepare` call or you can provide them via a call to `set-parameters` (discussed in more detail below).\n\n```clojure\n;; assuming require next.jdbc.prepare :as p\n(with-open [con (jdbc/get-connection ds)\n ps (jdbc/prepare con [\"...\"])]\n (jdbc/execute-one! (p/set-parameters ps [...])))\n```\n\n## Prepared Statement Parameters\n\nIf parameters are provided in the vector along with the SQL statement, in the call to `prepare`, then `set-parameter` is behind the scenes called for each of them. This is part of the `SettableParameter` protocol:\n\n* `(set-parameter v ps i)` -- by default this calls `(.setObject ps i v)` (for `nil` and `Object`)\n\nThis can be extended to any Clojure data type, to provide a customized way to add specific types of values as parameters to any `PreparedStatement`. For example, to have all `java.time.Instant`, `java.time.LocalDate` and `java.time.LocalDateTime` objects converted to `java.sql.Timestamp` automatically:\n\n```clojure\n(extend-protocol p/SettableParameter\n java.time.Instant\n (set-parameter [^java.time.Instant v ^PreparedStatement ps ^long i]\n (.setTimestamp ps i (java.sql.Timestamp/from v)))\n java.time.LocalDate\n (set-parameter [^java.time.LocalDate v ^PreparedStatement ps ^long i]\n (.setTimestamp ps i (java.sql.Timestamp/valueOf (.atStartOfDay v))))\n java.time.LocalDateTime\n (set-parameter [^java.time.LocalDateTime v ^PreparedStatement ps ^long i]\n (.setTimestamp ps i (java.sql.Timestamp/valueOf v))))\n```\n\n> Note: those conversions can also be enabled by requiring the [`next.jdbc.date-time` namespace](https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/api/next.jdbc.date-time).\n\nYou can also extend this protocol via metadata so you can do it on a per-object basis if you need:\n\n```clojure\n(with-meta obj {'next.jdbc.prepare/set-parameter (fn [v ps i]...)})\n```\n\nThe `next.jdbc.types` namespace provides functions to wrap values with per-object implementations of `set-parameter` for every standard `java.sql.Types` value. Each is named `as-xxx` corresponding to `java.sql.Types/XXX`.\n\nThe converse, converting database-specific types to Clojure values is handled by the `ReadableColumn` protocol, discussed in the previous section ([Result Set Builders](/doc/result-set-builders.md#readablecolumn)).\n\nAs noted above, `next.jdbc.prepare/set-parameters` is available for you to call on any existing `PreparedStatement` to set or update the parameters that will be used when the statement is executed:\n\n* `(set-parameters ps params)` -- loops over a sequence of parameter values and calls `set-parameter` for each one, as above.\n\nIf you need more specialized parameter handling than the protocol can provide, then you can create prepared statements explicitly, instead of letting `next.jdbc` do it for you, and then calling your own variant of `set-parameters` to install those parameters.\n\n## Batched Parameters\n\nBy default, `next.jdbc` assumes that you are providing a single set of parameter values and then executing the prepared statement. If you want to run a single prepared statement with multiple groups of parameters, you might want to take advantage of the increased performance that may come from using JDBC's batching machinery.\n\nYou could do this manually:\n\n```clojure\n;; assuming require next.jdbc.prepare :as p\n(with-open [con (jdbc/get-connection ds)\n ps (jdbc/prepare con [\"insert into status (id,name) values (?,?)\"])]\n (p/set-parameters ps [1 \"Approved\"])\n (.addBatch ps)\n (p/set-parameters ps [2 \"Rejected\"])\n (.addBatch ps)\n (p/set-parameters ps [3 \"New\"])\n (.addBatch ps)\n (.executeBatch ps)) ; returns int[]\n```\n\nHere we set parameters and add them in batches to the prepared statement, then we execute the prepared statement in batch mode. You could also do the above like this, assuming you have those groups of parameters in a sequence:\n\n```clojure\n(with-open [con (jdbc/get-connection ds)\n ps (jdbc/prepare con [\"insert into status (id,name) values (?,?)\"])]\n (run! #(.addBatch (p/set-parameters ps %))\n [[1 \"Approved\"] [2 \"Rejected\"] [3 \"New\"]])\n (.executeBatch ps)) ; returns int[]\n```\n\nBoth of those are somewhat ugly and contain a fair bit of boilerplate and Java interop, so a helper function is provided in `next.jdbc` to automate the execution of batched parameters:\n\n```clojure\n(with-open [con (jdbc/get-connection ds)\n ps (jdbc/prepare con [\"insert into status (id,name) values (?,?)\"])]\n (jdbc/execute-batch! ps [[1 \"Approved\"] [2 \"Rejected\"] [3 \"New\"]]))\n;; or:\n(jdbc/execute-batch! ds\n \"insert into status (id,name) values (?,?)\"\n [[1 \"Approved\"] [2 \"Rejected\"] [3 \"New\"]]\n ;; options hash map required here to disambiguate\n ;; this call from the 2- & 3-arity calls\n {})\n```\n\nBy default, this adds all the parameter groups and executes one batched command. It returns a (Clojure) vector of update counts (rather than `int[]`). If you provide an options hash map, you can specify a `:batch-size` and the parameter groups will be partitioned and executed as multiple batched commands. This is intended to allow very large sequences of parameter groups to be executed without running into limitations that may apply to a single batched command. If you expect the update counts to be very large (more than `Integer/MAX_VALUE`), you can specify `:large true` so that `.executeLargeBatch` is called instead of `.executeBatch`.\n\n> Note: not all databases support `.executeLargeBatch`.\n\nIf you want to get the generated keys from an `insert` done via `execute-batch!`, you need a couple of extras, compared to the above:\n\n```clojure\n(with-open [con (jdbc/get-connection ds)\n ;; ensure the PreparedStatement will return the keys:\n ps (jdbc/prepare con [\"insert into status (id,name) values (?,?)\"]\n {:return-keys true})]\n ;; this will call .getGeneratedKeys for each batch and return them as a\n ;; vector of datafiable result sets (the keys in map are database-specific):\n (jdbc/execute-batch! ps [[1 \"Approved\"] [2 \"Rejected\"] [3 \"New\"]]\n {:return-generated-keys true}))\n;; or:\n(jdbc/execute-batch! ds\n \"insert into status (id,name) values (?,?)\"\n [[1 \"Approved\"] [2 \"Rejected\"] [3 \"New\"]]\n {:return-keys true ; for creation of PreparedStatement\n :return-generated-keys true}) ; for batch result format\n```\n\nThis calls `rs/datafiable-result-set` behind the scenes so you can also pass a `:builder-fn` option to `execute-batch!` if you want something other than qualified as-is hash maps.\n\n> Note: not all databases support calling `.getGeneratedKeys` here (everything I test against seems to, except MS SQL Server). Some databases will only return one generated key per batch, rather than a generated key for every row inserted.\n\n### Caveats\n\nThere are several caveats around using batched parameters. Some JDBC drivers need a \"hint\" in order to perform the batch operation as a single command for the database. In particular, PostgreSQL requires the `:reWriteBatchedInserts true` option and MySQL requires `:rewriteBatchedStatements true` (both non-standard JDBC options, of course!). These should be provided as part of the db-spec hash map when the datasource is created.\n\nIn addition, if the batch operation fails for a group of parameters, it is database-specific whether the remaining groups of parameters are used, i.e., whether the operation is performed for any further groups of parameters after the one that failed. The result of calling `execute-batch!` is a vector of integers. Each element of the vector is the number of rows affected by the operation for each group of parameters. `execute-batch!` may throw a `BatchUpdateException` and calling `.getUpdateCounts` (or `.getLargeUpdateCounts`) on the exception may return an array containing a mix of update counts and error values (a Java `int[]` or `long[]`). Some databases don't always return an update count but instead a value indicating the number of rows is not known (but sometimes you can still get the update counts).\n\nFinally, some database drivers don't do batched operations at all -- they accept `.executeBatch` but they run the operation as separate commands for the database rather than a single batched command.\n\n[<: Result Set Builders](/doc/result-set-builders.md) | [Transactions :>](/doc/transactions.md)\n","cljdoc.doc/type":"cljdoc/markdown","slug":"prepared-statements","cljdoc.doc/contributors":["Sean Corfield"]}},{"title":"Transactions","attrs":{"cljdoc.doc/source-file":"doc/transactions.md","cljdoc/markdown":"# Transactions\n\nThe `transact` function and `with-transaction` macro were briefly mentioned in the [Getting Started](/doc/getting-started.md) section but we'll go into more detail here.\n\nAlthough `(transact transactable f)` is available, it is expected that you will mostly use `(with-transaction [tx transactable] body...)` when you want to execute multiple SQL operations in the context of a single transaction so that is what this section focuses on.\n\n## Connection-level Control\n\nBy default, all connections that `next.jdbc` creates are automatically committable, i.e., as each operation is performed, the effect is committed to the database directly before the next operation is performed. Any exceptions only cause the current operation to be aborted -- any prior operations have already been committed.\n\nIt is possible to tell `next.jdbc` to create connections that do not automatically commit operations: pass `{:auto-commit false}` as part of the options map to anything that creates a connection (including `get-connection` itself). You can then decide when to commit or rollback by calling `.commit` or `.rollback` on the connection object itself. You can also create save points (`(.setSavepoint con)`, `(.setSavepoint con name)`) and rollback to them (`(.rollback con save-point)`). You can also change the auto-commit state of an open connection at any time (`(.setAutoCommit con on-off)`).\n\n## Automatic Commit & Rollback\n\n`next.jdbc`'s transaction handling provides a convenient baseline for either committing a group of operations if they all succeed or rolling them all back if any of them fails, by throwing an exception. You can either do this on an existing connection -- and `next.jdbc` will try to restore the state of the connection after the transaction completes -- or by providing a datasource and letting `with-transaction` create and manage its own connection:\n\n```clojure\n(jdbc/with-transaction [tx my-datasource]\n (jdbc/execute! tx ...)\n (jdbc/execute! tx ...)) ; will commit, unless exception thrown\n\n(jdbc/with-transaction [tx my-datasource]\n (jdbc/execute! tx ...)\n (when ... (throw ...)) ; will rollback\n (jdbc/execute! tx ...))\n```\n\nIf `with-transaction` is given a datasource, it will create and close the connection for you. If you pass in an existing connection, `with-transaction` will set up a transaction on that connection and, after either committing or rolling back the transaction, will restore the state of the connection and leave it open.\n\nYou can also provide an options map as the third element of the binding vector (or the third argument to the `transact` function). The following options are supported:\n\n* `:isolation` -- the isolation level for this transaction (see [All The Options](/doc/all-the-options.md) for specifics),\n* `:read-only` -- set the transaction into read-only mode (if `true`),\n* `:rollback-only` -- set the transaction to always rollback, even on success (if `true`).\n\nThe latter can be particularly useful in tests, to run a series of SQL operations during a test and then roll them all back at the end.\n\n## Manual Rollback Inside a Transaction\n\nInstead of throwing an exception (which will propagate through `with-transaction` and therefore provide no result), you can also explicitly rollback if you want to return a result in that case:\n\n```clojure\n(jdbc/with-transaction [tx my-datasource]\n (let [result (jdbc/execute! tx ...)]\n (if ...\n (do\n (.rollback tx)\n result)\n (jdbc/execute! tx ...))))\n```\n\n## Save Points Inside a Transaction\n\nIn general, transactions are per-connection and do not nest in JDBC. If you nest calls to `with-transaction` using a `DataSource` argument (or a db-spec) then you will get separate connections inside each invocation and the transactions will be independent, as permitted by the isolation level.\n\nIf you nest such calls passing a `Connection` instead, the inner call will commit (or rollback) all operations on that connection up to that point -- including any performed in the outer call, prior to entering the inner call. The outer call will then commit (or rollback) any additional operations within its scope. This will be confusing at best and most likely buggy behavior! See below for ways to exercise more control over this behavior.\n\nIf you want the ability to selectively roll back certain groups of operations inside a transaction, you can use named or unnamed save points:\n\n```clojure\n(jdbc/with-transaction [tx my-datasource]\n (let [result (jdbc/execute! tx ...) ; op A\n sp1 (.setSavepoint tx)] ; unnamed save point\n\n (jdbc/execute! tx ...) ; op B\n\n (when ... (.rollback tx sp1)) ; just rolls back op B\n\n (let [sp2 (.setSavepoint tx \"two\")] ; named save point\n\n (jdbc/execute! tx ...) ; op C\n\n (when ... (.rollback tx sp2))) ; just rolls back op C\n\n result)) ; returns this and will commit op A\n ;; (and ops B & C if they weren't rolled back above)\n```\n\n### Nesting Transactions\n\nAs noted above, transactions do not nest in JDBC and `next.jdbc`'s default behavior is to allow you\nto overlap transactions (i.e., nested calls to `with-transaction`) and assume you know what you are\ndoing, although it would generally be buggy programming to do so.\n\nBy contrast, `clojure.java.jdbc` allowed the nested calls but simply _ignored_ the inner calls and\nbehaved as it you had only the outermost, top-level transaction. That allowed for buggy programming\ntoo, in a different way, but could be convenient if you wanted to override any transaction behavior\nin called code, as you might wish to do with a test fixture that set up and rolled back a\ntransaction at the top-level -- you would just silently lose the effects of any (nested)\ntransactions in the code under test.\n\n`next.jdbc` provides a way to control the behavior via a public, dynamic Var:\n\n* `next.jdbc.transaction/*nested-tx*` is initially set to `:allow` which allows nested calls but makes them overlap (as described above),\n* `(binding [next.jdbc.transaction/*nested-tx* :ignore] ...)` provides the same behavior as `clojure.java.jdbc` where nested calls are essentially ignored and only the outermost transaction takes effect,\n* `(binding [next.jdbc.transaction/*nested-tx* :prohibit] ...)` will cause any attempt to start a nested transaction to throw an exception instead; this could be a useful way to detect the potentially buggy behavior described above (for either `:allow` or `:ignore`).\n\n[<: Prepared Statements](/doc/prepared-statements.md) | [All The Options :>](/doc/all-the-options.md)\n","cljdoc.doc/type":"cljdoc/markdown","slug":"transactions","cljdoc.doc/contributors":["Sean Corfield","Simon Robson","jet"]}}]},{"title":"All The Options","attrs":{"cljdoc.doc/source-file":"doc/all-the-options.md","cljdoc/markdown":"# `next.jdbc` Options\n\nThis section documents all of the options that are supported by all of the functions in `next.jdbc`. Nearly every function accepts an optional hash map as the last argument, that can control many of the behaviors of the library.\n\nThe most general options are described first, followed by more specific options that apply only to certain functions.\n\n## Datasources and Connections\n\nAlthough `get-datasource` does not accept options, the \"db spec\" hash map passed in may contain the following options:\n\n* `:dbtype` -- a string that identifies the type of JDBC database being used,\n* `:dbname` -- a string that identifies the name of the actual database being used,\n* `:dbname-separator` -- an optional string that can be used to override the `/` or `:` that is normally placed in front of the database name in the JDBC URL,\n* `:host` -- an optional string that identifies the IP address or hostname of the server on which the database is running; the default is `\"127.0.0.1\"`; if `:none` is specified, `next.jdbc` will assume this is for a local database and will omit the host/port segment of the JDBC URL,\n* `:host-prefix` -- an optional string that can be used to override the `//` that is normally placed in front of the IP address or hostname in the JDBC URL,\n* `:port` -- an optional integer that identifies the port on which the database is running; for common database types, `next.jdbc` knows the default so this should only be needed for non-standard setups or \"exotic\" database types,\n* `:classname` -- an optional string that identifies the name of the JDBC driver class to be used for the connection; for common database types, `next.jdbc` knows the default so this should only be needed for \"exotic\" database types,\n* `:user` -- an optional string that identifies the database username to be used when authenticating,\n* `:password` -- an optional string that identifies the database password to be used when authenticating.\n\nAny additional keys provided in the \"db spec\" will be passed to the JDBC driver as `Properties` when each connection is made. Alternatively, when used with `next.jdbc.connection/->pool`, additional keys correspond to setters called on the pooled connection object.\n\nIf you are using HikariCP and `next.jdbc.connection/->pool` to create a connection pooled datasource, you need to provide `:username` for the database username (instead of, or as well as, `:user`).\n\nAny path that calls `get-connection` will accept the following options:\n\n* `:auto-commit` -- a `Boolean` that determines whether operations on this connection should be automatically committed (the default, `true`) or not; note that setting `:auto-commit false` is commonly required when you want to stream result set data from a query (along with fetch size etc -- see below),\n* `:read-only` -- a `Boolean` that determines whether the operations on this connection should be read-only or not (the default, `false`).\n* `:connection` -- a hash map of camelCase properties to set on the `Connection` object after it is created; these correspond to `.set*` methods on the `Connection` class and are set via the Java reflection API (using `org.clojure/java.data`). If `:autoCommit` or `:readOnly` are provided, they will take precedence over the fast, specific options above.\n\nIf you need additional options set on a connection, you can either use Java interop to set them directly, or provide them as part of the \"db spec\" hash map passed to `get-datasource` (although then they will apply to _all_ connections obtained from that datasource).\n\n> Note: If `plan`, `execute!`, or `execute-one!` are passed a `DataSource`, a \"db spec\" hash map, or a JDBC URL string, they will call `get-connection`, so they will accept the above options in those cases.\n\n## Generating SQL\n\nExcept for `query` (which is simply an alias for `execute!`), all the \"friendly\" SQL functions accept the following options (in addition to all the options that `plan`, `execute!`, and `execute-one!` can accept):\n\n* `:table-fn` -- the quoting function to be used on the string that identifies the table name, if provided,\n* `:column-fn` -- the quoting function to be used on any string that identifies a column name, if provided.\n\nThey also support a `:suffix` argument which can be used to specify a SQL string that should be appended to the generated SQL string before executing it, e.g., `:suffix \"FOR UPDATE\"`.\n\nIn addition, `find-by-keys` accepts the following options (see its docstring for more details):\n\n* `:columns` -- specify one or more columns to `SELECT` to override selecting all columns,\n* `:order-by` -- specify one or more columns, on which to sort the results,\n* `:top` / `:limit` / `:offset` / `:fetch` to support pagination of results.\n\nIn the simple case, the `:columns` option expects a vector of keywords and each will be processed according to `:column-fn`, if provided. A column alias can be specified using a vector pair of keywords and both will be processed according to `:column-fn`, e.g., `[:foo [:bar :quux]]` would expand to `foo, bar AS quux`. You can also specify the first element of the pair as a string which will be used as-is in the generated SQL, e.g., `[:foo [\"COUNT(*)\" :total]]` would expand to `foo, COUNT(*) AS total`. In the latter case, the alias keyword will still be processed according to `:column-fn` but the string will be untouched -- you are responsible for any quoting and/or other formatting that might be required to produce a valid SQL expression.\n\n> Note: `get-by-id` accepts the same options as `find-by-keys` but it will only ever produce one row, as a hash map, so sort order and pagination are less applicable, although `:columns` may be useful.\n\n## Generating Rows and Result Sets\n\nAny function that might realize a row or a result set will accept:\n\n* `:builder-fn` -- a function that implements the `RowBuilder` and `ResultSetBuilder` protocols; strictly speaking, `plan` and `execute-one!` only need `RowBuilder` to be implemented (and `plan` only needs that if it actually has to realize a row) but most generation functions will implement both for ease of use.\n* `:label-fn` -- if `:builder-fn` is specified as one of `next.jdbc.result-set`'s `as-modified-*` builders, this option must be present and should specify a string-to-string transformation that will be applied to the column label for each returned column name.\n* `:qualifier-fn` -- if `:builder-fn` is specified as one of `next.jdbc.result-set`'s `as-modified-*` builders, this option should specify a string-to-string transformation that will be applied to the table name for each returned column name. It will be called with an empty string if the table name is not available. It can be omitted for the `as-unqualified-modified-*` variants.\n\nIn addition, `execute!` accepts the `:multi-rs true` option to return multiple result sets -- as a vector of result sets.\n\n> Note: Subject to the caveats above about `:builder-fn`, that means that `plan`, `execute!`, `execute-one!`, and the \"friendly\" SQL functions will all accept these options for generating rows and result sets.\n\n## Statements & Prepared Statements\n\nAny function that creates a `Statement` or a `PreparedStatement` will accept the following options (see below for additional options for `PreparedStatement`):\n\n* `:concurrency` -- a keyword that specifies the concurrency level: `:read-only`, `:updatable`,\n* `:cursors` -- a keyword that specifies whether cursors should be closed or held over a commit: `:close`, `:hold`,\n* `:fetch-size` -- an integer that guides the JDBC driver in terms of how many rows to fetch at once; the actual behavior of specifying `:fetch-size` is database-specific: some JDBC drivers use a zero or negative value here to trigger streaming of result sets -- other JDBC drivers require this to be positive for streaming and may require additional options to be set on the connection _as well_,\n* `:max-rows` -- an integer that tells the JDBC driver to limit result sets to this many rows,\n* `:result-type` -- a keyword that affects how the `ResultSet` can be traversed: `:forward-only`, `:scroll-insensitive`, `:scroll-sensitive`,\n* `:timeout` -- an integer that specifies the (query) timeout allowed for SQL operations, in seconds. See [**Handling Timeouts**](/doc/tips-and-tricks.md#handling-timeouts) in **Tips & Tricks** for more details on this and other possible timeout settings.\n* `:statement` -- a hash map of camelCase properties to set on the `Statement` or `PreparedStatement` object after it is created; these correspond to `.set*` methods on the `Statement` class (which `PreparedStatement` inherits) and are set via the Java reflection API (using `org.clojure/java.data`). If `:fetchSize`, `:maxRows`, or `:queryTimeout` are provided, they will take precedence over the fast, specific options above.\n\nIf you specify either `:concurrency` or `:result-type`, you must specify _both_ of them. If you specify `:cursors`, you must also specify `:result-type` _and_ `:concurrency`.\n\n> Note: For MS SQL Server to return table names (for qualified column names), you must specify `:result-type` with one of the scroll values (and so you must also specify `:concurrency`).\n\nAny function that creates a `PreparedStatement` will additionally accept the following options:\n\n* `:return-keys` -- a truthy value asks that the JDBC driver to return any generated keys created by the operation; it can be `true` or it can be a vector of keywords identifying column names that should be returned.\n\nNot all databases or drivers support all of these options, or all values for any given option. If `:return-keys` is a vector of column names and that is not supported, `next.jdbc` will attempt a generic \"return generated keys\" option instead. If that is not supported, `next.jdbc` will fall back to a regular SQL operation. If other options are not supported, you may get a `SQLException`.\n\n> Note: If `plan`, `execute!`, or `execute-one!` are passed a `DataSource`, a \"db spec\" hash map, or a JDBC URL string, they will call `prepare` to create a `PreparedStatement`, so they will accept the above options in those cases.\n\nIn addition to the above, `next.jdbc/execute-batch!` (which may create a `PreparedStatement` if you pass in a SQL string and either a `Connection` or `DataSource`) accepts an options hash map that can also contain the following:\n\n* `:batch-size` -- an integer that determines how to partition the parameter groups for submitting to the database in batches,\n* `:large` -- a Boolean flag that indicates whether the batch will produce large update counts (`long` rather than `int` values),\n* `:return-generated-keys` -- a Boolean flag that indicates whether `.getGeneratedKeys` should be called on the `PreparedStatement` after each batch is executed (if `true`, `execute-batch!` will return a vector of hash maps containing generated keys).\n\n## Transactions\n\nThe `transact` function and `with-transaction` macro accept the following options:\n\n* `:isolation` -- a keyword that identifies the isolation to be used for this transaction: `:none`, `:read-committed`, `:read-uncommitted`, `:repeatedable-read`, or `:serializable`; these represent increasingly strict levels of transaction isolation and may not all be available depending on the database and/or JDBC driver being used,\n* `:read-only` -- a `Boolean` that indicates whether the transaction should be read-only or not (the default),\n* `:rollback-only` -- a `Boolean` that indicates whether the transaction should commit on success (the default) or rollback.\n\n## Plan Selection\n\nThe `next.jdbc.plan/select!` function accepts the following specific option:\n\n* `:into` -- a data structure into which the selected result from a `plan` operation are poured; by default this is `[]`; could be any value that is acceptable as the first argument to `into`, subject to `into` accepting the sequence of values produced by the `plan` reduction.\n\n[<: Transactions](/doc/transactions.md) | [`datafy`, `nav`, and `:schema` :>](/doc/datafy-nav-and-schema.md)\n","cljdoc.doc/type":"cljdoc/markdown","slug":"all-the-options","cljdoc.doc/contributors":["Sean Corfield","Lauri Oherd","Jakub Holy","Sooheon Kim"]}},{"title":"datafy, nav, and :schema","attrs":{"cljdoc.doc/source-file":"doc/datafy-nav-and-schema.md","cljdoc/markdown":"# `datafy`, `nav`, and the `:schema` option\n\nClojure 1.10 introduced a new namespace, [`clojure.datafy`](http://clojure.github.io/clojure/clojure.datafy-api.html), and two new protocols (`Datafiable` and `Navigable`) that allow for generalized, lazy navigation around data structures. Cognitect also released [REBL](http://rebl.cognitect.com/) -- a graphical, interactive tool for browsing Clojure data structures, based on the new `datafy` and `nav` functions.\n\nShortly after REBL's release, I added experimental support to `clojure.java.jdbc` for `datafy` and `nav` that supported lazy navigation through result sets into foreign key relationships and connected rows and tables. `next.jdbc` bakes that support into result sets produced by `execute!` and `execute-one!`.\n\nIn addition to `datafy` and `nav` support in the result sets, as of version 1.0.462, there is a `next.jdbc.datafy` namespace that can be required to extend these protocols to a number of JDBC object types. See **JDBC Datafication** near the end of this page for more detail of this.\n\n## The `datafy`/`nav` Lifecycle on Result Sets\n\nHere's how the process works, for result sets produced by `next.jdbc`:\n\n* `execute!` and `execute-one!` produce result sets containing rows that are `Datafiable`,\n* Tools like REBL can call `datafy` on result sets to render them as \"pure data\" (which they already are, but this makes them also `Navigable`),\n* Tools like REBL allow users to \"drill down\" into elements of rows in the \"pure data\" result set, using `nav`,\n* If a column in a row represents a foreign key into another table, calling `nav` will fetch the related row(s),\n* Those can in turn be `datafy`'d and `nav`'d to continue drilling down through connected data in the database.\n\nIn addition to `execute!` and `execute-one!`, you can call `next.jdbc.result-set/datafiable-result-set` on any `ResultSet` object to produce a result set whose rows are `Datafiable`. Inside a reduction over the result of `plan`, you can call `next.jdbc.result-set/datafiable-row` on a row to produce a `Datafiable` row. That will realize the entire row, including generating column names using the row builder specified (or `as-maps` by default).\n\n### Identifying Foreign Keys\n\nBy default, `next.jdbc` assumes that a column named `<something>id` or `<something>_id` is a foreign key into a table called `<something>` with a primary key called `id`. As an example, if you have a table `address` which has columns `id` (the primary key), `name`, `email`, etc, and a table `contact` which has various columns including `addressid`, then if you retrieve a result set based on `contact`, call `datafy` on it and then \"drill down\" into the columns, when `(nav row :contact/addressid v)` is called (where `v` is the value of that column in that row) `next.jdbc`'s implementation of `nav` will fetch a single row from the `address` table, identified by `id` matching `v`.\n\nYou can override this default behavior for any column in any table by providing a `:schema` option that is a hash map whose keys are column names (usually the table-qualified keywords that `next.jdbc` produces by default) and whose values are table-qualified keywords, optionally wrapped in vectors, that identity the name of the table to which that column is a foreign key and the name of the key column within that table.\n\nThe default behavior in the example above is equivalent to this `:schema` value:\n\n```clojure\n(jdbc/execute! ds\n [\"select * from contact where city = ?\" \"San Francisco\"]\n ;; a one-to-one or many-to-one relationship\n {:schema {:contact/addressid :address/id}})\n```\n\nIf you had a table to track the valid/bouncing status of email addresses over time, `:deliverability`, where `email` is the non-unique key, you could provide automatic navigation into that using:\n\n```clojure\n(jdbc/execute! ds\n [\"select * from contact where city = ?\" \"San Francisco\"]\n ;; one-to-many or many-to-many\n {:schema {:contact/addressid :address/id\n :address/email [:deliverability/email]}})\n```\n\nWhen you indicate a `*-to-many` relationship, by wrapping the foreign table/key in a vector, `next.jdbc`'s implementation of `nav` will fetch a multi-row result set from the target table.\n\nIf you use foreign key constraints in your database, you could probably generate this `:schema` data structure automatically from the metadata in your database. Similarly, if you use a library that depends on an entity relationship map (such as [seql](https://exoscale.github.io/seql/) or [walkable](https://walkable.gitlab.io/)), then you could probably generate this `:schema` data structure from that entity map.\n\n### Behind The Scenes\n\nMaking rows datafiable is implemented by adding metadata to each row with a key of `clojure.core.protocols/datafy` and a function as the value. That function closes over the connectable and options passed in to the `execute!` or `execute-one!` call that produced the result set containing those rows.\n\nWhen called (`datafy` on a row), it adds metadata to the row with a key of `clojure.core.protocols/nav` and another function as the value. That function also closes over the connectable and options passed in.\n\nWhen that is called (`nav` on a row, column name, and column value), if a `:schema` entry exists for that column or it matches the default convention described above, then it will fetch row(s) using `next.jdbc`'s `Executable` functions `-execute-one` or `-execute-all`, passing in the connectable and options closed over.\n\nThe protocol `next.jdbc.result-set/DatafiableRow` has a default implementation of `datafiable-row` for `clojure.lang.IObj` that just adds the metadata to support `datafy`. There is also an implementation baked into the result set handling behind `plan` so that you can call `datafiable-row` directly during reduction and get a fully-realized row that can be `datafy`'d (and then `nav`igated).\n\nIn addition, you can call `next.jdbc.result-set/datafiable-result-set` on any `ResultSet` object and get a fully realized, datafiable result set created using any of the result set builders.\n\n## JDBC Datafication\n\nIf you require `next.jdbc.datafy`, the `Datafiable` protocol is extended to several JDBC object types, so that calling `datafy` will turn them into hash maps according to Java Bean introspection, similar to `clojure.core/bean` although `next.jdbc` uses `clojure.java.data/from-java-shallow` (from [`org.clojure/java.data`](https://github.com/clojure/java.data)), with some additions as described below.\n\n* `java.sql.Connection` -- datafies as a bean; The `:metaData` property is a `java.sql.DatabaseMetaData`, which is also datafiable.\n* `DatabaseMetaData` -- datafies as a bean, with an additional `:all-tables` property (that is a dummy object); six properties are navigable to produce fully-realized datafiable result sets:\n * `all-tables` -- produced from `(.getTables this nil nil nil nil)`, this is all the tables and views available from the connection that produced the database metadata,\n * `catalogs` -- produced from `(.getCatalogs this)`\n * `clientInfoProperties` -- all the client properties that the database driver supports,\n * `schemas` -- produced from `(.getSchemas this)`,\n * `tableTypes` -- produced from `(.getTableTypes this)`,\n * `typeInfo` -- produced from `(.getTypeInfo this)`.\n* `ParameterMetaData` -- datafies as a vector of parameter descriptions; each parameter hash map has: `:class` (the name of the parameter class -- JVM), `:mode` (one of `:in`, `:in-out`, or `:out`), `:nullability` (one of: `:null`, `:not-null`, or `:unknown`), `:precision`, `:scale`, `:type` (the name of the parameter type -- SQL), and `:signed` (Boolean).\n* `ResultSet` -- datafies as a bean; if the `ResultSet` has an associated `Statement` and that in turn has an associated `Connection` then an additional key of `:rows` is provided which is a datafied result set, from `next.jdbc.result-set/datafiable-result-set` with default options. This is provided as a convenience, purely for datafication of other JDBC data types -- in normal `next.jdbc` usage, result sets are datafied under full user control.\n* `ResultSetMetaData` -- datafies as a vector of column descriptions; each column hash map has: `:auto-increment`, `:case-sensitive`, `:catalog`, `:class` (the name of the column class -- JVM), `:currency` (Boolean), `:definitely-writable`, `:display-size`, `:label`, `:name`, `:nullability`, `:precision`, `:read-only`, `:searchable`, `:signed`, `:scale`, `:schema`, `:table`, `:type`, and `:writable`.\n* `Statement` -- datafies as a bean.\n\nSee the Java documentation for these JDBC types for further details on what all the properties from each of these classes mean and which are `int`, `String`, or some other JDBC object type.\n\nIn addition, requiring this namespace will affect how `next.jdbc.result-set/metadata` behaves inside the reducing function applied to the result of `plan`. Without this namespace loaded, that function will return a raw `ResultSetMetaData` object (which must not leak outside the reducing function). With this namespace loaded, that function will, instead, return a Clojure data structure describing the columns in the result set.\n\n[<: All The Options](/doc/all-the-options.md) | [Migration from `clojure.java.jdbc` :>](/doc/migration-from-clojure-java-jdbc.md)\n","cljdoc.doc/type":"cljdoc/markdown","slug":"datafy-nav-and-schema","cljdoc.doc/contributors":["Sean Corfield"]}},{"title":"Migration from clojure.java.jdbc","attrs":{"cljdoc.doc/source-file":"doc/migration-from-clojure-java-jdbc.md","cljdoc/markdown":"# Migrating from `clojure.java.jdbc`\n\nThis page attempts to list all of the differences between [clojure.java.jdbc](https://github.com/clojure/java.jdbc) and `next.jdbc`. Some of them are large and obvious, some of them are small and subtle -- all of them are deliberate design choices.\n\n## Conceptually\n\n`clojure.java.jdbc` focuses heavily on a `db-spec` hash map to describe the various ways of interacting with the database and grew from very imperative origins that expose a lot of the JDBC API (multiple types of SQL execution, some operations returned hash maps, others update counts as integers, etc).\n\n`next.jdbc` focuses on using protocols and native Java JDBC types where possible (for performance and simplicity) and strives to present a more modern Clojure API with namespace-qualified keywords in hash maps, reducible SQL operations as part of the primary API, and a streamlined set of SQL execution primitives. Execution always returns a hash map (for one result) or a vector of hash maps (for multiple results) -- even update counts are returned as if they were result sets.\n\n### Rows and Result Sets\n\n`clojure.java.jdbc` returned result sets (and generated keys) as hash maps with simple, lower-case keys by default. `next.jdbc` returns result sets (and generated keys) as hash maps with qualified, as-is keys by default: each key is qualified by the name of table from which it is drawn, if known. The as-is default is chosen to a) improve performance and b) not mess with the data. Using a `:builder-fn` option of `next.jdbc.result-set/as-unqualified-maps` will produce simple, as-is keys. Using a `:builder-fn` option of `next.jdbc.result-set/as-unqualified-lower-maps` will produce simple, lower-case keys -- the most compatible with `clojure.java.jdbc`'s default behavior.\n\n> Note: `clojure.java.jdbc` would make column names unique by appending numeric suffixes, for example in a `JOIN` that produced columns `id` from multiple tables. `next.jdbc` does not do this: if you use _qualified_ column names -- the default -- then you would get `:sometable/id` and `:othertable/id`, but with _unqualified_ column names you would just get one `:id` in each row. It was always poor practice to rely on `clojure.java.jdbc`'s renaming behavior and it added quite an overhead to result set building, which is why `next.jdbc` does not support it -- use explicit column aliasing in your SQL instead if you want _unqualified_ column names!\n\nIf you used `:as-arrays? true`, you will most likely want to use a `:builder-fn` option of `next.jdbc.result-set/as-unqualified-lower-arrays`.\n\n> Note: When `next.jdbc` cannot obtain a `ResultSet` object and returns `{:next.jdbc/count N}` instead, these builder functions are not applied -- the `:builder-fn` option is not used in that situation.\n\n### Option Handling\n\nBecause `clojure.java.jdbc` focuses on a hash map for the `db-spec` that is passed around, it can hold options that act as defaults for all operations on it. In addition, all operations in `clojure.java.jdbc` can accept a hash map of options and can pass those options down the call chain. In `next.jdbc`, `get-datasource`, `get-connection`, and `prepare` all produce Java objects that cannot have any extra options attached. On one hand, that means that it is harder to provide \"default options\", and on the other hand it means you need to be a bit more careful to ensure that you pass the appropriate options to the appropriate function, since they cannot be passed through the call chain via the `db-spec`. That's where `next.jdbc/with-options` can come in handy to wrap a connectable (generally a datasource or a connection) but be careful where you are managing connections and/or transactions directly, as mentioned in the [Getting Started](/doc/getting-started.md) guide.\n\nIn [All The Options](all-the-options.md), the appropriate options are shown for each function, as well as which options _will_ get passed down the call chain, e.g., if a function can open a connection, it will accept options for `get-connection`; if a function can build a result set, it will accept `:builder-fn`. However, `get-datasource`, `get-connection`, and `prepare` cannot propagate options any further because they produce Java objects as their results -- in particular, `prepare` can't accept `:builder-fn` because it doesn't build result sets: only `plan`, `execute-one!`, and `execute!` can use `:builder-fn`.\n\nIn particular, this means that you can't globally override the default options (as you could with `clojure.java.jdbc` by adding your preferred defaults to the db-spec itself). If the default options do not suit your usage and you really don't want to override them in every call, it is recommended that you try to use `next.jdbc/with-options` first, and if that still doesn't satisfy you, write a wrapper namespace that implements the subset of the dozen API functions (from `next.jdbc` and `next.jdbc.sql`) that you want to use, overriding their `opts` argument with your defaults.\n\n## Primary API\n\n`next.jdbc` has a deliberately narrow primary API that has (almost) no direct overlap with `clojure.java.jdbc`:\n\n* `get-datasource` -- has no equivalent in `clojure.java.jdbc` but is intended to emphasize `javax.sql.DataSource` as a starting point,\n* `get-connection` -- overlaps with `clojure.java.jdbc` (and returns a `java.sql.Connection`) but accepts only a subset of the options (`:dbtype`/`:dbname` hash map, `String` JDBC URL); `clojure.java.jdbc/get-connection` accepts `{:datasource ds}` whereas `next.jdbc/get-connection` accepts the `javax.sql.DataSource` object directly,\n* `prepare` -- somewhat similar to `clojure.java.jdbc/prepare-statement` but it accepts a vector of SQL and parameters (compared to just a raw SQL string),\n* `plan` -- somewhat similar to `clojure.java.jdbc/reducible-query` but accepts arbitrary SQL statements for execution,\n* `execute!` -- has no direct equivalent in `clojure.java.jdbc` (but it can replace most uses of both `query` and `db-do-commands`),\n* `execute-one!` -- has no equivalent in `clojure.java.jdbc` (but it can replace most uses of `query` that currently use `:result-set-fn first`),\n* `transact` -- similar to `clojure.java.jdbc/db-transaction*`,\n* `with-transaction` -- similar to `clojure.java.jdbc/with-db-transaction`,\n* `with-options` -- provides a way to specify \"default options\" over a group of operations, by wrapping the connectable (datasource or connection).\n\nIf you were using a bare `db-spec` hash map with `:dbtype`/`:dbname`, or a JDBC URL string everywhere, that should mostly work with `next.jdbc` since most functions accept a \"connectable\", but it would be better to create a datasource first, and then pass that around. Note that `clojure.java.jdbc` allowed the `jdbc:` prefix in a JDBC URL to be omitted but `next.jdbc` _requires that prefix!_\n\nIf you were already creating `db-spec` as a pooled connection datasource -- a `{:datasource ds}` hashmap -- then passing `(:datasource db-spec)` to the `next.jdbc` functions is the simplest migration path. If you are migrating piecemeal and want to support _both_ `clojure.java.jdbc` _and_ `next.jdbc` at the same time in your code, you should consider using a datasource as the common way to work with both libraries. You can using `next.jdbc`'s `get-datasource` or the `->pool` function (in `next.jdbc.connection`) to create the a `javax.sql.DataSource` and then build a `db-spec` hash map with it (`{:datasource ds}`) and pass that around your program. `clojure.java.jdbc` calls can use that as-is, `next.jdbc` calls can use `(:datasource db-spec)`, so you don't have to adjust any of your call chains (assuming you're passing `db-spec` around) and you can migrate one function at a time.\n\nIf you were using other forms of the `db-spec` hash map, you'll need to adjust to one of the three modes above, since those are the only ones supported in `next.jdbc`.\n\nThe `next.jdbc.sql` namespace contains several functions with similarities to `clojure.java.jdbc`'s core API:\n\n* `insert!` -- similar to `clojure.java.jdbc/insert!` but only supports inserting a single map,\n* `insert-multi!` -- similar to `clojure.java.jdbc/insert-multi!` but only supports inserting columns and a vector of row values,\n* `query` -- similar to `clojure.java.jdbc/query`,\n* `find-by-keys` -- similar to `clojure.java.jdbc/find-by-keys` but will also accept a partial where clause (vector) instead of a hash map of column name/value pairs,\n* `get-by-id` -- similar to `clojure.java.jdbc/get-by-id`,\n* `update!` -- similar to `clojure.java.jdbc/update!` but will also accept a hash map of column name/value pairs instead of a partial where clause (vector),\n* `delete!` -- similar to `clojure.java.jdbc/delete!` but will also accept a hash map of column name/value pairs instead of a partial where clause (vector).\n\nIf you were using `db-do-commands` in `clojure.java.jdbc` to execute DDL, the following is the equivalent in `next.jdbc`:\n\n```clojure\n(defn do-commands [connectable commands]\n (if (instance? java.sql.Connection connectable)\n (with-open [stmt (next.jdbc.prepare/statement connectable)]\n (run! #(.addBatch stmt %) commands)\n (into [] (.executeBatch stmt)))\n (with-open [conn (next.jdbc/get-connection connectable)]\n (do-commands conn commands))))\n```\n\n### `:identifiers` and `:qualifier`\n\nIf you are using `:identifiers`, you will need to change to the appropriate `:builder-fn` option with one of `next.jdbc.result-set`'s `as-*` functions.\n\n`clojure.java.jdbc`'s default is the equivalent of `as-unqualified-lower-maps` (with the caveat that conflicting column names are not made unique -- see the note above in **Rows and Result Sets**). If you specified `:identifiers identity`, you can use `as-unqualified-maps`. If you provided your own string transformation function, you probably want `as-unqualified-modified-maps` and also pass your transformation function as the `:label-fn` option.\n\nIf you used `:qualifier`, you can get the same effect with `as-modified-maps` by passing `:qualifier-fn (constantly \"my_qualifier\")` (and the appropriate `:label-fn` -- either `identity` or `clojure.string/lowercase`).\n\n### `:entities`\n\nIf you are using `:entities`, you will need to change to the appropriate `:table-fn`/`:column-fn` options. Table naming and column naming can be controlled separately in `next.jdbc`. Instead of the `quoted` function, there is the `next.jdbc.quoted` namespace which contains functions for the common quoting strategies.\n\n### `:result-set-fn` and `:row-fn`\n\nIf you are using `:result-set-fn` and/or `:row-fn`, you will need to change to explicit calls (to the result set function, or to `map` the row function), or to use the `plan` approach with `reduce` or various transducing functions.\n\n> Note: this means that result sets are never exposed lazily in `next.jdbc` -- in `clojure.java.jdbc` you had to be careful that your `:result-set-fn` was eager, but in `next.jdbc` you either reduce the result set eagerly (via `plan`) or you get a fully-realized result set data structure back (from `execute!` and `execute-one!`). As with `clojure.java.jdbc` however, you can still stream result sets from the database and process them via reduction (was `reducible-query`, now `plan`). Remember that you can terminate a reduction early by using the `reduced` function to wrap the final value you produce.\n\n### Processing Database Metadata\n\nThere are no metadata-specific functions in `next.jdbc` but those in `clojure.java.jdbc` are only a very thin layer over the raw Java calls. Here's how metadata can be handled in `next.jdbc`:\n\n```clojure\n(with-open [con (p/get-connection ds opts)]\n (-> (.getMetaData con) ; produces java.sql.DatabaseMetaData\n (.getTables nil nil nil (into-array [\"TABLE\" \"VIEW\"]))\n (rs/datafiable-result-set ds opts)))\n```\n\nSeveral methods on `DatabaseMetaData` return a `ResultSet` object. All of those can be handled similarly.\n\n## Further Minor differences\n\nThese are mostly drawn from [Issue #5](https://github.com/seancorfield/next-jdbc/issues/5) although most of the bullets in that issue are described in more detail above.\n\n* Keyword options no longer end in `?` -- for consistency (in `clojure.java.jdbc`, some flag options ended in `?` and some did not; also some options that ended in `?` accepted non-`Boolean` values, e.g., `:as-arrays?` and `:explain?`),\n* `with-db-connection` has been replaced by just `with-open` containing a call to `get-connection`,\n* `with-transaction` can take a `:rollback-only` option, but there is no built-in way to change a transaction to rollback _dynamically_; either throw an exception (all transactions roll back on an exception) or call `.rollback` directly on the `java.sql.Connection` object (see [Manual Rollback Inside a Transactions](/doc/transactions.md#manual-rollback-inside-a-transaction) and the following section about save points),\n* `clojure.java.jdbc` implicitly allowed transactions to nest and just silently ignored the inner, nested transactions (so you only really had the top-level, outermost transaction); `next.jdbc` by default assumes you know what you are doing and so an inner (nested) transaction will commit or rollback the work done so far in outer transaction (and then when that outer transaction ends, the remaining work is rolled back or committed); `next.jdbc.transaction/*nested-tx*` is a dynamic var that can be bound to `:ignore` to get the same behavior as `clojure.java.jdbc`.\n* The extension points for setting parameters and reading columns are now `SettableParameter` and `ReadableColumn` protocols.\n\n[<: `datafy`, `nav`, and `:schema`](/doc/datafy-nav-and-schema.md)\n","cljdoc.doc/type":"cljdoc/markdown","slug":"migration-from-clojure-java-jdbc","cljdoc.doc/contributors":["Sean Corfield","Lauri Oherd"]}}],"config":{"cljdoc.doc/tree":[["Readme",{"file":"README.md"}],["Changes",{"file":"CHANGELOG.md"}],["Getting Started",{"file":"doc/getting-started.md"},["Friendly SQL Functions",{"file":"doc/friendly-sql-functions.md"}],["Tips & Tricks",{"file":"doc/tips-and-tricks.md"}],["Result Set Builders",{"file":"doc/result-set-builders.md"}],["Prepared Statements",{"file":"doc/prepared-statements.md"}],["Transactions",{"file":"doc/transactions.md"}]],["All The Options",{"file":"doc/all-the-options.md"}],["datafy, nav, and :schema",{"file":"doc/datafy-nav-and-schema.md"}],["Migration from clojure.java.jdbc",{"file":"doc/migration-from-clojure-java-jdbc.md"}]]}},"namespaces":[{"doc":"This namespace provides datafication of several JDBC object types,\nall within the `java.sql` package:\n\n* `Connection` -- datafies as a bean.\n* `DatabaseMetaData` -- datafies as a bean; six properties\n are navigable to produce fully-realized datafiable result sets.\n* `ParameterMetaData` -- datafies as a vector of parameter descriptions.\n* `ResultSet` -- datafies as a bean; if the `ResultSet` has an associated\n `Statement` and that in turn has an associated `Connection` then an\n additional key of `:rows` is provided which is a datafied result set,\n from `next.jdbc.result-set/datafiable-result-set` with default options.\n This is provided as a convenience, purely for datafication of other\n JDBC data types -- in normal `next.jdbc` usage, result sets are\n datafied under full user control.\n* `ResultSetMetaData` -- datafies as a vector of column descriptions.\n* `Statement` -- datafies as a bean.\n\nBecause different database drivers may throw `SQLException` for various\nunimplemented or unavailable properties on objects in various states,\nthe default behavior is to return those exceptions using the `:qualify`\noption for `clojure.java.data/from-java-shallow`, so for a property\n`:foo`, if its corresponding getter throws an exception, it would instead\nbe returned as `:foo/exception`. This behavior can be overridden by\n`binding` `next.jdbc.datafy/*datafy-failure*` to any of the other options\nsupported: `:group`, `:omit`, or `:return`. See the `clojure.java.data`\ndocumentation for more details.","name":"next.jdbc.datafy","platform":"clj","version-entity":{"id":1,"group-id":"seancorfield","artifact-id":"next.jdbc","version":"1.2.659"}},{"doc":"Standard implementations of `get-datasource` and `get-connection`.\n\nAlso provides `dbtypes` as a map of all known database types, and\nthe `->pool` and `component` functions for creating pooled datasource\nobjects.","name":"next.jdbc.connection","platform":"clj","version-entity":{"id":1,"group-id":"seancorfield","artifact-id":"next.jdbc","version":"1.2.659"}},{"doc":"The public API of the next generation java.jdbc library.\n\nThe basic building blocks are the `java.sql`/`javax.sql` classes:\n* `DataSource` -- something to get connections from,\n* `Connection` -- an active connection to the database,\n* `PreparedStatement` -- SQL and parameters combined, from a connection,\n\nand the following functions and a macro:\n* `get-datasource` -- given a hash map describing a database or a JDBC\n connection string, construct a `javax.sql.DataSource` and return it,\n* `get-connection` -- given a connectable, obtain a new `java.sql.Connection`\n from it and return that,\n* `plan` -- given a connectable and SQL + parameters or a statement,\n return a reducible that, when reduced will execute the SQL and consume\n the `ResultSet` produced,\n* `execute!` -- given a connectable and SQL + parameters or a statement,\n execute the SQL, consume the `ResultSet` produced, and return a vector\n of hash maps representing the rows (@1); this can be datafied to allow\n navigation of foreign keys into other tables (either by convention or\n via a schema definition),\n* `execute-one!` -- given a connectable and SQL + parameters or a statement,\n execute the SQL, consume the first row of the `ResultSet` produced, and\n return a hash map representing that row; this can be datafied to allow\n navigation of foreign keys into other tables (either by convention or\n via a schema definition),\n* `execute-batch!` -- given a `PreparedStatement` and groups of parameters,\n execute the statement in batch mode (via `.executeBatch`); given a\n connectable, a SQL string, and groups of parameters, create a new\n `PreparedStatement` from the SQL and execute it in batch mode.\n* `prepare` -- given a `Connection` and SQL + parameters, construct a new\n `PreparedStatement`; in general this should be used with `with-open`,\n* `transact` -- the functional implementation of `with-transaction`,\n* `with-transaction` -- execute a series of SQL operations within a transaction.\n\n@1 result sets are built, by default, as vectors of hash maps, containing\n qualified keywords as column names, but the row builder and result set\n builder machinery is open and alternatives are provided to produce\n unqualified keywords as column names, and to produce a vector the\n column names followed by vectors of column values for each row, and\n lower-case variants of each.\n\nThe following options are supported wherever a `Connection` is created:\n* `:auto-commit` -- either `true` or `false`,\n* `:read-only` -- either `true` or `false`,\n* `:connection` -- a hash map of camelCase properties to set, via reflection,\n on the `Connection` object after it is created.\n\nThe following options are supported wherever a `Statement` or\n`PreparedStatement` is created:\n* `:concurrency` -- `:read-only`, `:updatable`,\n* `:cursors` -- `:close`, `:hold`\n* `:fetch-size` -- the fetch size value,\n* `:max-rows` -- the maximum number of rows to return,\n* `:result-type` -- `:forward-only`, `:scroll-insensitive`, `:scroll-sensitive`,\n* `:timeout` -- the query timeout,\n* `:statement` -- a hash map of camelCase properties to set, via reflection,\n on the `Statement` or `PreparedStatement` object after it is created.\n\nIn addition, wherever a `PreparedStatement` is created, you may specify:\n* `:return-keys` -- either `true` or a vector of key names to return.","name":"next.jdbc","platform":"clj","version-entity":{"id":1,"group-id":"seancorfield","artifact-id":"next.jdbc","version":"1.2.659"}},{"doc":"Some helper functions that make common operations with `next.jdbc/plan`\nmuch easier.","name":"next.jdbc.plan","platform":"clj","version-entity":{"id":1,"group-id":"seancorfield","artifact-id":"next.jdbc","version":"1.2.659"}},{"doc":"Builders that treat NULL SQL values as 'optional' and omit the\ncorresponding keys from the Clojure hash maps for the rows.","name":"next.jdbc.optional","platform":"clj","version-entity":{"id":1,"group-id":"seancorfield","artifact-id":"next.jdbc","version":"1.2.659"}},{"doc":"This is the extensible core of the next generation java.jdbc library.\n\n* `Sourceable` -- for producing `javax.sql.DataSource` objects,\n* `Connectable` -- for producing new `java.sql.Connection` objects,\n* `Executable` -- for executing SQL operations,\n* `Preparable` -- for producing new `java.sql.PreparedStatement` objects,\n* `Transactable` -- for executing SQL operations transactionally.","name":"next.jdbc.protocols","platform":"clj","version-entity":{"id":1,"group-id":"seancorfield","artifact-id":"next.jdbc","version":"1.2.659"}},{"doc":"Some utility functions that make common operations easier by\nproviding some syntactic sugar over `execute!`/`execute-one!`.\n\nThis is intended to provide a minimal level of parity with\n`clojure.java.jdbc` (`insert!`, `insert-multi!`, `query`, `find-by-keys`,\n`get-by-id`, `update!`, and `delete!`).\n\nFor anything more complex, use a library like HoneySQL\nhttps://github.com/jkk/honeysql to generate SQL + parameters.\n\nThe following options are supported:\n* `:table-fn` -- specify a function used to convert table names (strings)\n to SQL entity names -- see the `next.jdbc.quoted` namespace for the\n most common quoting strategy functions,\n* `:column-fn` -- specify a function used to convert column names (strings)\n to SQL entity names -- see the `next.jdbc.quoted` namespace for the\n most common quoting strategy functions.\n\nIn addition, `find-by-keys` supports `:order-by` to add an `ORDER BY`\nclause to the generated SQL.","name":"next.jdbc.sql","platform":"clj","version-entity":{"id":1,"group-id":"seancorfield","artifact-id":"next.jdbc","version":"1.2.659"}},{"doc":"Implementation of SQL transaction logic.\n\nIn general, you cannot nest transactions. `clojure.java.jdbc` would\nignore any attempt to create a nested transaction, even tho' some\ndatabases do support it. `next.jdbc` allows you to call `with-transaction`\neven while you are inside an active transaction, but the behavior may\nvary across databases and the commit or rollback boundaries may not be\nwhat you expect. In order to avoid two transactions constructed on the\nsame connection from interfering with each other, `next.jdbc` locks on\nthe `Connection` object (this prevents concurrent transactions on separate\nthreads from interfering but will cause deadlock on a single thread --\nso beware).\n\nConsequently, this namespace exposes a dynamic variable, `*nested-tx*`,\nwhich can be used to vary the behavior when an attempt is made to start\na transaction when you are already inside a transaction.","name":"next.jdbc.transaction","platform":"clj","version-entity":{"id":1,"group-id":"seancorfield","artifact-id":"next.jdbc","version":"1.2.659"}},{"doc":"Mostly an implementation namespace for how `PreparedStatement` objects are\ncreated by the next generation java.jdbc library.\n\n`set-parameters` is public and may be useful if you have a `PreparedStatement`\nthat you wish to reuse and (re)set the parameters on it.\n\nDefines the `SettableParameter` protocol for converting Clojure values\nto database-specific values.\n\nSee also https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/api/next.jdbc.date-time\nfor implementations of `SettableParameter` that provide automatic\nconversion of Java Time objects to SQL data types.\n\nSee also https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/api/next.jdbc.types\nfor `as-xxx` functions that provide per-instance implementations of\n`SettableParameter` for each of the standard `java.sql.Types` values.","name":"next.jdbc.prepare","platform":"clj","version-entity":{"id":1,"group-id":"seancorfield","artifact-id":"next.jdbc","version":"1.2.659"}},{"doc":"Provides functions for use with the `:table-fn` and `:column-fn` options\nthat define how SQL entities should be quoted in strings constructed\nfrom Clojure data.","name":"next.jdbc.quoted","platform":"clj","version-entity":{"id":1,"group-id":"seancorfield","artifact-id":"next.jdbc","version":"1.2.659"}},{"doc":"Some utility functions for building SQL strings.\n\nThese were originally private functions in `next.jdbc.sql` but\nthey may proof useful to developers who want to write their own\n'SQL sugar' functions, such as a database-specific `upsert!` etc.","name":"next.jdbc.sql.builder","platform":"clj","version-entity":{"id":1,"group-id":"seancorfield","artifact-id":"next.jdbc","version":"1.2.659"}},{"doc":"Specs for the core API of next.jdbc.\n\nThe functions from `next.jdbc`, `next.jdbc.sql`, and `next.jdbc.prepare`\nhave specs here.\n\nJust `:args` are spec'd. These specs are intended to aid development\nwith `next.jdbc` by catching simple errors in calling the library.\nThe `connectable` argument is currently just `any?` but both\n`get-datasource` and `get-connection` have stricter specs. If you\nextend `Sourceable` or `Connectable`, those specs will likely be too strict.\n\nIn addition, there is an `instrument` function that provides a simple\nway to instrument all of the `next.jdbc` functions, and `unstrument`\nto undo that.","name":"next.jdbc.specs","platform":"clj","version-entity":{"id":1,"group-id":"seancorfield","artifact-id":"next.jdbc","version":"1.2.659"}},{"doc":"Provides convenience functions for wrapping values you pass into SQL\noperations that have per-instance implementations of `SettableParameter`\nso that `.setObject()` is called with the appropriate `java.sql.Types` value.","name":"next.jdbc.types","platform":"clj","version-entity":{"id":1,"group-id":"seancorfield","artifact-id":"next.jdbc","version":"1.2.659"}},{"doc":"Optional namespace that extends `next.jdbc.prepare/SettableParameter`\nto various date/time types so that they will all be treated as SQL\ntimestamps (which also supports date and time column types) and has\nfunctions to extend `next.jdbc.result-set/ReadableColumn`.\n\nSimply requiring this namespace will extend the `SettableParameter` protocol\nto the four types listed below.\n\nIn addition, there are several `read-as-*` functions here that will\nextend `next.jdbc.result-set/ReadableColumn` to allow `java.sql.Date`\nand `java.sql.Timestamp` columns to be read as (converted to) various\nJava Time types automatically. The expectation is that you will call at\nmost one of these, at application startup, to enable the behavior you want.\n\nDatabase support for Java Time:\n* H2 and SQLite support conversion of Java Time (`Instant`, `LocalDate`,\n `LocalDateTime`) out of the box,\n* Nearly all databases support conversion of `java.util.Date` out of\n the box -- except PostgreSQL apparently!\n\nTypes supported by this namespace:\n* `java.time.Instant`\n* `java.time.LocalDate`\n* `java.time.LocalDateTime`\n* `java.util.Date` -- mainly for PostgreSQL\n\nPostgreSQL does not seem able to convert `java.util.Date` to a SQL\ntimestamp by default (every other database can!) so you'll probably\nneed to require this namespace, even if you don't use Java Time, when\nworking with PostgreSQL.","name":"next.jdbc.date-time","platform":"clj","version-entity":{"id":1,"group-id":"seancorfield","artifact-id":"next.jdbc","version":"1.2.659"}},{"doc":"An implementation of `ResultSet` handling functions.\n\nDefines the following protocols:\n* `DatafiableRow` -- for turning a row into something datafiable\n* `ReadableColumn` -- to read column values by label or index\n* `RowBuilder` -- for materializing a row\n* `ResultSetBuilder` -- for materializing a result set\n\nA broad range of result set builder implementation functions are provided.\n\nAlso provides the default implementations for `Executable` and\nthe default `datafy`/`nav` behavior for rows from a result set.\n\nSee also https://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/api/next.jdbc.date-time\nfor implementations of `ReadableColumn` that provide automatic\nconversion of some SQL data types to Java Time objects.","name":"next.jdbc.result-set","platform":"clj","version-entity":{"id":1,"group-id":"seancorfield","artifact-id":"next.jdbc","version":"1.2.659"}}],"defs":[{"name":"as-numeric","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/NUMERIC` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"instrument","file":"next/jdbc/specs.clj","line":253,"arglists":[[]],"type":"var","namespace":"next.jdbc.specs","platform":"clj"},{"name":"as-sqlxml","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/SQLXML` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-unqualified-lower-arrays","file":"next/jdbc/result_set.clj","line":378,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces a vector of simple, lower-case column names followed by\nvectors of row values.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"plan","file":"next/jdbc.clj","line":192,"arglists":[["stmt"],["connectable","sql-params"],["connectable","sql-params","opts"]],"doc":"General SQL execution function (for working with result sets).\n\nReturns a reducible that, when reduced, runs the SQL and yields the result.\nThe reducible is also foldable (in the `clojure.core.reducers` sense) but\nsee the **Tips & Tricks** section of the documentation for some important\ncaveats about that.\n\nCan be called on a `PreparedStatement`, a `Connection`, or something that can\nproduce a `Connection` via a `DataSource`.\n\nYour reducing function can read columns by name (string or simple keyword)\nfrom each row of the underlying `ResultSet` without realizing the row as\na Clojure hash map. `select-keys` can also be used without realizing the row.\nOperations that imply an actual Clojure data structure (such as `assoc`,\n`dissoc`, `seq`, `keys`, `vals`, etc) will realize the row into a hash map\nusing the supplied `:builder-fn` (or `as-maps` by default).\n\nIf your reducing function needs to produce a hash map without calling a\nfunction that implicitly realizes the row, you can call:\n\n`(next.jdbc.result-set/datafiable-row row connectable opts)`\n\npassing in the current row (passed to the reducing function), a `connectable`,\nand an `opts` hash map. These can be the same values that you passed to `plan`\n(or they can be different, depending on how you want the row to be built,\nand how you want any subsequent lazy navigation to be handled).","type":"var","namespace":"next.jdbc","platform":"clj"},{"name":"as-unqualified-lower-maps","file":"next/jdbc/result_set.clj","line":254,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces bare vectors of hash map rows, with simple, lower-case keys.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"ResultSetBuilder","file":"next/jdbc/result_set.clj","line":141,"doc":"Protocol for building result sets in various representations.\n\nDefault implementations for building vectors of hash maps and vectors of\ncolumn names and row values: `MapResultSetBuilder` & `ArrayResultSetBuilder`","type":"protocol","members":[{"name":"->rs","arglists":[["_"]],"doc":"Called to create the basis of the result set.\n","type":"var"},{"name":"rs!","arglists":[["_","rs"]],"doc":"Called to finalize the result set once it is complete.\n","type":"var"},{"name":"with-row","arglists":[["_","rs","row"]],"doc":"Called with the result set and the row to be added.\n","type":"var"}],"namespace":"next.jdbc.result-set","platform":"clj"},{"name":"delete!","file":"next/jdbc/sql.clj","line":148,"arglists":[["connectable","table","where-params"],["connectable","table","where-params","opts"]],"doc":"Syntactic sugar over `execute-one!` to make certain common deletes easier.\n\nGiven a connectable object, a table name, and either a hash map of columns\nand values to search on or a vector of a SQL where clause and parameters,\nperform a delete on the table.","type":"var","namespace":"next.jdbc.sql","platform":"clj"},{"name":"select!","file":"next/jdbc/plan.clj","line":36,"arglists":[["connectable","cols","sql-params"],["connectable","cols","sql-params","opts"]],"doc":"Execute the SQL and params using `next.jdbc/plan` and (by default)\nreturn a vector of rows with just the selected columns.\n\n`(plan/select! ds [:id :name] [\"select * from table\"])`\n\nIf the `cols` argument is a vector of columns to select, then it is\napplied as:\n\n`(into [] (map #(select-keys % cols)) (jdbc/plan ...))`\n\nOtherwise, the `cols` argument is used as a function and mapped over\nthe raw result set as:\n\n`(into [] (map cols) (jdbc/plan ...))`\n\nThe usual caveats apply about operations on a raw result set that\ncan be done without realizing the whole row.\n\nNote: this allows for the following usage, which returns a vector\nof all the values for a single column:\n\n`(plan/select! ds :id (jdbc/plan ...))`\n\nThe result is a vector by default, but can be changed using the\n`:into` option to provide the initial data structure into which\nthe selected columns are poured, e.g., `:into #{}`","type":"var","namespace":"next.jdbc.plan","platform":"clj"},{"name":"as-unqualified-modified-maps","file":"next/jdbc/result_set.clj","line":236,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces bare vectors of hash map rows, with simple, modified keys.\n\nRequires the `:label-fn` option.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"DatafiableRow","file":"next/jdbc/result_set.clj","line":412,"doc":"Protocol for making rows datafiable and therefore navigable.\n\nThe default implementation just adds metadata so that `datafy` can be\ncalled on the row, which will produce something that `nav` can be called\non, to lazily navigate through foreign key relationships into other tables.\n\nIf `datafiable-row` is called when reducing the result set produced by\n`next.jdbc/plan`, the row is fully-realized from the `ResultSet`\nfirst, using the `:builder-fn` (or `as-maps` by default).","type":"protocol","members":[{"name":"datafiable-row","arglists":[["this","connectable","opts"]],"doc":"Produce a datafiable representation of a row from a `ResultSet`.\n","type":"var"}],"namespace":"next.jdbc.result-set","platform":"clj"},{"name":"reducible-result-set","file":"next/jdbc/result_set.clj","line":744,"arglists":[["rs"],["rs","opts"]],"doc":"Given a `ResultSet`, return an `IReduceInit` that can be reduced. An\noptions hash map may be provided.\n\nYou are responsible for ensuring the `Connection` for this `ResultSet`\nremains open until the reduction is complete!","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"as-double","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/DOUBLE` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-lower-maps","file":"next/jdbc/optional.clj","line":81,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces bare vectors of hash map rows, with lower-case keys and nil\ncolumns omitted.","type":"var","namespace":"next.jdbc.optional","platform":"clj"},{"name":"with-transaction","file":"next/jdbc.clj","line":344,"arglists":[[["sym","transactable","opts"],"&","body"]],"doc":"Given a transactable object, gets a connection and binds it to `sym`,\nthen executes the `body` in that context, committing any changes if the body\ncompletes successfully, otherwise rolling back any changes made.\n\nThe options map supports:\n* `:isolation` -- `:none`, `:read-committed`, `:read-uncommitted`,\n `:repeatable-read`, `:serializable`,\n* `:read-only` -- `true` / `false`,\n* `:rollback-only` -- `true` / `false`.","type":"macro","namespace":"next.jdbc","platform":"clj"},{"name":"mysql","file":"next/jdbc/quoted.clj","line":13,"arglists":[["s"]],"doc":"MySQL `quoting`\n","type":"var","namespace":"next.jdbc.quoted","platform":"clj"},{"name":"dbtypes","file":"next/jdbc/connection.clj","line":18,"doc":"A map of all known database types (including aliases) to the class name(s)\nand port that `next.jdbc` supports out of the box. For databases that have\nnon-standard prefixes for the `:dbname` and/or `:host` values in the JDBC\nstring, this table includes `:dbname-separator` and/or `:host-prefix`. The\ndefault prefix for `:dbname` is either `/` or `:` and for `:host` it is `//`.\nFor local databases, with no `:host`/`:port` segment in their JDBC URL, a\nvalue of `:none` is provided for `:host` in this table.\n\nFor known database types, you can use `:dbtype` (and omit `:classname`).\n\nIf you want to use a database that is not in this list, you can specify\na new `:dbtype` along with the class name of the JDBC driver in `:classname`.\nYou will also need to specify `:port`. For example:\n\n `{:dbtype \"acme\" :classname \"com.acme.JdbcDriver\" ...}`\n\nThe value of `:dbtype` should be the string that the driver is associated\nwith in the JDBC URL, i.e., the value that comes between the `jdbc:`\nprefix and the `://<host>...` part. In the above example, the JDBC URL\nthat would be generated would be `jdbc:acme://<host>:<port>/<dbname>`.\n\nIf you want `next.jdbc` to omit the host/port part of the URL, specify\n`:host :none`, which would produce a URL like: `jdbc:acme:<dbname>`,\nwhich allows you to work with local databases (or drivers that do not\nneed host/port information).\n\nThe default prefix for the host name (or IP address) is `//`. You\ncan override this via the `:host-prefix` option.\n\nThe default separator between the host/port and the database name is `/`.\nThe default separator between the subprotocol and the database name,\nfor local databases with no host/port, is `:`. You can override this\nvia the `:dbname-separator` option.\n\nJDBC drivers are not provided by `next.jdbc` -- you need to specify the\ndriver(s) you need as additional dependencies in your project. For\nexample:\n\n `[com.acme/jdbc \"1.2.3\"] ; lein/boot`\n\nor:\n\n `com.acme/jdbc {:mvn/version \"1.2.3\"} ; CLI/deps.edn`\n\nNote: the `:classname` value can be a string or a vector of strings. If\na vector of strings is provided, an attempt will be made to load each\nnamed class in order, until one succeeds. This allows for a given `:dbtype`\nto be used with different versions of a JDBC driver, if the class name\nhas changed over time (such as with MySQL).","type":"var","namespace":"next.jdbc.connection","platform":"clj"},{"name":"Preparable","file":"next/jdbc/protocols.clj","line":49,"doc":"Protocol for producing a new `java.sql.PreparedStatement` that should\nbe closed after use. Can be used by `Executable` functions.\n\nImplementation is provided for `Connection` only.","type":"protocol","members":[{"name":"prepare","arglists":[["this","sql-params","opts"]],"doc":"Produce a new `java.sql.PreparedStatement` for use with `with-open`.\n","type":"var"}],"namespace":"next.jdbc.protocols","platform":"clj"},{"name":"Sourceable","file":"next/jdbc/protocols.clj","line":14,"doc":"Protocol for producing a `javax.sql.DataSource`.\n\nImplementations are provided for strings, hash maps (`db-spec` structures),\nand also a `DataSource` (which just returns itself).\n\nExtension via metadata is supported.","type":"protocol","members":[{"name":"get-datasource","arglists":[["this"]],"doc":"Produce a `javax.sql.DataSource`.\n","type":"var"}],"namespace":"next.jdbc.protocols","platform":"clj"},{"name":"insert!","file":"next/jdbc/sql.clj","line":31,"arglists":[["connectable","table","key-map"],["connectable","table","key-map","opts"]],"doc":"Syntactic sugar over `execute-one!` to make inserting hash maps easier.\n\nGiven a connectable object, a table name, and a data hash map, inserts the\ndata as a single row in the database and attempts to return a map of generated\nkeys.","type":"var","namespace":"next.jdbc.sql","platform":"clj"},{"name":"jdbc-url","file":"next/jdbc/connection.clj","line":213,"arglists":[["db-spec"]],"doc":"Given a database spec (as a hash map), return a JDBC URL with all the\n attributes added to the query string. The result is suitable for use in\n calls to `->pool` and `component` as the `:jdbcUrl` key in the parameter\n map for the connection pooling library.\n\n This allows you to build a connection-pooled datasource that needs\n additional settings that the pooling library does not support, such as\n `:serverTimezone`:\n\n```clojure\n (def db-spec {:dbtype .. :dbname .. :user .. :password ..\n :serverTimezone \"UTC\"})\n (def ds (next.jdbc.connection/->pool\n HikariCP {:jdbcUrl (next.jdbc.connection/jdbc-url db-spec)\n :maximumPoolSize 15}))\n```\n\n This also clearly separates the attributes that should be part of the\n JDBC URL from the attributes that should be configured on the pool.\n\n Since JDBC drivers can handle URL encoding differently, if you are\n trying to pass attributes that might need encoding, you should make\n sure they are properly URL-encoded as values in the database spec hash map.\n This function does **not** attempt to URL-encode values for you!","type":"var","namespace":"next.jdbc.connection","platform":"clj"},{"name":"as-float","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/FLOAT` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"get-lower-column-names","file":"next/jdbc/result_set.clj","line":86,"arglists":[["rsmeta","opts"]],"doc":"Given `ResultSetMetaData`, return a vector of lower-case column names, each\nqualified by the table from which it came.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"prepare","file":"next/jdbc.clj","line":172,"arglists":[["connection","sql-params"],["connection","sql-params","opts"]],"doc":"Given a connection to a database, and a vector containing SQL and any\n parameters it needs, return a new `PreparedStatement`.\n\n In general, this should be used via `with-open`:\n\n```clojure\n (with-open [stmt (prepare spec sql-params opts)]\n (run-some-ops stmt))\n```\n\n See the list of options above (in the namespace docstring) for what can\n be passed to prepare.","type":"var","namespace":"next.jdbc","platform":"clj"},{"name":"as-smallint","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/SMALLINT` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"for-query","file":"next/jdbc/sql/builder.clj","line":174,"arglists":[["table","where-params","opts"]],"doc":"Given a table name and either a hash map of column names and values or a\nvector of SQL (where clause) and its parameters, return a vector of the\nfull `SELECT` SQL string and its parameters.\n\nApplies any `:table-fn` / `:column-fn` supplied in the options.\n\nHandles pagination options (`:top`, `:limit` / `:offset`, or `:offset` /\n`:fetch`) for SQL Server, MySQL / SQLite, ANSI SQL respectively.\n\nBy default, this selects all columns, but if the `:columns` option is\npresent the select will only be those columns.\n\nIf `:suffix` is provided in `opts`, that string is appended to the\n`SELECT ...` statement.","type":"var","namespace":"next.jdbc.sql.builder","platform":"clj"},{"name":"as-distinct","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/DISTINCT` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-modified-arrays","file":"next/jdbc/result_set.clj","line":347,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces a vector of modified column names followed by vectors of\nrow values.\n\nRequires both the `:qualifier-fn` and `:label-fn` options.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"as-other","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/OTHER` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-binary","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/BINARY` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-unqualified-modified-maps","file":"next/jdbc/optional.clj","line":63,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces bare vectors of hash map rows, with simple, modified keys\nand nil columns omitted.\n\nRequires the `:label-fn` option.","type":"var","namespace":"next.jdbc.optional","platform":"clj"},{"name":"as-nclob","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/NCLOB` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-tinyint","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/TINYINT` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-rowid","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/ROWID` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"unqualified-snake-kebab-opts","file":"next/jdbc.clj","line":379,"doc":"A hash map of options that will convert Clojure identifiers to\nsnake_case SQL entities (`:table-fn`, `:column-fn`), and will convert\nSQL entities to unqualified kebab-case Clojure identifiers (`:builder-fn`).","type":"var","namespace":"next.jdbc","platform":"clj"},{"name":"schema","file":"next/jdbc/quoted.clj","line":21,"arglists":[["quoting"]],"doc":"Given a quoting function, return a new quoting function that will\n process schema-qualified names by quoting each segment:\n```clojure\n (mysql (name :foo.bar)) ;=> `foo.bar`\n ((schema mysql) (name :foo.bar)) ;=> `foo`.`bar`\n```","type":"var","namespace":"next.jdbc.quoted","platform":"clj"},{"name":"as-longnvarchar","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/LONGNVARCHAR` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-cols","file":"next/jdbc/sql/builder.clj","line":19,"arglists":[["cols","opts"]],"doc":"Given a sequence of raw column names, return a string of all the\nformatted column names.\n\nIf a raw column name is a keyword, apply `:column-fn` to its name,\nfrom the options if present.\n\nIf a raw column name is a vector pair, treat it as an expression with\nan alias. If the first item is a keyword, apply `:column-fn` to its\nname, else accept it as-is. The second item should be a keyword and\nthat will have `:column-fn` applied to its name.\n\nThis allows columns to be specified as simple names, e.g., `:foo`,\nas simple aliases, e.g., `[:foo :bar]`, or as expressions with an\nalias, e.g., `[\"count(*)\" :total]`.","type":"var","namespace":"next.jdbc.sql.builder","platform":"clj"},{"name":"builder-adapter","file":"next/jdbc/result_set.clj","line":153,"arglists":[["builder-fn","column-by-index-fn"]],"doc":"Given any builder function (e.g., `as-lower-maps`) and a column reading\nfunction, return a new builder function that uses that column reading\nfunction instead of `.getObject` and `read-column-by-index` so you can\noverride the default behavior.\n\nThe default column-by-index-fn behavior would be equivalent to:\n\n (defn default-column-by-index-fn\n [builder ^ResultSet rs ^Integer i]\n (read-column-by-index (.getObject rs i) (:rsmeta builder) i))\n\nYour column-by-index-fn can use the result set metadata `(:rsmeta builder)`\nand/or the (processed) column name `(nth (:cols builder) (dec i))` to\ndetermine whether to call `.getObject` or some other method to read the\ncolumn's value, and can choose whether or not to use the `ReadableColumn`\nprotocol-based value processor (and could add metadata to the value to\nsatisfy that protocol on a per-instance basis).","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"as-date","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/DATE` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"for-order","file":"next/jdbc/sql/builder.clj","line":165,"arglists":[["order-by","opts"]],"doc":"Given an `:order-by` vector, return an `ORDER BY` clause.\n","type":"var","namespace":"next.jdbc.sql.builder","platform":"clj"},{"name":"execute-one!","file":"next/jdbc.clj","line":250,"arglists":[["stmt"],["connectable","sql-params"],["connectable","sql-params","opts"]],"doc":"General SQL execution function that returns just the first row of a result.\nFor any DDL or SQL statement that will return just an update count, this is\nthe preferred function to use.\n\nCan be called on a `PreparedStatement`, a `Connection`, or something that can\nproduce a `Connection` via a `DataSource`.\n\nNote: although this only returns the first row of a result set, it does not\nplace any limit on the result of the SQL executed.","type":"var","namespace":"next.jdbc","platform":"clj"},{"name":"unstrument","file":"next/jdbc/specs.clj","line":256,"arglists":[[]],"type":"var","namespace":"next.jdbc.specs","platform":"clj"},{"name":"SettableParameter","file":"next/jdbc/prepare.clj","line":29,"doc":"Protocol for setting SQL parameters in statement objects, which\ncan convert from Clojure values. The default implementation just\ncalls `.setObject` on the parameter value. It can be extended to\nuse other methods of `PreparedStatement` to convert and set parameter\nvalues. Extension via metadata is supported.","type":"protocol","members":[{"name":"set-parameter","arglists":[["val","stmt","ix"]],"doc":"Convert a Clojure value into a SQL value and store it as the ix'th\nparameter in the given SQL statement object.","type":"var"}],"namespace":"next.jdbc.prepare","platform":"clj"},{"name":"get-by-id","file":"next/jdbc/sql.clj","line":111,"arglists":[["connectable","table","pk"],["connectable","table","pk","opts"],["connectable","table","pk","pk-name","opts"]],"doc":"Syntactic sugar over `execute-one!` to make certain common queries easier.\n\nGiven a connectable object, a table name, and a primary key value, returns\na hash map of the first row that matches.\n\nBy default, the primary key is assumed to be `id` but that can be overridden\nin the five-argument call.\n\nAs with `find-by-keys`, you can specify `:columns` to return just a\nsubset of the columns in the returned row.\n\nTechnically, this also supports `:order-by`, `:top`, `:limit`, `:offset`,\nand `:fetch` -- like `find-by-keys` -- but they don't make as much sense\nhere since only one row is ever returned.","type":"var","namespace":"next.jdbc.sql","platform":"clj"},{"name":"as-null","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/NULL` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"datafiable-result-set","file":"next/jdbc/result_set.clj","line":607,"arglists":[["rs"],["rs","conn-or-opts"],["rs","connectable","opts"]],"doc":"Given a ResultSet, a connectable, and an options hash map, return a fully\nrealized, datafiable result set per the `:builder-fn` option passed in.\nIf no `:builder-fn` option is provided, `as-maps` is used as the default.\n\nThe connectable and the options can both be omitted. If connectable is\nomitted, `nil` is used and no foreign key navigation will be available\nfor any datafied result. If you want to pass a hash map as the connectable,\nyou must also pass an options hash map.\n\nThis can be used to process regular result sets or metadata result sets.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"as-unqualified-kebab-maps","file":"next/jdbc/result_set.clj","line":268,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces bare vectors of hash map rows, with simple, kebab-case keys.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"as-maps-adapter","file":"next/jdbc/optional.clj","line":97,"arglists":[["builder-fn","column-reader"]],"doc":"Given a map builder function (e.g., `as-lower-maps`) and a column reading\nfunction, return a new builder function that uses that column reading\nfunction instead of `.getObject` so you can override the default behavior.\n\nThis adapter omits SQL NULL values, even if the underlying builder does not.\n\nThe default column-reader behavior would be equivalent to:\n\n (defn default-column-reader\n [^ResultSet rs ^ResultSetMetaData rsmeta ^Integer i]\n (.getObject rs i))\n\nYour column-reader can use the result set metadata to determine whether\nto call `.getObject` or some other method to read the column's value.\n\n`read-column-by-index` is still called on the result of that read, if\nit is not `nil`.","type":"var","namespace":"next.jdbc.optional","platform":"clj"},{"name":"as-ref-cursor","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/REF_CURSOR` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"Executable","file":"next/jdbc/protocols.clj","line":33,"doc":"Protocol for executing SQL operations.\n\nImplementations are provided for `Connection`, `DataSource`,\n`PreparedStatement`, and `Object`, on the assumption that an `Object` can be\nturned into a `DataSource` and therefore used to get a `Connection`.","type":"protocol","members":[{"name":"-execute","arglists":[["this","sql-params","opts"]],"doc":"Produce a 'reducible' that, when reduced, executes the SQL and\nprocesses the rows of the `ResultSet` directly.","type":"var"},{"name":"-execute-all","arglists":[["this","sql-params","opts"]],"doc":"Executes the SQL and produces (by default) a vector of\nfully-realized, datafiable hash maps from the `ResultSet`.","type":"var"},{"name":"-execute-one","arglists":[["this","sql-params","opts"]],"doc":"Executes the SQL or DDL and produces the first row of the `ResultSet`\nas a fully-realized, datafiable hash map (by default).","type":"var"}],"namespace":"next.jdbc.protocols","platform":"clj"},{"name":"execute-batch!","file":"next/jdbc.clj","line":269,"arglists":[["ps","param-groups"],["ps","param-groups","opts"],["connectable","sql","param-groups","opts"]],"doc":"Given a `PreparedStatement` and a vector containing parameter groups,\ni.e., a vector of vector of parameters, use `.addBatch` to add each group\nof parameters to the prepared statement (via `set-parameters`) and then\ncall `.executeBatch`. A vector of update counts is returned.\n\nAn options hash map may also be provided, containing `:batch-size` which\ndetermines how to partition the parameter groups for submission to the\ndatabase. If omitted, all groups will be submitted as a single command.\nIf you expect the update counts to be larger than `Integer/MAX_VALUE`,\nyou can specify `:large true` and `.executeLargeBatch` will be called\ninstead.\n\nAlternatively, given a connectable, a SQL string, a vector containing\nparameter groups, and an options hash map, create a new `PreparedStatement`\n(after possibly creating a new `Connection`), and execute the SQL with\nthe specified parameter groups. That new `PreparedStatement` (and the\nnew `Connection`, if created) will be closed automatically after use.\n\nBy default, returns a Clojure vector of update counts. Some databases\nallow batch statements to also return generated keys and you can attempt that\nif you ensure the `PreparedStatement` is created with `:return-keys true`\nand you also provide `:return-generated-keys true` in the options passed\nto `execute-batch!`. Some databases will only return one generated key\nper batch, some return all the generated keys, some will throw an exception.\nIf that is supported, `execute-batch!` will return a vector of hash maps\ncontaining the generated keys as fully-realized, datafiable result sets,\nwhose content is database-dependent.\n\nMay throw `java.sql.BatchUpdateException` if any part of the batch fails.\nYou may be able to call `.getUpdateCounts` on that exception object to\nget more information about which parts succeeded and which failed.\n\nFor additional caveats and database-specific options you may need, see:\nhttps://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/doc/getting-started/prepared-statements#caveats\n\nNot all databases support batch execution.","type":"var","namespace":"next.jdbc","platform":"clj"},{"name":"as-integer","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/INTEGER` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-lower-arrays","file":"next/jdbc/result_set.clj","line":369,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces a vector of lower-case column names followed by vectors of\nrow values.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"as-decimal","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/DECIMAL` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-varbinary","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/VARBINARY` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"*nested-tx*","file":"next/jdbc/transaction.clj","line":25,"doc":"Controls the behavior when a nested transaction is attempted.\n\nPossible values are:\n* `:allow` -- the default: assumes you know what you are doing!\n* `:ignore` -- the same behavior as `clojure.java.jdbc`: the nested\n transaction is simply ignored and any SQL operations inside it are\n executed in the context of the outer transaction.\n* `:prohibit` -- any attempt to create a nested transaction will throw\n an exception: this is the safest but most restrictive approach so\n that you can make sure you don't accidentally have any attempts\n to create nested transactions (since that might be a bug in your code).","dynamic":true,"type":"var","namespace":"next.jdbc.transaction","platform":"clj"},{"name":"as-timestamp-with-timezone","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/TIMESTAMP_WITH_TIMEZONE` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"MapResultSetOptionalBuilder","file":"next/jdbc/optional.clj","line":12,"type":"var","namespace":"next.jdbc.optional","platform":"clj"},{"name":"as-time-with-timezone","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/TIME_WITH_TIMEZONE` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"create","file":"next/jdbc/prepare.clj","line":83,"arglists":[["con","sql","params",{"keys":["return-keys","result-type","concurrency","cursors","fetch-size","max-rows","timeout"],"as":"opts"}]],"doc":"This is an implementation detail -- use `next.jdbc/prepare` instead.\n\nGiven a `Connection`, a SQL string, some parameters, and some options,\nreturn a `PreparedStatement` representing that.","type":"var","namespace":"next.jdbc.prepare","platform":"clj"},{"name":"ansi","file":"next/jdbc/quoted.clj","line":11,"arglists":[["s"]],"doc":"ANSI \"quoting\"\n","type":"var","namespace":"next.jdbc.quoted","platform":"clj"},{"name":"find-by-keys","file":"next/jdbc/sql.clj","line":78,"arglists":[["connectable","table","key-map"],["connectable","table","key-map","opts"]],"doc":"Syntactic sugar over `execute!` to make certain common queries easier.\n\nGiven a connectable object, a table name, and either a hash map of\ncolumns and values to search on or a vector of a SQL where clause and\nparameters, returns a vector of hash maps of rows that match.\n\nIf `:all` is passed instead of a hash map or vector -- the query will\nselect all rows in the table, subject to any pagination options below.\n\nIf `:columns` is passed, only that specified subset of columns will be\nreturned in each row (otherwise all columns are selected).\n\nIf the `:order-by` option is present, add an `ORDER BY` clause. `:order-by`\nshould be a vector of column names or pairs of column name / direction,\nwhich can be `:asc` or `:desc`.\n\nIf the `:top` option is present, the SQL Server `SELECT TOP ?` syntax\nis used and the value of the option is inserted as an additional parameter.\n\nIf the `:limit` option is present, the MySQL `LIMIT ? OFFSET ?` syntax\nis used (using the `:offset` option if present, else `OFFSET ?` is omitted).\nPostgreSQL also supports this syntax.\n\nIf the `:offset` option is present (without `:limit`), the standard\n`OFFSET ? ROWS FETCH NEXT ? ROWS ONLY` syntax is used (using the `:fetch`\noption if present, else `FETCH...` is omitted).","type":"var","namespace":"next.jdbc.sql","platform":"clj"},{"name":"get-connection","file":"next/jdbc.clj","line":140,"arglists":[["spec"],["spec","opts"],["spec","user","password"],["spec","user","password","opts"]],"doc":"Given some sort of specification of a database, return a new `Connection`.\n\n In general, this should be used via `with-open`:\n\n```clojure\n (with-open [con (get-connection spec opts)]\n (run-some-ops con))\n```\n\n If you call `get-connection` on a `DataSource`, it just calls `.getConnection`\n and applies the `:auto-commit` and/or `:read-only` options, if provided.\n\n If you call `get-connection` on anything else, it will call `get-datasource`\n first to try to get a `DataSource`, and then call `get-connection` on that.\n\n If you want different per-connection username/password values, you can\n either put `:user` and `:password` into the `opts` hash map or pass them\n as positional arguments.","type":"var","namespace":"next.jdbc","platform":"clj"},{"name":"as-lower-maps","file":"next/jdbc/result_set.clj","line":246,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces bare vectors of hash map rows, with lower-case keys.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"as-arrays-adapter","file":"next/jdbc/result_set.clj","line":385,"arglists":[["builder-fn","column-reader"]],"doc":"Given an array builder function (e.g., `as-unqualified-arrays`) and a column\nreading function, return a new builder function that uses that column reading\nfunction instead of `.getObject` so you can override the default behavior.\n\nThe default column-reader behavior would be equivalent to:\n\n (defn default-column-reader\n [^ResultSet rs ^ResultSetMetaData rsmeta ^Integer i]\n (.getObject rs i))\n\nYour column-reader can use the result set metadata to determine whether\nto call `.getObject` or some other method to read the column's value.\n\n`read-column-by-index` is still called on the result of that read.\n\nNote: this is different behavior to `builder-adapter`'s `column-by-index-fn`.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"with-options","file":"next/jdbc.clj","line":358,"arglists":[["connectable","opts"]],"doc":"Given a connectable/transactable object and a set of (default) options\nthat should be used on all operations on that object, return a new\nwrapper object that can be used in its place.\n\nBear in mind that `get-datasource`, `get-connection`, and `with-transaction`\nreturn plain Java objects, so if you call any of those on this wrapped\nobject, you'll need to re-wrap the Java object `with-options` again. See\nthe Datasources, Connections & Transactions section of Getting Started for\nmore details, and some examples of use with these functions.","type":"var","namespace":"next.jdbc","platform":"clj"},{"name":"execute!","file":"next/jdbc.clj","line":231,"arglists":[["stmt"],["connectable","sql-params"],["connectable","sql-params","opts"]],"doc":"General SQL execution function.\n\nReturns a fully-realized result set. When `:multi-rs true` is provided, will\nreturn multiple result sets, as a vector of result sets. Each result set is\na vector of hash maps, by default, but can be controlled by the `:builder-fn`\noption.\n\nCan be called on a `PreparedStatement`, a `Connection`, or something that can\nproduce a `Connection` via a `DataSource`.","type":"var","namespace":"next.jdbc","platform":"clj"},{"name":"as-boolean","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/BOOLEAN` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-real","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/REAL` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-unqualified-lower-maps","file":"next/jdbc/optional.clj","line":90,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces bare vectors of hash map rows, with simple, lower-case keys\nand nil columns omitted.","type":"var","namespace":"next.jdbc.optional","platform":"clj"},{"name":"statement","file":"next/jdbc/prepare.clj","line":151,"arglists":[["con"],["con",{"keys":["result-type","concurrency","cursors","fetch-size","max-rows","timeout"],"as":"opts"}]],"doc":"Given a `Connection` and some options, return a `Statement`.\n","type":"var","namespace":"next.jdbc.prepare","platform":"clj"},{"name":"MapResultSetBuilder","file":"next/jdbc/result_set.clj","line":192,"type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"get-modified-column-names","file":"next/jdbc/result_set.clj","line":52,"arglists":[["rsmeta","opts"]],"doc":"Given `ResultSetMetaData`, return a vector of modified column names, each\nqualified by the table from which it came.\n\nRequires both the `:qualifier-fn` and `:label-fn` options.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"foldable-result-set","file":"next/jdbc/result_set.clj","line":758,"arglists":[["rs"],["rs","conn-or-opts"],["rs","connectable","opts"]],"doc":"Given a `ResultSet` and an optional connectable, return an `r/CollFold`\nthat can be folded. An options hash map may be provided.\n\nYou are responsible for ensuring the `Connection` for this `ResultSet`\nand the connectable both remain open until the fold is complete!\n\nIf the connectable is omitted, no foreign key navigation would be\navailable in any datafied result. If you want to pass a hash map as the\nconnectable, you must also pass an options hash map.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"as-unqualified-maps","file":"next/jdbc/result_set.clj","line":218,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces bare vectors of hash map rows, with simple keys.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"as-char","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/CHAR` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-ref","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/REF` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-maps-adapter","file":"next/jdbc/result_set.clj","line":274,"arglists":[["builder-fn","column-reader"]],"doc":"Given a map builder function (e.g., `as-lower-maps`) and a column reading\nfunction, return a new builder function that uses that column reading\nfunction instead of `.getObject` so you can override the default behavior.\n\nThe default column-reader behavior would be equivalent to:\n\n (defn default-column-reader\n [^ResultSet rs ^ResultSetMetaData rsmeta ^Integer i]\n (.getObject rs i))\n\nYour column-reader can use the result set metadata to determine whether\nto call `.getObject` or some other method to read the column's value.\n\n`read-column-by-index` is still called on the result of that read.\n\nNote: this is different behavior to `builder-adapter`'s `column-by-index-fn`.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"as-array","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/ARRAY` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"get-unqualified-modified-column-names","file":"next/jdbc/result_set.clj","line":68,"arglists":[["rsmeta","opts"]],"doc":"Given `ResultSetMetaData`, return a vector of unqualified modified column\nnames.\n\nRequires the `:label-fn` option.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"for-insert","file":"next/jdbc/sql/builder.clj","line":97,"arglists":[["table","key-map","opts"]],"doc":"Given a table name and a hash map of column names and their values,\nreturn a vector of the full `INSERT` SQL string and its parameters.\n\nApplies any `:table-fn` / `:column-fn` supplied in the options.\n\nIf `:suffix` is provided in `opts`, that string is appended to the\n`INSERT ...` statement.","type":"var","namespace":"next.jdbc.sql.builder","platform":"clj"},{"name":"select-one!","file":"next/jdbc/plan.clj","line":10,"arglists":[["connectable","cols","sql-params"],["connectable","cols","sql-params","opts"]],"doc":"Execute the SQL and params using `next.jdbc/plan` and return just the\nselected columns from just the first row.\n\n`(plan/select-one! ds [:total] [\"select count(*) as total from table\"])`\n;;=> {:total 42}\n\nIf the `cols` argument is a vector of columns to select, then it is\napplied using `select-keys`, otherwise, the `cols` argument is used as\na function directly. That means it can be a simple keyword to return\njust that column -- which is the most common expected usage:\n\n`(plan/select-one! ds :total [\"select count(*) as total from table\"])`\n;;=> 42\n\nThe usual caveats apply about operations on a raw result set that\ncan be done without realizing the whole row.","type":"var","namespace":"next.jdbc.plan","platform":"clj"},{"name":"as-keys","file":"next/jdbc/sql/builder.clj","line":49,"arglists":[["key-map","opts"]],"doc":"Given a hash map of column names and values, return a string of all the\ncolumn names.\n\nApplies any `:column-fn` supplied in the options.","type":"var","namespace":"next.jdbc.sql.builder","platform":"clj"},{"name":"as-longvarbinary","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/LONGVARBINARY` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"read-as-default","file":"next/jdbc/date_time.clj","line":94,"arglists":[[]],"doc":"After calling this function, `next.jdbc.result-set/ReadableColumn`\nwill be extended to `java.sql.Date` and `java.sql.Timestamp` so that any\ndate or timestamp columns will be read as-is. This is provided for\ncompleteness, to undo the effects of `read-as-instant` or `read-as-local`.","type":"var","namespace":"next.jdbc.date-time","platform":"clj"},{"name":"as-maps","file":"next/jdbc/optional.clj","line":35,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces bare vectors of hash map rows, with nil columns omitted.","type":"var","namespace":"next.jdbc.optional","platform":"clj"},{"name":"Transactable","file":"next/jdbc/protocols.clj","line":57,"doc":"Protocol for running SQL operations in a transaction.\n\nImplementations are provided for `Connection`, `DataSource`, and `Object`\n(on the assumption that an `Object` can be turned into a `DataSource`).","type":"protocol","members":[{"name":"-transact","arglists":[["this","body-fn","opts"]],"doc":"Run the `body-fn` inside a transaction.\n","type":"var"}],"namespace":"next.jdbc.protocols","platform":"clj"},{"name":"ArrayResultSetBuilder","file":"next/jdbc/result_set.clj","line":314,"type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"InspectableMapifiedResultSet","file":"next/jdbc/result_set.clj","line":436,"doc":"Protocol for exposing aspects of the (current) result set via functions.\n\nThe intent here is to expose information that is associated with either\nthe (current row of the) result set or the result set metadata, via\nfunctions that can be called inside a reducing function being used over\n`next.jdbc/plan`, including situations where the reducing function has\nto realize a row by calling `datafiable-row` but still wants to call\nthese functions on the (realized) row.","type":"protocol","members":[{"name":"column-names","arglists":[["this"]],"doc":"Return a vector of the column names from the result set.\n\nReifies the result builder, in order to construct column names,\nbut should not cause any row realization.","type":"var"},{"name":"metadata","arglists":[["this"]],"doc":"Return the raw `ResultSetMetaData` object from the result set.\n\nShould not cause any row realization.\n\nIf `next.jdbc.datafy` has been required, this metadata will be\nfully-realized as a Clojure data structure, otherwise this should\nnot be allowed to 'leak' outside of the reducing function as it may\ndepend on the connection remaining open, in order to be valid.","type":"var"},{"name":"row-number","arglists":[["this"]],"doc":"Return the current 1-based row number, if available.\n\nShould not cause any row realization.","type":"var"}],"namespace":"next.jdbc.result-set","platform":"clj"},{"name":"update!","file":"next/jdbc/sql.clj","line":134,"arglists":[["connectable","table","key-map","where-params"],["connectable","table","key-map","where-params","opts"]],"doc":"Syntactic sugar over `execute-one!` to make certain common updates easier.\n\nGiven a connectable object, a table name, a hash map of columns and values\nto set, and either a hash map of columns and values to search on or a vector\nof a SQL where clause and parameters, perform an update on the table.","type":"var","namespace":"next.jdbc.sql","platform":"clj"},{"name":"by-keys","file":"next/jdbc/sql/builder.clj","line":57,"arglists":[["key-map","clause","opts"]],"doc":"Given a hash map of column names and values and a clause type\n(`:set`, `:where`), return a vector of a SQL clause and its parameters.\n\nApplies any `:column-fn` supplied in the options.","type":"var","namespace":"next.jdbc.sql.builder","platform":"clj"},{"name":"*datafy-failure*","file":"next/jdbc/datafy.clj","line":86,"doc":"How datafication failures should be handled, based on `clojure.java.data`.\n\nDefaults to `:qualify`, but can be `:group`, `:omit`, `:qualify`, or `:return`.","dynamic":true,"type":"var","namespace":"next.jdbc.datafy","platform":"clj"},{"name":"read-as-local","file":"next/jdbc/date_time.clj","line":80,"arglists":[[]],"doc":"After calling this function, `next.jdbc.result-set/ReadableColumn`\nwill be extended to `java.sql.Date` and `java.sql.Timestamp` so that any\ndate or timestamp columns will automatically be read as `java.time.LocalDate`\nor `java.time.LocalDateTime` respectively.","type":"var","namespace":"next.jdbc.date-time","platform":"clj"},{"name":"as-modified-maps","file":"next/jdbc/optional.clj","line":52,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces bare vectors of hash map rows, with modified keys and nil\ncolumns omitted.\n\nRequires both the `:qualifier-fn` and `:label-fn` options.","type":"var","namespace":"next.jdbc.optional","platform":"clj"},{"name":"get-column-names","file":"next/jdbc/result_set.clj","line":36,"arglists":[["rsmeta","_"]],"doc":"Given `ResultSetMetaData`, return a vector of column names, each qualified by\nthe table from which it came.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"as-datalink","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/DATALINK` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"snake-kebab-opts","file":"next/jdbc.clj","line":371,"doc":"A hash map of options that will convert Clojure identifiers to\nsnake_case SQL entities (`:table-fn`, `:column-fn`), and will convert\nSQL entities to qualified kebab-case Clojure identifiers (`:builder-fn`).","type":"var","namespace":"next.jdbc","platform":"clj"},{"name":"Connectable","file":"next/jdbc/protocols.clj","line":24,"doc":"Protocol for producing a new JDBC connection that should be closed when you\nare finished with it.\n\nImplementations are provided for `DataSource`, `PreparedStatement`, and\n`Object`, on the assumption that an `Object` can be turned into a `DataSource`.","type":"protocol","members":[{"name":"get-connection","arglists":[["this","opts"]],"doc":"Produce a new `java.sql.Connection` for use with `with-open`.\n","type":"var"}],"namespace":"next.jdbc.protocols","platform":"clj"},{"name":"query","file":"next/jdbc/sql.clj","line":67,"arglists":[["connectable","sql-params"],["connectable","sql-params","opts"]],"doc":"Syntactic sugar over `execute!` to provide a query alias.\n\nGiven a connectable object, and a vector of SQL and its parameters,\nreturns a vector of hash maps of rows that match.","type":"var","namespace":"next.jdbc.sql","platform":"clj"},{"name":"as-clob","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/CLOB` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-arrays","file":"next/jdbc/result_set.clj","line":330,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces a vector of column names followed by vectors of row values.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"component","file":"next/jdbc/connection.clj","line":287,"arglists":[["clazz","db-spec"],["clazz","db-spec","close-fn"]],"doc":"Takes the same arguments as `->pool` but returns an entity compatible\nwith Stuart Sierra's Component: when `com.stuartsierra.component/start`\nis called on it, it builds a connection pooled datasource, and returns\nan entity that can either be invoked as a function with no arguments\nto return that datasource, or can have `com.stuartsierra.component/stop`\ncalled on it to shutdown the datasource (and return a new startable\nentity).\n\nBy default, the datasource is shutdown by calling `.close` on it.\nIf the datasource class implements `java.io.Closeable` then a direct,\ntype-hinted call to `.close` will be used, with no reflection,\notherwise Java reflection will be used to find the first `.close`\nmethod in the datasource class that takes no arguments and returns `void`.\n\nIf neither of those behaviors is appropriate, you may supply a third\nargument to this function -- `close-fn` -- which performs whatever\naction is appropriate to your chosen datasource class.","type":"var","namespace":"next.jdbc.connection","platform":"clj"},{"name":"as-?","file":"next/jdbc/sql/builder.clj","line":13,"arglists":[["key-map","_"]],"doc":"Given a hash map of column names and values, or a vector of column names,\nreturn a string of `?` placeholders for them.","type":"var","namespace":"next.jdbc.sql.builder","platform":"clj"},{"name":"postgres","file":"next/jdbc/quoted.clj","line":19,"doc":"PostgreSQL \"quoting\" (ANSI)\n","type":"var","namespace":"next.jdbc.quoted","platform":"clj"},{"name":"RowBuilder","file":"next/jdbc/result_set.clj","line":124,"doc":"Protocol for building rows in various representations.\n\nThe default implementation for building hash maps: `MapResultSetBuilder`","type":"protocol","members":[{"name":"->row","arglists":[["_"]],"doc":"Called once per row to create the basis of each row.\n","type":"var"},{"name":"column-count","arglists":[["_"]],"doc":"Return the number of columns in each row.\n","type":"var"},{"name":"row!","arglists":[["_","row"]],"doc":"Called once per row to finalize each row once it is complete.\n","type":"var"},{"name":"with-column","arglists":[["_","row","i"]],"doc":"Called with the row and the index of the column to be added;\nthis is expected to read the column value from the `ResultSet`!","type":"var"},{"name":"with-column-value","arglists":[["_","row","col","v"]],"doc":"Called with the row, the column name, and the value to be added;\nthis is a low-level function, typically used by `with-column`.","type":"var"}],"namespace":"next.jdbc.result-set","platform":"clj"},{"name":"as-timestamp","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/TIMESTAMP` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"for-insert-multi","file":"next/jdbc/sql/builder.clj","line":117,"arglists":[["table","cols","rows","opts"]],"doc":"Given a table name, a vector of column names, and a vector of row values\n(each row is a vector of its values), return a vector of the full `INSERT`\nSQL string and its parameters.\n\nApplies any `:table-fn` / `:column-fn` supplied in the options.\n\nIf `:suffix` is provided in `opts`, that string is appended to the\n`INSERT ...` statement.","type":"var","namespace":"next.jdbc.sql.builder","platform":"clj"},{"name":"as-kebab-maps","file":"next/jdbc/result_set.clj","line":260,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces bare vectors of hash map rows, with kebab-case keys.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"as-unqualified-arrays","file":"next/jdbc/result_set.clj","line":338,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces a vector of simple column names followed by vectors of row\nvalues.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"as-time","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/TIME` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"->pool","file":"next/jdbc/connection.clj","line":247,"arglists":[["clazz","db-spec"]],"doc":"Given a (connection pooled datasource) class and a database spec, return a\nconnection pool object built from that class and the database spec.\n\nAssumes the `clazz` has a `.setJdbcUrl` method (which HikariCP and c3p0 do).\n\nIf you already have a JDBC URL and want to use this method, pass `:jdbcUrl`\nin the database spec (instead of `:dbtype`, `:dbname`, etc).\n\nProperties for the connection pool object can be passed as mixed case\nkeywords that correspond to setter methods (just as `:jdbcUrl` maps to\n`.setJdbcUrl`). `clojure.java.data/to-java` is used to construct the\nobject and call the setters.\n\nNote that the result is not type-hinted (because there's no common base\nclass or interface that can be assumed). In particular, connection pooled\ndatasource objects may need to be closed but they don't necessarily implement\n`java.io.Closeable` (HikariCP does, c3p0 does not).","type":"var","namespace":"next.jdbc.connection","platform":"clj"},{"name":"get-datasource","file":"next/jdbc.clj","line":75,"arglists":[["spec"]],"doc":"Given some sort of specification of a database, return a `DataSource`.\n\nA specification can be a JDBC URL string (which is passed to the JDBC\ndriver as-is), or a hash map.\n\nFor the hash map, there are two formats accepted:\n\nIn the first format, these keys are required:\n* `:dbtype` -- a string indicating the type of the database\n* `:dbname` -- a string indicating the name of the database to be used\n\nThe following optional keys are commonly used:\n* `:user` -- the username to authenticate with\n* `:password` -- the password to authenticate with\n* `:host` -- the hostname or IP address of the database (default: `127.0.0.1`);\n can be `:none` which means the host/port segment of the JDBC URL should\n be omitted entirely (for 'local' databases)\n* `:port` -- the port for the database connection (the default is database-\n specific -- see below)\n* `:classname` -- if you need to override the default for the `:dbtype`\n (or you want to use a database that next.jdbc does not know about!)\n\nThe following optional keys can be used to control how JDBC URLs are\nassembled. This may be needed for `:dbtype` values that `next.jdbc`\ndoes not recognize:\n* `:dbname-separator` -- override the `/` or `:` that normally precedes\n the database name in the JDBC URL\n* `:host-prefix` -- override the `//` that normally precedes the IP\n address or hostname in the JDBC URL\n\nIn the second format, this key is required:\n* `:jdbcUrl` -- a JDBC URL string\n\nAny additional options provided will be passed to the JDBC driver's\n`.getConnection` call as a `java.util.Properties` structure.\n\nDatabase types supported (for `:dbtype`), and their defaults:\n* `derby` -- `org.apache.derby.jdbc.EmbeddedDriver` -- also pass `:create true`\n if you want the database to be automatically created\n* `duckdb` -- `org.duckdb.DuckDBDriver` -- embedded database\n* `h2` -- `org.h2.Driver` -- for an on-disk database\n* `h2:mem` -- `org.h2.Driver` -- for an in-memory database\n* `hsqldb`, `hsql` -- `org.hsqldb.jdbcDriver`\n* `jtds:sqlserver`, `jtds` -- `net.sourceforge.jtds.jdbc.Driver` -- `1433`\n* `mariadb` -- `org.mariadb.jdbc.Driver` -- `3306`\n* `mysql` -- `com.mysql.cj.jdbc.Driver`, `com.mysql.jdbc.Driver` -- `3306`\n* `oracle:oci` -- `oracle.jdbc.OracleDriver` -- `1521`\n* `oracle:thin`, `oracle` -- `oracle.jdbc.OracleDriver` -- `1521`\n* `oracle:sid` -- `oracle.jdbc.OracleDriver` -- `1521` -- uses the legacy `:`\n separator for the database name but otherwise behaves like `oracle:thin`\n* `postgresql`, `postgres` -- `org.postgresql.Driver` -- `5432`\n* `pgsql` -- `com.impossibl.postgres.jdbc.PGDriver` -- no default port\n* `redshift` -- `com.amazon.redshift.jdbc.Driver` -- no default port\n* `sqlite` -- `org.sqlite.JDBC`\n* `sqlserver`, `mssql` -- `com.microsoft.sqlserver.jdbc.SQLServerDriver` -- `1433`\n* `timesten:client` -- `com.timesten.jdbc.TimesTenClientDriver`\n* `timesten:direct` -- `com.timesten.jdbc.TimesTenDriver`\n\nFor more details about `:dbtype` and `:classname` values, see:\nhttps://cljdoc.org/d/com.github.seancorfield/next.jdbc/CURRENT/api/next.jdbc.connection#dbtypes","type":"var","namespace":"next.jdbc","platform":"clj"},{"name":"as-unqualified-modified-arrays","file":"next/jdbc/result_set.clj","line":358,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces a vector of simple, modified column names followed by\nvectors of row values.\n\nRequires the `:label-fn` option.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"clob-column-reader","file":"next/jdbc/result_set.clj","line":305,"arglists":[["rs","_","i"]],"doc":"An example column-reader that still uses `.getObject` but expands CLOB\ncolumns into strings.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"get-unqualified-column-names","file":"next/jdbc/result_set.clj","line":46,"arglists":[["rsmeta","_"]],"doc":"Given `ResultSetMetaData`, return a vector of unqualified column names.\n","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"ReadableColumn","file":"next/jdbc/result_set.clj","line":100,"doc":"Protocol for reading objects from the `java.sql.ResultSet`. Default\nimplementations (for `Object` and `nil`) return the argument, and the\n`Boolean` implementation ensures a canonicalized `true`/`false` value,\nbut it can be extended to provide custom behavior for special types.\nExtension via metadata is supported.","type":"protocol","members":[{"name":"read-column-by-index","arglists":[["val","rsmeta","idx"]],"doc":"Function for transforming values after reading them via a column index.\n","type":"var"},{"name":"read-column-by-label","arglists":[["val","label"]],"doc":"Function for transforming values after reading them via a column label.\n","type":"var"}],"namespace":"next.jdbc.result-set","platform":"clj"},{"name":"as-maps","file":"next/jdbc/result_set.clj","line":208,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces bare vectors of hash map rows.\n\nThis is the default `:builder-fn` option.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"insert-multi!","file":"next/jdbc/sql.clj","line":45,"arglists":[["connectable","table","cols","rows"],["connectable","table","cols","rows","opts"]],"doc":"Syntactic sugar over `execute!` to make inserting columns/rows easier.\n\nGiven a connectable object, a table name, a sequence of column names, and\na vector of rows of data (vectors of column values), inserts the data as\nmultiple rows in the database and attempts to return a vector of maps of\ngenerated keys.\n\nNote: this expands to a single SQL statement with placeholders for every\nvalue being inserted -- for large sets of rows, this may exceed the limits\non SQL string size and/or number of parameters for your JDBC driver or your\ndatabase!","type":"var","namespace":"next.jdbc.sql","platform":"clj"},{"name":"oracle","file":"next/jdbc/quoted.clj","line":17,"doc":"Oracle \"quoting\" (ANSI)\n","type":"var","namespace":"next.jdbc.quoted","platform":"clj"},{"name":"as-nvarchar","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/NVARCHAR` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-varchar","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/VARCHAR` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"jdbc-url-format?","file":"next/jdbc/specs.clj","line":45,"arglists":[["url"]],"doc":"JDBC URLs must begin with `jdbc:` followed by the `dbtype` and\na second colon. Note: `clojure.java.jdbc` incorrectly allowed\n`jdbc:` to be omitted at the beginning of a JDBC URL.","type":"var","namespace":"next.jdbc.specs","platform":"clj"},{"name":"as-nchar","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/NCHAR` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-unqualified-maps","file":"next/jdbc/optional.clj","line":43,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces bare vectors of hash map rows, with simple keys and nil\ncolumns omitted.","type":"var","namespace":"next.jdbc.optional","platform":"clj"},{"name":"as-bit","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/BIT` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"sql-server","file":"next/jdbc/quoted.clj","line":15,"arglists":[["s"]],"doc":"SQL Server [quoting]\n","type":"var","namespace":"next.jdbc.quoted","platform":"clj"},{"name":"get-unqualified-lower-column-names","file":"next/jdbc/result_set.clj","line":94,"arglists":[["rsmeta","opts"]],"doc":"Given `ResultSetMetaData`, return a vector of unqualified column names.\n","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"read-as-instant","file":"next/jdbc/date_time.clj","line":64,"arglists":[[]],"doc":"After calling this function, `next.jdbc.result-set/ReadableColumn`\nwill be extended to (`java.sql.Date` and) `java.sql.Timestamp` so that any\ntimestamp columns will automatically be read as `java.time.Instant`.\n\nNote that `java.sql.Date` columns will still be returns as-is because they\ncannot be converted to an instant (they lack a time component).","type":"var","namespace":"next.jdbc.date-time","platform":"clj"},{"name":"as-struct","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/STRUCT` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"as-java-object","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/JAVA_OBJECT` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"for-update","file":"next/jdbc/sql/builder.clj","line":228,"arglists":[["table","key-map","where-params","opts"]],"doc":"Given a table name, a vector of column names to set and their values, and\neither a hash map of column names and values or a vector of SQL (where clause)\nand its parameters, return a vector of the full `UPDATE` SQL string and its\nparameters.\n\nApplies any `:table-fn` / `:column-fn` supplied in the options.\n\nIf `:suffix` is provided in `opts`, that string is appended to the\n`UPDATE ...` statement.","type":"var","namespace":"next.jdbc.sql.builder","platform":"clj"},{"name":"as-modified-maps","file":"next/jdbc/result_set.clj","line":226,"arglists":[["rs","opts"]],"doc":"Given a `ResultSet` and options, return a `RowBuilder` / `ResultSetBuilder`\nthat produces bare vectors of hash map rows, with modified keys.\n\nRequires both the `:qualifier-fn` and `:label-fn` options.","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"for-order-col","file":"next/jdbc/sql/builder.clj","line":145,"arglists":[["col","opts"]],"doc":"Given a column name, or a pair of column name and direction,\nreturn the sub-clause for addition to `ORDER BY`.","type":"var","namespace":"next.jdbc.sql.builder","platform":"clj"},{"name":"transact","file":"next/jdbc.clj","line":334,"arglists":[["transactable","f"],["transactable","f","opts"]],"doc":"Given a transactable object and a function (taking a `Connection`),\nexecute the function over the connection in a transactional manner.\n\nSee `with-transaction` for supported options.","type":"var","namespace":"next.jdbc","platform":"clj"},{"name":"as-longvarchar","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/LONGVARCHAR` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"clob->string","file":"next/jdbc/result_set.clj","line":299,"arglists":[["clob"]],"doc":"Given a CLOB column value, read it as a string.\n","type":"var","namespace":"next.jdbc.result-set","platform":"clj"},{"name":"set-parameters","file":"next/jdbc/prepare.clj","line":48,"arglists":[["ps","params"]],"doc":"Given a `PreparedStatement` and a vector of parameter values, update the\n`PreparedStatement` with those parameters and return it.","type":"var","namespace":"next.jdbc.prepare","platform":"clj"},{"name":"as-blob","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/BLOB` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"},{"name":"for-delete","file":"next/jdbc/sql/builder.clj","line":76,"arglists":[["table","where-params","opts"]],"doc":"Given a table name and either a hash map of column names and values or a\nvector of SQL (where clause) and its parameters, return a vector of the\nfull `DELETE` SQL string and its parameters.\n\nApplies any `:table-fn` / `:column-fn` supplied in the options.\n\nIf `:suffix` is provided in `opts`, that string is appended to the\n`DELETE ...` statement.","type":"var","namespace":"next.jdbc.sql.builder","platform":"clj"},{"name":"as-bigint","file":"next/jdbc/types.clj","line":36,"arglists":[["obj"]],"doc":"Wrap a Clojure value in a thunk with metadata to implement `set-parameter`\nso that `.setObject()` is called with the `java.sql.Types/BIGINT` SQL type.","type":"var","namespace":"next.jdbc.types","platform":"clj"}],"latest":"1.2.659","version-entity":{"group-id":"seancorfield","artifact-id":"next.jdbc","version":"1.2.659"}}