2012-07-13 18:32:43 +00:00
(ns honeysql.core-test
2015-03-02 23:07:50 +00:00
(:refer-clojure :exclude [format update])
2015-06-14 19:58:51 +00:00
(:require [#?@(:clj [clojure.test :refer]
:cljs [cljs.test :refer-macros]) [deftest testing is]]
2012-08-24 21:08:22 +00:00
[honeysql.core :as sql]
2015-06-14 19:58:51 +00:00
[honeysql.helpers :refer [select modifiers from join left-join
right-join full-join where group having
order-by limit offset values columns
2017-02-18 13:50:30 +00:00
insert-into with]]
2015-06-14 19:58:51 +00:00
honeysql.format-test))
2012-07-13 18:32:43 +00:00
;; TODO: more tests
(deftest test-select
2017-02-18 13:50:30 +00:00
(let [m1 (-> (with [:cte (-> (select :*)
(from :example)
(where [:= :example-column 0]))])
(select :f.* :b.baz :c.quux [:b.bla :bla-bla]
2013-08-06 18:05:17 +00:00
:%now (sql/raw "@x := 10"))
2012-08-24 21:08:22 +00:00
;;(un-select :c.quux)
2012-08-24 20:50:56 +00:00
(modifiers :distinct)
(from [:foo :f] [:baz :b])
2012-10-19 16:41:26 +00:00
(join :draq [:= :f.b :draq.x])
(left-join [:clod :c] [:= :f.a :c.d])
(right-join :bock [:= :bock.z :c.e])
2014-11-05 21:04:21 +00:00
(full-join :beck [:= :beck.x :c.y])
2012-08-24 20:50:56 +00:00
(where [:or
2013-08-06 18:27:56 +00:00
[:and [:= :f.a "bort"] [:not= :b.baz :?param1]]
2012-08-24 20:50:56 +00:00
[:< 1 2 3]
2012-08-25 02:47:54 +00:00
[:in :f.e [1 (sql/param :param2) 3]]
2012-08-24 20:50:56 +00:00
[:between :f.e 10 20]])
2012-08-24 21:08:22 +00:00
;;(merge-where [:not= nil :b.bla])
2012-08-24 20:50:56 +00:00
(group :f.a)
(having [:< 0 :f.e])
2015-04-17 10:29:20 +00:00
(order-by [:b.baz :desc] :c.quux [:f.a :nulls-first])
2012-08-24 20:50:56 +00:00
(limit 50)
2012-08-24 21:08:22 +00:00
(offset 10))
2017-02-18 13:50:30 +00:00
m2 {:with [[:cte {:select [:*]
:from [:example]
:where [:= :example-column 0]}]]
:select [:f.* :b.baz :c.quux [:b.bla :bla-bla]
2013-08-06 18:05:17 +00:00
:%now (sql/raw "@x := 10")]
2012-08-24 21:08:22 +00:00
;;:un-select :c.quux
:modifiers :distinct
:from [[:foo :f] [:baz :b]]
2012-10-19 16:41:26 +00:00
:join [:draq [:= :f.b :draq.x]]
:left-join [[:clod :c] [:= :f.a :c.d]]
:right-join [:bock [:= :bock.z :c.e]]
2014-11-05 21:04:21 +00:00
:full-join [:beck [:= :beck.x :c.y]]
2012-08-24 21:08:22 +00:00
:where [:or
2013-08-06 18:27:56 +00:00
[:and [:= :f.a "bort"] [:not= :b.baz :?param1]]
2012-08-24 21:08:22 +00:00
[:< 1 2 3]
2012-08-25 02:47:54 +00:00
[:in :f.e [1 (sql/param :param2) 3]]
2012-08-24 21:08:22 +00:00
[:between :f.e 10 20]]
;;:merge-where [:not= nil :b.bla]
:group-by :f.a
:having [:< 0 :f.e]
2015-04-17 10:29:20 +00:00
:order-by [[:b.baz :desc] :c.quux [:f.a :nulls-first]]
2012-08-24 21:08:22 +00:00
:limit 50
:offset 10}
m3 (sql/build m2)
m4 (apply sql/build (apply concat m2))]
(testing "Various construction methods are consistent"
2015-02-24 22:35:28 +00:00
(is (= m1 m3 m4)))
2012-08-24 20:50:56 +00:00
(testing "SQL data formats correctly"
2017-02-18 13:50:30 +00:00
(is (= ["WITH cte AS (SELECT * FROM example WHERE example_column = ?) 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 (? < ? AND ? < ?) OR (f.e in (?, ?, ?)) OR f.e BETWEEN ? AND ?) GROUP BY f.a HAVING ? < f.e ORDER BY b.baz DESC, c.quux, f.a NULLS FIRST LIMIT ? OFFSET ? "
0 "bort" "gabba" 1 2 2 3 1 2 3 10 20 0 50 10]
2015-03-04 03:54:06 +00:00
(sql/format m1 {:param1 "gabba" :param2 2}))))
2015-06-14 19:58:51 +00:00
#?(:clj (testing "SQL data prints and reads correctly"
(is (= m1 (read-string (pr-str m1))))))
2015-01-07 00:58:56 +00:00
(testing "SQL data formats correctly with alternate param naming"
(is (= (sql/format m1 :params {:param1 "gabba" :param2 2} :parameterizer :postgresql)
2017-02-18 13:50:30 +00:00
["WITH cte AS (SELECT * FROM example WHERE example_column = $1) 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 = $2 AND b.baz <> $3) OR ($4 < $5 AND $6 < $7) OR (f.e in ($8, $9, $10)) OR f.e BETWEEN $11 AND $12) GROUP BY f.a HAVING $13 < f.e ORDER BY b.baz DESC, c.quux, f.a NULLS FIRST LIMIT $14 OFFSET $15 "
0 "bort" "gabba" 1 2 2 3 1 2 3 10 20 0 50 10])))
2015-04-17 19:15:23 +00:00
(testing "Locking"
2017-02-18 13:50:30 +00:00
(is (= ["WITH cte AS (SELECT * FROM example WHERE example_column = ?) 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 (? < ? AND ? < ?) OR (f.e in (?, ?, ?)) OR f.e BETWEEN ? AND ?) GROUP BY f.a HAVING ? < f.e ORDER BY b.baz DESC, c.quux, f.a NULLS FIRST LIMIT ? OFFSET ? FOR UPDATE "
0 "bort" "gabba" 1 2 2 3 1 2 3 10 20 0 50 10]
2015-04-17 19:15:23 +00:00
(sql/format (assoc m1 :lock {:mode :update})
{:param1 "gabba" :param2 2}))))))
2015-02-20 16:05:09 +00:00
(deftest test-cast
(is (= ["SELECT foo, CAST(bar AS integer)"]
(sql/format {:select [:foo (sql/call :cast :bar :integer)]})))
(is (= ["SELECT foo, CAST(bar AS integer)"]
(sql/format {:select [:foo (sql/call :cast :bar 'integer)]}))))
2015-03-31 17:32:48 +00:00
(deftest test-value
(is (= ["INSERT INTO foo (bar) VALUES (?)" {:baz "my-val"}]
(->
(insert-into :foo)
(columns :bar)
(values [[(honeysql.format/value {:baz "my-val"})]])
2017-03-22 19:38:15 +00:00
sql/format)))
(is (= ["INSERT INTO foo (a, b, c) VALUES (?, ?, ?), (?, ?, ?)"
"a" "b" "c" "a" "b" "c"]
(-> (insert-into :foo)
(values [(array-map :a "a" :b "b" :c "c")
(hash-map :a "a" :b "b" :c "c")])
sql/format))))
2015-04-21 02:49:33 +00:00
(deftest test-operators
2015-05-20 15:23:36 +00:00
(testing "="
(testing "with nil"
(is (= ["SELECT * FROM customers WHERE name IS NULL"]
(sql/format {:select [:*]
:from [:customers]
:where [:= :name nil]})))
(is (= ["SELECT * FROM customers WHERE name = ?" nil]
(sql/format {:select [:*]
:from [:customers]
:where [:= :name :?name]}
{:name nil})))))
2015-04-21 02:49:33 +00:00
(testing "in"
(doseq [[cname coll] [[:vector []] [:set #{}] [:list '()]]]
(testing (str "with values from a " (name cname))
(let [values (conj coll 1)]
2016-05-18 21:21:51 +00:00
(is (= ["SELECT * FROM customers WHERE (id in (?))" 1]
2015-04-21 02:49:33 +00:00
(sql/format {:select [:*]
:from [:customers]
2015-04-21 18:28:28 +00:00
:where [:in :id values]})))
(is (= ["SELECT * FROM customers WHERE (id in (?))" 1]
(sql/format {:select [:*]
:from [:customers]
:where [:in :id :?ids]}
{:ids values}))))))
(testing "with more than one integer"
(let [values [1 2]]
2016-05-18 21:21:51 +00:00
(is (= ["SELECT * FROM customers WHERE (id in (?, ?))" 1 2]
2015-04-21 18:28:28 +00:00
(sql/format {:select [:*]
:from [:customers]
:where [:in :id values]})))
(is (= ["SELECT * FROM customers WHERE (id in (?, ?))" 1 2]
(sql/format {:select [:*]
:from [:customers]
:where [:in :id :?ids]}
{:ids values})))))
(testing "with more than one string"
(let [values ["1" "2"]]
(is (= ["SELECT * FROM customers WHERE (id in (?, ?))" "1" "2"]
(sql/format {:select [:*]
:from [:customers]
:where [:in :id values]})
(sql/format {:select [:*]
:from [:customers]
:where [:in :id :?ids]}
{:ids values})))))))
2015-08-06 18:03:06 +00:00
(deftest test-case
2016-05-18 21:21:51 +00:00
(is (= ["SELECT CASE WHEN foo < ? THEN ? WHEN (foo > ? AND (foo mod ?) = ?) THEN (foo / ?) ELSE ? END FROM bar"
0 -1 0 2 0 2 0]
2015-08-06 18:03:06 +00:00
(sql/format
{:select [(sql/call
:case
[:< :foo 0] -1
[:and [:> :foo 0] [:= (sql/call :mod :foo 2) 0]] (sql/call :/ :foo 2)
:else 0)]
:from [:bar]})))
(let [param1 1
param2 2
param3 "three"]
2016-05-18 21:21:51 +00:00
(is (= ["SELECT CASE WHEN foo = ? THEN ? WHEN foo = bar THEN ? WHEN bar = ? THEN (bar * ?) ELSE ? END FROM baz"
param1 0 param2 0 param3 "param4"]
2015-08-06 18:03:06 +00:00
(sql/format
{:select [(sql/call
:case
[:= :foo :?param1] 0
[:= :foo :bar] (sql/param :param2)
[:= :bar 0] (sql/call :* :bar :?param3)
:else "param4")]
:from [:baz]}
{:param1 param1
:param2 param2
:param3 param3})))))
2016-02-09 22:05:34 +00:00
(deftest test-raw
2016-02-09 20:02:17 +00:00
(is (= ["SELECT 1 + 1 FROM foo"]
2016-02-09 22:05:34 +00:00
(-> (select (sql/raw "1 + 1"))
(from :foo)
sql/format))))
(deftest test-call
2016-02-09 20:02:17 +00:00
(is (= ["SELECT min(?) FROM ?" "time" "table"]
2016-02-09 22:05:34 +00:00
(-> (select (sql/call :min "time"))
(from "table")
sql/format))))
2016-03-01 14:39:21 +00:00
(deftest join-test
(testing "nil join"
(is (= ["SELECT * FROM foo INNER JOIN x ON foo.id = x.id INNER JOIN y"]
(-> (select :*)
(from :foo)
(join :x [:= :foo.id :x.id] :y nil)
sql/format)))))
2015-06-14 19:58:51 +00:00
2018-01-16 02:13:14 +00:00
(deftest join-using-test
(testing "nil join"
(is (= ["SELECT * FROM foo INNER JOIN x USING (id) INNER JOIN y USING (foo, bar)"]
(-> (select :*)
(from :foo)
(join :x [:using :id] :y [:using :foo :bar])
sql/format)))))
2017-07-18 18:27:39 +00:00
(deftest inline-test
(is (= ["SELECT * FROM foo WHERE id = 5"]
(-> (select :*)
(from :foo)
(where [:= :id (sql/inline 5)])
sql/format))))
2015-06-14 19:58:51 +00:00
#?(:cljs (cljs.test/run-all-tests))