ryoakg
6/6/2016 - 7:48 AM

jdbc-cursor-capability.clj

;;; http://chokkoyamada.github.io/blog/2013/05/27/dig-into-jdbc-4/

(set-env! :dependencies '[[funcool/clojure.jdbc "0.6.1"]])
(require '[jdbc.proto])
(import (java.sql ResultSet))

(defn- concurrency [^java.sql.DatabaseMetaData metadata ^Integer result-set-type]
  (cond-> #{}
    (.supportsResultSetConcurrency metadata result-set-type ResultSet/CONCUR_READ_ONLY) (conj :CONCUR_READ_ONLY)
    (.supportsResultSetConcurrency metadata result-set-type ResultSet/CONCUR_UPDATABLE) (conj :CONCUR_UPDATABLE)))

(defn- result-set-types [^java.sql.DatabaseMetaData metadata]
  (cond-> {}
    (.supportsResultSetType metadata ResultSet/TYPE_FORWARD_ONLY)        (conj [:FORWARD_ONLY       (concurrency metadata ResultSet/TYPE_FORWARD_ONLY)])
    (.supportsResultSetType metadata ResultSet/TYPE_SCROLL_INSENSITIVE)  (conj [:SCROLL_INSENSITIVE (concurrency metadata ResultSet/TYPE_SCROLL_INSENSITIVE)])
    (.supportsResultSetType metadata ResultSet/TYPE_SCROLL_SENSITIVE)    (conj [:SCROLL_SENSITIVE   (concurrency metadata ResultSet/TYPE_SCROLL_SENSITIVE)])))

(defn- holdability [^java.sql.DatabaseMetaData metadata]
  {:default
   ({ResultSet/HOLD_CURSORS_OVER_COMMIT :HOLD_CURSORS_OVER_COMMIT
     ResultSet/CLOSE_CURSORS_AT_COMMIT  :CLOSE_CURSORS_AT_COMMIT} (.getResultSetHoldability metadata))
   :supports (cond-> #{}
               (.supportsResultSetHoldability metadata ResultSet/HOLD_CURSORS_OVER_COMMIT) (conj :HOLD_CURSORS_OVER_COMMIT)
               (.supportsResultSetHoldability metadata ResultSet/CLOSE_CURSORS_AT_COMMIT)  (conj :CLOSE_CURSORS_AT_COMMIT))})

(defn- cursor-capability [db-spec]
  (with-open [conn (jdbc/connection db-spec)]
    (let [metadata (jdbc.proto/get-database-metadata conn)]
      {:hodability (holdability metadata)
       :result-set-types (result-set-types metadata)})))

(comment
  (cursor-capability {:classname "org.h2.Driver", :subprotocol "h2", :subname "./test"})
  ;; ↓
  {:hodability {:default :CLOSE_CURSORS_AT_COMMIT, :supports #{:CLOSE_CURSORS_AT_COMMIT}},
   :result-set-types
   {:FORWARD_ONLY #{:CONCUR_UPDATABLE :CONCUR_READ_ONLY}, :SCROLL_INSENSITIVE #{:CONCUR_UPDATABLE :CONCUR_READ_ONLY}}})