Search code examples
mysqlhaskellhaskell-snap-framework

How to connect to MySQL using Snap's MysqlSimple snaplet


The Snap Framework has a tutorial on how to write a web-application using snaplets. There exists a snaplet for connecting to MySQL, Snap.Snaplets.MysqlSimple, that depends on the library Database.MySQL.Simple, and it seems the snaplet is mostly a thin wrapper to keep the connection handle implicit.

The only example available in the documentation does not work. As described in a 2011 Haskell-cafe post (!), the example lacks some type annotations before it can derive the type of the result. Is there a simple example of a fully functional Snap application that connects to MySQL and fetches some result?

Additional question: I want to change the MySQL connection settings. Running the application creates a file called snaplets/mysql-simple/devel.cfg. Changing the settings in this file does not seem to affect the application even after recompiling, restarting and/or reloading.


Solution

  • The following example uses the default MySQL connection settings:

    {-# LANGUAGE TemplateHaskell #-}
    {-# LANGUAGE OverloadedStrings #-}
    
    module Main where
    
    import Snap
    import Snap.Snaplet
    import Snap.Snaplet.Heist
    import Snap.Snaplet.MysqlSimple
    
    import Control.Lens.TH
    
    import Data.Int
    import Data.Maybe
    import qualified Data.Text as T
    
    data App = App
        { _heist       :: Snaplet (Heist App)
        , _db          :: Snaplet Mysql
        }
    
    makeLenses ''App
    
    instance HasHeist App where
      heistLens = subSnaplet heist
    
    main :: IO ()
    main = serveSnaplet defaultConfig appInit
    
    appInit :: SnapletInit App App
    appInit = makeSnaplet "myapp" "Some application" Nothing $ do
      h <- nestSnaplet "heist" heist $ heistInit "templates"
      d <- nestSnaplet "db" db mysqlInit
      addRoutes [ ("/", defaultHandler), ("", heistServe) ]
      return $ App h d
    
    defaultHandler :: Handler App App ()
    defaultHandler = do
      ns <- q
      forM_ ns $ \ (Only i) -> 
        writeText $ T.concat [ "id = ", T.pack (show i), "\n"]
    
    q :: Handler App App [Only Int64]
    q = with db $ query_ ("select id from sometable")