This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-08-29
Channels
- # aleph (5)
- # announcements (2)
- # bangalore-clj (2)
- # beginners (52)
- # cider (10)
- # cljsrn (1)
- # clojure (160)
- # clojure-dev (24)
- # clojure-europe (3)
- # clojure-france (1)
- # clojure-india (1)
- # clojure-italy (3)
- # clojure-nl (6)
- # clojure-spec (13)
- # clojure-uk (51)
- # clojurescript (45)
- # code-reviews (1)
- # core-async (41)
- # cursive (41)
- # datomic (17)
- # emacs (37)
- # fulcro (42)
- # graphql (7)
- # joker (4)
- # music (1)
- # nrepl (2)
- # off-topic (21)
- # pathom (19)
- # pedestal (12)
- # re-frame (48)
- # reitit (6)
- # rewrite-clj (8)
- # shadow-cljs (41)
- # specter (6)
- # sql (21)
- # tools-deps (8)
- # vim (7)
- # xtdb (27)
(let [result (sql/query @db/spec
[ "SELECT
tags.tag_id,
post_tags.base_value
FROM post_tags
INNER JOIN tags ON post_tags.tag_id=tags.tag_id
WHERE post_tags.post_id IN ?"
(vec post-ids)])]
I'm having trouble with array parameters and jdbc-next? Is this possible at all? I've heard that using parameterised statements with ?
makes things a lot safer so I'm a little uncomfortable concatonating a string together if I can get this to work? (`post-ids` is a lazy-seq, I tried a set and vector too)
I get the error:
org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of clojure.lang.PersistentVector. Use setObject() with an explicit Types value to specify the type to use.
at org.postgresql.jdbc.PgPreparedStatement.setObject(PgPreparedStatement.java:955)
at next.jdbc.prepare$eval7663$fn__7664.invokePrim(prepare.clj:36)
at next.jdbc.prepare$eval7663$fn__7664.invoke(prepare.clj)
at next.jdbc.prepare$eval7642$fn__7643$G__7633__7652.invoke(prepare.clj:23)
sadly you need to construct the ? placeholders individually
this is why people use things like honeysql
could I maybe use apply
?
hmm no
if you are using apply to construct a string containing multiple "?", sure :D
You have to have a ?
for each element of the vector
that's what I meant, yeah
yeah, well I'll write it in a concatted string for now and I might move to honeysql and tidy up my backened later 🙂
(into [(str "SELECT ... IN (" (clojure.string/join "," (repeat (count post-ids) "?") ")")] post-ids)
okay, let me try that ,
that was quick hahaah
This is still safe because you're using parameters ?
It's quick because it's a common SQL question and I write that code several times a week 🙂
HoneySQL lets you just say (where ... [:in post_tags.post_id post-ids])
as I recall.
I guess you could have (defn place-fill [coll] (string/join "," (repeat (count coll) "?")))
(! 657)-> clj -Sdeps '{:deps {honeysql {:mvn/version "RELEASE"}}}'
Clojure 1.10.1
user=> (require '[honeysql.helpers :refer :all] '[honeysql.core :refer [format]])
...
nil
user=> (def post-ids (range 20))
#'user/post-ids
user=> (-> (select :tags.tag_id :post_tags.base_value) (from :post_tags) (join :tags [:= :post_tags.tag_id :tags.tag_id]) (where [:in :post_tags.post_id post-ids]) (format))
["SELECT tags.tag_id, post_tags.base_value FROM post_tags INNER JOIN tags ON post_tags.tag_id = tags.tag_id WHERE (post_tags.post_id in (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?))" 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
user=>
Like soSorry wasn't ignoring you I was just implementing it 🙂 Thank you for your help as always you guys!
its working, thank you!
For postgres, you should use select ... from ... where id = ANY(?)
, then send a long-array
as the value for the ?
@isak Thank you that actually worked nicely as well! So our tags are now entirely from the database now 🙂