Fix #19 by caching loaded database driver classes

This commit is contained in:
Sean Corfield 2019-05-08 15:11:37 -07:00
parent c509525592
commit 99ee285689
2 changed files with 27 additions and 19 deletions

View file

@ -10,4 +10,4 @@
The following changes have been committed to the **master** branch and will be in the next release:
* None at this time.
* Fix #19 by caching loaded database driver classes.

View file

@ -72,13 +72,16 @@
p))
(defn- get-driver-connection
"Common logic for loading the `DriverManager` and the designed JDBC driver
class and obtaining the appropriate `Connection` object."
"Common logic for loading the designated JDBC driver class and
obtaining the appropriate `Connection` object."
[url etc]
;; force DriverManager to be loaded
(DriverManager/getLoginTimeout)
(DriverManager/getConnection url (as-properties etc)))
(def ^:private driver-cache
"An optimization for repeated calls to get-datasource, or for get-connection
called on a db-spec hash map, so that we only try to load the classes once."
(atom {}))
(defn- spec->url+etc
"Given a database spec, return a JDBC URL and a map of any additional options."
[{:keys [dbtype dbname host port classname] :as db-spec}]
@ -107,22 +110,27 @@
etc (dissoc db-spec :dbtype :dbname :host :port :classname)]
;; verify the datasource is loadable
(if-let [class-name (or classname (classnames subprotocol))]
(swap! driver-cache update class-name
#(if % %
(do
;; force DriverManager to be loaded
(DriverManager/getLoginTimeout)
(if (string? class-name)
(clojure.lang.RT/loadClassForName class-name)
(loop [[clazz & more] class-name]
(when-let [load-failure
(let [loaded
(try
(clojure.lang.RT/loadClassForName clazz)
nil
(catch Exception e
e))]
(if (instance? Throwable loaded)
(if (seq more)
(recur more)
(throw load-failure))))))
(throw loaded))
loaded)))))))
(throw (ex-info (str "Unknown dbtype: " dbtype) db-spec)))
[url etc]))
(def class-name "java.lang.String")
(defn- string->url+etc
"Given a JDBC URL, return it with an empty set of options with no parsing."
[s]