Created
January 15, 2019 15:10
-
-
Save codeasone/9a6cdfba83aabb84e02271b8e9964dec to your computer and use it in GitHub Desktop.
Coercion of namespaced keywords to and from postgresql enumerated types
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns clj-postgresql.enum | |
"Coerce Clojure keywords of the form :type/value to Postgres ENUM" | |
(:require [clj-postgresql.core :as pg] | |
[clojure.java.jdbc :as jdbc :refer [sql-value]] | |
[clojure.string :as s] | |
[clojure.test :refer :all]) | |
(:import org.postgresql.util.PGobject)) | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;; Writing | |
;; | |
(defn kw->pgenum [kw] | |
(let [type (-> (namespace kw) | |
(s/replace "-" "_")) | |
value (name kw)] | |
(doto (PGobject.) | |
(.setType type) | |
(.setValue value)))) | |
(extend-type clojure.lang.Keyword | |
jdbc/ISQLValue | |
(sql-value [kw] | |
(kw->pgenum kw))) | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;; Reading | |
;; | |
(def +schema-enums+ | |
"A set of all PostgreSQL enums in schema.sql. Used to convert | |
enum-values back into Clojure keywords." | |
#{"processing_status"}) | |
(extend-type String | |
jdbc/IResultSetReadColumn | |
(result-set-read-column [val rsmeta idx] | |
(let [type (.getColumnTypeName rsmeta idx)] | |
(if (contains? +schema-enums+ type) | |
(keyword (s/replace type "_" "-") val) | |
val)))) | |
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
;; Tests | |
;; | |
(deftest enum-handling-writing-to-db | |
(testing "when a valid value is used" | |
(testing "coercion of namespaced keywords to the DB works" | |
(jdbc/with-db-transaction [tx (pg/spec)] | |
(jdbc/insert! tx :files {:name "my-file.txt", :status :processing-status/pending})) | |
)) | |
(testing "when an invalid value is used" | |
(testing "coercion of namespaced keywords to the DB fail" | |
(jdbc/with-db-transaction [tx (pg/spec)] | |
(is (thrown? org.postgresql.util.PSQLException | |
(jdbc/insert! tx :files {:name "my-file.txt", :status :processing-status/unsupported})))) | |
))) | |
(deftest enum-handling-reading-from-db | |
(testing "coercion of string values for enumerated types in DB to keywords works" | |
(jdbc/with-db-transaction [tx (pg/spec)] | |
(is (= (first (jdbc/query tx ["SELECT * FROM files"])) | |
{:status :processing-status/pending, :name "my-file.txt"}))) | |
)) | |
;; Credits: https://www.bevuta.com/en/blog/using-postgresql-enums-in-clojure/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment