This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-06-16
Channels
- # admin-announcements (1)
- # announcements (1)
- # babashka (130)
- # beginners (120)
- # calva (11)
- # cider (5)
- # clj-kondo (9)
- # cljsrn (17)
- # clojure (63)
- # clojure-australia (1)
- # clojure-canada (21)
- # clojure-europe (37)
- # clojure-israel (4)
- # clojure-uk (6)
- # clojurescript (170)
- # conjure (5)
- # core-async (23)
- # cursive (16)
- # datomic (4)
- # defnpodcast (1)
- # emacs (5)
- # fulcro (1)
- # gis (2)
- # graalvm (31)
- # graphql (4)
- # helix (6)
- # honeysql (16)
- # jobs-discuss (3)
- # juxt (1)
- # lsp (7)
- # malli (20)
- # meander (12)
- # missionary (6)
- # off-topic (50)
- # pathom (4)
- # re-frame (4)
- # react (1)
- # ring (2)
- # shadow-cljs (63)
- # spacemacs (2)
- # sql (15)
- # testing (6)
- # vim (8)
- # xtdb (7)
I want to reset an Oracle expired password programmatically, which I can achieve using interop directly against java.sql.DriverManager, by calling DriverManager/getConnection and supplying a Properties "info" argument which contains the Oracle specific connection property "oracle.jdbc.newPassword". Is it possible to do this using next.jdbc?
@mark926 In theory, you can just add :oracle.jdbc.newPassword "newsecret"
to your db-spec hash map and when you first call get-connection
, that will happen.
When next.jdbc
processes a db-spec hash map, it extracts the parts it needs to build the JDBC URL itself and then builds a Properties
object with the rest of the hash map and passes it to the driver when creating that connection.
See https://github.com/seancorfield/next-jdbc/blob/develop/src/next/jdbc/connection.clj#L141-L146 — etc
is the “rest” of the db-spec hash map after the URL parts have been removed https://github.com/seancorfield/next-jdbc/blob/develop/src/next/jdbc/connection.clj#L162-L165
Is there a way to conveniently generate a record builder given a record type? There's probably some reflection-heavy way but I'd rather not go there if I can avoid it A way to generalize this https://github.com/seancorfield/next-jdbc/blob/develop/test/next/jdbc/result_set_test.clj#L382
I’d ask: why would you want to do that?
(but there’s always map->MyRecord
available for every record type which you could map
over the result set if you really must have records instead of hash maps)
Don't get me wrong, I don't really want to do that 🙂 It's a temporary measure meant to fix a bad design choice in a service which shouldn't even be using an in-memory sql db. I hope I can improve its performance that way, assuming building records instead of maps will be both faster and less GC intensive.
Just ended up wrapping defrecord
to emit the constructor
(defn emit-builder
[name fields]
(let [builder (symbol (str "->" name "Builder"))
rs (with-meta 'rs {:tag (.getName ResultSet)})
rsmeta (with-meta 'rsmeta {:tag (.getName ResultSetMetaData)})]
`(defn ~builder [~rs ~rsmeta]
(reify
rs/RowBuilder
(~'->row [_#] (new ~name [email protected](for [f (map str fields)] `(.getObject ~rs ~f))))
(~'column-count [_#] 0)
(~'with-column [_# row# _#] row#)
(~'with-column-value [_# row# _# _#] row#)
(~'row! [_# row#] row#)
rs/ResultSetBuilder
(~'->rs [_#] (transient []))
(~'with-row [_# ~'rs row#] (conj! ~rs row#))
(~'rs! [_# ~'rs] (persistent! ~rs))
clojure.lang.ILookup
(~'valAt [this# k#] (get this# k# nil))
(~'valAt [this# k# not-found#]
(case k#
:cols ~(mapv keyword fields)
:rsmeta ~rsmeta
not-found#))))))
(defmacro defsqlrecord
[name fields & opts]
(let [builder (symbol (str "->" name "Builder"))
adapter (symbol (str name "Adapter"))]
`(do
(defrecord ~name ~fields [email protected])
~(emit-builder name fields)
(def ~adapter (next-adapter/hugsql-adapter-next-jdbc
{:builder-fn ~builder}))
~name)))
Not building a result set is going to be faster — if you can use plan
and reduce
.
My commiserations 🙂