Fork me on GitHub
#sql
<
2021-03-09
>
fabrao04:03:23

hello all, I have a sequence in postgresql, is there any way to use this sequence with next/jdbc to do insert! without using insert as string?

jb recluse05:03:25

(jdbc/execute! ds ["create sequence my_seq start 1 increment 2"])
=> [#:next.jdbc{:update-count 0}]
(jdbc/execute! ds ["create table my_tbl (id int primary key, my_col varchar)"])
=> [#:next.jdbc{:update-count 0}]
(jdbc/execute! ds ["insert into my_tbl values (nextval('my_seq'), ?)" "foo"])
=> [#:next.jdbc{:update-count 1}]
(jdbc/execute! ds ["select * from my_tbl"])
=> [#:my_tbl{:id 1, :my_col "foo"}]
(jdbc/execute! ds ["insert into my_tbl values (nextval('my_seq'), ?)" "bar"])
=> [#:next.jdbc{:update-count 1}]
(jdbc/execute! ds ["select * from my_tbl"])
=> [#:my_tbl{:id 1, :my_col "foo"} #:my_tbl{:id 3, :my_col "bar"}]
not sure if i hit on the nuance you are looking for?

jb recluse05:03:58

oh, not even close, you wanted to use insert!

jb recluse05:03:17

it appears that insert! expects all the values to be sent as ?-params, which is not how using seqs in postgres works afaik. so i dont think you'll be able to do this. however a suitably designed table doesnt need to explicitly use a sequence:

(jdbc/execute! ds ["create table my_serial_tbl (id serial primary key, my_col varchar)"])
=> [#:next.jdbc{:update-count 0}]
(require '[next.jdbc.sql :as sql])
=> nil
(sql/insert! ds :my_serial_tbl {:my_col "foo"})
=> #:my_serial_tbl{:id 1, :my_col "foo"}
(jdbc/execute! ds ["select * from my_serial_tbl"])
=> [#:my_serial_tbl{:id 1, :my_col "foo"}]

jb recluse06:03:40

(def my-insert (-> (insert-into :my_tbl)
                   (values [{:id "nextval('my_seq')" :my_col "'foo'"}])
                   (sql/format :parameterizer :none)))
=> #'user/my-insert
(jdbc/execute! ds my-insert)
=> [#:next.jdbc{:update-count 1}]
(jdbc/execute! ds ["select * from my_tbl"])
=> [#:my_tbl{:id 1, :my_col "foo"} #:my_tbl{:id 3, :my_col "bar"} #:my_tbl{:id 5, :my_col "foo"}]
this is using honeysql as @U04V70XH6 recommended. note that you have to supply the single quotes for strings when you turn off parameterization (which you have to do to get the nextval call to work)

seancorfield06:03:47

@U017JCS7L2Y That's with V1. Not much of that applies with V2 which handles string inlining correctly, as well as also supporting nextval out of the box.

seancorfield06:03:18

(-> (insert-into :my_tbl)
    (values [{:id [:nextval "my_seq"] :my_col "foo"}])
    (sql/format {:inline true}))
That should work on V2 as you expect.

fabrao08:03:19

yes, that´s I want, like nextval

fabrao09:03:09

Hello Sean, your example is not working

fabrao09:03:00

this is working

(->
   (sfmt-help/insert-into :smtb_flow)
   (sfmt-help/values [{:id_flow (sfmt/call :nextval "seq_fluxo") :nm_flow "Teste" :id_company 1 :ds_flow_title "Teste" :dt_created (sfmt/call :NOW)}])
   (sfmt/format {:parameterizer :none})

jb recluse14:03:30

@U0YJJPFRA are you using v2 as indicated? it worked for me:

(require '[honey.sql :as sql])
(require '[honey.sql.helpers :refer :all :as h])
(-> (insert-into :my_tbl)
    (values [{:id [:nextval "my_seq"] :my_col "foo"}])
    (sql/format {:inline true}))
produces
["INSERT INTO my_tbl (id, my_col) VALUES (NEXTVAL('my_seq'), 'foo')"]
when using
seancorfield/honeysql {:mvn/version "2.0.0-alpha2"}

fabrao21:03:53

Ho, I did not check about version 2

seancorfield21:03:32

It's worth noting that the nextval('seq') form works like that only because it is evaluated inline, but if you are not inlining all your parameters (and you probably should not do that -- b/c of SQL injection dangers), then you can just choose to line part of the expression:

(values [{:id [:nextval [:inline "my_seq"]] :my_col "foo"}])
(without the {:inline true} in the sql/format call)

seancorfield21:03:38

What will happen here is that "foo" will be lifted out as a parameter, but the sequence name will be inlined:

["INSERT INTO my_tbl (id, my_col) VALUES (NEXTVAL('my_seq'), ?)" "foo"]
which gives you the best of both worlds.

jb recluse21:03:26

definitely worth noting, thanks! i was not aware that was possible

seancorfield21:03:40

V2 syntax is a lot more composable than V1.

seancorfield04:03:28

Can you explain what you mean by "a sequence in postgresql"?

seancorfield04:03:12

And, in general, if you don't want to work with strings -- and the next.jdbc.sql functions don't do what you need -- the recommendation is always to use HoneySQL to produce the vector of SQL string and parameters.