From a9c32acfd2a160d82a1c0c0f8484ddd202126b95 Mon Sep 17 00:00:00 2001 From: Carlo Zancanaro Date: Tue, 14 May 2013 12:55:28 +1000 Subject: 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). --- src/clojure_sql/core.clj | 45 ++++++++++++++++++++++-------------------- test/clojure_sql/core_test.clj | 11 +++++++++++ 2 files changed, 35 insertions(+), 21 deletions(-) create mode 100644 test/clojure_sql/core_test.clj 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"]) -- cgit v1.2.3