honeysql 2024-11-22

Anyone have some guidance on how to extend honey-sql operators with respect to NOT BETWEEN? Currently I’ve done:

{:select [:*]
  :from   [:orders]
  :where  [:not
           [[:between :amount 100 500]]]}
Which formats to:
SELECT *
   FROM orders
  WHERE NOT (amount BETWEEN 100 AND 500)
But, ideally I’d like it to be:
SELECT *
  FROM orders
  WHERE amount NOT BETWEEN 100 AND 500
Perhaps I’m being a little too picky, but I’m mostly just curious. Thanks in advance.

I would most definitely just use [:not [:between ...]]. So, you don't need those extra [...]. But you can register custom clauses with honey.sql/register-clause!.

✅ 1

I ended up doing:

(honey/register-fn!
    :not-between
    (fn [_ [x a b]]
      (let [[sql-x & params-x] (honey/format-expr x {:nested true})
            [sql-a & params-a] (honey/format-expr a {:nested true})
            [sql-b & params-b] (honey/format-expr b {:nested true})]
        (-> [(str sql-x " NOT BETWEEN " sql-a " AND " sql-b)]
            (into params-x)
            (into params-a)
            (into params-b)))))

So it’s now:

(-> {:select [:*], :from [:orders], :where [:not-between :amount 100 500]}
      (honey/format {:inline true}))
;;==> ["SELECT * FROM orders WHERE amount NOT BETWEEN 100 AND 500"]

10 lines of code to replace [:not [:between ...]] with [:not-between ...]. :)

I know I’m being a little much 🙂

Create a GH issue and I'll add it to core. NOT BETWEEN is a reasonable bit of syntax -- I just didn't know about it when I implemented BETWEEN 🙂