Skip to content

Instantly share code, notes, and snippets.

@ikitommi
Last active Apr 5, 2020
Embed
What would you like to do?
Postgres key transformations
(ns postgres)
(require '[clojure.string :as str])
(require '[malli.core :as m])
(require '[malli.transform :as mt])
(defn -transform-keys [f m]
(reduce-kv
(fn [acc k v] (assoc acc (f k) v))
(empty m)
m))
(def upper-keys (partial -transform-keys (comp keyword str/upper-case name)))
(def lower-keys (partial -transform-keys (comp keyword str/lower-case name)))
;;
;; named property-driven transformations
;;
(def my-schema
(m/schema
[:map {:closed true
:encode/postgres upper-keys
:decode/postgres lower-keys}
[:id {:optional true
:postgres/type :bigserial
:postgres/key :primary} int?]
[:instrument-id {:postgres/type :bigint
:postgres/null? false} int?]]))
(def postgres-transformer (mt/transformer {:name :postgres}))
(m/encode my-schema {:id 1, :instrument-id 2} postgres-transformer)
; => {:ID 1, :INSTRUMENT-ID 2}
(m/decode my-schema {:ID 1, :INSTRUMENT-ID 2} postgres-transformer)
; => {:id 1, :instrument-id 2}
;;
;; named transformations
;;
(def my-schema
(m/schema
[:map {:closed true
:postgres/type :table}
[:id {:optional true
:postgres/type :bigserial
:postgres/key :primary} int?]
[:instrument-id {:postgres/type :bigint
:postgres/null? false} int?]]))
(def postgres-transformer
(let [t (fn [f] {:compile (fn [schema _]
(when (-> schema m/properties :postgres/type (= :table)) f))})]
(mt/transformer
{:name :postgres
:decoders {:map (t lower-keys)}
:encoders {:map (t upper-keys)}})))
(m/encode my-schema {:id 1, :instrument-id 2} postgres-transformer)
; => {:ID 1, :INSTRUMENT-ID 2}
(m/decode my-schema {:ID 1, :INSTRUMENT-ID 2} postgres-transformer)
; => {:id 1, :instrument-id 2}
;; no-op for other schemas
(m/decoder [:map [:x int?]] postgres-transformer)
; => #object[clojure.core$identity]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment