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
|
* 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.
|
* _[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`).
|
* Fix `:unit_count` references in **Getting Started** (were `:unit_cost`).
|
||||||
* Update `test-runner`.
|
* 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` -- 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,
|
* `: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,
|
* `: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,
|
* `: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,
|
* `: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.
|
* `: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
|
the database name in the JDBC URL
|
||||||
* `: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
|
||||||
|
* `: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:
|
In the second format, this key is required:
|
||||||
* `:jdbcUrl` -- a JDBC URL string
|
* `:jdbcUrl` -- a JDBC URL string
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,8 @@
|
||||||
string, this table includes `:dbname-separator` and/or `:host-prefix`. The
|
string, this table includes `:dbname-separator` and/or `:host-prefix`. The
|
||||||
default prefix for `:dbname` is either `/` or `:` and for `:host` it is `//`.
|
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
|
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`).
|
For known database types, you can use `:dbtype` (and omit `:classname`).
|
||||||
|
|
||||||
|
|
@ -79,14 +80,17 @@
|
||||||
:host :none}
|
:host :none}
|
||||||
"jtds" {:classname "net.sourceforge.jtds.jdbc.Driver"
|
"jtds" {:classname "net.sourceforge.jtds.jdbc.Driver"
|
||||||
:alias-for "jtds:sqlserver"
|
:alias-for "jtds:sqlserver"
|
||||||
|
:property-separator ";"
|
||||||
:port 1433}
|
:port 1433}
|
||||||
"jtds:sqlserver" {:classname "net.sourceforge.jtds.jdbc.Driver"
|
"jtds:sqlserver" {:classname "net.sourceforge.jtds.jdbc.Driver"
|
||||||
|
:property-separator ";"
|
||||||
:port 1433}
|
:port 1433}
|
||||||
"mariadb" {:classname "org.mariadb.jdbc.Driver"
|
"mariadb" {:classname "org.mariadb.jdbc.Driver"
|
||||||
:port 3306}
|
:port 3306}
|
||||||
"mssql" {:classname "com.microsoft.sqlserver.jdbc.SQLServerDriver"
|
"mssql" {:classname "com.microsoft.sqlserver.jdbc.SQLServerDriver"
|
||||||
:alias-for "sqlserver"
|
:alias-for "sqlserver"
|
||||||
:dbname-separator ";DATABASENAME="
|
:dbname-separator ";DATABASENAME="
|
||||||
|
:property-separator ";"
|
||||||
:port 1433}
|
:port 1433}
|
||||||
"mysql" {:classname ["com.mysql.cj.jdbc.Driver"
|
"mysql" {:classname ["com.mysql.cj.jdbc.Driver"
|
||||||
"com.mysql.jdbc.Driver"]
|
"com.mysql.jdbc.Driver"]
|
||||||
|
|
@ -117,6 +121,7 @@
|
||||||
:host :none}
|
:host :none}
|
||||||
"sqlserver" {:classname "com.microsoft.sqlserver.jdbc.SQLServerDriver"
|
"sqlserver" {:classname "com.microsoft.sqlserver.jdbc.SQLServerDriver"
|
||||||
:dbname-separator ";DATABASENAME="
|
:dbname-separator ";DATABASENAME="
|
||||||
|
:property-separator ";"
|
||||||
:port 1433}
|
:port 1433}
|
||||||
"timesten:client" {:classname "com.timesten.jdbc.TimesTenClientDriver"
|
"timesten:client" {:classname "com.timesten.jdbc.TimesTenClientDriver"
|
||||||
:dbname-separator ":dsn="
|
:dbname-separator ":dsn="
|
||||||
|
|
@ -151,7 +156,7 @@
|
||||||
As a special case, the database spec can contain jdbcUrl (just like ->pool),
|
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."
|
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 property-separator
|
||||||
jdbcUrl]
|
jdbcUrl]
|
||||||
:as db-spec}]
|
:as db-spec}]
|
||||||
(let [etc (dissoc db-spec
|
(let [etc (dissoc db-spec
|
||||||
|
|
@ -208,7 +213,8 @@
|
||||||
(throw (ex-info (str "Unknown dbtype: " dbtype
|
(throw (ex-info (str "Unknown dbtype: " dbtype
|
||||||
", and :classname not provided.")
|
", and :classname not provided.")
|
||||||
db-spec)))
|
db-spec)))
|
||||||
[url etc]))))
|
[url etc (or property-separator
|
||||||
|
(-> dbtype dbtypes :property-separator))]))))
|
||||||
|
|
||||||
(defn jdbc-url
|
(defn jdbc-url
|
||||||
"Given a database spec (as a hash map), return a JDBC URL with all the
|
"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.
|
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!"
|
This function does **not** attempt to URL-encode values for you!"
|
||||||
[db-spec]
|
[db-spec]
|
||||||
(let [[url etc] (spec->url+etc db-spec)
|
(let [[url etc ps] (spec->url+etc db-spec)
|
||||||
url-and (if (str/index-of url "?") "&" "?")]
|
url-and (or ps (if (str/index-of url "?") "&" "?"))]
|
||||||
(str url url-and (str/join "&"
|
(if (seq etc)
|
||||||
|
(str url url-and (str/join (or ps "&")
|
||||||
(reduce-kv (fn [pairs k v]
|
(reduce-kv (fn [pairs k v]
|
||||||
(conj pairs (str (name k) "=" v)))
|
(conj pairs (str (name k) "=" v)))
|
||||||
[]
|
[]
|
||||||
etc)))))
|
etc)))
|
||||||
|
url)))
|
||||||
|
|
||||||
(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
|
||||||
|
|
|
||||||
|
|
@ -54,28 +54,72 @@
|
||||||
(#'c/spec->url+etc {:dbtype "sqlserver" :dbname db-name :port 1433})))))
|
(#'c/spec->url+etc {:dbtype "sqlserver" :dbname db-name :port 1433})))))
|
||||||
|
|
||||||
(deftest custom-dbtypes
|
(deftest custom-dbtypes
|
||||||
(is (= ["jdbc:acme:my-db" {}]
|
(is (= ["jdbc:acme:my-db" {} nil]
|
||||||
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
|
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
|
||||||
:dbname "my-db" :host :none})))
|
: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"
|
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
|
||||||
:dbname "my-db"})))
|
: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"
|
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
|
||||||
:dbname "my-db" :host "12.34.56.70" :port 1234})))
|
: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"
|
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
|
||||||
:dbname "my-db" :host :none
|
:dbname "my-db" :host :none
|
||||||
:dbname-separator ":dsn="})))
|
: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"
|
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
|
||||||
:dbname "my-db"
|
:dbname "my-db"
|
||||||
:host-prefix "(*)"})))
|
: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"
|
(#'c/spec->url+etc {:dbtype "acme" :classname "java.lang.String"
|
||||||
:dbname "my-db" :host "12.34.56.70" :port 1234
|
:dbname "my-db" :host "12.34.56.70" :port 1234
|
||||||
:host-prefix "(*)"}))))
|
: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
|
;; these are the 'local' databases that we can always test against
|
||||||
(def test-db-type ["derby" "h2" "h2:mem" "hsqldb" "sqlite"])
|
(def test-db-type ["derby" "h2" "h2:mem" "hsqldb" "sqlite"])
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue