revise api

This commit is contained in:
Justin Kramer 2012-07-13 10:53:19 -04:00
parent f3556016aa
commit b9f1e17c91
5 changed files with 60 additions and 40 deletions

View file

@ -7,7 +7,8 @@ SQL as Clojure data structures.
## Usage ## Usage
```clj ```clj
(require '[honeysql.core :refer [format-sql sql merge-sql sql-fn sql-raw]]) (require '[honeysql.core :as sql :refer [select from where limit merge-select
merge-where]])
;; Everything is centered around maps representing SQL queries ;; Everything is centered around maps representing SQL queries
(def sqlmap {:select [:a :b :c] (def sqlmap {:select [:a :b :c]
@ -15,43 +16,55 @@ SQL as Clojure data structures.
:where [:= :f.a "baz"]}) :where [:= :f.a "baz"]})
;; format-sql turns maps into clojure.java.jdbc-compatible, parameterized SQL ;; format-sql turns maps into clojure.java.jdbc-compatible, parameterized SQL
(format-sql sqlmap) (sql/format sqlmap)
=> ["SELECT a, b, c FROM foo WHERE (f.a = ?)" ["baz"]] => ["SELECT a, b, c FROM foo WHERE (f.a = ?)" ["baz"]]
;; The sql function is a helper for building query maps ;; The sql function is a helper for building query maps
(= sqlmap (= sqlmap
(sql :select [:a :b :c] (sql/sql :select [:a :b :c]
:from :foo :from :foo
:where [:= :f.a "baz"])) :where [:= :f.a "baz"]))
=> true => true
;; Providing a map as the first argument to sql will use that map as a base, ;; You can also use clause-specific helper functions, if you prefer. They
;; with the new clauses replacing old ones ;; compose together nicely.
(format-sql (sql sqlmap :select :* :limit 10)) (= sqlmap
(-> (select :a :b :c)
(from :foo)
(where [:= :f.a "baz"])))
=> true
;; Providing a map as the first argument to sql or clause helper functions will
;; use that map as a base, with the new clauses replacing old ones
(sql/format (sql/sql sqlmap :select :* :limit 10))
=> ["SELECT * FROM foo WHERE (f.a = ?) LIMIT 10" ["baz"]]
(sql/format (-> sqlmap (select :*) (limit 10)))
=> ["SELECT * FROM foo WHERE (f.a = ?) LIMIT 10" ["baz"]] => ["SELECT * FROM foo WHERE (f.a = ?) LIMIT 10" ["baz"]]
;; To add to clauses instead of replacing them, use merge-sql ;; To add to clauses instead of replacing them, use merge-sql, or merge-select,
(format-sql ;; merge-from, etc.
(merge-sql sqlmap :select [:d :e] :where [:> :b 10])) (sql/format
(sql/merge-sql sqlmap :select [:d :e] :where [:> :b 10]))
=> ["SELECT a, b, c, d, e FROM foo WHERE ((f.a = ?) AND (b > 10))" ["baz"]]
(sql/format
(-> sqlmap (merge-select :d :e) (merge-where [:> :b 10])))
=> ["SELECT a, b, c, d, e FROM foo WHERE ((f.a = ?) AND (b > 10))" ["baz"]] => ["SELECT a, b, c, d, e FROM foo WHERE ((f.a = ?) AND (b > 10))" ["baz"]]
;; Queries can be nested ;; Queries can be nested
(format-sql (sql/format
(sql :select :* (sql/sql :select :*
:from :foo :from :foo
:where [:in :foo.a (sql :select :a :where [:in :foo.a (sql/sql :select :a :from :bar)]))
:from :bar)]))
=> ["SELECT * FROM foo WHERE (foo.a IN (SELECT a FROM bar))"] => ["SELECT * FROM foo WHERE (foo.a IN (SELECT a FROM bar))"]
;; There are helper functions and data literals for handling SQL function ;; There are helper functions and data literals for handling SQL function
;; calls and raw SQL fragments ;; calls and raw SQL fragments
(sql :select [(sql-fn :count :*) (sql-raw "@var := foo.bar")] (sql/sql :select [(sql/call :count :*) (sql/raw "@var := foo.bar")]
:from :foo) :from :foo)
=> {:from (:foo), :select (#sql/fn [:count :*] #sql/raw "@var := foo.bar")} => {:from (:foo), :select (#sql/call [:count :*] #sql/raw "@var := foo.bar")}
(format-sql *1) (sql/format *1)
=> ["SELECT COUNT(*), @var := foo.bar FROM foo"] => ["SELECT COUNT(*), @var := foo.bar FROM foo"]
``` ```
## License ## License

View file

@ -1,2 +1,2 @@
{sql/fn honeysql.format/read-sql-fn {sql/call honeysql.format/read-sql-call
sql/raw honeysql.format/read-sql-raw} sql/raw honeysql.format/read-sql-raw}

View file

@ -1,10 +1,11 @@
(ns honeysql.core (ns honeysql.core
(:refer-clojure :exclude [group-by]) (:refer-clojure :exclude [group-by format])
(:require [honeysql.format :as format])) (:require [honeysql.format :as format]
[honeysql.util :refer [defalias]]))
(def sql-fn format/sql-fn) (defalias call format/call)
(def sql-raw format/sql-raw) (defalias raw format/raw)
(def format-sql format/format-sql) (defalias format format/format)
(defn select [& fields] (defn select [& fields]
(let [[m fields] (if (map? (first fields)) (let [[m fields] (if (map? (first fields))

View file

@ -1,33 +1,34 @@
(ns honeysql.format (ns honeysql.format
(:refer-clojure :exclude [format])
(:require [clojure.string :as string])) (:require [clojure.string :as string]))
;;(set! *warn-on-reflection* true) ;;(set! *warn-on-reflection* true)
;;;; ;;;;
(deftype SqlFn [name args]) (deftype SqlCall [name args])
(defn sql-fn [name & args] (defn call [name & args]
(SqlFn. name args)) (SqlCall. name args))
(defn read-sql-fn [form] (defn read-sql-call [form]
(apply sql-fn form)) (apply call form))
(defmethod print-method SqlFn [^SqlFn o ^java.io.Writer w] (defmethod print-method SqlCall [^SqlCall o ^java.io.Writer w]
(.write w (str "#sql/fn " (pr-str (into [(.name o)] (.args o)))))) (.write w (str "#sql/call " (pr-str (into [(.name o)] (.args o))))))
(defmethod print-dup SqlFn [o w] (defmethod print-dup SqlCall [o w]
(print-method o w)) (print-method o w))
;;;; ;;;;
(deftype SqlRaw [s]) (deftype SqlRaw [s])
(defn sql-raw [s] (defn raw [s]
(SqlRaw. (str s))) (SqlRaw. (str s)))
(defn read-sql-raw [form] (defn read-sql-raw [form]
(sql-raw form)) (raw form))
(defmethod print-method SqlRaw [^SqlRaw o ^java.io.Writer w] (defmethod print-method SqlRaw [^SqlRaw o ^java.io.Writer w]
(.write w (str "#sql/raw " (pr-str (.s o))))) (.write w (str "#sql/raw " (pr-str (.s o)))))
@ -75,7 +76,7 @@
(declare to-sql) (declare to-sql)
(defn format-sql [sql-map] (defn format [sql-map]
(binding [*params* (atom [])] (binding [*params* (atom [])]
(let [sql-str (to-sql sql-map)] (let [sql-str (to-sql sql-map)]
(if (seq @*params*) (if (seq @*params*)
@ -104,7 +105,7 @@
(str (to-sql (first x)) (str (to-sql (first x))
" AS " " AS "
(to-sql (second x))))) (to-sql (second x)))))
SqlFn SqlCall
(-to-sql [x] (binding [*fn-context?* true] (-to-sql [x] (binding [*fn-context?* true]
(let [fn-name (name (.name x)) (let [fn-name (name (.name x))
fn-name (fn-aliases fn-name fn-name) fn-name (fn-aliases fn-name fn-name)
@ -152,7 +153,7 @@
(paren-wrap (paren-wrap
(string/join (str " " (string/upper-case op-name) " ") (string/join (str " " (string/upper-case op-name) " ")
(map format-predicate args))) (map format-predicate args)))
(to-sql (apply sql-fn pred))))))) (to-sql (apply call pred)))))))
(defmulti format-clause (defmulti format-clause
"Takes a map entry representing a clause and returns an SQL string" "Takes a map entry representing a clause and returns an SQL string"

5
src/honeysql/util.clj Normal file
View file

@ -0,0 +1,5 @@
(ns honeysql.util)
(defmacro defalias [sym var-sym]
`(let [v# (var ~var-sym)]
(intern *ns* (with-meta (quote ~sym) (meta v#)) @v#)))