diff --git a/src/honeysql/format.clj b/src/honeysql/format.clj index 004a640..d09d520 100644 --- a/src/honeysql/format.clj +++ b/src/honeysql/format.clj @@ -46,6 +46,7 @@ (defn- undasherize [s] (string/replace s "-" "_")) + (defn quote-identifier [x & {:keys [style split] :or {split true}}] (let [qf (if style (quote-fns style) @@ -213,50 +214,58 @@ (extend-protocol ToSql clojure.lang.Keyword - (-to-sql [x] (let [s ^String (name x)] - (condp = (.charAt s 0) - \% (let [call-args (string/split (subs s 1) #"\." 2)] - (to-sql (apply call (map keyword call-args)))) - \? (to-sql (param (keyword (subs s 1)))) - (quote-identifier x)))) + (-to-sql [x] + (let [s ^String (name x)] + (condp = (.charAt s 0) + \? (to-sql (param (keyword (subs s 1)))) + (quote-identifier x)))) clojure.lang.Symbol - (-to-sql [x] (quote-identifier x)) + (-to-sql [x] + (let [s ^String (name x)] + (condp = (.charAt s 0) + \? (to-sql (param (keyword (subs s 1)))) + (quote-identifier x)))) java.lang.Number (-to-sql [x] (str x)) java.lang.Boolean (-to-sql [x] (if x "TRUE" "FALSE")) - clojure.lang.Sequential - (-to-sql [x] (if *fn-context?* - ;; list argument in fn call - (paren-wrap (comma-join (map to-sql x))) - ;; alias - (str (to-sql (first x)) - ; Omit AS in FROM, JOIN, etc. - Oracle doesn't allow it - (if (= :select *clause*) - " AS " - " ") - (if (string? (second x)) - (quote-identifier (second x)) - (to-sql (second x)))))) + clojure.lang.IPersistentVector + (-to-sql [x] + (if *fn-context?* + ;; list argument in fn call + (paren-wrap (comma-join (map to-sql x))) + ;; alias + (str (to-sql (first x)) + " AS " + (if (string? (second x)) + (quote-identifier (second x)) + (to-sql (second x)))))) + clojure.lang.IPersistentList + (-to-sql [x] + (let [fn-name (name (first x)) + fn-name (fn-aliases fn-name fn-name)] + (apply fn-handler fn-name (rest x)))) SqlCall - (-to-sql [x] (binding [*fn-context?* true] - (let [fn-name (name (.name x)) - fn-name (fn-aliases fn-name fn-name)] - (apply fn-handler fn-name (.args x))))) + (-to-sql [x] + (binding [*fn-context?* true] + (let [fn-name (name (.name x)) + fn-name (fn-aliases fn-name fn-name)] + (apply fn-handler fn-name (.args x))))) SqlRaw (-to-sql [x] (.s x)) clojure.lang.IPersistentMap - (-to-sql [x] (let [clause-ops (concat - (filter #(contains? x %) clause-order) - (remove known-clauses (keys x))) - sql-str (binding [*subquery?* true - *fn-context?* false] - (space-join - (map (comp #(-format-clause % x) #(find x %)) - clause-ops)))] - (if *subquery?* - (paren-wrap sql-str) - sql-str))) + (-to-sql [x] + (let [clause-ops (concat + (filter #(contains? x %) clause-order) + (remove known-clauses (keys x))) + sql-str (binding [*subquery?* true + *fn-context?* false] + (space-join + (map (comp #(-format-clause % x) #(find x %)) + clause-ops)))] + (if *subquery?* + (paren-wrap sql-str) + sql-str))) nil (-to-sql [x] "NULL")) @@ -266,15 +275,16 @@ (defn to-sql [x] (if (satisfies? ToSql x) (-to-sql x) - (let [[x pname] (if (instance? SqlParam x) - (let [pname (param-name x)] - (if (map? @*input-params*) - [(get @*input-params* pname) pname] - (let [x (first @*input-params*)] - (swap! *input-params* rest) - [x pname]))) - ;; Anonymous param name -- :_1, :_2, etc. - [x (keyword (str "_" (swap! *param-counter* inc)))])] + (let [[x pname] + (if (instance? SqlParam x) + (let [pname (param-name x)] + (if (map? @*input-params*) + [(get @*input-params* pname) pname] + (let [x (first @*input-params*)] + (swap! *input-params* rest) + [x pname]))) + ;; Anonymous param name -- :_1, :_2, etc. + [x (keyword (str "_" (swap! *param-counter* inc)))])] (swap! *param-names* conj pname) (swap! *params* conj x) "?"))) diff --git a/src/honeysql/helpers.clj b/src/honeysql/helpers.clj index 91c1ca2..fb4df1e 100644 --- a/src/honeysql/helpers.clj +++ b/src/honeysql/helpers.clj @@ -20,24 +20,19 @@ (if (coll? x) x [x])) (defhelper select [m fields] - (assoc m :select (collify fields))) - -(defhelper merge-select [m fields] (update-in m [:select] concat (collify fields))) +(defhelper replace-select [m fields] + (assoc m :select (collify fields))) + (defhelper un-select [m fields] (update-in m [:select] #(remove (set (collify fields)) %))) (defhelper from [m tables] - (assoc m :from (collify tables))) - -(defhelper merge-from [m tables] (update-in m [:from] concat (collify tables))) -(defmethod build-clause :where [_ m pred] - (if (nil? pred) - m - (assoc m :where pred))) +(defhelper replace-from [m tables] + (assoc m :from (collify tables))) (defn- prep-where [args] (let [[m preds] (if (map? (first args)) @@ -51,20 +46,14 @@ (into [logic-op] preds))] [m pred logic-op])) -(defn where [& args] - (let [[m pred] (prep-where args)] - (if (nil? pred) - m - (assoc m :where pred)))) - -(defmethod build-clause :merge-where [_ m pred] +(defmethod build-clause :where [_ m pred] (if (nil? pred) m (assoc m :where (if (not (nil? (:where m))) [:and (:where m) pred] pred)))) -(defn merge-where [& args] +(defn where [& args] (let [[m pred logic-op] (prep-where args)] (if (nil? pred) m @@ -72,26 +61,37 @@ [logic-op (:where m) pred] pred))))) -(defhelper join [m clauses] - (assoc m :join clauses)) +(defmethod build-clause :replace-where [_ m pred] + (if (nil? pred) + m + (assoc m :where pred))) -(defhelper merge-join [m clauses] +(defn replace-where [& args] + (let [[m pred] (prep-where args)] + (if (nil? pred) + m + (assoc m :where pred)))) + +(defhelper join [m clauses] (update-in m [:join] concat clauses)) -(defhelper left-join [m clauses] - (assoc m :left-join clauses)) +(defhelper replace-join [m clauses] + (assoc m :join clauses)) -(defhelper merge-left-join [m clauses] +(defhelper left-join [m clauses] (update-in m [:left-join] concat clauses)) -(defhelper right-join [m clauses] - (assoc m :right-join clauses)) +(defhelper replace-left-join [m clauses] + (assoc m :left-join clauses)) -(defhelper merge-right-join [m clauses] +(defhelper right-join [m clauses] (update-in m [:right-join] concat clauses)) +(defhelper replace-right-join [m clauses] + (assoc m :right-join clauses)) + (defmethod build-clause :group-by [_ m fields] - (assoc m :group-by (collify fields))) + (update-in m [:group-by] concat (collify fields))) (defn group [& args] (let [[m fields] (if (map? (first args)) @@ -99,28 +99,23 @@ [{} args])] (build-clause :group-by m fields))) -(defhelper merge-group-by [m fields] - (update-in m [:group-by] concat (collify fields))) +(defmethod build-clause :replace-group-by [_ m fields] + (assoc m :group-by (collify fields))) + +(defn replace-group [& args] + (let [[m fields] (if (map? (first args)) + [(first args) (rest args)] + [{} args])] + (build-clause :replace-group-by m fields))) (defmethod build-clause :having [_ m pred] - (if (nil? pred) - m - (assoc m :having pred))) - -(defn having [& args] - (let [[m pred] (prep-where args)] - (if (nil? pred) - m - (assoc m :having pred)))) - -(defmethod build-clause :merge-having [_ m pred] (if (nil? pred) m (assoc m :having (if (not (nil? (:having m))) [:and (:having m) pred] pred)))) -(defn merge-having [& args] +(defn having [& args] (let [[m pred logic-op] (prep-where args)] (if (nil? pred) m @@ -128,12 +123,23 @@ [logic-op (:having m) pred] pred))))) -(defhelper order-by [m fields] - (assoc m :order-by (collify fields))) +(defmethod build-clause :replace-having [_ m pred] + (if (nil? pred) + m + (assoc m :having pred))) -(defhelper merge-order-by [m fields] +(defn replace-having [& args] + (let [[m pred] (prep-where args)] + (if (nil? pred) + m + (assoc m :having pred)))) + +(defhelper order-by [m fields] (update-in m [:order-by] concat (collify fields))) +(defhelper replace-order-by [m fields] + (assoc m :order-by (collify fields))) + (defhelper limit [m l] (if (nil? l) m @@ -147,12 +153,12 @@ (defhelper modifiers [m ms] (if (nil? ms) m - (assoc m :modifiers (collify ms)))) + (update-in m [:modifiers] concat (collify ms)))) -(defhelper merge-modifiers [m ms] +(defhelper replace-modifiers [m ms] (if (nil? ms) m - (update-in m [:modifiers] concat (collify ms)))) + (assoc m :modifiers (collify ms)))) (defmethod build-clause :insert-into [_ m table] (assoc m :insert-into table)) @@ -162,11 +168,11 @@ ([m table] (build-clause :insert-into m table))) (defhelper columns [m fields] - (assoc m :columns (collify fields))) - -(defhelper merge-columns [m fields] (update-in m [:columns] concat (collify fields))) +(defhelper replace-columns [m fields] + (assoc m :columns (collify fields))) + (defmethod build-clause :values [_ m vs] (assoc m :values vs))