polysemy-hasql-0.0.1.0: lib/Polysemy/Hasql/Test/Database.hs
module Polysemy.Hasql.Test.Database where
import qualified Data.UUID as UUID
import Data.UUID (UUID)
import Exon (exon)
import Hasql.Connection (Connection)
import Hasql.Session (QueryError)
import Polysemy.Db.Data.DbConfig (DbConfig (DbConfig))
import Polysemy.Db.Data.DbConnectionError (DbConnectionError)
import qualified Polysemy.Db.Data.DbError as DbError
import Polysemy.Db.Data.DbError (DbError)
import Polysemy.Db.Data.DbName (DbName (DbName))
import Polysemy.Db.Effect.Random (Random, random)
import Polysemy.Db.Interpreter.Random (interpretRandom)
import Time (GhcTime)
import Sqel.Data.PgTypeName (pattern PgTypeName, pgTableName)
import Sqel.Data.TableSchema (TableSchema)
import Polysemy.Hasql.Effect.Database (ConnectionSource, Database)
import qualified Polysemy.Hasql.Effect.DbConnectionPool as DbConnectionPool
import Polysemy.Hasql.Effect.DbConnectionPool (DbConnectionPool)
import Polysemy.Hasql.Interpreter.Database (interpretDatabase)
import Polysemy.Hasql.Interpreter.DbConnectionPool (interpretDbConnectionPool, interpretDbConnectionPoolSingle)
import Polysemy.Hasql.Session (convertQueryError, runStatement)
import qualified Polysemy.Hasql.Statement as Statement
suffixedTableSchema ::
Text ->
TableSchema d ->
TableSchema d
suffixedTableSchema suffix =
#pg . #name %~ \ (PgTypeName name) -> pgTableName [exon|#{name}-#{suffix}|]
createTestDb ::
Members [Random UUID, Stop DbError, Embed IO] r =>
DbConfig ->
Connection ->
Sem r DbConfig
createTestDb dbConfig@(DbConfig _ _ (DbName name) _ _) connection = do
suffix <- UUID.toText <$> random
let
suffixedName = DbName [exon|#{name}-#{suffix}|]
suffixed = dbConfig & #name .~ suffixedName
suffixed <$ runStatement connection () (Statement.createDb suffixedName)
withTestDb ::
Members [Stop DbError, Resource, Mask, Race, Embed IO, Final IO] r =>
DbConfig ->
(DbConfig -> Sem r a) ->
Sem r a
withTestDb baseConfig f =
interpretDbConnectionPoolSingle baseConfig do
resumeHoist DbError.Connection $ DbConnectionPool.acquire "test" >>= \ connection ->
bracket (acquire baseConfig connection) (release connection) (raise . raise . f)
where
acquire config connection =
interpretRandom $ createTestDb config connection
release connection (DbConfig _ _ name _ _) =
mapStop convertQueryError (runStatement connection () (Statement.dropDb name))
type TestConnectionEffects =
[
Database !! DbError,
Scoped ConnectionSource (Database !! DbError),
DbConnectionPool !! DbConnectionError
]
withTestConnection ::
Members [Stop DbError, Time t dt, Log, Resource, Mask, Race, Embed IO, Final IO] r =>
DbConfig ->
InterpretersFor TestConnectionEffects r
withTestConnection baseConfig ma =
withTestDb baseConfig \ dbConfig ->
interpretDbConnectionPool dbConfig Nothing Nothing $
interpretDatabase $
ma
type TestStoreDeps =
[
Resource,
Embed IO,
Scoped ConnectionSource (Database !! DbError),
Database !! DbError,
Error DbError,
Random UUID,
Log,
Stop QueryError,
Stop DbError,
GhcTime
]