A discussion I had today (elsewhere) made me wonder if I could make the quoted symbolic form of HoneySQL queries easier to use. You can write '{select * from users where (= status "approved")} today and it formats the same as the (longer) keyword version: {:select :* :from :users :where [:= :status "approved"]} -- but it's hard to use variables/parameters with the quoted form, compared to the keyword form. Sure, you can use ?name and then provide an options hash map with {:params {:name "whatever"}} but that's quite a bit of extra typing.
I figured it might be nicer to have something like (sql/formatf '{select * from users where (= username ?1)} "whatever") and have it "do the right thing", i.e., construct an appropriate {:params {...}} hash map for you.
I created https://github.com/seancorfield/honeysql/issues/495 for feedback/discussion and implemented a basic version of formatf, currently undocumented. You can try it out via the latest develop SHA on GitHub or as a snapshot version 2.4.9999-SNAPSHOT
I guess there are two questions:
• Is this actually useful enough to add at all?
• How would folks expect/want to see options being passed into a variadic function like that and how/would you care about parameters that are hash maps potentially conflicting with an options hash map?
The latter Q is in the issue.
I continue to worry away at this particular problem (that, it seems, very few other people care about! 🙂 ) and tonight added another experimental possible solution: https://github.com/seancorfield/honeysql/blob/develop/src/honey/sql.cljc#L2104-L2131
I like formatv better because it is explicit:
... some code that sets up the user-name binding ...
(sql/formatv [user-name] '{select * from users where (= username user-name)})
This uses clojure.template/apply-template behind the scenes to replace the declared symbol (`user-name`) with its locally bound value in the DSL.
format& exists too -- it replaces all locally bound symbols in the DSL which may or may not be a good idea.
formatf still exists, which lets you use ?1, ?2 as positional parameters and then you provide the parameters as trailing arguments (but it doesn't support formatting options -- whereas formatv and format& do).