summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorCarlo Zancanaro <carlo@clearboxsystems.com.au>2013-06-13 18:24:05 +1000
committerCarlo Zancanaro <carlo@clearboxsystems.com.au>2013-06-13 18:24:05 +1000
commit148f752b5f48707dc3d7fe448d1faf33d5cd0228 (patch)
treea61345f51f248c5061cf47630ea5eafcdf638408 /test
parente2bd4b4939d34fc9400c9843b691428d3888ecc4 (diff)
Starting a re-write of the DSL, to be followed by the compiler.
Flip around field/table aliases, do joins a bit differently. They're my main aims at the moment! I'll also add a preprocessor for the compiler to massage it into a nicer form there. I discovered that joins can be done with a pretty sweet syntax in SQL: (tableA LEFT JOIN tableB) RIGHT JOIN tableC This is pretty much perfect for my purposes. Flipping alias maps just makes more sense and removes a whole bunch of `flip-map` calls that would be unnecessary if the aliases were the other way around. The user-facing side of the DSL will be left unchanged, though. The user provides an `{old-name new-name}` map and internally we convert that into `{new-name old-name}`. Like magic. I'm also adding a bunch more tests. Hopefully that will make things more likely to work for long periods of time. Peace out!
Diffstat (limited to 'test')
-rw-r--r--test/clojure_sql/core_test.clj63
-rw-r--r--test/clojure_sql/dsl_test.clj168
2 files changed, 206 insertions, 25 deletions
diff --git a/test/clojure_sql/core_test.clj b/test/clojure_sql/core_test.clj
index 236e421..6a12698 100644
--- a/test/clojure_sql/core_test.clj
+++ b/test/clojure_sql/core_test.clj
@@ -3,28 +3,41 @@
(:require [clojure-sql.core :refer :all]
[midje.sweet :refer :all]))
-(fact
- @(table :user)
- => ["SELECT * FROM \"user\""]
-
- @(-> (table :user) (select '(= :username "george")))
- => ["SELECT * FROM \"user\" WHERE (\"user\".\"username\" = ?)" "george"]
-
- @(-> (table :user) (project {:username :u}))
- => ["SELECT \"user\".\"username\" AS \"u\" FROM \"user\""]
-
- @(-> (table :user) (project {'(+ :username :password) :u}))
- => ["SELECT (\"user\".\"username\" + \"user\".\"password\") AS \"u\" FROM \"user\""])
-
-(into {} (-> (table :user) (project '{(+ :username :password) :u})))
-
-(-> (table :users)
- (project '[:username (+ 1 2 3)])
- (rename '{(+ 1 2 3) :x})
- (select `(exists ~(-> (table :users)
- (select '(= 10 :username)))))
- println)
-
-(-> (table :users)
- (project {:username :un})
- (select '(= :username 10)))
+(comment
+
+ (fact
+ @(table :user)
+ => ["SELECT * FROM \"user\""]
+
+ @(-> (table :user) (project [:username]))
+ => ["SELECT \"user\".\"username\" AS \"username\" FROM \"user\""]
+
+ @(-> (table :user) (select '(= :username "george")))
+ => ["SELECT * FROM \"user\" WHERE (\"user\".\"username\" = ?)" "george"]
+
+ @(-> (table :user) (project {:username :u}))
+ => ["SELECT \"user\".\"username\" AS \"u\" FROM \"user\""]
+
+ @(-> (table :user) (project {'(+ :age :modifier) :u}))
+ => ["SELECT (\"user\".\"age\" + \"user\".\"modifier\") AS \"u\" FROM \"user\""]
+
+ @(-> (table :user)
+ (project [:id])
+ (join (-> (table :x)
+ (project [:id])
+ (join (-> (table :y)
+ (project [:id]))
+ :type :left))))
+ => ["SELECT \"user\".\"id\" AS \"id\" FROM \"user\" INNER JOIN \"x\" ON ((\"user\".\"id\" = \"x\".\"id\"))"])
+
+ (into {} (-> (table :user) (project '{(+ :username :password) :u})))
+
+ (-> (table :users)
+ (project '[:username (+ 1 2 3)])
+ (rename '{(+ 1 2 3) :x})
+ (select `(exists ~(-> (table :users)
+ (select '(= 10 :username))))))
+
+ (-> (table :users)
+ (project {:username :un})
+ (select '(= :username 10))))
diff --git a/test/clojure_sql/dsl_test.clj b/test/clojure_sql/dsl_test.clj
new file mode 100644
index 0000000..182749e
--- /dev/null
+++ b/test/clojure_sql/dsl_test.clj
@@ -0,0 +1,168 @@
+(ns clojure-sql.dsl-test
+ (:refer-clojure :exclude [sort-by])
+ (:require [clojure-sql.dsl :refer :all]
+ [midje.sweet :refer :all]))
+
+(unfinished join)
+
+(fact "Table creates basic queries on tables"
+
+ (table ..name..)
+ => {:tables {..name.. ..name..}}
+ ;(provided (keyword? ..name..) => true)
+
+ (table {..name.. ..alias..})
+ => {:tables {..alias.. ..name..}}
+
+ (table {..name.. ..alias.., ..name2.. ..alias2..})
+ => {:tables {..alias.. ..name..,
+ ..alias2.. ..name2..}})
+
+
+(fact "Project restricts (and/or adds) fields of a query"
+
+ (prerequisites (keyword? ..table-alias..) => true
+ (keyword? ..table..) => true
+ (keyword? ..field..) => true
+ (keyword? ..field-alias..) => true
+ (keyword? ..field2..) => true
+ (keyword? ..field2-alias..) => true)
+
+ (fact "projecting onto a single field from one table"
+ (-> (table {..table.. ..table-alias..})
+ (project [..field..]))
+ => {:tables {..table-alias.. ..table..}
+ :fields {..field.. [..table-alias.. ..field..]}}
+
+ (-> (table {..table.. ..table-alias..})
+ (project {..field.. ..field-alias..}))
+ => {:tables {..table-alias.. ..table..}
+ :fields {..field-alias.. [..table-alias.. ..field..]}})
+
+
+ (fact "projecting onto multiple fields from one table"
+ (-> (table {..table.. ..table-alias..})
+ (project [..field.. ..field2..]))
+ => {:tables {..table-alias.. ..table..}
+ :fields {..field.. [..table-alias.. ..field..]
+ ..field2.. [..table-alias.. ..field2..]}}
+
+ (-> (table {..table.. ..table-alias..})
+ (project {..field.. ..field-alias.., ..field2.. ..field2-alias..}))
+ => {:tables {..table-alias.. ..table..}
+ :fields {..field-alias.. [..table-alias.. ..field..]
+ ..field2-alias.. [..table-alias.. ..field2..]}})
+
+ (fact "projecting one a field from multiple tables"
+ (prerequisites ..tables.. =contains=> {:tables {..table.. ..table.., ..table2.. ..table2..}})
+
+ (project ..tables.. [..field..])
+ => (throws clojure.lang.ExceptionInfo)
+
+ (project ..tables.. {..field.. ..field-alias..})
+ => (throws clojure.lang.ExceptionInfo))
+
+ (fact "projecting a subset of the current projection from one table"
+ ;; Note that these two facts are retaining the ..table.. in the
+ ;; fields rather than using the ..table-alias.. they would have
+ ;; used otherwise. This shows they are filtering the existing
+ ;; fields rather than removing and re-adding the fields.
+ (project {:tables {..table-alias.. ..table..}
+ :fields {..field.. [..table.. ..field..]
+ ..field2.. [..table.. ..field2..]}}
+ [..field..])
+ => {:tables {..table-alias.. ..table..}
+ :fields {..field.. [..table.. ..field..]}}
+
+ (project {:tables {..table-alias.. ..table..}
+ :fields {..field.. [..table.. ..field..]
+ ..field2.. [..table.. ..field2..]}}
+ {..field.. ..field-alias..})
+ => {:tables {..table-alias.. ..table..}
+ :fields {..field-alias.. [..table.. ..field..]}})
+
+ (fact "projecting a disjoint set from the current projection from one table"
+ (project {:tables {..table-alias.. ..table..}
+ :fields {[..table.. ..field..] ..field..}}
+ [..field2..])
+ => {:tables {..table-alias.. ..table..}
+ :fields {..field2.. [..table-alias.. ..field2..]}})
+
+ (fact "projecting a superset from the current projection from one table"
+ (project {:tables {..table.. ..table..}
+ :fields {..field.. [..table.. ..field..]}}
+ [..field.. ..field2..])
+ => {:tables {..table.. ..table..}
+ :fields {..field.. [..table.. ..field..]
+ ..field2.. [..table.. ..field2..]}}
+
+ ;; once again - note the table aliases
+ (project {:tables {..table-alias.. ..table..}
+ :fields {..field.. [..table.. ..field..]}}
+ [..field.. ..field2..])
+ => {:tables {..table-alias.. ..table..}
+ :fields {..field.. [..table.. ..field..]
+ ..field2.. [..table-alias.. ..field2..]}})
+
+
+
+ (fact "projecting a subset of the current projection from two table"
+ (prerequisites ..tables.. =contains=> {:tables {..table.. ..table.., ..table2.. ..table2..}})
+
+ (project {:tables ..tables..
+ :fields {..field.. [..table.. ..field..]
+ ..field2.. [..table.. ..field2..]}}
+ [..field..])
+ => {:tables ..tables..
+ :fields {..field.. [..table.. ..field..]}}
+
+ (project {:tables ..tables..
+ :fields {..field.. [..table.. ..field..]
+ ..field2.. [..table.. ..field2..]}}
+ {..field.. ..field-alias..})
+ => {:tables ..tables..
+ :fields {..field-alias.. [..table.. ..field..]}})
+
+ (fact "projecting a disjoint set from the current projection from two tables"
+ (project {:tables {..table-alias.. ..table.., ..table2-alias.. ..table2..}
+ :fields {[..table.. ..field..] ..field..}}
+ [..field2..])
+ => (throws clojure.lang.ExceptionInfo))
+
+ (fact "projecting a superset from the current projection from two tables"
+ (project {:tables {..table-alias.. ..table.., ..table2-alias.. ..table2..}
+ :fields {[..table.. ..field..] ..field..}}
+ [..field.. ..field2..])
+ => (throws clojure.lang.ExceptionInfo)))
+
+
+
+(fact "renaming fields does what you'd expect (renames them, removes the old alias)"
+ (prerequisites (keyword? ..table..) => true
+ (keyword? ..field..) => true
+ (keyword? ..field2..) => true
+ (keyword? ..field-alias..) => true)
+
+ (-> (table ..table..)
+ (project [..field..])
+ (rename {..field.. ..field-alias..}))
+ => {:tables {..table.. ..table..}
+ :fields {..field-alias.. [..table.. ..field..]}}
+
+ (-> (table ..table..)
+ (project [..field.. ..field2..])
+ (rename {..field.. ..field-alias..}))
+ => {:tables {..table.. ..table..}
+ :fields {..field-alias.. [..table.. ..field..]
+ ..field2.. [..table.. ..field2..]}}
+
+ (-> {:tables {..table.. ..table..,
+ ..table2.. ..table2..}
+ :fields {..field.. [..table.. ..field..]
+ ..field2.. [..table.. ..field2..]}}
+ (rename {..field.. ..field-alias..}))
+ => {:tables {..table.. ..table.., ..table2.. ..table2..}
+ :fields {..field-alias.. [..table.. ..field..]
+ ..field2.. [..table.. ..field2..]}})
+
+