honeysql

Discussion of https://github.com/seancorfield/honeysql :slightly_smiling_face:
bertofer 2018-09-12T11:44:05.000100Z

Hi, is there a way to use boolean expressions in select statements in honeysql? like select (a.numeric_field > 100) AS over_threshold

seancorfield 2018-09-12T16:12:07.000100Z

@bertofer I think you have to use #sql/call in there, like this:

user=> (require '[honeysql.helpers :refer :all] '[honeysql.core :as h] '[honeysql.types :as sql])
...
nil
user=> (h/format (select [#sql/call [:> :a 100] :threshold]))
["SELECT a > ? AS threshold" 100]
user=> 

seancorfield 2018-09-12T16:17:02.000100Z

(without the #sql/call you get SELECT > AS a AS threshold which is obviously wrong -- and should at least blow up with an assert in the next version -- but ideally should not treat the expression as an alias in that position either!)

bertofer 2018-09-12T19:15:45.000100Z

Yes is what I ended up doing, thanks @seancorfield! I was doing it like a fn call though, like (sql/call :> :a 100), can you explain what is the difference with #sql/call [:> :a 100]? What’s the meaning of # here? I’m a bit new to clojure yet πŸ™‚

seancorfield 2018-09-12T20:14:00.000100Z

@bertofer # indicates a reader literal so #sql/call [:> :a 100] says "read the following form -- [:> :a 100] -- and treat it as a "sql/call" object...

bertofer 2018-09-12T20:15:29.000100Z

Okei, thanks ! πŸ™‚

seancorfield 2018-09-12T20:16:26.000100Z

The reader doesn't evaluate forms:

user=> #sql/call [:> (keyword "a") (* 10 10)]
#sql/call [:> (keyword "a") (* 10 10)]
user=> (h/format *1)
["keyword(?) > (? * ?)" "a" 10 10]
user=> (sql/call :> (keyword "a") (* 10 10))
#sql/call [:> :a 100]
user=> (h/format *1)
["a > ?" 100]
user=> 

seancorfield 2018-09-12T20:17:07.000100Z

There are pros and cons to both approaches.

seancorfield 2018-09-12T20:18:35.000100Z

For example

user=> #sql/call [:> :a (* :b 10)]
#sql/call [:> :a (* :b 10)]
user=> (h/format *1)
["a > (b * ?)" 10]
user=> 
lets you lift the 10 out as a parameter and treat :b as a column name -- so the multiplication is done in SQL.

πŸ‘ 1
seancorfield 2018-09-12T20:19:15.000100Z

(sql/call :> :a (* :b 10)) will fail trying to evaluate :b times 10 πŸ™‚

πŸ‘ 1