71 lines
2.3 KiB
Clojure
71 lines
2.3 KiB
Clojure
(ns kit.edge.db.postgres
|
|
(:require
|
|
[cheshire.core :as cheshire]
|
|
[next.jdbc]
|
|
[next.jdbc.prepare :as prepare]
|
|
[next.jdbc.result-set :as result-set])
|
|
(:import
|
|
[clojure.lang IPersistentMap IPersistentVector]
|
|
[java.sql Array PreparedStatement Timestamp]
|
|
[java.time Instant LocalDate LocalDateTime]
|
|
[org.postgresql.util PGobject]))
|
|
|
|
(def ->json cheshire/generate-string)
|
|
(def <-json #(cheshire/parse-string % true))
|
|
|
|
(defn ->pgobject
|
|
"Transforms Clojure data to a PGobject that contains the data as
|
|
JSON. PGObject type defaults to `jsonb` but can be changed via
|
|
metadata key `:pgtype`"
|
|
[x]
|
|
(let [pgtype (:pgtype (meta x) "jsonb")]
|
|
(doto (PGobject.)
|
|
(.setType pgtype)
|
|
(.setValue (->json x)))))
|
|
|
|
(defn <-pgobject
|
|
"Transform PGobject containing `json` or `jsonb` value to Clojure data"
|
|
[^PGobject v]
|
|
(let [type (.getType v)
|
|
value (.getValue v)]
|
|
(if (#{"jsonb" "json"} type)
|
|
(when value
|
|
(with-meta (<-json value) {:pgtype type}))
|
|
value)))
|
|
|
|
(extend-protocol result-set/ReadableColumn
|
|
Array
|
|
(read-column-by-label [^Array v _] (vec (.getArray v)))
|
|
(read-column-by-index [^Array v _2 _3] (vec (.getArray v)))
|
|
|
|
PGobject
|
|
(read-column-by-label [^PGobject v _] (<-pgobject v))
|
|
(read-column-by-index [^PGobject v _2 _3] (<-pgobject v)))
|
|
|
|
(extend-protocol prepare/SettableParameter
|
|
Instant
|
|
(set-parameter [^Instant v ^PreparedStatement ps ^long i]
|
|
(.setTimestamp ps i (Timestamp/from v)))
|
|
|
|
LocalDate
|
|
(set-parameter [^LocalDate v ^PreparedStatement ps ^long i]
|
|
(.setTimestamp ps i (Timestamp/valueOf (.atStartOfDay v))))
|
|
|
|
LocalDateTime
|
|
(set-parameter [^LocalDateTime v ^PreparedStatement ps ^long i]
|
|
(.setTimestamp ps i (Timestamp/valueOf v)))
|
|
|
|
IPersistentMap
|
|
(set-parameter [m ^PreparedStatement s i]
|
|
(.setObject s i (->pgobject m)))
|
|
|
|
IPersistentVector
|
|
(set-parameter [^clojure.lang.IPersistentVector v ^java.sql.PreparedStatement stmt ^long idx]
|
|
(let [conn (.getConnection stmt)
|
|
meta (.getParameterMetaData stmt)
|
|
type-name (.getParameterTypeName meta idx)]
|
|
(if-let [elem-type (when (= (first type-name) \_)
|
|
(apply str (rest type-name)))]
|
|
(.setObject stmt idx (.createArrayOf conn elem-type (to-array v)))
|
|
(.setObject stmt idx (->pgobject v))))))
|