diff --git a/doc/reference/db.md b/doc/reference/db.md
index f188a4620..286602fd0 100644
--- a/doc/reference/db.md
+++ b/doc/reference/db.md
@@ -2,192 +2,408 @@
## Overview
+
+
+
+
## Generic Database Interface
-::: tip usage
-(import :std/db/dbi)
-:::
+ (import :std/db/dbi)
-### connection?
-::: tip usage
-```
-(connection? ...)
-```
-:::
-Please document me!
+
-### statement?
-::: tip usage
-```
-(statement? ...)
-```
-:::
+### `sql-connect`
-Please document me!
+First things first we must connect to a database. Though the actual function to
+connect differs between databases, `sql-connect` also makes a `will` so that the
+connection is automagically closed using [`sql-close`](#sqlClose) when garbage collected.
-### sql-error?
-::: tip usage
-```
-(sql-error? ...)
-```
-:::
+ (import :std/db/postgresql)
+ (def db (sql-connect postgresql-connect host: "localhost" user: "foo" passwd: "bar"))
+ ;; => #
-Please document me!
-### sql-connect
-::: tip usage
-```
-(sql-connect ...)
-```
-:::
+
-Please document me!
+### `connection?`
-### sql-close
-::: tip usage
-```
-(sql-close ...)
-```
-:::
+This predicate asks if the thing passed is in fact a connection.
-Please document me!
+ (connection? db) ;; => #t
+ (connection? car) ;; => #f
-### sql-prepare
-::: tip usage
-```
-(sql-prepare ...)
-```
-:::
-Please document me!
+
-### sql-bind
-::: tip usage
-```
-(sql-bind ...)
-```
-:::
+### `sql-eval`
-Please document me!
+Often when interacting with the **DB** we do not actually need a result.
+`sql-eval` returns *unspecified* when run. In fact, three letters out of four,
+(C)reate, (U)pdate and (D)elete, often need nothing at all.
-### sql-clear
-::: tip usage
-```
-(sql-clear ...)
-```
-:::
+ (sql-eval db "CREATE TEMPORARY TABLE foo (bar text)") ;; => #!void
+ (sql-eval db "INSERT INTO foo VALUES ('huh?')") ;; => #!void
+ (sql-eval db "UPDATE foo SET bar = 'bar' WHERE bar = 'huh?'") ;; => #!void
+ (sql-eval db "DELETE FROM foo WHERE bar = 'bar'") ;; => #!void
-Please document me!
+It can take arguments.
-### sql-reset
-::: tip usage
-```
-(sql-reset ...)
-```
-:::
+ (sql-eval db "INSERT INTO foo VALUES ($1)" "yay!") ;; => #!void
-Please document me!
-### sql-reset/clear
-::: tip usage
-```
-(sql-reset/clear ...)
-```
-:::
+
-Please document me!
+### `sql-eval-query`
-### sql-finalize
-::: tip usage
-```
-(sql-finalize ...)
-```
-:::
+The **R** in **CRUD** is likely what is most often used.
-Please document me!
+ (sql-eval-query db "SELECT * from foo") ;; => ("yay!")
-### sql-eval
-::: tip usage
-```
-(sql-eval ...)
-```
-:::
+Of course `SELECT` is not the only query that returns things. It can take
+arguments as well.
-Please document me!
+ (sql-eval-query
+ db "INSERT INTO foo
+ VALUES ('huh?') returning foo.*") ;; => ("huh?")
+ (sql-eval-query
+ db "INSERT INTO foo
+ VALUES ('huh?, again?') returning foo.*") ;; => ("huh?, again?")
-### sql-eval-query
-::: tip usage
-```
-(sql-eval-query ...)
-```
-:::
-Please document me!
+ (sql-eval-query db "WITH q AS (
+ UPDATE foo SET bar = 'bar'
+ WHERE bar != 'huh?' returning true)
+ SELECT count(*) FROM q") ;; => (2)
-### sql-exec
-::: tip usage
-```
-(sql-exec ...)
-```
-:::
-Please document me!
+ (sql-eval-query db "DELETE FROM foo returning foo.*")
+ ;; => ("huh?" "bar" "bar")
-### sql-query
-::: tip usage
-```
-(sql-query ...)
-```
-:::
-Please document me!
+
-### in-sql-query
-::: tip usage
-```
-(in-sql-query ...)
-```
-:::
+### `sql-prepare`
-Please document me!
+Often an evaluation of a query is not enough.
-### sql-columns
-::: tip usage
-```
-(sql-columns ...)
-```
-:::
+- There’s the simple matter of column names as we only return a list of
+ results.
-Please document me!
+- We may want to pass arguments.
-### sql-txn-begin
-::: tip usage
-```
-(sql-txn-begin ...)
-```
-:::
+For that purpose there’s a prepared statement. They are `willed to run`
+[`sql-finalize`](#sqlFinalize) before taking out the trash.
-Please document me!
+ (def istmt (sql-prepare db "INSERT INTO foo VALUES ('bar') RETURNING foo.*;"))
-### sql-txn-commit
-::: tip usage
-```
-(sql-txn-commit ...)
-```
-:::
+ (def bind-istmt (sql-prepare db "INSERT INTO foo VALUES ($1) returning 'hahaha' AS baz"))
-Please document me!
+ (def stmt (sql-prepare db "SELECT foo AS bat FROM foo"))
+ (def bind-stmt (sql-prepare db "SELECT true AS funnyColumn, * FROM foo WHERE bar = $1"))
-### sql-txn-abort
-::: tip usage
-```
-(sql-txn-abort ...)
-```
-:::
-Please document me!
+
+
+### `statement?`
+
+Is this an **SQL Statement**?
+
+ (statement? istmt) ;; => #t
+ (statement? 'foobar) ;; =? #f
+
+
+
+
+### `sql-columns`
+
+We’ve got some predicative-ly confirmed prepared statements. `sql-columns` gives
+us the column names.
+
+ (map sql-columns [ istmt bind-istmt stmt bind-stmt ])
+ ;; => (("bar") ("baz") ("bat") ("funnycolumn" "bar"))
+
+
+
+
+### `sql-exec`
+
+Like the name says this function executes a prepared statement from
+[`sql-prepare`](#sqlPrepare). Like [`sql-eval`](#sqlEval), which in fact uses this after it prepares a
+statement for you, it returns a useless value.
+
+ (sql-exec istmt)
+
+A statement can be executed many times.
+
+ [ (sql-exec istmt) (sql-exec istmt) ] ;; => (#!void #!void)
+
+ (sql-eval-query db "SELECT * FROM foo")
+ ("bar" "bar" "bar")
+
+Unlike [`sql-eval`](#sqlEval), `sql-exec` does not take arguments.
+
+ (sql-exec bind-istmt "yay!")
+ ; Evaluation aborted on Wrong number of arguments passed to procedure
+ ; (std/db/dbi#sql-exec '# "yay!")
+
+Not only that, calling it with a statement that requires arguments is an error
+as well.
+
+ (sql-exec bind-istmt)
+ ; Evaluation aborted on postgresql-exec!: [sql-error] bind message supplies 0
+ ; parameters, but prepared statement "stmt539" requires 1 --- irritants: (S .
+ ; ERROR) (V . ERROR) (C . 08P01) (M . bind message supplies 0 parameters, but
+ ; prepared statement "stmt539" requires 1) (F . postgres.c) (L . 1665) (R .
+ ; exec_bind_message)
+
+That’s because arguments need to be bound with [`sql-bind`](#sqlBind).
+
+
+
+
+### `sql-query`
+
+Similar to [`sql-eval-query`](#sqlEvalQuery) `sql-query` returns the results of the
+[`sql-prepare`](#sqlPrepare)’d statement in list form.
+
+ (sql-query stmt) => ("(bar)" "(bar)" "(bar)")
+
+Like [`sql-exec`](#sqlExec) it does not take arguments because they need to be bound with
+[`sql-bind`](#sqlBind).
+
+
+
+
+### `in-sql-query`
+
+For more advanced uses `in-sql-query` takes a statement and returns an [iterator.](iterators.md)
+
+ (import :std/iter)
+
+ (for ((r (in-sql-query stmt)))
+ (displayln r))
+ ;(bar)
+ ;(bar)
+ ;(bar)
+ ;; => #!void
+
+Being able to take rows from the DB one at a time has some advantages,
+especially with [reset](#sqlReset), or even [reset/clear](#sqlResetClear).
+
+
+
+
+### `sql-bind`
+
+For [`sql-prepare`](#sqlPrepare)’d statements that take arguments `sql-bind` sets them to the
+value before we run the statement.
+
+ (sql-bind bind-istmt "yay!") ;; => #!void
+ (sql-bind bind-stmt "yay!") ;; => #!void
+
+It does not run it, just sets up the specified environment.
+
+ (sql-query stmt) ;; => ("(bar)" "(bar)" "(bar)")
+
+To run it we of course use [`sql-exec`](#sqlExec) or [`sql-query`](#sqlQuery).
+
+ (sql-exec bind-istmt) ;; => #!void
+ (sql-query bind-stmt) ;; => (#(#t "yay!"))
+
+A bound statement can run many times.
+
+ (sql-exec bind-istmt) ;; => #!void
+
+ (sql-query bind-stmt) ;; => (#(#t "yay!") #(#t "yay!"))
+
+A statement can be rebound.
+
+ (sql-bind bind-istmt "huh?") ;; => ("hahaha")
+ (sql-query bind-istmt) ;; => #!void
+ (sql-query stmt)
+ ;; => ("(bar)" "(bar)" "(bar)" "(yay!)" "(yay!)" "(huh?)")
+
+It can also be [cleared](#sqlClear), [reset](#sqlReset), or even [reset/clear](#sqlResetClear)’d.
+
+
+
+
+### `sql-clear`
+
+Simply clear the local variables bound to a statement.
+
+ (sql-clear bind-stmt) ;; => #
+ (sql-query bind-stmt)
+ ; Evaluation aborted on postgresql-query!: [sql-error] bind message supplies 0
+ ; parameters, but prepared statement "stmt149" requires 1 --- irritants: (S .
+ ; ERROR) (V . ERROR) (C . 08P01) (M . bind message supplies 0 parameters, but
+ ; prepared statement "stmt149" requires 1) (F . postgres.c) (L . 1665) (R .
+ ; exec_bind_message)
+
+
+
+
+### `sql-reset`
+
+When interacting with the DB a stored proc, after being run, has a reference to
+the results and can be considered “set”.
+
+Imagine a statement that returns a certain amount of rows.
+
+ (for ((r (in-sql-query stmt)))
+ (displayln r))
+ ;(bar)
+ ;(bar)
+ ;(bar)
+ ;(yay!)
+ ;(yay!)
+ ;(huh?)
+ ;; => #!void
+
+For some reason we only want a few. We can so do so and reset it so the database
+knows we are done with it.
+
+ (def count 0)
+ (for ((r (in-sql-query stmt)))
+ (set! count (1+ count))
+ (displayln r count)
+ (when (= count 3) (sql-reset stmt)))
+ ;(bar)1
+ ;(bar)2
+ ;(bar)3
+ ;; => #!void
+
+
+
+
+### `sql-reset/clear`
+
+This [clears](#sqlClear), and [resets](#sqlReset), a stored procedure.
+
+ (sql-query bind-stmt) ;; => (#(#t "yay!") #(#t "yay!"))
+ (for ((r (in-sql-query bind-stmt)))
+ (displayln r) (sql-reset/clear bind-stmt))
+ ;#(#t yay!)
+ ;; => #!void
+ (sql-query bind-stmt)
+ ; Evaluation aborted on postgresql-query!: [sql-error] bind message supplies 0
+ ; parameters, but prepared statement "stmt137" requires 1 --- irritants: (S .
+ ; ERROR) (V . ERROR) (C . 08P01) (M . bind message supplies 0 parameters, but
+ ; prepared statement "stmt137" requires 1) (F . postgres.c) (L . 1665) (R .
+ ; exec_bind_message)
+
+
+
+
+### `sql-finalize`
+
+When a stored procedure is finalized it is gone for good. While this is done by
+the [garbage collection](#sqlPrepare) there may be times when we want to get rid of it now.
+
+ (map sql-finalize [stmt istmt bind-stmt bind-istmt])
+ ;; => (#!void #!void #!void #!void)
+ (sql-query stmt)
+ ; Evaluation aborted on Invalid operation; statement finalized
+ ; #
+
+
+
+
+### `sql-txn-begin`
+
+Begins a transaction. See [`sql-error?`](#sqlError) for a transaction if you do not know what
+one is.
+
+ (sql-txn-begin db) ;; => #!void
+
+
+
+
+### `sql-txn-commit`
+
+Commits a transaction if there’s one that can be commited. It errors if the
+transaction cannot be commited and otherwise, if there is no transaction, does
+nothing at all.
+
+See [`sql-error?`](#sqlError) for a transaction that can and cannot be commited.
+
+ (sql-txn-commit db) ;; => #!void
+ (sql-txn-commit db) ;; => #!void
+ (sql-txn-commit db) ;; => #!void
+ (sql-txn-commit db) ;; => #!void
+ (sql-txn-commit db) ;; => #!void
+
+
+
+
+### `sql-txn-abort`
+
+Aborts a transaction. Sometimes we choose to abort, sometimes it is needed.
+
+ (sql-txn-abort db)
+
+
+
+
+### `sql-error?`
+
+Is this error a database error or something else? This predicate tells us so.
+
+Using it with [try](sugar.md), we can for example we can make a connection not error if we
+have a transaction that error yet leave other errors thrown.
+
+To start with, no catcher.
+
+ (sql-txn-begin db) ;; => #!void
+ (sql-eval-query db "SELECT 1") ;; => (1)
+ (sql-eval-query db "SELECT asd")
+ ; Evaluation aborted on postgresql-prepare!: [sql-error] column "asd" does not
+ ; exist --- irritants: (S . ERROR) (V . ERROR) (C . 42703) (M . column "asd"
+ ; does not exist) (P . 8) (F . parse_relation.c) (L . 3349) (R .
+ ; errorMissingColumn)
+
+ (sql-txn-commit db))
+ ; Evaluation aborted on postgresql-exec!: [sql-error] current transaction is
+ ; aborted, commands ignored until end of transaction block --- irritants: (S .
+ ; ERROR) (V . ERROR) (C . 25P02) (M . current transaction is aborted, commands
+ ; ignored until end of transaction block) (F . postgres.c) (L . 1682) (R .
+ ; exec_bind_message)
+
+ (sql-eval-query db "SELECT 1")
+ ; Evaluation aborted on postgresql-prepare!: [sql-error] current transaction is
+ ; aborted, commands ignored until end of transaction block --- irritants: (S .
+ ; ERROR) (V . ERROR) (C . 25P02) (M . current transaction is aborted, commands
+ ; ignored until end of transaction block) (F . postgres.c) (L . 1424) (R .
+ ; exec_parse_message)
+
+Now a better `try`.
+
+ (import :std/sugar)
+
+ (try
+ (sql-txn-begin db)
+ (sql-eval-query db "SELECT 1")
+ (sql-eval-query db "SELECT asd")
+ (catch sql-error? => (lambda _ (sql-txn-abort db)))
+ (finally (sql-txn-commit db))) ;; => #!void
+
+ (sql-eval-query db "SELECT 1") ;; => (1)
+
+
+
+
+### `sql-close`
+
+Close a database connection.
+ (sql-eval-query db "SELECT 1") ;; => (1)
+ (sql-close db) ;; => #!void
+ (sql-eval-query db "SELECT 1")
+ ; Evaluation aborted on Invalid operation; connection closed
+ ; #
+ (sql-close db) ;; => #!void
+ (sql-close db) ;; => #!void
## SQLite driver
diff --git a/doc/reference/sugar.md b/doc/reference/sugar.md
index 7b46f6ce9..fc2c0b60c 100644
--- a/doc/reference/sugar.md
+++ b/doc/reference/sugar.md
@@ -18,6 +18,8 @@ footprint, it only defines macros.
For the simplest macros that fit with a single expansion rule,
`defrule` provides a short-hand compared to writing a `defrules` with a single rewrite rule.
+
+
## try
```scheme
(try