HoneySQL takes care of translating anything I write to the DB with :kebab-case to the matching sql snake_case form. In some applications I have a translation occurring in my read functions that converts the result keys into kebab-case, but sometimes this misses (e.g. when I’m not “reading” but getting the postgres result of a create action). What’s the simplest way of ensuring I’ve got kebab-case results in everything I see coming from the DB? Is it meticulously adding the conversion fn to each accessor, or is there some higher-level way?
That will depend on which JDBC wrapper you are using: both clojure.java.jdbc and next.jdbc support ways to automatically turn SQL entities in result sets into Clojure keywords. HoneySQL only generates the SQL – it does not execute it – so it doesn’t even see the result sets coming back.
In clojure.java.jdbc, you can specify the :identifiers option and provide a function that operates on the string that is the SQL entity name. The default value for this is clojure.string/lower-case.
In next.jdbc, there are a range of :builder-fn options in the next.jdbc.result-set namespace, including as-modified-maps and as-unqualified-modified-maps which accept :qualifier-fn and :label-fn options to operate on the qualifier (table name) and column label respectively.
There’s a great library called camel-snake-kebab which handles all sorts of translations related to this. That means you don’t need to write your own string manipulation.
I can verify that camel-snake-kebab is terrifically useful. And somehow I knew one answer would probably be next.jdbc
As I haven’t scoped out serious the change to our application stack would be with next instead of normal jdbc, though, I’m glad to hear that jdbc has a solution, too.
Which JDBC library are you using?
clojure.java.jdbc. It’s the one I learned from Luminus originally, and I’ve never changed.
Happy to help if you do decide to switch. This covers most of the basic differences: https://cljdoc.org/d/seancorfield/next.jdbc/1.0.462/doc/migration-from-clojure-java-jdbc
But clojure.java.jdbc is rock solid. We’ve used it in production for nine years and I’ve been keeping it maintained all that time. I didn’t want to make breaking changes to it, at this point, so next.jdbc is the “1.0” that I never quite got to with c.j.j. 
I’m having a bad time figuring out where that :identifiers option is supposed to be specified. Right now I setup a pool like so:
(defstate ^:dynamic *db*
:start {:datasource
(let [db (-> env :humforms :db)]
(hik/make-datasource db))}
:stop (hik/close-datasource (:datasource *db*)))
I thought I would add :identifiers to my db map there (which is the one that includes user credentials, pool information, etc) but I get
Execution error at com.zaxxer.hikari.util.PropertyElf/setProperty (PropertyElf.java:135).
Property identifiers does not exist on target class org.postgresql.ds.PGSimpleDataSource
Ugh! Mount 
What are you passing into the clojure.java.jdbc calls? *db*? If so, you should be able to add default settings into *db* at startup. Not db which is coming from your environment – which is the map passed to hik/make-datasource.
(defstate ^:dynamic *db*
:start {:identifiers csk/->kebab-case ; or whatever
:datasource
(let [db (-> env :humforms :db)]
(hik/make-datasource db))}
:stop (hik/close-datasource (:datasource *db*)))
You could also add :entities csk/->snake_case to default the behavior for c.j.j.'s insert/update etc.
Just wanted to revisit this and mention that as of 1.1.569, next.jdbc provides out-of-the-box support for camel-snake-kebab (if you have it on your classpath): https://github.com/seancorfield/next-jdbc/releases/tag/v1.1.569
That same release provides built-in support for Stuart Sierra’s Component library in the form of next.jdbc.connection/component which provides a Component wrapped around the ->pool function for building connection pooled datasources with HikariCP and c3p0. I guess Mount users could leverage ->pool here.
In the latest version (1.1.582), the ability to construct a JDBC URL has been directly exposed in next.jdbc.connection/jdbc-url so that you can construct a connection string easily that can then be passed to ->pool or component as a :jdbcUrl attribute. This allows for a cleaner separation of “db spec” attributes and connection pool parameters.
In addition, 1.1.569 (mentioned above) introduced next.jdbc/with-options which allows you to wrap a java.sql.DataSource with options, such as :builder-fn, :table-fn, :column-fn, so you can globally control case conversions (with some caveats – read the docs please!).
This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.