summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlo Zancanaro <carlo@clearboxsystems.com.au>2013-05-14 12:55:28 +1000
committerCarlo Zancanaro <carlo@clearboxsystems.com.au>2013-05-14 12:55:28 +1000
commita9c32acfd2a160d82a1c0c0f8484ddd202126b95 (patch)
tree23a3c1a392a2eb1195dae3312e403977e7ec5ebd
parent1c5a0359f7b048ad01a25607661229e13b5a6be7 (diff)
Parametrise deref behaviour, add two small tests.
Now a user can decide what the query's behaviour on deref should be. This means a user using jdbc can plug in with (set-query-deref-behaviour! #(... jdbc-query-code-here ...)) if they want, but if a user wants to use the code for something else then they can do so without needing to import jdbc stuff. (I'll admit I'm not sure what else they'd do with it, but that's slightly beside the point.) Still left to do is to provide a helper for the common case (performing an SQL query with jdbc).
-rw-r--r--src/clojure_sql/core.clj45
-rw-r--r--test/clojure_sql/core_test.clj11
2 files changed, 35 insertions, 21 deletions
diff --git a/src/clojure_sql/core.clj b/src/clojure_sql/core.clj
index e1dfb90..0032bb6 100644
--- a/src/clojure_sql/core.clj
+++ b/src/clojure_sql/core.clj
@@ -5,6 +5,24 @@
[clojure-sql.util :as u]
[clojure.walk]))
+(declare compile-query)
+
+
+(def ^:dynamic *database-type* nil)
+(defn set-database-type! [new-type]
+ (alter-var-root #'*database-type* (constantly new-type)))
+
+(def ^:dynamic *query-deref-behaviour* #(compile-query *database-type* %))
+(defn set-query-deref-behaviour! [f]
+ (alter-var-root #'*query-deref-behaviour* (constantly f)))
+
+(defrecord ^:private Query []
+ clojure.lang.IDeref
+ (deref [this] (*query-deref-behaviour* this)))
+
+
+
+
(defn add-parentheses [s]
(str \( s \)))
@@ -16,14 +34,10 @@
(defmethod table-name :default [_ table]
(str \" (name table) \"))
-(defmulti sql-string (fn [db _] db))
-(defmethod sql-string :default [_ string]
- (str \' (string/replace string "'" "''") \'))
-
;; compile-* multimethods are of the signature:
-;; (db, expr) -> (SQL, replacements)
+;; (db, expr) -> [SQL & replacements]
(def is-unary? (comp boolean '#{not}))
(def is-predicate? (comp boolean '#{= < > <= >= is in}))
@@ -145,9 +159,6 @@
(defmethod table-name :mysql [_ table]
(str \` (name table) \`))
-(defmethod sql-string :mysql [_ string]
- (str \" (string/replace string "\"" "\\\"") \"))
-
@@ -163,18 +174,12 @@
;; table: tablename -> table_alias
;; fields: (table_alias, fieldname) -> field_alias
-;; joins: [(tablename -> table_alias, type, on)]
+;; joins: [(tablename -> type, table_alias, on)]
;; where: expression
-;; group-by: [field]
-;; having: expression
-
-(def ^:dynamic *database-type* nil)
-(defrecord Table []
- clojure.lang.IDeref
- (deref [this] (compile-query *database-type* this)))
+;; sort-by: [[field direction]]
(defn table [arg]
- (into (->Table)
+ (into (->Query)
(if (map? arg)
{:table arg}
{:table {arg arg}})))
@@ -290,7 +295,7 @@
(project [:id :fname :sname])
(select '(= :deleted false)))
uid-pid-match '(= :uid :pid)
- is-carlo `(= :fname "Carlo")
+ is-carlo `(= :fname "Carlo'; SELECT * FROM users --")
query (-> (join (-> users
(rename {:id :uid}))
(join (-> people
@@ -304,14 +309,13 @@
@query))
(-> (table :users)
- (project [:username])
(join (table :something-else-with-a-username)
true)
(select '(or (= :username "john")
(not (= :username "carlo"))))
+ (project [:username])
deref)
-
(-> (table {:nodes :child})
(project [:parent-id, :name])
(rename {:name :child.name})
@@ -322,7 +326,6 @@
(project [:child.name :parent.name])
deref #_println)
-
(deref (-> (table :anotherStack)
(project [:anotherNumber])
(join (-> (table :collection)
diff --git a/test/clojure_sql/core_test.clj b/test/clojure_sql/core_test.clj
new file mode 100644
index 0000000..1161ece
--- /dev/null
+++ b/test/clojure_sql/core_test.clj
@@ -0,0 +1,11 @@
+(ns clojure-sql.core-test
+ (:refer-clojure :exclude [sort-by])
+ (:require [clojure-sql.core :refer :all]
+ [midje.sweet :refer :all]))
+
+(fact
+ (compile-query nil (table :user))
+ => ["SELECT * FROM \"user\""]
+
+ (compile-query nil (-> (table :user) (select '(= :username "george"))))
+ => ["SELECT * FROM \"user\" WHERE (\"user\".\"username\" = ?)" "george"])