Allow mysql upserts
While I have a bespoke version of this externally, it would be nice to gracefully take advantage of honeysql's reader literals for sql fn calls and the like.
This commit is contained in:
parent
7001826d4b
commit
910d1c72a1
5 changed files with 55 additions and 1 deletions
|
|
@ -1,5 +1,7 @@
|
||||||
## 0.6.2 In development
|
## 0.6.2 In development
|
||||||
|
|
||||||
|
* Support mysql upserts (@dball)
|
||||||
|
|
||||||
## 0.6.1
|
## 0.6.1
|
||||||
|
|
||||||
* Define parameterizable protocol on nil (@dball)
|
* Define parameterizable protocol on nil (@dball)
|
||||||
|
|
|
||||||
16
README.md
16
README.md
|
|
@ -143,6 +143,22 @@ The column values do not have to be literals, they can be nested queries:
|
||||||
"user"]
|
"user"]
|
||||||
```
|
```
|
||||||
|
|
||||||
|
MySQL upserts are supported:
|
||||||
|
|
||||||
|
```clj
|
||||||
|
(-> (insert-into :properties)
|
||||||
|
(columns :name :surname :age)
|
||||||
|
(values
|
||||||
|
[["Jon" "Smith" 34]
|
||||||
|
["Andrew" "Cooper" 12]
|
||||||
|
["Jane" "Daniels" 56]])
|
||||||
|
(upsert :mysql {:age #sql/call [:values :age]})
|
||||||
|
sql/format)
|
||||||
|
=> ["INSERT INTO properties (name, surname, age)
|
||||||
|
VALUES (?, ?, 34), (?, ?, 12), (?, ?, 56)"
|
||||||
|
"Jon" "Smith" "Andrew" "Cooper" "Jane" "Daniels"]
|
||||||
|
```
|
||||||
|
|
||||||
Updates are possible too (note the double S in `sset` to avoid clashing
|
Updates are possible too (note the double S in `sset` to avoid clashing
|
||||||
with `clojure.core/set`):
|
with `clojure.core/set`):
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -191,6 +191,7 @@
|
||||||
:offset 210
|
:offset 210
|
||||||
:lock 215
|
:lock 215
|
||||||
:values 220
|
:values 220
|
||||||
|
:upsert 225
|
||||||
:query-values 230})
|
:query-values 230})
|
||||||
|
|
||||||
(def clause-store (atom default-clause-priorities))
|
(def clause-store (atom default-clause-priorities))
|
||||||
|
|
@ -495,6 +496,22 @@
|
||||||
(comma-join (for [x values]
|
(comma-join (for [x values]
|
||||||
(str "(" (comma-join (map to-sql (vals x))) ")"))))))
|
(str "(" (comma-join (map to-sql (vals x))) ")"))))))
|
||||||
|
|
||||||
|
(defmulti format-upsert-clause
|
||||||
|
(fn [mode updates] mode))
|
||||||
|
|
||||||
|
(defmethod format-upsert-clause :mysql
|
||||||
|
[_ updates]
|
||||||
|
(when-not (seq updates)
|
||||||
|
(let [msg "upserts clause must have an :updates map"]
|
||||||
|
(throw (IllegalArgumentException. msg))))
|
||||||
|
(str "ON DUPLICATE KEY UPDATE "
|
||||||
|
(comma-join (for [[column value] updates]
|
||||||
|
(str (to-sql column) "=" (to-sql value))))))
|
||||||
|
|
||||||
|
(defmethod format-clause :upsert [[_ upsert] _]
|
||||||
|
(let [{:keys [mode updates]} upsert]
|
||||||
|
(format-upsert-clause mode updates)))
|
||||||
|
|
||||||
(defmethod format-clause :query-values [[_ query-values] _]
|
(defmethod format-clause :query-values [[_ query-values] _]
|
||||||
(to-sql query-values))
|
(to-sql query-values))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -159,6 +159,9 @@
|
||||||
lock
|
lock
|
||||||
(assoc :lock lock)))
|
(assoc :lock lock)))
|
||||||
|
|
||||||
|
(defhelper upsert [m mode updates]
|
||||||
|
(assoc m :upsert {:mode mode :updates updates}))
|
||||||
|
|
||||||
(defhelper modifiers [m ms]
|
(defhelper modifiers [m ms]
|
||||||
(if (nil? ms)
|
(if (nil? ms)
|
||||||
m
|
m
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,23 @@
|
||||||
(is (= (format-clause (first {:insert-into [:foo {:select [:bar] :from [:baz]}]}) nil)
|
(is (= (format-clause (first {:insert-into [:foo {:select [:bar] :from [:baz]}]}) nil)
|
||||||
"INSERT INTO foo SELECT bar FROM baz"))
|
"INSERT INTO foo SELECT bar FROM baz"))
|
||||||
(is (= (format-clause (first {:insert-into [[:foo [:a :b :c]] {:select [:d :e :f] :from [:baz]}]}) nil)
|
(is (= (format-clause (first {:insert-into [[:foo [:a :b :c]] {:select [:d :e :f] :from [:baz]}]}) nil)
|
||||||
"INSERT INTO foo (a, b, c) SELECT d, e, f FROM baz")))
|
"INSERT INTO foo (a, b, c) SELECT d, e, f FROM baz"))
|
||||||
|
(is (= (format {:insert-into :letters
|
||||||
|
:columns [:domain_key]
|
||||||
|
:values [["a"] ["b"] ["c"]]})
|
||||||
|
["INSERT INTO letters (domain_key) VALUES (?), (?), (?)" "a" "b" "c"]))
|
||||||
|
(is (= (format {:insert-into :letters
|
||||||
|
:columns [:domain_key]
|
||||||
|
:values [["a"] ["b"] ["c"]]
|
||||||
|
:upsert {:mode :mysql
|
||||||
|
:updates {:id :id}}})
|
||||||
|
["INSERT INTO letters (domain_key) VALUES (?), (?), (?) ON DUPLICATE KEY UPDATE id=id" "a" "b" "c"]))
|
||||||
|
(is (= (format {:insert-into :letters
|
||||||
|
:columns [:domain_key :rank]
|
||||||
|
:values [["a" 1] ["b" 2] ["c" 3]]
|
||||||
|
:upsert {:mode :mysql
|
||||||
|
:updates {:rank #sql/call [:values :rank]}}})
|
||||||
|
["INSERT INTO letters (domain_key, rank) VALUES (?, 1), (?, 2), (?, 3) ON DUPLICATE KEY UPDATE rank=values(rank)" "a" "b" "c"])))
|
||||||
|
|
||||||
(deftest exists-test
|
(deftest exists-test
|
||||||
(is (= (format {:exists {:select [:a] :from [:foo]}})
|
(is (= (format {:exists {:select [:a] :from [:foo]}})
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue