sql

All things SQL and JDBC...
Mark Mac 2021-06-16T16:00:53.222300Z

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?

seancorfield 2021-06-16T16:06:35.223300Z

@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.

seancorfield 2021-06-16T16:07:38.224400Z

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.

seancorfield 2021-06-16T16:09:05.225Z

See https://github.com/seancorfield/next-jdbc/blob/develop/src/next/jdbc/connection.clj#L141-L146etc 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

Ben Sless 2021-06-16T17:04:08.226800Z

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

seancorfield 2021-06-16T17:07:54.227300Z

I’d ask: why would you want to do that?

seancorfield 2021-06-16T17:09:29.228300Z

(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)

Mark Mac 2021-06-16T17:15:19.228400Z

That worked, thought I'd tried that - but obv hadn't got it quite right - thanks

1
Ben Sless 2021-06-16T17:20:34.231200Z

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.

Ben Sless 2021-06-16T17:22:45.231700Z

which means I would ideally like to avoid the map->Record constructor

Ben Sless 2021-06-16T17:35:47.232400Z

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 ~@(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 ~@opts)
       ~(emit-builder name fields)
       (def ~adapter (next-adapter/hugsql-adapter-next-jdbc
                      {:builder-fn ~builder}))
       ~name)))

seancorfield 2021-06-16T17:48:29.232800Z

Not building a result set is going to be faster — if you can use plan and reduce.

Ben Sless 2021-06-16T17:51:47.233900Z

true, that will be the next step, but it will require a more involved solution

seancorfield 2021-06-16T18:01:20.234100Z

My commiserations 🙂

Ben Sless 2021-06-16T18:02:32.234500Z

I've seen things you would not believe 🙂

1