Fixes #66 by adding support for :jdbcUrl in db-spec hash map
This commit is contained in:
parent
0f0f6fbe92
commit
6c42d7ce67
5 changed files with 84 additions and 55 deletions
|
|
@ -6,6 +6,7 @@ Only accretive/fixative changes will be made from now on.
|
||||||
|
|
||||||
The following changes have been committed to the **master** branch since the 1.0.7 release:
|
The following changes have been committed to the **master** branch since the 1.0.7 release:
|
||||||
|
|
||||||
|
* 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.
|
||||||
* Address #65 by adding a HugSQL "quick start" to the Friendly SQL Functions section of the docs.
|
* Address #65 by adding a HugSQL "quick start" to the Friendly SQL Functions section of the docs.
|
||||||
* Add `next.jdbc.specs/unstrument`. PR #64 (@gerred).
|
* Add `next.jdbc.specs/unstrument`. PR #64 (@gerred).
|
||||||
* Address #63 by improving documentation around qualified column names and `:qualifier` (`clojure.java.jdbc`) migration.
|
* Address #63 by improving documentation around qualified column names and `:qualifier` (`clojure.java.jdbc`) migration.
|
||||||
|
|
|
||||||
|
|
@ -68,6 +68,8 @@ We described the database with just `:dbtype` and `:dbname` because it is create
|
||||||
|
|
||||||
> Note: You can see the full list of `:dbtype` values supported in [next.jdbc/get-datasource](https://cljdoc.org/d/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/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.
|
> Note: You can see the full list of `:dbtype` values supported in [next.jdbc/get-datasource](https://cljdoc.org/d/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/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.
|
||||||
|
|
||||||
|
If 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.
|
||||||
|
|
||||||
### `execute!` & `execute-one!`
|
### `execute!` & `execute-one!`
|
||||||
|
|
||||||
We 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. When no result set is produced, `next.jdbc` returns a "result set" containing the "update count" from the operation (which is usually the number of rows affected). By default, H2 uses uppercase names and `next.jdbc` returns these as-is.
|
We 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. When no result set is produced, `next.jdbc` returns a "result set" containing the "update count" from the operation (which is usually the number of rows affected). By default, H2 uses uppercase names and `next.jdbc` returns these as-is.
|
||||||
|
|
@ -172,7 +174,7 @@ Then import the appropriate classes into your code:
|
||||||
(com.mchange.v2.c3p0 ComboPooledDataSource PooledDataSource)))
|
(com.mchange.v2.c3p0 ComboPooledDataSource PooledDataSource)))
|
||||||
```
|
```
|
||||||
|
|
||||||
Finally, create the connection pooled datasource. `db-spec` here contains the regular `next.jdbc` options (`:dbtype`, `:dbname`, and maybe `:host`, `:port`, `:classname` etc). 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).
|
Finally, 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).
|
||||||
|
|
||||||
Some important notes regarding HikariCP:
|
Some important notes regarding HikariCP:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,11 @@
|
||||||
"Given some sort of specification of a database, return a `DataSource`.
|
"Given some sort of specification of a database, return a `DataSource`.
|
||||||
|
|
||||||
A specification can be a JDBC URL string (which is passed to the JDBC
|
A specification can be a JDBC URL string (which is passed to the JDBC
|
||||||
driver as-is), or a hash map. For the hash map, these keys are required:
|
driver as-is), or a hash map.
|
||||||
|
|
||||||
|
For the hash map, there are two formats accepted:
|
||||||
|
|
||||||
|
In the first format, these keys are required:
|
||||||
* `:dbtype` -- a string indicating the type of the database
|
* `:dbtype` -- a string indicating the type of the database
|
||||||
* `:dbname` -- a string indicating the name of the database to be used
|
* `:dbname` -- a string indicating the name of the database to be used
|
||||||
|
|
||||||
|
|
@ -81,10 +85,13 @@
|
||||||
* `:host-prefix` -- override the `//` that normally precedes the IP
|
* `:host-prefix` -- override the `//` that normally precedes the IP
|
||||||
address or hostname in the JDBC URL
|
address or hostname in the JDBC URL
|
||||||
|
|
||||||
|
In the second format, this key is required:
|
||||||
|
* `:jdbcUrl` -- a JDBC URL string
|
||||||
|
|
||||||
Any additional options provided will be passed to the JDBC driver's
|
Any additional options provided will be passed to the JDBC driver's
|
||||||
`.getConnection` call as a `java.util.Properties` structure.
|
`.getConnection` call as a `java.util.Properties` structure.
|
||||||
|
|
||||||
Database types supported, and their defaults:
|
Database types supported (for `:dbtype`), and their defaults:
|
||||||
* `derby` -- `org.apache.derby.jdbc.EmbeddedDriver` -- also pass `:create true`
|
* `derby` -- `org.apache.derby.jdbc.EmbeddedDriver` -- also pass `:create true`
|
||||||
if you want the database to be automatically created
|
if you want the database to be automatically created
|
||||||
* `h2` -- `org.h2.Driver` -- for an on-disk database
|
* `h2` -- `org.h2.Driver` -- for an on-disk database
|
||||||
|
|
|
||||||
|
|
@ -136,10 +136,20 @@
|
||||||
(atom {}))
|
(atom {}))
|
||||||
|
|
||||||
(defn- spec->url+etc
|
(defn- spec->url+etc
|
||||||
"Given a database spec, return a JDBC URL and a map of any additional options."
|
"Given a database spec, return a JDBC URL and a map of any additional options.
|
||||||
|
|
||||||
|
As a special case, the database spec can contain jdbcUrl (just like ->pool),
|
||||||
|
in which case it will return that URL as-is and a map of any other options."
|
||||||
[{:keys [dbtype dbname host port classname
|
[{:keys [dbtype dbname host port classname
|
||||||
dbname-separator host-prefix]
|
dbname-separator host-prefix
|
||||||
|
jdbcUrl]
|
||||||
:as db-spec}]
|
:as db-spec}]
|
||||||
|
(let [etc (dissoc db-spec
|
||||||
|
:dbtype :dbname :host :port :classname
|
||||||
|
:dbname-separator :host-prefix
|
||||||
|
:jdbcUrl)]
|
||||||
|
(if jdbcUrl
|
||||||
|
[jdbcUrl etc]
|
||||||
(let [;; allow aliases for dbtype
|
(let [;; allow aliases for dbtype
|
||||||
subprotocol (-> dbtype dbtypes :alias-for (or dbtype))
|
subprotocol (-> dbtype dbtypes :alias-for (or dbtype))
|
||||||
host (or host (-> dbtype dbtypes :host) "127.0.0.1")
|
host (or host (-> dbtype dbtypes :host) "127.0.0.1")
|
||||||
|
|
@ -165,10 +175,7 @@
|
||||||
(or host-prefix (-> dbtype dbtypes :host-prefix (or "//")))
|
(or host-prefix (-> dbtype dbtypes :host-prefix (or "//")))
|
||||||
host
|
host
|
||||||
(when port (str ":" port))
|
(when port (str ":" port))
|
||||||
db-sep dbname))
|
db-sep dbname))]
|
||||||
etc (dissoc db-spec
|
|
||||||
:dbtype :dbname :host :port :classname
|
|
||||||
:dbname-separator :host-prefix)]
|
|
||||||
;; verify the datasource is loadable
|
;; verify the datasource is loadable
|
||||||
(if-let [class-name (or classname (-> dbtype dbtypes :classname))]
|
(if-let [class-name (or classname (-> dbtype dbtypes :classname))]
|
||||||
(swap! driver-cache update class-name
|
(swap! driver-cache update class-name
|
||||||
|
|
@ -190,7 +197,7 @@
|
||||||
(throw loaded))
|
(throw loaded))
|
||||||
loaded)))))))
|
loaded)))))))
|
||||||
(throw (ex-info (str "Unknown dbtype: " dbtype) db-spec)))
|
(throw (ex-info (str "Unknown dbtype: " dbtype) db-spec)))
|
||||||
[url etc]))
|
[url etc]))))
|
||||||
|
|
||||||
(defn ->pool
|
(defn ->pool
|
||||||
"Given a (connection pooled datasource) class and a database spec, return a
|
"Given a (connection pooled datasource) class and a database spec, return a
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,18 @@
|
||||||
(is (str/index-of (pr-str ds) url))
|
(is (str/index-of (pr-str ds) url))
|
||||||
(with-open [con (p/get-connection ds {})]
|
(with-open [con (p/get-connection ds {})]
|
||||||
(is (instance? java.sql.Connection con)))))
|
(is (instance? java.sql.Connection con)))))
|
||||||
|
(testing "datasource via jdbcUrl"
|
||||||
|
(let [[url etc] (#'c/spec->url+etc db)
|
||||||
|
ds (p/get-datasource (assoc etc :jdbcUrl url))]
|
||||||
|
(if (= "derby" (:dbtype db))
|
||||||
|
(is {:create true} etc)
|
||||||
|
(is {} etc))
|
||||||
|
(is (instance? javax.sql.DataSource ds))
|
||||||
|
(is (str/index-of (pr-str ds) (str "jdbc:" (:dbtype db))))
|
||||||
|
;; checks get-datasource on a DataSource is identity
|
||||||
|
(is (identical? ds (p/get-datasource ds)))
|
||||||
|
(with-open [con (p/get-connection ds {})]
|
||||||
|
(is (instance? java.sql.Connection con)))))
|
||||||
(testing "datasource via HikariCP"
|
(testing "datasource via HikariCP"
|
||||||
;; the type hint is only needed because we want to call .close
|
;; the type hint is only needed because we want to call .close
|
||||||
(with-open [^HikariDataSource ds (c/->pool HikariDataSource db)]
|
(with-open [^HikariDataSource ds (c/->pool HikariDataSource db)]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue