From bc0b7e904f0bf1f8d129ee16563408867e7369a0 Mon Sep 17 00:00:00 2001 From: Donald Ball Date: Fri, 17 Apr 2015 15:15:23 -0400 Subject: [PATCH] Support locking selects This will need documentation before being merged. --- src/honeysql/format.clj | 17 +++++++++++++++++ src/honeysql/helpers.clj | 5 +++++ test/honeysql/core_test.clj | 7 ++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/honeysql/format.clj b/src/honeysql/format.clj index 5e5a3d7..cb60d35 100644 --- a/src/honeysql/format.clj +++ b/src/honeysql/format.clj @@ -188,6 +188,7 @@ :order-by 190 :limit 200 :offset 210 + :lock 215 :values 220 :query-values 230}) @@ -426,6 +427,22 @@ (defmethod format-clause :offset [[_ offset] _] (str "OFFSET " (to-sql offset))) +(defmulti format-lock-clause identity) + +(defmethod format-lock-clause :update [_] + "FOR UPDATE") + +(defmethod format-lock-clause :mysql-share [_] + "LOCK IN SHARE MODE") + +(defmethod format-lock-clause :postgresql-share [_] + "FOR SHARE") + +(defmethod format-clause :lock [[_ lock] _] + (let [{:keys [mode wait]} lock + clause (format-lock-clause mode)] + (str clause (when (false? wait) " NOWAIT")))) + (defmethod format-clause :insert-into [[_ table] _] (if (and (sequential? table) (sequential? (first table))) (str "INSERT INTO " diff --git a/src/honeysql/helpers.clj b/src/honeysql/helpers.clj index e94eae6..a9825b3 100644 --- a/src/honeysql/helpers.clj +++ b/src/honeysql/helpers.clj @@ -154,6 +154,11 @@ m (assoc m :offset (if (coll? o) (first o) o)))) +(defhelper lock [m lock] + (cond-> m + lock + (assoc :lock lock))) + (defhelper modifiers [m ms] (if (nil? ms) m diff --git a/test/honeysql/core_test.clj b/test/honeysql/core_test.clj index d7c5543..c6a790f 100644 --- a/test/honeysql/core_test.clj +++ b/test/honeysql/core_test.clj @@ -60,7 +60,12 @@ (testing "SQL data formats correctly with alternate param naming" (is (= (sql/format m1 :params {:param1 "gabba" :param2 2} :parameterizer :postgresql) ["SELECT DISTINCT f.*, b.baz, c.quux, b.bla AS bla_bla, now(), @x := 10 FROM foo f, baz b INNER JOIN draq ON f.b = draq.x LEFT JOIN clod c ON f.a = c.d RIGHT JOIN bock ON bock.z = c.e FULL JOIN beck ON beck.x = c.y WHERE ((f.a = $1 AND b.baz <> $2) OR (1 < 2 AND 2 < 3) OR (f.e in (1, $3, 3)) OR f.e BETWEEN 10 AND 20) GROUP BY f.a HAVING 0 < f.e ORDER BY b.baz DESC, c.quux LIMIT 50 OFFSET 10 " - "bort" "gabba" 2]))))) + "bort" "gabba" 2]))) + (testing "Locking" + (is (= ["SELECT DISTINCT f.*, b.baz, c.quux, b.bla AS bla_bla, now(), @x := 10 FROM foo f, baz b INNER JOIN draq ON f.b = draq.x LEFT JOIN clod c ON f.a = c.d RIGHT JOIN bock ON bock.z = c.e FULL JOIN beck ON beck.x = c.y WHERE ((f.a = ? AND b.baz <> ?) OR (1 < 2 AND 2 < 3) OR (f.e in (1, ?, 3)) OR f.e BETWEEN 10 AND 20) GROUP BY f.a HAVING 0 < f.e ORDER BY b.baz DESC, c.quux LIMIT 50 OFFSET 10 FOR UPDATE " + "bort" "gabba" 2] + (sql/format (assoc m1 :lock {:mode :update}) + {:param1 "gabba" :param2 2})))))) (deftest test-cast (is (= ["SELECT foo, CAST(bar AS integer)"]