-
Notifications
You must be signed in to change notification settings - Fork 14
/
core.clj
120 lines (100 loc) · 3.69 KB
/
core.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
(ns jdbc-ring-session.core
(:require [clojure.java.jdbc :as jdbc]
[taoensso.nippy :as nippy]
[ring.middleware.session.store :refer :all])
(:import java.util.UUID
org.apache.commons.codec.binary.Base64))
(defn serialize-mysql [value]
(nippy/freeze value))
(defn serialize-postgres [value]
(nippy/freeze value))
(defn serialize-oracle [value]
(-> value nippy/freeze Base64/encodeBase64))
(defn serialize-h2 [value]
(nippy/freeze value))
(defn serialize-sqlserver [value]
(nippy/freeze value))
(defn deserialize-mysql [value]
(when value
(nippy/thaw value)))
(defn deserialize-postgres [value]
(when value
(nippy/thaw value)))
(defn deserialize-oracle [blob]
(when blob
(-> blob (.getBytes 1 (.length blob)) Base64/decodeBase64 nippy/thaw)))
(defn deserialize-h2 [value]
(when value
(nippy/thaw value)))
(defn deserialize-sqlserver [value]
(when value
(nippy/thaw value)))
(def serializers
{:mysql serialize-mysql
:postgres serialize-postgres
:oracle serialize-oracle
:h2 serialize-h2
:sqlserver serialize-sqlserver})
(def deserializers
{:mysql deserialize-mysql
:postgres deserialize-postgres
:oracle deserialize-oracle
:h2 deserialize-h2
:sqlserver deserialize-sqlserver})
(defn detect-db [db-spec]
(let [db-name (with-open [conn (jdbc/get-connection db-spec)]
(.. conn getMetaData getDatabaseProductName toLowerCase))]
(cond
(.contains db-name "oracle") :oracle
(.contains db-name "postgres") :postgres
(.contains db-name "mysql") :mysql
(.contains db-name "h2") :h2
(.contains db-name "sql server") :sqlserver
:else (throw (Exception. (str "unrecognized DB: " db-name))))))
(defn read-session-value [datasource table deserialize key]
(jdbc/with-db-transaction [conn datasource]
(-> (jdbc/query conn [(str "select value from " (name table) " where session_id = ?") key])
first :value deserialize)))
(defn update-session-value! [conn table serialize key value]
(jdbc/with-db-transaction [conn conn]
(let [data {:idle_timeout (:ring.middleware.session-timeout/idle-timeout value)
:absolute_timeout (:ring.middleware.session-timeout/absolute-timeout value)
:value (serialize value)}
updated (jdbc/update! conn table data ["session_id = ? " key])]
(when (zero? (first updated))
(jdbc/insert! conn table (assoc data :session_id key)))
key)))
(defn insert-session-value! [conn table serialize value]
(let [key (str (UUID/randomUUID))]
(jdbc/insert!
conn
table
{:session_id key
:idle_timeout (:ring.middleware.session-timeout/idle-timeout value)
:absolute_timeout (:ring.middleware.session-timeout/absolute-timeout value)
:value (serialize value)})
key))
(deftype JdbcStore [datasource table serialize deserialize]
SessionStore
(read-session
[_ key]
(read-session-value datasource table deserialize key))
(write-session
[_ key value]
(jdbc/with-db-transaction [conn datasource]
(if key
(update-session-value! conn table serialize key value)
(insert-session-value! conn table serialize value))))
(delete-session
[_ key]
(jdbc/delete! datasource table ["session_id = ?" key])
nil))
(ns-unmap *ns* '->JdbcStore)
(defn jdbc-store
""
[db-spec & [{:keys [table serialize deserialize]
:or {table :session_store}}]]
(let [db-type (detect-db db-spec)
serialize (or serialize (serializers db-type))
deserialize (or deserialize (deserializers db-type))]
(JdbcStore. db-spec table serialize deserialize)))