Fork me on GitHub
#sql
<
2022-01-07
>
Eugen07:01:51

I saw the datafy ns - but don't know how to use it

seancorfield07:01:39

@eugen.stan It depends what you want to do. https://cljdoc.org/d/com.github.seancorfield/next.jdbc/1.2.761/doc/migration-from-clojure-java-jdbc#processing-database-metadata shows how to get metadata via interop but, personally, I tend to rely on the datafy/nav stuff via Portal (I used to use Cognitect's REBL for that).

hiredman19:01:06

I don't recall seeing portal before, very neat, works with my "jvm on vm and browser on local machine" dev setup

1
Eugen08:01:02

thanks, interop is fine until I get more familiar with this

Eugen08:01:16

clj꞉calcite-clj.simple꞉> 
[{:REF_GENERATION nil,
  :SELF_REFERENCING_COL_NAME nil,
  :TABLE_CAT nil,
  :TYPE_CAT nil,
  :TYPE_SCHEM nil,
  :REMARKS nil,
  :TYPE_NAME nil,
  :TABLE_SCHEM "SALES",
  :TABLE_TYPE "TABLE",
  :TABLE_NAME "DEPTS"}
 {:REF_GENERATION nil,
  :SELF_REFERENCING_COL_NAME nil,
  :TABLE_CAT nil,
  :TYPE_CAT nil,
  :TYPE_SCHEM nil,
  :REMARKS nil,
  :TYPE_NAME nil,
  :TABLE_SCHEM "SALES",
  :TABLE_TYPE "TABLE",
  :TABLE_NAME "EMPS"}]
😄

Cora (she/her)23:01:16

soooo if I wanted to use update! where one of the values is an expression... is that possible? or do I need to run execute-one! with sql building instead

Cora (she/her)23:01:46

where by expression I mean COALESCE(submitted_at, now())

Cora (she/her)23:01:43

it seems like I need to fall back on execute-one!

seancorfield23:01:20

That's why HoneySQL exists 🙂

seancorfield23:01:02

dev=> (sql/format (-> (h/update :table) (h/set {:foo [:coalesce :submitted_at [:now]]}) (h/where [:= :id 100])))
["UPDATE table SET foo = COALESCE(submitted_at, NOW()) WHERE id = ?" 100]
But, yeah, next.jdbc.sql/update! is deliberately a very simple "SQL builder".

seancorfield23:01:41

Some people prefer the symbolic form -- it's a bit more datalog-y:

dev=> (sql/format '{update table set {foo (coalesce submitted_at (now))} where (= id 100)})
["UPDATE table SET foo = COALESCE(submitted_at, NOW()) WHERE id = ?" 100]

Cora (she/her)23:01:47

yeah, I just switched to honeysql for this part

Cora (she/her)23:01:32

whoa, that symbolic form is interesting

Cora (she/her)23:01:48

is there a way to not hard-code values?

seancorfield23:01:56

You could do it all with keywords and vectors.

Cora (she/her)23:01:53

how do you mean?

Cora (she/her)23:01:21

I was meaning since it's quoted you can't use bindings in the sql

seancorfield23:01:22

dev=> (let [id 123]
 #_=>   (sql/format {:update :table :set {:foo [:coalesce :submitted_at [:now]]} :where [:= :id id]}))
["UPDATE table SET foo = COALESCE(submitted_at, NOW()) WHERE id = ?" 123]

Cora (she/her)23:01:23

(let [i 200]
  (hsql/format '{update table set {foo (coalesce submitted_at (now))} where (= id i)}))

Cora (she/her)23:01:51

oh, is there a function in honeysql to convert {:id 1 :status_id 2} to [:and [:= :id 1] [:= :status_id 2]] ?

Cora (she/her)23:01:15

it's simple enough to write yourself but if there's something that already exists I'd rather just use that

Cora (she/her)23:01:42

(hsqlh/where (reduce-kv (fn [where col val]
                          (conj where [:= col val]))
                        [:and]
                        where-map))

seancorfield23:01:05

Oh, that's an interesting idea! Feel free to create an issue.

seancorfield23:01:28

BTW, you can mix'n'match the keyword and symbol versions:

dev=> (let [id 123] (sql/format {:update :table :set '{foo (coalesce submitted_at (now))} :where [:= :id id]}))
["UPDATE table SET foo = COALESCE(submitted_at, NOW()) WHERE id = ?" 123]

Cora (she/her)23:01:45

oh, interesting

Cora (she/her)23:01:49

that makes sense

seancorfield23:01:23

And of course you could always do something awful like this:

dev=> (let [id 123] (sql/format (update '{update table set {foo (coalesce submitted_at (now))} where (= id)} 'where concat [id])))
["UPDATE table SET foo = COALESCE(submitted_at, NOW()) WHERE id = ?" 123]
don't try this at home kids!

seancorfield23:01:16

A more datalog-y approach is to use named parameters:

dev=> (sql/format '{update table set {foo (coalesce submitted_at (now))} where (= id ?id)} {:params {:id 123}})
["UPDATE table SET foo = COALESCE(submitted_at, NOW()) WHERE id = ?" 123]

seancorfield23:01:07

(I kinda like that version)

Cora (she/her)23:01:50

huh, yeah, that's nice

Cora (she/her)23:01:11

is count on a vec O(1)?