honeysql

Discussion of https://github.com/seancorfield/honeysql :slightly_smiling_face:
2021-03-03T04:48:47.065600Z

I tend to use the query data structure directly, personally. When the readme just shows how a helper is used, I usually evaluate it at the repl to see the structure of the map it returns.

borkdude 2021-03-03T12:26:04.066100Z

Does / should honeysql support inlining arrays?

(def sql (sql/format (-> (h/insert-into :users)
                         ;; (sql/columns :foo)
                         (h/values [{:foo (into-array [1 2 3])}]))
                     {:inline true}))
["INSERT INTO users (foo) VALUES ([Ljava.lang.Long;@34b3d918)"]

seancorfield 2021-03-03T17:22:37.066600Z

Does it work in v1 and just not in v2?

borkdude 2021-03-03T21:17:34.067300Z

@seancorfield Just tried with v1, same thing

seancorfield 2021-03-03T21:30:53.068100Z

There are some situations where HoneySQL expands collections and others where it assumes the JDBC library will handle the value.

seancorfield 2021-03-03T21:32:37.069500Z

Oh, is this just about inlining? What should an array inline into? And is it portable across other databases?

seancorfield 2021-03-03T21:32:56.069800Z

(I'm pretty sure the answer to 3) is "no")

borkdude 2021-03-03T21:40:52.070400Z

There is an ANSI array standard now. I tried this:

(def array-sql2
  (sql/format {:insert-into :foo
               :values [{:foo [:raw (format "array [%s]" (str/join "," [1 2 3]))]}]}))
and that worked, but I haven't tested with e.g. postgres

borkdude 2021-03-03T21:46:04.071200Z

can I do something like this?

:select [:raw "ARRAY['hello','bob','and','sally']"]
This comes back with: column :raw does not exist

rwstauner 2021-03-03T21:50:50.071500Z

i think there's a (sql/raw "...")

borkdude 2021-03-03T21:51:33.072400Z

Anyway, this seemed to work:

(pg/execute! db ["select ARRAY['hello','bob','and','sally'] from users limit 1"])
so I think the standard (ANSI) sql notation for arrays is ARRAY[1,2,3]. Maybe :inline could do that. More research needed probably.

seancorfield 2021-03-03T22:07:42.073800Z

{:select [[[:raw ...]]]} because SELECT takes a sequence of things, and those things can be aliases (which are wrapped in a sequence) and the thing you would alias is a function call [:raw ...]

seancorfield 2021-03-03T22:08:03.074300Z

That looks slightly less weird with the select helper but still a bit odd.

seancorfield 2021-03-03T22:08:16.074600Z

and in v2 there's :array

borkdude 2021-03-03T22:17:25.075500Z

confirming that :select [[[:raw "ARRAY['hello','bob','and','sally']"]]] works. also :select [[[:array [1 2 3]]]] works and also [:array (into-array [1 2 3])] works. TIL!

borkdude 2021-03-03T22:19:02.076600Z

I'm not sure how this would compose with :inline still, e.g. when you insert values. Can you do {:values [{:foo [:array [1 2 3]]}]}?

borkdude 2021-03-03T22:20:10.076800Z

it worked!

borkdude 2021-03-03T22:20:29.077100Z

(def sql (sql/format {:insert-into :foo
                      :values [{:foo [:array [1 2 3]]}]}
                     {:inline true}))
["INSERT INTO foo (foo) VALUES (ARRAY[1, 2, 3])"]

borkdude 2021-03-03T22:20:55.077300Z

This lib is truly amazing ;)

❤️ 2
seancorfield 2021-03-03T22:25:44.078Z

Yeah, :inline knows how to inline basic stuff: strings, numbers, booleans, but not much else.

seancorfield 2021-03-03T22:27:42.079300Z

Since [:array [1 2 3]] itself expands to ARRAY[?, ?, ?] and params, then :inline can handle it (by just inlining those numbers back into the SQL).