Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

these are my proposed naming changes so that people can use clojureql…

….core without any name conflicts with clojure.core. these names are more transparent to what is happening under the hood.
  • Loading branch information...
commit 65c0384b5bf32adaea6521c00e893ff6d91b9ff8 1 parent 6cb0b6f
@ninjudd ninjudd authored
View
24 README.md
@@ -117,7 +117,7 @@ Aggregates
@(-> (table db :salary) (project [:avg/wage]))
>>> ({:avg(wage) 250.0000M})
- (-> (table db :salary) (project [:avg/wage:expenses]) compile)
+ (-> (table db :salary) (project [:avg/wage:expenses]) sql)
>>> "SELECT avg(salary.wage, salary.expenses) FROM salary;
**Note:** These examples demonstrate a simple uniform interface across ClojureQL. For more advanced
@@ -136,13 +136,13 @@ aggregations, use the **aggregate** function.
Manipulation
------------
- @(conj! users {:name "Jack"})
+ @(insert! users {:name "Jack"})
>>> ({:id 1 :name "Lau"} {:id 2 :name "Christophe"} {:id 3 :name "Frank"} {:id 4 :name "Jack"})
- @(disj! users {:name "Jack"})
+ @(delete! users {:name "Jack"})
>>> ({:id 1 :name "Lau"} {:id 2 :name "Christophe"} {:id 3 :name "Frank"})
- @(update-in! users (where (= :id 1)) {:name "Test"})
+ @(update! users (where (= :id 1)) {:name "Test"})
>>> ({:id 1 :name "Tst"} {:id 2 :name "Christophe"} {:id 3 :name "Frank"})
**Note:** All of these take either a single map or a collection of maps as their final argument.
@@ -165,16 +165,16 @@ Compound ops
Since this is a true Relational Algebra implementation, everything composes!
- @(-> (conj! users {:name "Jack"}) ; Add a row
- (disj! (where (= {:name "Lau"}))) ; Remove another
- (sort :id :desc) ; Prepare to sort in descending order
- (project #{:id :title}) ; Include these columns in the query
- (select (where (!= :id 5))) ; But filter out ID = 5
- (join :salary :id) ; Join with table salary USING column id
- (limit 10)) ; Dont extract more than 10 hits
+ @(-> (insert! users {:name "Jack"}) ; Add a row
+ (delete! (where (= {:name "Lau"}))) ; Remove another
+ (order-by [:id:desc]) ; Prepare to sort in descending order
+ (project #{:id :title}) ; Include these columns in the query
+ (select (where (!= :id 5))) ; But filter out ID = 5
+ (join :salary :id) ; Join with table salary USING column id
+ (take-limit 10)) ; Don't extract more than 10 hits
>>> ({:id 3 :name "Frank"} {:id 2 :name "Christophe"})
-**Note:** This executes SQL statements 3 times in this order: conj!, disj!, @
+**Note:** This executes SQL statements 3 times in this order: insert!, delete!, @
Helpers
-------
View
3  project.clj
@@ -2,6 +2,5 @@
:description "SQL abstractions for Clojure"
:dependencies [[org.clojure/clojure "1.2.0"]
[org.clojure/clojure-contrib "1.2.0"]
- [mysql/mysql-connector-java "5.1.6"]]
- :dev-dependencies [[swank-clojure "1.3.0-SNAPSHOT"]])
+ [mysql/mysql-connector-java "5.1.6"]])
View
55 src/clojureql/core.clj
@@ -4,9 +4,6 @@
you to access tables and rows as objects that have uniform interfaces
for queries, inserts and deletions."
:url "http://github.com/LauJensen/clojureql"}
- (:refer-clojure
- :exclude [compile take sort conj! disj! < <= > >= =]
- :rename {take take-coll})
(:use
[clojureql internal predicates]
[clojure.string :only [join] :rename {join join-str}]
@@ -19,35 +16,34 @@
; RELATIONAL ALGEBRA
(defprotocol Relation
- (select [this predicate] "Queries the table using a predicate")
- (project [this fields] "Projects fields onto the query")
- (join [this table2 join_on] "Joins two table")
- (outer-join [this table2 type join_on] "Makes an outer join of type :left|:right|:full")
- (rename [this newnames] "Renames colums in a join")
- (aggregate [this aggregates]
- [this aggregates group-by] "Computes aggregates grouped by the specified fields")
+ (select [this predicate] "Queries the table using a predicate")
+ (project [this fields] "Projects fields onto the query")
+ (join [this table2 join_on] "Joins two table")
+ (outer-join [this table2 type join_on] "Makes an outer join of type :left|:right|:full")
+ (rename [this newnames] "Renames colums in a join")
+ (aggregate [this aggregates]
+ [this aggregates group-by] "Computes aggregates grouped by the specified fields")
- (conj! [this records] "Inserts record(s) into the table")
- (disj! [this predicate] "Deletes record(s) from the table")
- (update-in! [this pred records] "Inserts or updates record(s) where pred is true")
+ (insert! [this records] "Inserts record(s) into the table")
+ (delete! [this predicate] "Deletes record(s) from the table")
+ (update! [this pred records] "Updates record(s) where pred is true")
- (limit [this n] "Queries the table with LIMIT n")
- (order-by [this col] "Orders the Query by the column")
+ (take-limit [this n] "Queries the table with LIMIT n")
+ (drop-offset [this n] "Queries the table with OFFSET n")
+ (order-by [this fields] "Orders the results by fields.")
+ (options [this opts] "Appends opt(ion)s to the query")
- (sort [this col type] "Sorts the query either :asc or :desc")
- (options [this opts] "Appends opt(ion)s to the query")
-
- (compile [this] "Returns an SQL statement"))
+ (sql [this] "Returns an SQL statement"))
(defrecord RTable [cnx tname tcols restriction renames joins options]
clojure.lang.IDeref
(deref [this]
(if cnx
- (with-cnx cnx (with-results rs [(compile this)] (doall rs)))
- (with-results rs [(compile this)] (doall rs))))
+ (with-cnx cnx (with-results rs [(sql this)] (doall rs)))
+ (with-results rs [(sql this)] (doall rs))))
Relation
- (compile [this]
+ (sql [this]
(let [sql-string
(if (seq joins)
(cond
@@ -63,7 +59,7 @@
(-> (:position joins) name .toUpperCase)
(-> (:type joins) name .toUpperCase)
(-> (.options t2 (str "GROUP BY " (-> t2 :tcols first name)))
- compile)
+ sql)
t2alias
(.replaceAll pred t2name t2alias)
(or options ""))
@@ -143,7 +139,7 @@
(.options table (str "GROUP BY " (to-fieldlist tname group-by)))
table)))
- (conj! [this records]
+ (insert! [this records]
(letfn [(exec [] (if (map? records)
(insert-records tname records)
(apply insert-records tname records)))]
@@ -152,13 +148,13 @@
(exec)))
this)
- (disj! [this predicate]
+ (delete! [this predicate]
(if cnx
(with-cnx cnx (delete-rows tname [(compile-expr predicate)]))
(delete-rows tname [(compile-expr predicate)]))
this)
- (update-in! [this pred records]
+ (update! [this pred records]
(letfn [(exec [] (if (map? records)
(update-or-insert-values tname [pred] records)
(apply update-or-insert-values tname [pred] records)))]
@@ -170,10 +166,9 @@
(options [this opts]
(assoc this :options (str options \space opts)))
- (limit [this n] (.options this (str "LIMIT " n)))
- (order-by [this col] (.options this (str "ORDER BY " (qualify tname col))))
- (sort [this col dir] (.options this (str "ORDER BY " (qualify tname col) \space
- (if (:asc dir) "ASC" "DESC")))))
+ (take-limit [this n] (.options this (str "LIMIT " n)))
+ (drop-offset [this n] (.options this (str "OFFSET " n)))
+ (order-by [this fields] (.options this (str "ORDER BY " (to-fieldlist tname fields)))))
(defn table
([connection-info table-name]
View
41 test/clojureql/core_test.clj
@@ -1,67 +1,64 @@
(ns clojureql.core-test
(:use [clojureql core internal predicates]
- clojure.test)
- (:refer-clojure
- :exclude [compile take sort conj! disj!]
- :rename {take take-coll}))
+ clojure.test))
(deftest sql-compilation
(testing "Simple selects"
(are [x y] (= x y)
- (-> (table {} :users [:*]) compile)
+ (-> (table {} :users [:*]) sql)
"SELECT users.* FROM users"
- (-> (table {} :users [:id :name]) compile)
+ (-> (table {} :users [:id :name]) sql)
"SELECT users.id,users.name FROM users"
- (-> (table {} :users [:avg/wage]) compile)
+ (-> (table {} :users [:avg/wage]) sql)
"SELECT avg(users.wage) FROM users"
- (-> (table {} :users [[:avg/wage :as :avg]]) compile)
+ (-> (table {} :users [[:avg/wage :as :avg]]) sql)
"SELECT avg(users.wage) AS avg FROM users"))
(testing "Where predicates"
(are [x y] (= x y)
(-> (table {} :users [:id])
(select (where (= :id 5)))
- compile)
+ sql)
"SELECT users.id FROM users WHERE (id = 5)"
(-> (table {} :users [:id])
(select (where (or (= :id 5) (>= :id 10))))
- compile)
+ sql)
"SELECT users.id FROM users WHERE ((id = 5) OR (id >= 10))"
(-> (table {} :users [:id])
(select (where (and (= :id 5) (>= :id 10))))
- compile)
+ sql)
"SELECT users.id FROM users WHERE ((id = 5) AND (id >= 10))"
(-> (table {} :users [:id])
(select (where (and (= :id 5) (or (>= :id 10)
(<= :id 20)))))
- compile)
+ sql)
"SELECT users.id FROM users WHERE ((id = 5) AND ((id >= 10) OR (id <= 20)))"
(-> (table {} :users [:id])
(select (where (and (!= :id 5) (or (> :id 10)
(< :id 20)))))
- compile)
+ sql)
"SELECT users.id FROM users WHERE ((id != 5) AND ((id > 10) OR (id < 20)))"))
(testing "Projections"
(are [x y] (= x y)
(-> (table {} :users [:id])
(project #{:name :title})
- compile)
+ sql)
"SELECT users.id,users.name,users.title FROM users"))
(testing "Joins"
(are [x y] (= x y)
(-> (table {} :users [:id])
(join (table {} :salary [:wage]) :id)
- compile)
+ sql)
"SELECT users.id,salary.wage FROM users JOIN salary USING(id)"
(-> (table {} :users [:id])
(join (table {} :salary [:wage]) (where (= :user.id :salary.id)))
- compile)
+ sql)
"SELECT users.id,salary.wage FROM users JOIN salary ON (user.id = salary.id)"))
(testing "Renaming in joins"
(are [x y] (= x y)
(-> (table {} :users [:id])
(join (table {} :salary [:wage]) (where (= :user.id :salary.id)))
(rename {:id :idx}) ; TODO: This should only work with fully qualified names
- compile)
+ sql)
"SELECT users.id,salary.wage FROM users AS users(idx) JOIN salary ON (user.id = salary.id)"))
; TODO: Shouldn't this be ON (users.idx = salary.id) ?
(testing "Aggregate functions"
@@ -69,29 +66,29 @@
(-> (table {} :users)
(select (where (= :admin true)))
(aggregate [:count/* :avg/wage])
- compile)
+ sql)
"SELECT count(users.*),avg(users.wage) FROM users WHERE (admin = true)"
(-> (table {} :users)
(select (where (= :admin true)))
(aggregate [:count/*, "corr(x,y)"] [:country :city])
- compile)
+ sql)
"SELECT users.country,users.city,count(users.*),corr(x,y) FROM users WHERE (admin = true) GROUP BY users.country,users.city"
(-> (table {} :users)
(select (where (= :admin true)))
(aggregate [:count/*, :corr/x:y] [:country :city])
- compile)
+ sql)
"SELECT users.country,users.city,count(users.*),corr(users.x,users.y) FROM users WHERE (admin = true) GROUP BY users.country,users.city"))
(testing "Table aliases"
(are [x y] (= x y)
(let [u1 (table {} {:users :u1} [:id :article :price])
w1 (table {} {:salary :w1})]
- (compile (join u1 w1 (where (= :u1.id :w1.id)))))
+ (sql (join u1 w1 (where (= :u1.id :w1.id)))))
"SELECT u1.id,u1.article,u1.price FROM users u1 JOIN salary w1 ON (u1.id = w1.id)"
(let [u1 (table {} {:users :u1} [:id :article :price])
w1 (table {} {:salary :w1} [])]
(-> (join u1 w1 (where (= :u1.id :w1.id)))
(select (where (= :s2.article "NULL")))
- compile))
+ sql))
(str "SELECT u1.id,u1.article,u1.price FROM users u1 "
"JOIN salary w1 ON (u1.id = w1.id) WHERE (s2.article = NULL)")))
)

0 comments on commit 65c0384

Please sign in to comment.
Something went wrong with that request. Please try again.