Adds a basic README file

This commit is contained in:
Diogo Biazus 2015-05-31 14:16:25 -04:00
parent d34c06a4eb
commit d38acbe88c

123
README.md Normal file
View File

@ -0,0 +1,123 @@
# Hasql [![Build Status](https://travis-ci.org/nikita-volkov/hasql.svg?branch=master)](https://travis-ci.org/nikita-volkov/hasql)
Hasql provides a robust and concise yet powerful API for communication with arbitrary relational databases using SQL.
Currently the only backend available is for PostgreSQL ([which can yield great performance improvements](https://nikita-volkov.github.io/hasql-benchmarks/) over HDBC or postgresql-simple).
The code used here file is the [demo found in the repository](https://github.com/nikita-volkov/hasql/blob/master/demo/Main.hs)
## Openning a connection
For greater convenience the Hasql has a built-in connection pool. All interactions with the database backend are done within the context of such a pool.
So we have functions to create a pool and one to release all resources held by the pool:
```haskell
H.acquirePool
:: Hasql.Backend.Cx c =>
Hasql.Backend.CxSettings c -> H.PoolSettings -> IO (H.Pool c)
```
and
```haskell
H.releasePool :: H.Pool c -> IO ()
```
To create the pool we need to pass the connection settings (which are backend dependent) and the pool settings. The code sample below will open a connection to a PostgreSQL database.
```haskell
{-# LANGUAGE QuasiQuotes, ScopedTypeVariables, OverloadedStrings #-}
-- Import the API from the "hasql" library
import qualified Hasql as H
-- Import the backend API from the "hasql-postgres" library
import qualified Hasql.Postgres as HP
let postgresSettings = HP.ParamSettings "localhost" 5432 "postgres" "" "postgres"
-- Prepare the pool settings with a smart constructor,
-- which checks the inputted values on correctness.
-- Set the connection pool size to 6 and the timeout to 30 seconds.
poolSettings <- maybe (fail "Improper session settings") return $
H.poolSettings 6 30
-- Acquire the database connections pool.
-- Gotta help the compiler with the type signature of the pool a bit.
pool :: H.Pool HP.Postgres
<- H.acquirePool postgresSettings poolSettings
```
## Executing a statement
To execute statements we will use a ```Session```, which is just a wrapper for the ```ReaderT``` monad.
This allow us to use the pool for all our session sub-computations.
So the ```session``` function, is a wrapper for the ```runReaderT```, and besides a parameter with the pool,
we need to pass a function with the return type in ```H.Session``` monad. And as the return we get
either a ```SessionError``` or the result of our function.
The function we will use to actually execute the transactions is the ```tx```
which conveniently enough receives a transaction mode, the transactions we want to execute (along with their session context)
and returns the type ```H.Session c m r```.
It is **important** to notice that running ```IO``` in ```Tx``` is prohibited.
let's take a look at the signatures proceding:
```haskell
H.session
:: H.Pool c -> H.Session c m a -> m (Either (H.SessionError c) a)
H.tx
:: (Control.Monad.Trans.Control.MonadBaseControl IO m,
Hasql.Backend.CxTx c) =>
H.TxMode -> (forall s. H.Tx c s r) -> H.Session c m r
```
The following code excerpt shows us how the demo code uses these functions to open a
session and start a transaction to create a new table:
```haskell
-- Provide a context for execution of transactions.
-- 'Session' is merely a convenience wrapper around 'ReaderT'.
H.session pool $ do
-- Execute a group of statements without any locking and ACID guarantees:
H.tx Nothing $ do
H.unitEx [H.stmt|DROP TABLE IF EXISTS a|]
H.unitEx [H.stmt|CREATE TABLE a (id SERIAL NOT NULL, balance INT8, PRIMARY KEY (id))|]
```
## Transactions (isolation levels and transaction modes)
You have probably noticed that the first parameter of ```tx``` belongs to the type ```TxMode```.
This parameter deserves some consideration, for it will determine the behaviour of our transaction.
Let's take a look at its type definition:
```haskell
type TxMode = Maybe (TxIsolationLevel, TxWriteMode)
data TxIsolationLevel =
RepeatableReads |
Serializable |
ReadCommitted |
ReadUncommitted
type TxWriteMode = Maybe Bool
```
So when the ```mode``` is ```Nothing```, no transaction is explicitly estabilished on the server.
In PostgreSQL's case this means all commands be commited immediatly after execution
and their isolation level will be *Read Committed*.
If we pass the tuple, the first element will be the transaction isolation level, you can read more about
[transaction isolation levels on wikipedia](https://en.wikipedia.org/wiki/Isolation_(database_systems)#Isolation_levels).
The second element is the write mode, which will be interpreted as:
* ```Nothing``` indicates a "read" mode.
* ```Just True``` indicates a "write" mode.
* ```Just False``` indicates a "write" mode without committing (can be useful for testing purposes).