Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Copy documentation from clojureql.org into docs directory #134

Merged
merged 3 commits into from

2 participants

This page is out of date. Refresh to see the latest.
Showing with 398 additions and 0 deletions.
  1. +98 −0 docs/examples.md
  2. +300 −0 docs/manual.md
View
98 docs/examples.md
@@ -0,0 +1,98 @@
+# Example code
+
+Below you will find illustrative examples. In addition we recommend
+viewing the screencast which accompanied the beta1 release of
+*ClojureQL* found here - The content is dated but still relevant, with
+only two exceptions: `to-sql` is now renamed to `compile` and
+`with-results` has an updated syntax which you can see under documentation.
+
+## Select all
+
+```clojure
+user=> (table :users)
+SELECT users.* FROM users
+```
+
+The simplest of all queries. When reading, disregard the `user=>` part
+as it simply demonstrates that these queries are executed in a REPL.
+
+## Select certain columns
+
+```clojure
+user=> (-> (table :users)
+ (project [:id :name :email]))
+SELECT users.id,users.name,users.email FROM users
+```
+
+Project is a non-additive way to specify which columns to include in
+the select.
+
+## Sort the results
+
+```clojure
+user=> (-> (table :users)
+ (sort [:id]))
+SELECT users.* FROM users ORDER BY id asc
+```
+
+If you do not specify sorting order (`asc` / `desc`) then `asc` is assumed.
+
+### Sort in descending order
+
+```clojure
+user=> (-> (table :users)
+ (sort [:id#desc]))
+SELECT users.* FROM users ORDER BY users.id desc
+```
+
+### Multiple calls to sort
+
+```clojure
+user=> (-> (table :users)
+ (sort [:id#asc])
+ (sort [:id#desc]))
+SELECT * FROM (SELECT users.* FROM users ORDER BY users.id asc) ORDER
+BY users.id desc
+```
+
+`sort`, `take` and `limit` spawn subselect when called multiple times on the
+same table.
+
+## Limit / Offset
+
+```clojure
+user=> (-> (table :users)
+ (take 5)
+ (drop 2))
+SELECT users.* FROM users LIMIT 3 OFFSET 2
+```
+
+## Distinct
+
+```clojure
+user=> (-> (table :users) distinct)
+SELECT DISTINCT users.* FROM users
+```
+
+Distinct is mostly interesting because of its simple implementation,
+demonstrating how simple it is for users to extend *ClojureQL*. Here
+is a sample implementation:
+
+```clojure
+(defn distinct
+ "A distinct which works on both tables and collections"
+ [table]
+ (modify obj :distinct))
+```
+
+## Aggregates
+
+```clojure
+user=> (-> (table :users)
+ (aggregate [[:count/* :as :cnt]] [:id]))
+SELECT users.id,count(*) AS cnt FROM users GROUP BY users.id
+```
+
+Aggregates accepts an optional second argument which is a vector
+containing the column names to group by. Above you also see the syntax
+for aliasing.
View
300 docs/manual.md
@@ -0,0 +1,300 @@
+# General
+
+ClojureQL is designed to have a consistent uniform API. The following
+rules are always guaranteed:
+
+* All functions which work on tables return a new table. This allows
+ you to compound multiple operations.
+* Any function which name ends in a bang (!) forces execution of the query
+* All functions take the table as their first argument, allowing use
+ of the -> threading operator
+* In all places where you specificy columns can you use both keywords
+ and strings, however certain compiler optimizations are only
+ available when using keywords.
+* To execute a query you must dereference it. Here are two equivalent
+ examples of dereferencing:
+
+```clojure
+@(table db :t1)
+
+(deref (table db :t1))
+```
+
+## Column specification syntax
+
+ClojureQL uses a bit of syntax to keep your queries concise and
+elegant. Below are example conversions of keywords to SQL column
+specifications. (note: It is not necessary to learn this syntax as
+strings can be used instead, however it is recommended)
+
+<table>
+ <thead>
+ <td>Input</td>
+ <td>Output</td>
+ </thead>
+ <tr>
+ <td><code>:table</code></td>
+ <td>"table"</td>
+ </tr>
+ <tr>
+ <td><code>:table.col</code></td>
+ <td>"table.col"</td>
+ </tr>
+ <tr>
+ <td><code>:function/col</code></td>
+ <td>"function(col)"</td>
+ </tr>
+ <tr>
+ <td><code>:function/col1:col2</code></td>
+ <td>"function(col1, col2)"</td>
+ </tr>
+ <tr>
+ <td><code>:col#asc</code></td>
+ <td> "col asc"</td>
+ </tr>
+ <tr>
+ <td><code>:col#desc</code></td>
+ <td>"col desc"</td>
+ </tr>
+</table>
+
+## Connection specification
+
+Example
+```clojure
+(def db
+ {:classname "com.mysql.jdbc.Driver"
+ :subprotocol "mysql"
+ :user "cql"
+ :password "cql"
+ :subname "//localhost:3306/cql"})
+```
+Complete specification
+
+### DriverManager:
+`:classname` (required) a `String`, the jdbc driver class name.
+`:subprotocol` (required) a `String`, the jdbc subprotocol.
+`:subname` (required) a `String`, the jdbc subname.
+`(others)` (optional) passed to the driver as properties.
+
+### DataSource:
+`:datasource` (optional) a `javax.sql.DataSource`
+`:username` (optional) a `String`
+`:password` (optional) a `String`, required if `:username` is supplied
+
+### JNDI:
+`:name` (optional) a String or `javax.naming.Name`
+`:environment` (optional) a `java.util.Map`
+
+### Options:
+`:auto-commit` (optional) a `Boolean`
+`:fetch-size` (optional) an integer
+
+## Public functions for composing queries
+
+### table (args: table-name, or: connection-info, table-name)
+
+Creates a table object optionally associated with a connection
+specification. This can be either a keyword from a previous call to
+(`open-global`) or a `hash-map`.
+
+### select (args: this, predicate)
+
+Confines the query to rows for which the predicate is true
+
+Ex.
+```clojure
+ (select (table :users) (where (= :id 5)))
+```
+
+### project (args: this, fields)
+
+Confines the query to the fieldlist supplied in fields
+
+Ex.
+```clojure
+(project (table :users) [:email])
+```
+
+### take (args: table, n)
+
+Limits the query to n number of rows
+
+### drop (args: table, n)
+
+Skips n number of rows
+
+### sort (args: table, spec)
+
+Sorts a table as per the definition given in spec.
+
+Ex.
+```clojure
+(sort (table :t1) [:id :rank]) ; implicitly ASC
+
+(sort (table :t2) [:id#asc :rank#desc])
+```
+
+### distinct (args: table)
+
+Makes the query distinct
+
+### join (args: this, table2, join_on)
+
+Joins two tables on join_on
+
+Ex.
+```clojure
+(join (table :one) (table :two) :id)
+
+(join (table :one) (table :two) (where (= :one.col :two.col)))
+```
+
+### outer-join (args: this, table2, type, join_on)
+
+Joins two tables on join_on and sets the direction of the join. type
+can be `:right`, `:left`, `:full` etc. Backend support may vary.
+
+Ex.
+```clojure
+(outer-join (table :one) (table :two) :left :id)
+
+(outer-join (table :one) (table :two) :left (where (= :one.id :two.id)))
+```
+
+### rename (args: this, newnames)
+
+Renames colums when joining. Newnames is a map of replacement pairs
+
+Ex.
+```clojure
+(-> (join (table :one) (table :two) :id)
+
+(project [:id]) (rename {:one.id :idx}))
+```
+
+### aggregate (args: either (this, aggregates) or (this aggregates, group-by))
+
+Selects aggregates from a table. Aggregates are denoted with the
+`:function/field` syntax. They can be aliased by supplying a vector
+`[:function/field :as :myfn]`. Optionally accepts a group-by argument
+
+Ex.
+```clojure
+(-> (table :one) (aggregate [[:count/* :as :cnt]] [:id]))
+```
+
+### modify (args: this, modifiers)
+
+Allows for arbitrary modifiers to be applied on the result. Can either
+be called directly or via helper interfaces like `distinct`.
+
+Ex.
+```clojure
+(-> (table :one) (modify \"TOP 5\")) ; MSSqls special LIMIT syntax (-> (table :one) distinct)
+```
+
+### difference (args: this, relations, opts)
+
+Selects the difference between tables. Mode can take a keyword which
+can be anything which your backend supports. Commonly `:all` is used
+to allow duplicate rows.
+
+Ex.
+```clojure
+(-> (table :one) (difference (table :two) :all))
+```
+
+### intersection (args: this, relations, opts)
+
+Selects the intersection between tables. Mode can take a keyword which
+can be anything which your backend supports. Commonly `:all` is used to
+allow duplicate rows.
+
+Ex.
+```clojure
+(-> (table :one) (intersection (table :two) :all))
+```
+
+### union (args: this, relations, opts)
+
+Selects the union between tables. Mode can take a keyword which can be
+anything which your backend supports. Commonly `:all` is used to allow
+duplicate rows.
+
+Ex.
+```clojure
+(-> (table :one) (union (table :two) :all))
+```
+
+## Table manipulation functions
+
+### conj! (args: this, records)
+
+Inserts record(s) into the table
+
+Ex.
+```clojure
+(conj! (table :one) {:age 22})
+
+(conj! (table :one) [{:age 22} {:age 23}])
+```
+
+### disj! (args: this, predicate)
+
+Deletes record(s) from the table
+
+Ex.
+```clojure
+(disj! (table :one) (where (= :age 22)))
+```
+
+### update-in! (args: this, pred, records)
+
+Inserts or updates record(s) where `pred` is `true`. Accepts records
+as both maps and collections.
+
+Ex.
+```clojure
+(update-in! (table :one) (where (= :id 5)) {:age 22})
+```
+
+## Helper functions
+
+### pick! (args: table, keyword)
+
+For queries where you know only a single result will be returned,
+`pick!` calls the keyword on that result. You can supply multiple
+keywords in a collection. Returns nil for no-hits, throws an exception
+on multiple hits.
+
+Ex.
+```clojure
+(-> (table :users) (select (where (= :id 5))) ; We know this will only match 1 row
+ (pick! :email))
+```
+
+### where (args: clause)
+
+Constructs a where-clause for queries.
+
+Ex.
+```clojure
+(where (or (< :a 2) (>= :b 4))) => \"((a < ?) OR (b >= ?))\"
+```
+
+If you call str on the result, you'll get the above. If you call
+(`:env`) you will see the captured environment
+
+Use as: `(select tble (where ...))`
+
+### with-results (args: [results, table])
+
+Executes the body, wherein the results of the query can be accessed
+via the name supplies as results.
+
+Ex.
+```clojure
+(with-results [res table]
+ (println res))
+```
Something went wrong with that request. Please try again.