Code Monkey home page Code Monkey logo

hasql's Introduction

Hasql Build Status

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 over HDBC or postgresql-simple).

The code used here file is the demo found in the repository

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:

H.acquirePool
  :: Hasql.Backend.Cx c =>
     Hasql.Backend.CxSettings c -> H.PoolSettings -> IO (H.Pool c)

and

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.

{-# 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:

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:

-- 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:

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.

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).

hasql's People

Contributors

diogob avatar nikita-volkov avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.