Fixes #167 by adding property separator
This commit is contained in:
parent
a568f0fa87
commit
164572969b
5 changed files with 75 additions and 16 deletions
|
|
@ -4,6 +4,7 @@ Only accretive/fixative changes will be made from now on.
|
|||
|
||||
* 1.2.next in progress
|
||||
* _[Experimental! Will change in response to feedback!]_ Add `next.jdbc/with-logging` to create a wrapped connectable that will invoke logging functions with the SQL/parameters and optionally the result for each operation.
|
||||
* Fix #167 by adding `:property-separator` to `next.jdbc.connection/dbtypes` and using it in `jdbc-url`.
|
||||
* Fix `:unit_count` references in **Getting Started** (were `:unit_cost`).
|
||||
* Update `test-runner`.
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ Although `get-datasource` does not accept options, the "db spec" hash map passed
|
|||
* `: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,
|
||||
* `: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,
|
||||
* `: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,
|
||||
* `:property-separator` -- an optional string that can be used to override the separators used in `jdbc-url` for the properties (after the initial JDBC URL portion); by default `?` and `&` are used to build JDBC URLs with properties; for SQL Server drivers (both MS and jTDS) `:property-separator ";"` is used, so this option should only be necessary when you are specifying "unusual" databases that `next.jdbc` does not already know about,
|
||||
* `: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,
|
||||
* `:user` -- an optional string that identifies the database username to be used when authenticating,
|
||||
* `:password` -- an optional string that identifies the database password to be used when authenticating.
|
||||
|
|
|
|||
|
|
@ -103,6 +103,11 @@
|
|||
the database name in the JDBC URL
|
||||
* `:host-prefix` -- override the `//` that normally precedes the IP
|
||||
address or hostname in the JDBC URL
|
||||
* `:property-separator` -- an optional string that can be used to override
|
||||
the separators used in `jdbc-url` for the properties (after the initial
|
||||
JDBC URL portion); by default `?` and `&` are used to build JDBC URLs
|
||||
with properties; for SQL Server drivers (both MS and jTDS)
|
||||
`:property-separator \";\"` is used
|
||||
|
||||
In the second format, this key is required:
|
||||
* `:jdbcUrl` -- a JDBC URL string
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@
|
|||
string, this table includes `:dbname-separator` and/or `:host-prefix`. The
|
||||
default prefix for `:dbname` is either `/` or `:` and for `:host` it is `//`.
|
||||
For local databases, with no `:host`/`:port` segment in their JDBC URL, a
|
||||
value of `:none` is provided for `:host` in this table.
|
||||
value of `:none` is provided for `:host` in this table. In addition,
|
||||
`:property-separator` can specify how you build the JDBC URL.
|
||||
|
||||
For known database types, you can use `:dbtype` (and omit `:classname`).
|
||||
|
||||
|
|
@ -79,14 +80,17 @@
|
|||
:host :none}
|
||||
"jtds" {:classname "net.sourceforge.jtds.jdbc.Driver"
|
||||
:alias-for "jtds:sqlserver"
|
||||
:property-separator ";"
|
||||
:port 1433}
|
||||
"jtds:sqlserver" {:classname "net.sourceforge.jtds.jdbc.Driver"
|
||||
:property-separator ";"
|
||||
:port 1433}
|
||||
"mariadb" {:classname "org.mariadb.jdbc.Driver"
|
||||
:port 3306}
|
||||
"mssql" {:classname "com.microsoft.sqlserver.jdbc.SQLServerDriver"
|
||||
:alias-for "sqlserver"
|
||||
:dbname-separator ";DATABASENAME="
|
||||
:property-separator ";"
|
||||
:port 1433}
|
||||
"mysql" {:classname ["com.mysql.cj.jdbc.Driver"
|
||||
"com.mysql.jdbc.Driver"]
|
||||
|
|
@ -117,6 +121,7 @@
|
|||
:host :none}
|
||||
"sqlserver" {:classname "com.microsoft.sqlserver.jdbc.SQLServerDriver"
|
||||
:dbname-separator ";DATABASENAME="
|
||||
:property-separator ";"
|
||||
:port 1433}
|
||||
"timesten:client" {:classname "com.timesten.jdbc.TimesTenClientDriver"
|
||||
:dbname-separator ":dsn="
|
||||
|
|
@ -151,7 +156,7 @@
|
|||
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
|
||||
dbname-separator host-prefix
|
||||
dbname-separator host-prefix property-separator
|
||||
jdbcUrl]
|
||||
:as db-spec}]
|
||||
(let [etc (dissoc db-spec
|
||||
|
|
@ -208,7 +213,8 @@
|
|||
(throw (ex-info (str "Unknown dbtype: " dbtype
|
||||
", and :classname not provided.")
|
||||
db-spec)))
|
||||
[url etc]))))
|
||||
[url etc (or property-separator
|
||||
(-> dbtype dbtypes :property-separator))]))))
|
||||
|
||||
(defn jdbc-url
|
||||
"Given a database spec (as a hash map), return a JDBC URL with all the
|
||||
|
|
@ -236,13 +242,15 @@
|
|||
sure they are properly URL-encoded as values in the database spec hash map.
|
||||
This function does **not** attempt to URL-encode values for you!"
|
||||
[db-spec]
|
||||
(let [[url etc] (spec->url+etc db-spec)
|
||||
url-and (if (str/index-of url "?") "&" "?")]
|
||||
(str url url-and (str/join "&"
|
||||
(let [[url etc ps] (spec->url+etc db-spec)
|
||||
url-and (or ps (if (str/index-of url "?") "&" "?"))]
|
||||
(if (seq etc)
|
||||
(str url url-and (str/join (or ps "&")
|
||||
(reduce-kv (fn [pairs k v]
|
||||
(conj pairs (str (name k) "=" v)))
|
||||
[]
|
||||
etc)))))
|
||||
etc)))
|
||||
url)))
|
||||
|
||||
(defn ->pool
|
||||
"Given a (connection pooled datasource) class and a database spec, return a
|
||||
|
|
|
|||
|
|
@ -54,28 +54,72 @@
|
|||
(#'c/spec->url+etc {:dbtype "sqlserver" :dbname db-name :port 1433})))))
|
||||
|
||||
(deftest custom-dbtypes
|
||||
(is (= ["jdbc:acme:my-db" {}]
|
||||
(is (= ["jdbc:acme:my-db" {} nil]
|
||||
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
|
||||
:dbname "my-db" :host :none})))
|
||||
(is (= ["jdbc:acme://127.0.0.1/my-db" {}]
|
||||
(is (= ["jdbc:acme://127.0.0.1/my-db" {} nil]
|
||||
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
|
||||
:dbname "my-db"})))
|
||||
(is (= ["jdbc:acme://12.34.56.70:1234/my-db" {}]
|
||||
(is (= ["jdbc:acme://12.34.56.70:1234/my-db" {} nil]
|
||||
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
|
||||
:dbname "my-db" :host "12.34.56.70" :port 1234})))
|
||||
(is (= ["jdbc:acme:dsn=my-db" {}]
|
||||
(is (= ["jdbc:acme:dsn=my-db" {} nil]
|
||||
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
|
||||
:dbname "my-db" :host :none
|
||||
:dbname-separator ":dsn="})))
|
||||
(is (= ["jdbc:acme:(*)127.0.0.1/my-db" {}]
|
||||
(is (= ["jdbc:acme:(*)127.0.0.1/my-db" {} nil]
|
||||
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
|
||||
:dbname "my-db"
|
||||
:host-prefix "(*)"})))
|
||||
(is (= ["jdbc:acme:(*)12.34.56.70:1234/my-db" {}]
|
||||
(is (= ["jdbc:acme:(*)12.34.56.70:1234/my-db" {} nil]
|
||||
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
|
||||
:dbname "my-db" :host "12.34.56.70" :port 1234
|
||||
:host-prefix "(*)"}))))
|
||||
|
||||
(deftest jdbc-url-tests
|
||||
(testing "basic URLs work"
|
||||
(is (= "jdbc:acme:my-db"
|
||||
(c/jdbc-url {:dbtype "acme" :classname "java.lang.String"
|
||||
:dbname "my-db" :host :none})))
|
||||
(is (= "jdbc:acme://127.0.0.1/my-db"
|
||||
(c/jdbc-url {:dbtype "acme" :classname "java.lang.String"
|
||||
:dbname "my-db"})))
|
||||
(is (= "jdbc:acme://12.34.56.70:1234/my-db"
|
||||
(c/jdbc-url {:dbtype "acme" :classname "java.lang.String"
|
||||
:dbname "my-db" :host "12.34.56.70" :port 1234})))
|
||||
(is (= "jdbc:acme:dsn=my-db"
|
||||
(c/jdbc-url {:dbtype "acme" :classname "java.lang.String"
|
||||
:dbname "my-db" :host :none
|
||||
:dbname-separator ":dsn="})))
|
||||
(is (= "jdbc:acme:(*)127.0.0.1/my-db"
|
||||
(c/jdbc-url {:dbtype "acme" :classname "java.lang.String"
|
||||
:dbname "my-db"
|
||||
:host-prefix "(*)"})))
|
||||
(is (= "jdbc:acme:(*)12.34.56.70:1234/my-db"
|
||||
(c/jdbc-url {:dbtype "acme" :classname "java.lang.String"
|
||||
:dbname "my-db" :host "12.34.56.70" :port 1234
|
||||
:host-prefix "(*)"}))))
|
||||
(testing "URLs with properties work"
|
||||
(is (= "jdbc:acme:my-db?useSSL=true"
|
||||
(c/jdbc-url {:dbtype "acme" :classname "java.lang.String"
|
||||
:dbname "my-db" :host :none
|
||||
:useSSL true})))
|
||||
(is (boolean (#{"jdbc:acme:my-db?useSSL=true&user=dba"
|
||||
"jdbc:acme:my-db?user=dba&useSSL=true"}
|
||||
(c/jdbc-url {:dbtype "acme" :classname "java.lang.String"
|
||||
:dbname "my-db" :host :none
|
||||
:useSSL true :user "dba"}))))
|
||||
|
||||
(is (= "jdbc:jtds:sqlserver:my-db;useSSL=true"
|
||||
(c/jdbc-url {:dbtype "jtds"
|
||||
:dbname "my-db" :host :none
|
||||
:useSSL true})))
|
||||
(is (boolean (#{"jdbc:jtds:sqlserver:my-db;useSSL=true;user=dba"
|
||||
"jdbc:jtds:sqlserver:my-db;user=dba;useSSL=true"}
|
||||
(c/jdbc-url {:dbtype "jtds"
|
||||
:dbname "my-db" :host :none
|
||||
:useSSL true :user "dba"}))))))
|
||||
|
||||
;; these are the 'local' databases that we can always test against
|
||||
(def test-db-type ["derby" "h2" "h2:mem" "hsqldb" "sqlite"])
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue