0

I tried to use java.jdbc insert! function, which can receive multiple objects. the clojure.java.jdbc/insert! should be called like this:

(clojure.java.jdbc/insert! db {:name "john" :password "123"} {:name "george" :password "234"})

I defined a function to do add multiple user records:

(defn add-users [user & more]
   (-add-users db-spec user more))

(defmacro -add-users
   ([db user] `(j/with-db-connection [con-db# db]
                           (j/insert! con-db# ~user)))
   ([db user & more] (let [users (-mk-user-list user more)]
                       `(j/with-db-connection [con-db# db]
                          (j/insert! con-db# ~@(flatten users)))))
(defmacro -mk-usre-list
  ([user] `~user)
  ([user & more] `(list ~user (-mk-user-list ~@more))))

when I macroexpand the -add-users, looks the result is ok like this:

=> (macroexpand '(-add-users db-spec {:name "john" :password "1234"}))

 (let* [db-spec__21320__auto__ db-spec] (clojure.core/with-open [con__21321__auto__ (clojure.java.jdbc/get-connection db-spec__21320__auto__)] (clojure.core/let [con-db__23557__auto__ (clojure.java.jdbc/add-connection db-spec__21320__auto__ con__21321__auto__)] (clojure.java.jdbc/insert! con-db__23557__auto__ {:name "john", :password "1234"}))))

But when I run :

=> (add-users {:name "john" :password "1234"})

IllegalArgumentException insert called with columns but no values  clojure.java.jdbc/insert-sql (jdbc.clj:992)

What's wrong with this macro? or how should I wrap and pass any number of arguments to function like insert! which needs the arguments flattened?

[Update] the problem is found: insert! needs table while in code it's not there.

(j/insert! con-db# ~user) should be (j/insert! con-db# :users ~user) (j/insert! con-db# ~@(flatten users)) should be (j/insert! con-db# :users ~@(flatten users))

But is there anyway simpler to do it?

1
  • the problem of this piece of code is found: Commented Aug 7, 2015 at 21:10

2 Answers 2

2

You can solve this without a macro, using apply:

user=> (doc apply)
-------------------------
clojure.core/apply
([f args] [f x args] [f x y args] [f x y z args] [f a b c d & args])
  Applies fn f to the argument list formed by prepending intervening arguments to args.

(defn my-insert! [x & more]
  (apply jdbc/insert! db :table x more))
Sign up to request clarification or add additional context in comments.

Comments

0

In recent versions of clojure.java.jdbc, you can use insert-multi! which accepts a sequence of hash maps for the rows:

(defn my-insert! [& more]
  (jdbc/insert-multi! db-spec :table more))

or you could just do:

(jdbc/insert-multi! db-spec :table [user-1 user-2 user-3])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.