next-jdbc/src/next/jdbc/datafy.clj

92 lines
4.1 KiB
Clojure
Raw Normal View History

2020-05-31 07:19:48 +00:00
;; copyright (c) 2020 Sean Corfield, all rights reserved
(ns next.jdbc.datafy
"This namespace provides datafication of several JDBC object types:
* `java.sql.Connection` -- datafies as a bean; `:metaData` is navigable
and produces `java.sql.DatabaseMetaData`.
* `java.sql.DatabaseMetaData` -- datafies as a bean; five properties
are navigable to produce fully-realized datafiable result sets.
* `java.sql.ResultSetMetaData` -- datafies as a vector of column descriptions."
(:require [clojure.core.protocols :as core-p]
[next.jdbc.result-set :as rs])
(:import (java.sql Connection
DatabaseMetaData
ResultSetMetaData)))
(set! *warn-on-reflection* true)
(def ^:private column-meta
{:catalog (fn [^ResultSetMetaData o i] (.getCatalogName o i))
:class (fn [^ResultSetMetaData o i] (.getColumnClassName o i))
:display-size (fn [^ResultSetMetaData o i] (.getColumnDisplaySize o i))
:label (fn [^ResultSetMetaData o i] (.getColumnLabel o i))
:name (fn [^ResultSetMetaData o i] (.getColumnName o i))
:precision (fn [^ResultSetMetaData o i] (.getPrecision o i))
:scale (fn [^ResultSetMetaData o i] (.getScale o i))
:schema (fn [^ResultSetMetaData o i] (.getSchemaName o i))
:table (fn [^ResultSetMetaData o i] (.getTableName o i))
;; the is* fields:
:nullability (fn [^ResultSetMetaData o i]
(condp = (.isNullable o i)
ResultSetMetaData/columnNoNulls :not-null
ResultSetMetaData/columnNullable :null
:unknown))
:auto-increment (fn [^ResultSetMetaData o i] (.isAutoIncrement o i))
:case-sensitive (fn [^ResultSetMetaData o i] (.isCaseSensitive o i))
:currency (fn [^ResultSetMetaData o i] (.isCurrency o i))
:definitely-writable (fn [^ResultSetMetaData o i] (.isDefinitelyWritable o i))
:read-only (fn [^ResultSetMetaData o i] (.isReadOnly o i))
:searchable (fn [^ResultSetMetaData o i] (.isSearchable o i))
:signed (fn [^ResultSetMetaData o i] (.isSigned o i))
:writable (fn [^ResultSetMetaData o i] (.isWritable o i))})
(defn- safe-bean [o]
(try
;; ensure we return a basic hash map:
(merge {} (bean o))
(catch Throwable t
{:exception (ex-message t)
:cause (ex-message (ex-cause t))})))
(extend-protocol core-p/Datafiable
Connection
(datafy [this]
(with-meta (safe-bean this)
{`core-p/nav (fn [_ k v]
(if (= :metaData k)
(.getMetaData this)
v))}))
DatabaseMetaData
(datafy [this]
(with-meta (safe-bean this)
{`core-p/nav (fn [_ k v]
(condp = k
:catalogs
(rs/datafiable-result-set (.getCatalogs this)
(.getConnection this)
{})
:clientInfoProperties
(rs/datafiable-result-set (.getClientInfoProperties this)
(.getConnection this)
{})
:schemas
(rs/datafiable-result-set (.getSchemas this)
(.getConnection this)
{})
:tableTypes
(rs/datafiable-result-set (.getTableTypes this)
(.getConnection this)
{})
:typeInfo
(rs/datafiable-result-set (.getTypeInfo this)
(.getConnection this)
{})
v))}))
ResultSetMetaData
(datafy [this]
(mapv #(reduce-kv (fn [m k f] (assoc m k (f this %)))
{}
column-meta)
(range 1 (inc (.getColumnCount this))))))