/
jdbc.clj
164 lines (129 loc) · 5.15 KB
/
jdbc.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
(ns datumbazo.driver.next.jdbc
(:require [clojure.set :as set]
[clojure.string :as str]
[datumbazo.driver.core :as d]
[datumbazo.io :as io]
[datumbazo.util :as util]
[next.jdbc :as jdbc]
[next.jdbc.prepare :as jdbc.prepare]
[next.jdbc.result-set :as jdbc.result-set])
(:import [java.sql Connection PreparedStatement]))
(defn kebab [s]
(str/replace s #"_" "-"))
(defn as-kebab-maps [rs opts]
(jdbc.result-set/as-modified-maps rs (assoc opts :qualifier-fn kebab :label-fn kebab)))
(defn as-unqualified-kebab-maps [rs opts]
(jdbc.result-set/as-unqualified-modified-maps rs (assoc opts :label-fn kebab)))
(defn- rename-update-count [row]
(set/rename-keys row {:next.jdbc/update-count :count}))
(defrecord Driver [config ^Connection connection]
d/Connectable
(-connect [this db opts]
(->> (or connection
(jdbc/get-connection
(or (:datasource db)
{:classname (:classname db)
:dbname (:name db)
:dbtype (name (:scheme db))
:host (:server-name db)
:password (:password db)
:port (:server-port db)
:user (:username db)})))
(assoc this :connection)))
(-connection [this db]
connection)
(-disconnect [this db]
(some-> connection .close)
(assoc this :connection nil))
d/Executeable
(-execute-all [this db sql opts]
(->> (jdbc/execute! connection sql (merge config opts))
(mapv rename-update-count)))
(-execute-one [this db sql opts]
(->> (jdbc/execute! connection sql (merge config opts))
(mapv rename-update-count)))
d/Preparable
(-prepare [this db sql opts]
(jdbc/prepare connection sql (merge config opts)))
d/Transactable
(-transact [this db f opts]
(jdbc/transact (:connection this) #(f (assoc-in db [:driver :connection] %)) (merge config opts))))
(defmethod d/driver :next.jdbc
[db & [opts]]
(map->Driver {:config (:next.jdbc db)}))
(extend-protocol jdbc.result-set/ReadableColumn
java.sql.Date
(read-column-by-label [val _]
(io/decode-date val))
(read-column-by-index [val _ _]
(io/decode-date val))
java.sql.Timestamp
(read-column-by-label [val _]
(io/decode-date val))
(read-column-by-index [val _ _]
(io/decode-date val)))
(extend-protocol jdbc.prepare/SettableParameter
clojure.lang.BigInt
(set-parameter [^clojure.lang.BigInt v ^PreparedStatement ps ^long i]
(.setObject ps i v))
java.util.Date
(set-parameter [^java.util.Date v ^PreparedStatement ps ^long i]
(.setTimestamp ps i (java.sql.Timestamp. (.getTime v))))
java.time.Instant
(set-parameter [^java.time.Instant v ^PreparedStatement ps ^long i]
(.setTimestamp ps i (java.sql.Timestamp/from v)))
java.time.LocalDate
(set-parameter [^java.time.LocalDate v ^PreparedStatement ps ^long i]
(.setTimestamp ps i (java.sql.Timestamp/valueOf (.atStartOfDay v))))
java.time.LocalDateTime
(set-parameter [^java.LocalDateTime v ^PreparedStatement ps ^long i]
(.setTimestamp ps i (java.sql.Timestamp/valueOf v))))
;; Joda Time
(util/with-library-loaded :joda-time
(extend-protocol jdbc.prepare/SettableParameter
org.joda.time.DateTime
(set-parameter [^org.joda.time.DateTime v ^PreparedStatement ps ^long i]
(.setTimestamp ps i (io/encode-timestamp v)))))
;; PostgreSQL
(util/with-library-loaded :postgresql
(extend-protocol jdbc.result-set/ReadableColumn
org.postgresql.jdbc.PgArray
(read-column-by-label [val _]
(io/decode-array val))
(read-column-by-index [val _ _]
(io/decode-array val))
org.postgresql.util.PGobject
(read-column-by-label [val _]
(io/decode-pgobject val))
(read-column-by-index [val _ _]
(io/decode-pgobject val))))
;; PostGIS
(util/with-library-loaded :postgis
(extend-protocol jdbc.result-set/ReadableColumn
org.postgis.PGgeo
(read-column-by-label [val _]
(io/decode-pggeometry val))
(read-column-by-index [val _ _]
(io/decode-pggeometry val)))
(extend-protocol jdbc.prepare/SettableParameter
org.postgis.LineString
(set-parameter [^org.postgis.LineString v ^PreparedStatement ps ^long i]
(.setObject ps i (io/encode-pggeometry v)))
org.postgis.LinearRing
(set-parameter [^org.postgis.LinearRing v ^PreparedStatement ps ^long i]
(.setObject ps i (io/encode-pggeometry v)))
org.postgis.MultiLineString
(set-parameter [^org.postgis.MultiLineString v ^PreparedStatement ps ^long i]
(.setObject ps i (io/encode-pggeometry v)))
org.postgis.MultiPoint
(set-parameter [^org.postgis.MultiPoint v ^PreparedStatement ps ^long i]
(.setObject ps i (io/encode-pggeometry v)))
org.postgis.MultiPolygon
(set-parameter [^org.postgis.MultiPolygon v ^PreparedStatement ps ^long i]
(.setObject ps i (io/encode-pggeometry v)))
org.postgis.Point
(set-parameter [^org.postgis.Point v ^PreparedStatement ps ^long i]
(.setObject ps i (io/encode-pggeometry v)))
org.postgis.Polygon
(set-parameter [^org.postgis.Polygon v ^PreparedStatement ps ^long i]
(.setObject ps i (io/encode-pggeometry v)))))