While there is nothing wrong with putting SQL in strings, many reasonable features will require you to dynamically produce those strings based on user input.
honeysql
to your deps.edn
.{:paths ["src"]
:deps {org.clojure/clojure {:mvn/version "1.12.0"}
ring/ring {:mvn/version "1.13.0"}
metosin/reitit-ring {:mvn/version "0.5.5"}
org.clojure/tools.logging {:mvn/version "1.3.0"}
org.slf4j/slf4j-simple {:mvn/version "2.0.16"}
hiccup/hiccup {:mvn/version "2.0.0-RC3"}
com.github.seancorfield/next.jdbc {:mvn/version "1.3.955"}
org.postgresql/postgresql {:mvn/version "42.7.4"}
com.zaxxer/HikariCP {:mvn/version "5.1.0"}
io.github.cdimascio/dotenv-java {:mvn/version "3.0.0"}
ring/ring-defaults {:mvn/version "0.5.0"}
msolli/proletarian {:mvn/version "1.0.86-alpha"}
cheshire/cheshire {:mvn/version "5.13.0"}
com.github.seancorfield/honeysql {:mvn/version "2.6.1203"}}
:aliases {:dev {:extra-paths ["dev" "test"]
:extra-deps {nrepl/nrepl {:mvn/version "1.2.0"}
lambdaisland/kaocha {:mvn/version "1.91.1392"}}}
:format {:deps {dev.weavejester/cljfmt {:mvn/version "0.13.0"}}}
:lint {:deps {clj-kondo/clj-kondo {:mvn/version "2024.09.27"}}}}}
honey.sql/format
, replace the query for inserting hominid
sNothing special about this one, but this example project doesn't have a killer use for dynamic SQL yet. It should suffice to show how it's done. Refer to honeysql's documentation for more info.
(ns example.cave.jobs
(:require [example.system :as-alias system]
[honey.sql :as sql]
[next.jdbc :as jdbc])
(:import (java.util UUID)))
(set! *warn-on-reflection* true)
(defn process-cave-insert
[{::system/keys [db]} _job-type payload]
(jdbc/execute!
db
(sql/format
{:insert-into :prehistoric/hominid
:values [{:name "Grunk"
:cave_id (UUID/fromString (:id payload))}]})))
(defn handlers
[]
{:prehistoric.cave/insert #'process-cave-insert})