I’ve working with a codebase on honeysql1, and need to stick with it for the time being, so can’t easily in this case use honeysql2 and honeysql1 side by side.
I’d like to add a case statement - is there a better way than sql/raw "case when a = 1 then b when a = 2 then c end"?
can’t easily in this case use honeysql2 and honeysql1 side by side.Depends on what you mean by "easily".
You can always require them with different aliases and pass them to different formatting/querying functions, depending on how you've implemented your DB layer. Or you can use only sql/format from v2 and have your query functions accept not only HoneySQL maps but also vectors that are created by formatting functions. Then every v1 code branch would use something like (query conn sqlmap-v1) and every v2 branch would use (query conn (sql/format sqlmap-v2)).
As for the CASE question - in v1 it's done via a fn call:
user=> (sql/format {:select [(sql/call :case [:= :a 1] :b [:= :a 2] :c)]})
["SELECT CASE WHEN a = ? THEN b WHEN a = ? THEN c END" 1 2]Ah thanks - I appreciate the v1 code. I like the migration idea you suggested, too thanks, sounds like a good way of handling it.
The v2 version deliberately uses both different namespaces and a different artifact name so you can indeed use both side-by-side and migrate your code from v1 to v2, one query at a time. We use both versions at work and are slowly migrating old HoneySQL code this way.
Our queries stay as maps and go all through a central execute function which does the formatting, so it wasn't immediately obvious how to do one by one - but it looks like we could use the strategy that @p-himik describes. Thanks for considering the migration path!
Yeah, I consider combining formatting and querying like that to be an anti-pattern since it complects the operations and makes it harder to switch libraries.
But, yeah, allowing your "central execute function" to accept either a hash map (and use v1 format) or a vector (SQL + params, produced by a v2 call "above") seems like a good approach, especially since it will then decomplect the query-running from the formatting over time.
It's also worth noting that most of the underlying DSL-as-data has not changed between v1 and v2 so you can use the new v2 helpers to simplify things (v1 had both join and merge-join and where and merge-where etc, whereas v2 just has smart join and where helpers that handle both cases).
Note also that there is a (deliberately undocumented) call function in v2 so many instances of v1's sql/call will continue to work with v2 -- and it just makes a vector under the hood -- so your (sql/call :case ...) would work for both v1 and v2.