Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell: HDBC, connection state and possibly pool

Tags:

haskell

Say, I have simple app which uses HDBC to interact with a database. It could be a snap app or a command line app. I'd like a generic view on this - not snap or anything specific. A good example would be the the chapter 22 from "Real World Haskell".

So I would hide all my SQL related functions like connect, saveArticle, getArticle etc. in a separate DB.hs file. All the DB functions would take a connection handle as an argument.

Now, how would I initiate the connection once and put it in a state so that all those DB functions just use it without initiating connection individually? Is this possible? Maybe I am thinking wrong or with OO concepts in mind but ... I would like to "initialize" my connection (like you would initialize an object in OO). I don't want every DB function to create and close new connection.

Do I have to create a pool and pass the pool to the functions as argument instead of connection handle? What is the simplest example of doing it?

Whether it is a pool or connection handle, how do I put it in a state so my functions just grab it when needed and don't repetitively "open" and "close" all the time? If yes, how is it done correctly?

Do I need to create a pool and put it in a state so functions just query the pool for connections from global state? Again, example would be really appreciated.

Thanks.

like image 547
r.sendecky Avatar asked Mar 23 '12 01:03

r.sendecky


2 Answers

There is no such thing as module state or application state, so you have to find an other strategy. I much recommend a reader monad, with the environment holding the db connection. That will cost you a few returns in some functions, but will be very solid.

Below is a simple pseudo-haskell example.

type AppState = AppState { dbcon :: DatabaseConnection }

type App = ReaderT AppState IO

main = do
  db <- makeNewDbConnection
  runReaderT getDbTableCount $ AppState db

getDbTableCount :: App Integer
getDbTableCount = do
  (count:_) <- runDb "select count(*) from table;"
  return $ read count

runDb :: String -> App [String]
runDb req = do
  con <- asks dbcon
  return $ dbQuery con req
like image 85
Paul R Avatar answered Nov 15 '22 06:11

Paul R


You may want to take a look at bos' resource-pool library.

like image 22
sclv Avatar answered Nov 15 '22 08:11

sclv