public
Last active

Example generating HaskellDB records for SQLite3 during configuration.

  • Download Gist
postConfHaskellDB.lhs
Literate Haskell
import Distribution.Simple

This is an example Setup.hs for a haskell program making use of HaskellDB.

import System.Directory ( removeFile, removeDirectoryRecursive )

HaskellDB needs to have the structure of all database tables laid out as data.

import Database.HaskellDB
import Database.HaskellDB.DBSpec

If your database schema is already defined, and is not under your control, then it is wasted effort to go about defining the table data by hand. So let's let HaskellDB work for us!

import Database.HaskellDB.DBSpecToDBDirect

One important feature of the HaskellDB convenience layer is the ability to intelligently map table and column names to valid haskell names, this mapping can be customized, but the defaults are OK.

import Database.HaskellDB.DBSpec.PPHelpers ( mkIdentPreserving )

For this example we will be connecting to a SQLite3 database.

import Database.HaskellDB.HDBC.SQLite3 ( sqliteConnect )

HDBC-SQLite3 >= 2.3.1 is needed because HaskellDB needs a working 'describeTable' function.

main :: IO ()
main =

Using 'defaultMainWithHooks' allows us to provide the custom handlers which will 'generate' and 'clean' our table records created by HaskellDB.

    defaultMainWithHooks

Extending 'simpleUserHooks' prevents us from doing too much work.

    simpleUserHooks { postConf  = generate
                    , postClean = clean
                    }

The 'generate' function has hardcoded paths to the stub SQLite3 database used to generate the records, and the Haskell module namespace to create the source files under. A more complete solution might get these parameters from the environment.

generate _ _ _ _ = do    -- none of the arguments are used in this example
    putStrLn "Generating HaskellDB records..."
    dbInfo <- withDB dbPath (dbToDBSpec False mkIdentPreserving dbPath)
    dbInfoToModuleFiles "src/" dbNS dbInfo
  where
    dbPath = "config/stub.sqlite3"
    dbNS   = "Example.DB.Generated"
    withDB = sqliteConnect

The two heavy lifters here are 'dbToDBSpec' and 'dbInfoToModuleFiles'. Simply, 'dbToDBSpec' makes use of the underlying drivers 'describeTable' function to gather the table information from the database and convert it to a format HaskellDB will operate on. Then 'dbInfoToModuleFiles' uses this information to generate Haskell source files containing the necessary source code needed to work with this database using HaskellDB.

For completeness, cleaning up these generated files can be automated when the user calls 'cabal clean'.

clean _ _ _ _ = do    -- none of the arguments are used in this example
    putStrLn "Removing generated HaskellDB records..."
    removeFile "src/Example/DB/Generated.hs"
    removeDirectoryRecursive "src/Example/DB/Generated"

Now go out and code!

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.