camdez.com

Rule #1: There are no rules.

Dasherize HoneySQL Columns

| Comments

Well…Korma didn’t work out… There are lots of things to like about it, but I honestly can’t deal with the fact that when you join on a belongs-to relationship, it simply merges all of columns into a single map (:id-2?).

Anyway, I’ve moved on to HoneySQL for now. Which still features the_kind_of_attribute_names only a database could love. Let’s kick that to the curb.

First off, the input piece:

1
2
3
4
5
6
7
8
9
10
11
(ns camdez.blog.dasherize-honeysql
  (:require [honeysql.core :as sql]
            [honeysql.helpers :refer :all]
            [clojure.java.jdbc :as jdbc]
            [clojure.string :as str))

(-> (insert-into :muscle-cars)
    (values [{:name "1964 Pontiac GTO"
              :engine-displacement 389}])
    sql/format)
; => ["INSERT INTO muscle_cars (name, engine_displacement) VALUES (?, 389)" "1964 Pontiac GTO"]

Lo and behold! HoneySQL already has that one covered!

But if we fetch it back…

1
2
3
4
5
6
(jdbc/query db (-> (select :*)
                   (from :muscle-cars)
                   sql/format))
; => ({:id 1
;      :name "1964 Pontiac GTO"
;      :engine_displacement 389})

…ugly underscores.

The solution is that clojure.java.jdbc/query allows us to pass a function which is used to format the database column names on the way out. The default is just to call clojure.string/lower-case, so we’ll write a new function to do our dashification:

1
2
(defn- format-column-name [col]
  (-> col str/lower-case (str/replace "_" "-")))

Now let’s try again, passing our formatter:

1
2
3
4
5
6
7
(jdbc/query db (-> (select :*)
                   (from :muscle-cars)
                   sql/format)
            :identifiers format-column-name)
; => ({:id 1
;      :name "1964 Pontiac GTO"
;      :engine-displacement 389})

Perfect! Finally, since we always want to do this, let’s write our own query function to encapsulate the common elements:

1
2
3
4
5
6
7
8
(defn query [db honey]
  (jdbc/query db (sql/format honey) :identifiers format-column-name))

(query db (-> (select :*)
              (from :muscle-cars)))
; => ({:id 1
;      :name "1964 Pontiac GTO"
;      :engine-displacement 389})

Ahhhhh… Delicious kebab-case… :)

Comments