Reputation: 995
My Clojure skills are non-existant, as are my SQLite skills. For some reason I was stuck with this project at work, but I'm having a heck of a time with it.
Basically, a user submits a form and it goes to PayPal and we get it back, and we update the database that they bought something. Additionally, we also erase the temporary session out of the database that we use for their shopping cart.
My job is to add to the database the quantity of what they bought. That's my used_quantity
below. In PHP/MySQL I would do something like:
update sa_forms set used_quantity = used_quantity + {quantity} where id = {id} LIMIT 1
but it seems like I actually have to do two steps to add to the quantity.
The only thing I addedwas the let
statement. Without it, this whole thing works fine. With it, it breaks.
insert-db-order (if (:login session)
(doseq [order db-orders]
(j/insert! SQLDB :sa_orders
{:form_id (:form_id order)
:user_id (:user_id order)
:form_name (:form_name order)
:user_name username
:total_cost_paid (* (:payment_amt order) (:quantity order))
:date_completed (.getTime (java.util.Date.))
:order_content (:html order)
:created_at (.getTime (java.util.Date.))
:updated_at (.getTime (java.util.Date.))
:status false
:quantity (:quantity order)})
(let [quantityOf (j/query SQLDB ["SELECT used_quantity FROM sa_forms WHERE id = ? LIMIT 1" (:form_id order)])]
(j/update! SQLDB :sa_forms
{:used_quantity (+ (:used_quantity quantityOf) (:quantity order))}
(sql/where {:id (:form_id order)}))
)
)
(doseq [id (keys session-orders)]
(j/insert! SQLDB :sa_orders
{:form_id (:form_id (id session-orders))
:user_id anonymous-key
:form_name (:form_name (id session-orders))
:user_name username
:total_cost_paid (* (:payment_amt (id session-orders)) (:quantity (id session-orders)))
:date_completed (.getTime (java.util.Date.))
:order_content (:html (id session-orders))
:created_at (.getTime (java.util.Date.))
:updated_at (.getTime (java.util.Date.))
:status false
:quantity (:quantity (id session-orders))}))
)
I have been getting errors all day, and I've tried multiple things. Like, for example:
{:used_quantity (+ (int(:used_quantity quantityOf)) (:quantity order))}
Because it said a map cannot be an number. I've tried
{:used_quantity (+ (quantityOf) (:quantity order))}
Thinking because I'm only selecting one value, I don't need to show what I'm referencing.
I've also tried to pprint
the value, or the key, or all of it, and it's all either came up as nil
or nothing, which wasn't helpful.
In this ordeal, I learned I have to put variable definers inside of a let
statement though, among other things, but I've spent 9 and a half hours on this and I've moved from getting one error to the next.
Can somebody offer me some clojure? In layman's terms preferably. I'm still trying to grasp the jargon of this language, and the odd syntax...
Thanks!
Upvotes: 1
Views: 414
Reputation: 995
I sent it to my coworker who has worked with Clojure before and he fixed it after a few hours. I'm not sure if this will help anyone, but he did this:
(doseq [order db-orders]
(do
(j/execute! SQLDB "UPDATE sa_forms SET used_quantity = used_quantity + " (:quantity order) " WHERE ? LIMIT 1" (:form_id order));
)
)
I've minimized my solution so there isn't a bunch of unneeded mark-up, but basically he added a do
statement inside the doseq
and we just wrote the SQL statement normally instead of using Clojure.
Like I said, I doubt this will help anyone, but there's the solution to my problem.
Upvotes: 0
Reputation: 20194
For starters, check the type of the values you are using in the context where you are getting exceptions.
user> (type '({:quantity 1}))
clojure.lang.PersistentList
user> (type {:quantity 1})
clojure.lang.PersistentArrayMap
sql/query
should be returning a sequential datatype, even if you set a limit of 1. A keyword used as a function with a seq as an argument will give a nil result:
user> (:quantity '({:quantity 1}))
nil
wrapping in parens, as you also tried, is also guaranteed to be an error
user> ('({:quantity 1}))
ClassCastException clojure.lang.PersistentList cannot be cast to clojure.lang.IFn user/eval8554/fn--8555 (form-init7057475948894346608.clj:1)
The way to get your result should look more like this:
user> (+ (:quantity (first '({:quantity 1}))) 2)
3
Upvotes: 1