experimenter-0.1.0.0: src/Experimenter/DB.hs
{-# LANGUAGE OverloadedStrings #-}
module Experimenter.DB where
import Conduit as C
import Control.Monad.Logger
import Control.Monad.Trans.Reader (ReaderT)
import Data.Char
import Data.List (foldl')
import qualified Data.Text as T
import qualified Database.Esqueleto as E
import Database.Persist.Postgresql (SqlBackend, withPostgresqlPool)
import Experimenter.DatabaseSetting
type DB m = ReaderT SqlBackend (LoggingT (ResourceT m))
type SimpleDB = DB IO
logFun :: (MonadIO m) => LoggingT m a -> m a
logFun = runStdoutLoggingT . filterLogger (\s _ -> s /= "SQL")
-- logFun :: NoLoggingT m a -> m a
-- logFun = runNoLoggingT
runDB :: (MonadUnliftIO m) => DatabaseSetting -> DB m a -> m a
runDB = runDBWithM runResourceT
runDBSimple :: DatabaseSetting -> SimpleDB a -> IO a
runDBSimple = runDBWithM runResourceT
runDBWithM :: (MonadUnliftIO m1) => (m1 a -> m a) -> DatabaseSetting -> ReaderT SqlBackend (LoggingT m1) a -> m a
runDBWithM runM dbSetting action = runM $ logFun $ withPostgresqlPool (connectionString dbSetting) (parallelConnections dbSetting) $ \pool -> E.runSqlPool action pool
-- withPostgresqlPool :: (MonadLogger m, MonadUnliftIO m) => ConnectionString -> Int -> (Pool SqlBackend -> m a) -> m a
-- runSqlPool :: (MonadUnliftIO m, BackendCompatible SqlBackend backend) => ReaderT backend m a -> Pool backend -> m a
-- | Create indices for fast lookups in the DB.
indexCreation :: (MonadIO m) => ReaderT SqlBackend (NoLoggingT (ResourceT m)) ()
indexCreation = mapM_ ((\x -> E.rawExecute ("CREATE INDEX IF NOT EXISTS " <> mkName x <> " ON " <> x) []) . mkLowerCase) indices
where
mkName txt = foldl' (\acc (from, to) -> T.replace from to acc) (txt <> "index") replacements
replacements = [("(", "_"), (")", "_"), (",", "_"), ("\"", "")]
mkLowerCase x = toLowerCase ( T.takeWhile (/= '(') x) <> T.singleton '(' <> toLowerCase (T.tail $ T.dropWhile (/= '(') x)
toLowerCase =
let go c
| isUpper c = T.pack ['_', toLower c]
| otherwise = T.singleton c
in T.dropWhile (== '_') . T.concatMap go
indices =
[ -- "ExpsInfoParam(exps)"
-- , "ExpsMaster(exps)"
-- , "ExpsSetup(exps)"
-- , "Param(exps)"
-- , "Exp(exps)"
-- , "ExpExecutionLock(exp)"
-- , "ExpProgress(exp)"
-- , "ParamSetting(exp)"
-- , "ExpResult(exp)"
-- , "PrepStartStatePart(resultData)"
-- , "PrepEndStatePart(resultData)"
-- , "PrepInput(prepResultData)"
-- , "PrepInputValue(prepInput)"
-- , "PrepMeasure(prepResultData)"
-- , "PrepResultStep(measure)"
-- , "RepResult(expResult)"
"RepResultStep(measure)"
, "WarmUpResultStep(measure)"
, "PrepResultStep(measure)"
, "RepMeasure(repResult)"
, "WarmUpMeasure(repResult)"
, "PrepMeasure(prepResultData)"
, "RepInputValue(repInput)"
, "WarmUpInputValue(warmUpInput)"
, "PrepInputValue(prepInput)"
, "RepStartStatePart(resultData)"
, "RepEndStatePart(resultData)"
-- , "\"user\"(ident)" -- user is a postgres keyword!
]