Skip to content

Commit

Permalink
Fix #19 by caching loaded database driver classes
Browse files Browse the repository at this point in the history
  • Loading branch information
seancorfield committed May 8, 2019
1 parent c509525 commit 99ee285
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 19 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
44 changes: 26 additions & 18 deletions src/next/jdbc/connection.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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}]
Expand Down Expand Up @@ -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))]
(do
(if (string? class-name)
(clojure.lang.RT/loadClassForName class-name)
(loop [[clazz & more] class-name]
(when-let [load-failure
(try
(clojure.lang.RT/loadClassForName clazz)
nil
(catch Exception e
e))]
(if (seq more)
(recur more)
(throw load-failure))))))
(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]
(let [loaded
(try
(clojure.lang.RT/loadClassForName clazz)
(catch Exception e
e))]
(if (instance? Throwable loaded)
(if (seq more)
(recur more)
(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]
Expand Down

0 comments on commit 99ee285

Please sign in to comment.