honeysql

Discussion of https://github.com/seancorfield/honeysql :slightly_smiling_face:
mkurtak 2020-09-08T17:29:34.000600Z

Hello. I am trying to figure out how to insert enum values in PostgreSQL with next.jdbc and honeysql. Everything works fine when I use plain next.jdbc with calling as-other as described here: https://github.com/seancorfield/next-jdbc/blob/develop/doc/tips-and-tricks.md#working-with-enumerated-types But I am not able to insert enum with honeysql

mkurtak 2020-09-08T17:29:45.000900Z

(-> (h/insert-into :table)
    (h/values (map #(update :enum-field (comp jdbc-types/as-other name)) records))
    (hsql/format))
[3:24 PM] this code throws exception java.lang.AssertionError Assert failed: Alias should have two parts

seancorfield 2020-09-08T17:45:03.001600Z

@michal.kurtak Shouldn't there be a % in that anon function?

seancorfield 2020-09-08T17:45:29.002100Z

(map #(update % :enum-field (comp jdbc-types/as-other name)) records)

mkurtak 2020-09-08T17:53:20.003500Z

sory this is just a copy from real code, where is i use threading macro

seancorfield 2020-09-08T17:53:27.003700Z

@michal.kurtak OK, I've repro'd and I think you're running into this known bug https://github.com/seancorfield/honeysql/issues/267

seancorfield 2020-09-08T17:55:28.005500Z

I haven't yet figured out the best solution for this. The problem is that the jdbc-types/as-* functions have to wrap the value in a vector so metadata can be applied (so a custom set-parameter implementation is used), but HoneySQL doesn't like vector values due to a bug in how it tries to parse hash maps.

mkurtak 2020-09-08T17:55:46.005700Z

(defn- scrape->row
  [scrape]
  (-> scrape
      (update :scrape/artists (partial into-array String))
      (update :scrape/web-scraper (comp jdbc-types/as-other name))))
(defn insert-scrapes!
  [db scrapes]
  (db/execute! db (-> (h/insert-into :scrape)
                      (h/values (map scrape->row scrapes))
                      (hsql/format))))

mkurtak 2020-09-08T17:55:51.005900Z

this is the full code

mkurtak 2020-09-08T17:56:10.006100Z

hmm

mkurtak 2020-09-08T17:56:42.006800Z

i have workaround it without honeysql

mkurtak 2020-09-08T17:56:45.007Z

(defn insert-scrapes-no-honey!
  [db scrapes]
  (let [columns [:scrape/external-ref-id
                 :scrape/title
                 :scrape/artists
                 :scrape/url
                 :scrape/description
                 :scrape/published
                 :scrape/rating
                 :scrape/web-scraper]
        rows (->> scrapes
                  (map scrape->row)
                  (map (apply juxt columns))
                  (vec))]
    (jdbc-sql/insert-multi! db :scrape columns rows jdbc/snake-kebab-opts)))

seancorfield 2020-09-08T17:57:54.007900Z

You could simplify that, I think, with columns (keys (first scrapes)) ?

seancorfield 2020-09-08T17:58:12.008400Z

(assuming your maps always contain all those keys and only those keys)

seancorfield 2020-09-08T17:59:03.009700Z

I personally don't find HoneySQL adds much value for inserts but it is definitely a bug that it fails to handle vector values in hash maps in values.

mkurtak 2020-09-08T18:00:10.010400Z

well, there are other keys in scrape so i cannot use this simplification

mkurtak 2020-09-08T18:02:33.010900Z

and what about the recommendation you’ve gave in the issue? “Can you try using `{:identifier 123 :genres #sql/array ["Genre"]}`, which should generate”

seancorfield 2020-09-08T18:42:55.011600Z

That would help for :scrape/artists which you are passing as an array, but it won't help for as-other

seancorfield 2020-09-08T18:43:30.012100Z

It's just a bug in HoneySQL that I need to figure out how to fix (without breaking anything else).

seancorfield 2020-09-08T18:44:00.012600Z

My recommendation for now is: use next.jdbc directly for inserts.

mkurtak 2020-09-08T20:23:48.014200Z

Ok, i understand and will use next.jdbc for inserts. Thank you for your help