Home

Documentation

Here you will always find the most recent documentation for the ClojureQL project.

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:

@(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)

Input Output
:table "table"
:table.col "table.col"
:function/col "function(col)"
:function/col1:col2 "function(col1, col2)"
:col#asc "col asc"
:col#desc "col desc"

Connection specification

Example

(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. (select (table :users) (where (= :id 5)))

project (args: this, fields)

Confines the query to the fieldlist supplied in fields

Ex. (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. (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. (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. (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. (-> (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. (-> (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. (-> (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. (-> (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. (-> (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. (-> (table :one) (union (table :two) :all))

Table manipulation functions

conj! (args: this, records)

Inserts record(s) into the table

Ex. (conj! (table :one) {:age 22}) (conj! (table :one) [{:age 22} {:age 23}])

disj! (args: this, predicate)

Deletes record(s) from the table

Ex. (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. (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. (-> (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. (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. (with-results [res table] (println res))"